NAME
Crypt::NaCl::Sodium::box - Public-key authenticated encryption (Curve25519/XSalsa20/Poly1305 MAC)
VERSION
version 0.03
SYNOPSIS
use Crypt::NaCl::Sodium qw( :utils );
my $crypto_box = Crypt::NaCl::Sodium->box();
my ($a_skey, $a_pkey, $a_key, $b_skey,
$b_pkey, $b_key,
$a_precal_key, $b_precal_key,
$nonce, $decrypted_msg, $msg, $secret);
## Alice
########
# Alice generates secret keypair
($a_pkey, $a_skey) = $crypto_box->keypair();
# ... and shares the public key with Bob
send_to( Bob => { public_key => $a_pkey } );
## Bob
########
# Bob generates his secret keypair
($b_pkey, $b_skey) = $crypto_box->keypair();
# Bob receives the public key from Alice
$a_key = receive_for( Bob => 'public_key' );
# ... and shares his public key with Alice
send_to( Alice => { public_key => $b_pkey } );
# now Alice and Bob can start communicating
## Alice
########
# Alice receives the public key from Bob
$b_key = receive_for( Alice => 'public_key' );
# Alice generates random nonce
$nonce = $crypto_box->nonce();
send_to( Bob => { nonce => $nonce } );
# Alice's message to Bob
$msg = "Hi Bob!";
# encrypts using combined mode
$secret = $crypto_box->encrypt( $msg, $nonce, $b_key, $a_skey );
# message is ready for Bob
send_to( Bob => { secret => $secret } );
## Bob
########
# Bob receives the random nonce
$nonce = receive_for( Bob => 'nonce' );
# and is now ready to receive first message from Alice
$secret = receive_for( Bob => 'secret' );
# since Bob already has Alice's public key we have all information required to decrypt message
$decrypted_msg = $crypto_box->decrypt( $secret, $nonce, $a_key, $b_skey );
# Bob is going to send a lot of messages to Alice, so we speed up the
# encryption and decryption by pre-calculating the shared key
$b_precal_key = $crypto_box->beforenm( $a_key, $b_skey );
# now it is time to reply
$msg = "Hello Alice!";
# generates new nonce
$nonce = $crypto_box->nonce();
# this time we use detached mode using precalculated key
($mac, $secret) = $crypto_box->encrypt_afternm( $msg, $nonce, $b_precal_key );
# Alice needs all pieces to verify and decrypt Bob's message
send_to( Alice => { nonce => $nonce } );
send_to( Alice => { mac => $mac } );
send_to( Alice => { secret => $secret } );
## Alice
########
# Bob used the detached mode
$nonce = receive_for( Alice => 'nonce' );
$mac = receive_for( Alice => 'mac' );
$secret = receive_for( Alice => 'secret' );
# Alice also pre-calculates the shared key
$a_precal_key = $crypto_box->beforenm( $b_key, $a_skey );
# we have now all information required to decrypt message
$decrypted_msg = $crypto_box->decrypt_detached_afternm( $mac, $secret, $nonce, $a_precal_key );
# NOTE: send_to() and receive_for() and user functions providing transport of
# messages
DESCRIPTION
crypto_box
function is designed to meet the standard notions of privacy and third-party unforgeability for a public-key authenticated-encryption scheme using nonces.
The crypto_box
function is not meant to provide non-repudiation. On the contrary: the crypto_box function guarantees repudiability. A receiver can freely modify a boxed message, and therefore cannot convince third parties that this particular message came from the sender. The sender and receiver are nevertheless protected against forgeries by other parties. crypto_box
uses public-key authenticators rather than public-key signatures.
Users who want public verifiability (or receiver-assisted public verifiability) should instead use Crypt::NaCl::Sodium::sign.
Using public-key authenticated encryption, parties involved can encrypt a confidential message using their public keys, while keeping their secret keys confidential.
Using the sender's public key, only the receiver can verify that the encrypted message was actually created by the sender and was not tampered with, before eventually decrypting it. This bidirectional guarantee around identity is known as mutual authentication.
The same keypair can be used with multiple other users, without the need of generating a distinct set of keys.
Nonce (number used once) does not have to be protected, but it is crucial that the same nonce has not been ever reused with the same {sender, receiver}
set.
METHODS
keypair
my ($public_key, $secret_key) = $crypto_box->keypair();
# or deterministically derived from a single key seed
my ($public_key, $secret_key) = $crypto_box->keypair( $seed );
Helper method to generate a random secret key and corresponding public key to be used by $crypto_box
.
See "seed" for more details when generating key pair using given $seed
.
The length of the $public_key
equals "PUBLICKEYBYTES".
The length of the $secret_key
equals "SECRETKEYBYTES".
NOTE: keep the secret key confidential.
Returns Data::BytesLocker objects.
public_key
my $public_key = $crypto_box->public_key( $secret_key );
Computes the public key for given secret key.
The length of the $public_key
equals "PUBLICKEYBYTES".
Returns Data::BytesLocker objects.
seed
my $seed = $crypto_box->seed();
my ($public_key, $secret_key) = $crypto_box->keypair( $seed );
Helper method to generate a random seed, that can be used to deterministically compute the key pair derived from it.
The length of the $seed
equals "SEEDBYTES".
Returns Data::BytesLocker objects.
beforenm
my $shared_key = $crypto_box->beforenm( $recipient_public_key, $sender_secret_key );
Applications that send several messages to the same receiver or receive several messages from the same sender can gain speed by calculating the shared key only once, and reusing it in subsequent operations.
The length of the $shared_key
equals "BEFORENMBYTES".
Returns Data::BytesLocker objects.
nonce
my $nonce = $crypto_box->nonce();
Helper method to generate a random nonce to be used by $crypto_box
.
The length of the nonce equals "NONCEBYTES".
If initial value has been passed as the argument, it will then padded with null
bytes.
my $counter = 121;
my $nonce = $crypto_box->nonce($counter);
$nonce =~ /^121\0+$/ or die;
NOTE: nonce does not have to be random nor confidential, but it must never be reused with the same {sender, receiver}
set.
If random nonce is being used it needs to be provided to the other party to allow decryption.
If counter is being used store it alongside the recipient's public key to avoid accidental reuse on the next session. In connection-oriented protocols counter-based nonce could help rejecting duplicate messages.
Returns Data::BytesLocker object.
encrypt
# combined mode - MAC and encrypted message stored together
my $secret = $crypto_box->encrypt($msg, $nonce,
$recipient_public_key, $sender_secret_key);
# detached mode - MAC and encrypted message returned separate
my ($mac, $ciphertext) = $crypto_box->encrypt($msg, $nonce,
$recipient_public_key, $sender_secret_key);
Encrypts the plaintext message using given $nonce
, $recipient_public_key
and $sender_secret_key
.
In scalar context works in combined mode, where MAC and encrypted message are stored together. The length of the $secret
equals the length of $msg
+ "MACBYTES".
In list context the $mac
and $ciphertext
are returned separately. The length of the $ciphertext
equals the length of $msg
, while length of $mac
is "MACBYTES".
Returns Data::BytesLocker object.
encrypt_afternm
# combined mode - MAC and encrypted message stored together
my $secret = $crypto_box->encrypt_afternm($msg, $nonce,
$shared_key);
# detached mode - MAC and encrypted message returned separate
my ($mac, $ciphertext) = $crypto_box->encrypt_afternm($msg, $nonce,
$shared_key);
Encrypts the plaintext message using given $nonce
and pre-calculated $shared_key
(as returned by "beforenm").
In scalar context works in combined mode, where MAC and encrypted message are stored together. The length of the $secret
equals the length of $msg
+ "MACBYTES".
In list context the $mac
and $ciphertext
are returned separately. The length of the $ciphertext
equals the length of $msg
, while length of $mac
is "MACBYTES".
Returns Data::BytesLocker object.
decrypt
my $msg;
eval {
$msg = $crypto_box->decrypt($secret, $nonce,
$sender_public_key, $recipient_secret_key);
};
if ( $@ ) {
warn "Message forged!";
} else {
print "Decrypted message: $msg\n";
}
Verify and decrypt the secret message using given $nonce
, $sender_public_key
and $recipient_secret_key
.
Function croaks if the verification fails. Otherwise returns the decrypted message.
The length of the $msg
equals the length of $secret
- "MACBYTES".
Returns Data::BytesLocker object.
decrypt_detached
my $msg;
eval {
$msg = $crypto_box->decrypt_detached($mac, $ciphertext, $nonce,
$sender_public_key, $recipient_secret_key);
};
if ( $@ ) {
warn "Message forged!";
} else {
print "Decrypted message: $msg\n";
}
Verify and decrypt the secret message $ciphertext
authenticated with $mac
using given $nonce
, $sender_public_key
and $recipient_secret_key
.
Function croaks if the verification fails. Otherwise returns the decrypted message.
The length of the $msg
equals the length of $ciphertext
.
Returns Data::BytesLocker object.
decrypt_afternm
my $msg;
eval {
$msg = $crypto_box->decrypt_afternm($secret, $nonce,
$shared_key);
};
if ( $@ ) {
warn "Message forged!";
} else {
print "Decrypted message: $msg\n";
}
Verify and decrypt the secret message using given $nonce
and pre-calculated $shared_key
(as returned by "beforenm").
Function croaks if the verification fails. Otherwise returns the decrypted message.
The length of the $msg
equals the length of $secret
- "MACBYTES".
Returns Data::BytesLocker object.
decrypt_detached_afternm
my $msg;
eval {
$msg = $crypto_box->decrypt_detached_afternm($mac, $ciphertext, $nonce,
$shared_key);
};
if ( $@ ) {
warn "Message forged!";
} else {
print "Decrypted message: $msg\n";
}
Verify and decrypt the secret message $ciphertext
authenticated with $mac
using given $nonce
and pre-calculated $shared_key
(as returned by "beforenm").
Function croaks if the verification fails. Otherwise returns the decrypted message.
The length of the $msg
equals the length of $ciphertext
.
Returns Data::BytesLocker object.
CONSTANTS
NONCEBYTES
my $nonce_length = $crypto_box->NONCEBYTES;
Returns the length of nonce.
SECRETKEYBYTES
my $skey_length = $crypto_box->SECRETKEYBYTES;
Returns the length of secret key.
PUBLICKEYBYTES
my $pkey_length = $crypto_box->PUBLICKEYBYTES;
Returns the length of public key.
SEEDBYTES
my $seed_length = $crypto_box->SEEDBYTES;
Returns the length of seed key.
BEFORENMBYTES
my $shared_key_length = $crypto_box->BEFORENMBYTES;
Returns the length of pre-calculated shared key.
MACBYTES
my $mac_length = $crypto_box->MACBYTES;
Returns the length of MAC.
ALGORITHM DETAILS
crypto_box
for encryption uses XSalsa20 stream cipher (which is based on Salsa20, but with much longer nonce) and Poly1305 MAC for authentication, for key exchange Curve25519 is used.
SEE ALSO
Data::BytesLocker - guarded data storage
A state-of-the-art Diffie-Hellman function - Curve25519
Extending the Salsa20 nonce - the paper introducing XSalsa20
AUTHOR
Alex J. G. Burzyński <ajgb@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2015 by Alex J. G. Burzyński <ajgb@cpan.org>.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.