NAME

Crypt::Sodium::XS::box - Asymmetric (public/secret key) authenticated encryption

SYNOPSIS

use Crypt::Sodium::XS::box ":default";
use Crypt::Sodium::XS::Util "sodium_increment";

my ($pk, $sk) = box_keypair();
my ($pk2, $sk2) = box_keypair();
my $nonce = box_nonce();

my $ct = box_encrypt("hello", $nonce, $pk2, $sk);
my $pt = box_decrypt($ct, $nonce, $pk, $sk2);
# $pt is now "hello" (MemVault)

$nonce = sodium_increment($nonce);
($ct, my $mac) = box_encrypt_detached("world", $nonce, $pk, $sk2);
$pt = box_decrypt_detached($ct, $mac, $nonce, $pk2, $sk);
# $pt is now "world" (MemVault)

my $precalc1 = box_beforenm($pk2, $sk);
my $precalc2 = box_beforenm($pk, $sk2);
# $precalc and $precalc2 hold identical derived secret keys

$nonce = box_nonce();
$ct = $precalc->encrypt("goodbye", $nonce, $shared_key);
$pt = $precalc2->decrypt($ct, $nonce, $shared_key2);
# $pt is now "goodbye" (MemVault)

$ct = box_seal_encrypt("anonymous message", $pk2);
$pt = box_seal_decrypt($ct, $pk, $sk);

DESCRIPTION

Using public-key authenticated encryption, Alice can encrypt a confidential message specifically for Bob, using Bob's public key.

Based on Bob's public key, Alice can compute a shared secret key. Using Alice's public key and his secret key, Bob can compute the exact same shared secret key. That shared secret key can be used to verify that the encrypted message was not tampered with, before eventually decrypting it.

In order to send messages to Bob, Alice only needs Bob's public key. Bob should never ever share his secret key (not even with Alice).

For verification and decryption, Bob only needs Alice's public key, the nonce and the ciphertext. Alice should never ever share her secret key either, even with Bob.

Bob can reply to Alice using the same system, without having to generate a distinct key pair. The nonce doesn't have to be confidential, but it should be used with just one invocation of "box_encrypt" for a particular pair of public and secret keys.

One easy way to generate a nonce is to use "box_nonce", considering the size of the nonces the risk of any random collisions is negligible. For some applications, if you wish to use nonces to detect missing messages or to ignore replayed messages, it is also acceptable to use a simple incrementing counter as a nonce. A better alternative is to use the Crypt::Sodium::XS::secretstream API.

When doing so you must ensure that the same nonce can never be re-used (for example you may have multiple threads or even hosts generating messages using the same key pairs).

As stated above, senders can decrypt their own messages, and compute a valid authentication tag for any messages encrypted with a given shared secret key. This is generally not an issue for online protocols. If this is not acceptable, check out "box_seal_encrypt" and "box_seal_decrypt", as well as the Crypt::Sodium::XS::kx.

FUNCTIONS

Nothing is exported by default. A :default tag imports the functions and constants as documented below. A separate import tag is provided for each of the primitives listed in "PRIMITIVES". For example, :curve25519xchacha20poly1305 imports box_curve25519xchacha20poly1305_decrypt. You should use at least one import tag.

box_beforenm

my $precalc = box_beforenm($their_public_key, $my_secret_key);

Returns a precalculation box object. This is useful if you send or receive many messages using the same public key. See "PRECALCULATION INTERFACE".

box_decrypt

my $plaintext = box_decrypt(
  $ciphertext,
  $mac,
  $nonce,
  $their_public_key,
  $my_secret_key,
  $flags
);

Croaks on decryption failure.

NOTE: this is the libsodium function crypto_box_open_easy. Its name is slightly different for consistency of this API.

box_decrypt_detached

my ($plaintext, $mac) = box_decrypt(
  $ciphertext,
  $mac,
  $nonce,
  $their_public_key,
  $my_secret_key,
  $flags
);

Croaks on decryption failure.

NOTE: this is the libsodium function crypto_box_open_detached. Its name is slightly different for consistency of this API.

box_encrypt

my $ciphertext
  = box_encrypt($message, $nonce, $their_public_key, $my_secret_key);

NOTE: this is the libsodium function crypto_box. Its name is slightly different for consistency of this API.

box_encrypt_detached

my ($ciphertext, $mac)
  = box_encrypt_detached($message, $nonce, $their_public_key, $my_secret_key);

NOTE: this is the libsodium function crypto_box_easy_detached. Its name is slightly different for consistency of this API.

box_keypair

my ($public_key, $secret_key) = box_keypair();
my ($public_key, $secret_key) = box_keypair($seed);

$seed is optional. If provided, it must be "box_SEEDBYTES" in length. Using the same seed will generate the same key pair, so it must be kept confidential. If omitted, a key pair is randomly generated.

box_nonce

my $nonce = box_nonce();
my $nonce = box_nonce($base_nonce);

box_seal_encrypt

my $ciphertext = box_seal_encrypt($message, $their_public_key);

NOTE: this is the libsodium function crypto_box_seal. Its name is slightly different for consistency of this API.

box_seal_decrypt

my $plaintext = box_seal($ciphertext, $my_public_key, $my_secret_key, $flags);

Croaks on decryption failure.

NOTE: this is the libsodium function crypto_box_seal_open. Its name is slightly different for consistency of this API.

PRECALCULATION INTERFACE

Applications that send several messages to the same recipient or receive several messages from the same sender can improve performance by calculating the shared key only once, via the precalculation interface.

A precalculated box object is created by calling the "box_beforenm" function. It is an opaque object which provides the following methods:

decrypt
my $plaintext = $precalc->decrypt($ciphertext, $nonce, $flags);

Croaks on decryption failure.

decrypt_detached
my $plaintext = $precalc->decrypt($ciphertext, $mac, $nonce, $flags);

Croaks on decryption failure.

encrypt
my $ciphertext = $precalc->encrypt($plaintext, $nonce);
encrypt_detached
my ($ciphertext, $mac) = $precalc->encrypt($plaintext, $nonce);

CONSTANTS

box_PRIMITIVE

my $default_primitive = box_PRIMITIVE();

box_BEFORENMBYTES

my $shared_key_length = box_BEFORENMBYTES();

box_MACBYTES

my $mac_length = box_MACBYTES();

box_MESSAGEBYTES_MAX

my $message_max_length = box_MESSAGEBYTES_MAX();

box_NONCEBYTES

my $nonce_length = box_NONCEBYTES();

box_PUBLICKEYBYTES

my $public_key_length = box_PUBLICKEYBYTES();

box_SEALBYTES

my $seal_length = box_SEALBYTES();

ciphertext for sealed boxes is message length + seal length.

box_SECRETKEYBYTES

my $secret_key_length = box_SECRETKEYBYTES();

box_SEEDBYTES

my $keypair_seed_length = box_SEEDBYTES();

PRIMITIVES

All constants (except _PRIMITIVE) and functions have box_<primitive>-prefixed couterparts (e.g., box_curve25519xchacha20poly1305_encrypt, box_curve25519xsalsa20poly1305_SEEDBYTES).

  • curve25519xchacha20poly1305

  • curve25519xsalsa20poly1305

SEE ALSO

Crypt::Sodium::XS
Crypt::Sodium::XS::OO::box
https://doc.libsodium.org/public-key_cryptography/authenticated_encryption

FEEDBACK

For reporting bugs, giving feedback, submitting patches, etc. please use the following:

  • IRC channel #sodium on irc.perl.org.

  • Email the author directly.

AUTHOR

Brad Barden <perlmodules@5c30.org>

COPYRIGHT & LICENSE

Copyright (c) 2022 Brad Barden. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 265:

You forgot a '=back' before '=head1'