Crypt::NaCl::Sodium::aead - Authenticated Encryption with Additional Data (ChaCha20/Poly1305 MAC, AES256-GCM)
version 1.0.8.0
use Crypt::NaCl::Sodium qw( :utils ); my $crypto_aead = Crypt::NaCl::Sodium->aead(); my ($key, $nonce, $additional_data, $decrypted_msg, $msg, $secret); ## Alice ######## # Alice generates secret key $key = $crypto_aead->keygen(); # ... and shares it with Bob send_to( Bob => { key => $key } ); # now Alice and Bob can start communicating # then generates random nonce $nonce = $crypto_aead->nonce(); send_to( Bob => { nonce => $nonce } ); # Alice's message to Bob $msg = "Hi Bob!"; # unencrypted metadata $additional_data = "greeting"; # Bob will need it to decrypt and verify secret message send_to( Bob => { additional_data => $additional_data } ); # the secret will include the additional data $secret = $crypto_aead->encrypt( $msg, $additional_data, $nonce, $key ); # message is ready for Bob send_to( Bob => { secret => $secret } ); ## Bob ######## # Bob receives the secret key from Alice $key = receive_for( Bob => 'key' ); # and random nonce $nonce = receive_for( Bob => 'nonce' ); # Bob is now ready to receive first message from Alice # first the additional data $additional_data = receive_for( Bob => 'additional_data' ); # then the secret itself $secret = receive_for( Bob => 'secret' ); # he has now all information required to decrypt message $decrypted_msg = $crypto_aead->decrypt( $secret, $additional_data, $nonce, $key ); # time to reply $msg = "Hello Alice!"; # generates new nonce $nonce = $crypto_aead->nonce(); # Bob replies with no additional data $additional_data = ""; # let's encrypt now $secret = $crypto_aead->encrypt( $msg, $additional_data, $nonce, $key ); # Alice needs all pieces to verify and decrypt Bob's message send_to( Alice => { nonce => $nonce } ); send_to( Alice => { additional_data => $additional_data } ); send_to( Alice => { secret => $secret } ); ## Alice ######## # Bob's data sent to Alice $nonce = receive_for( Alice => 'nonce' ); $additional_data = receive_for( Alice => 'additional_data' ); $secret = receive_for( Alice => 'secret' ); # we have now all information required to decrypt message $decrypted_msg = $crypto_aead->decrypt( $secret, $additional_data, $nonce, $key ); # NOTE: send_to() and receive_for() and user functions providing transport of # messages
Authenticated Encryption with Additional Data combines the secret-key encryption with a mechanism to include an optional, non-confidential (not-encrypted) data which can provide some protocol-specific metadata.
The additional data is included when computing the MAC of the secret and the decryption will never be performed, even partially, before verification.
The generated key must be distributed in secret.
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 key. The recommended way is to generate the initial nonce with first message and then increment it for each subsequent message using the same key - see "increment" in Crypt::NaCl::Sodium.
The default algorithm is ChaCha20 with Poly1305 MAC.
ChaCha20
Poly1305 MAC
If Intel SSSE3 extensions, aesni and pcmul instructions are available the hardware-accelerated AES256-GCM cipher can also be used.
Intel SSSE3
aesni
pcmul
AES256-GCM
The nonce is 64 bits long,
Methods that use IETF-compatible extended nonce (96-bit) and a 32-bit counter are also available as "ietf_nonce", "ietf_encrypt" and "ietf_decrypt".
IETF
my $key = $crypto_aead->keygen();
Helper method to generate a random key to be used by $crypto_aead.
$crypto_aead
The length of the $key equals "KEYBYTES".
$key
NOTE: keep the key confidential.
Returns Data::BytesLocker object.
my $nonce = $crypto_aead->nonce();
Helper method to generate a random nonce to be used by $crypto_aead.
The length of the nonce equals "NPUBBYTES".
If initial value has been passed as the argument, it will then padded with null bytes.
null
my $counter = 121; my $nonce = $crypto_aead->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 key.
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 key to avoid accidental reuse on the next session. In connection-oriented protocols counter-based nonce could help rejecting duplicate messages.
my $nonce_ietf = $crypto_aead->ietf_nonce();
Same as above but generates IETF-compatible extended nonce.
The length of the nonce equals "IETF_NPUBBYTES".
my $secret = $crypto_aead->encrypt($msg, $additional_data, $nonce, $key);
Encrypts the plaintext message using given $nonce and $key. Even when empty the $additional_data will be used to compute the MAC of the secret message.
$nonce
$additional_data
The length of the $secret is at most equal to the length of $msg + "ABYTES".
$secret
$msg
my $secret = $crypto_aead->ietf_encrypt($msg, $additional_data, $nonce_ietf, $key);
Same as above but uses IETF-compatible extended nonce.
my $msg; eval { $msg = $crypto_aead->decrypt($secret, $additional_data, $nonce, $key); }; if ( $@ ) { warn "Message forged!"; } else { print "Decrypted message: $msg\n"; }
Verify and decrypt the secret message with $additional_data using given $nonce and $key.
Function croaks if the verification fails. Otherwise returns the decrypted message.
The length of the $msg is at most equal to the length of $secret - "ABYTES".
my $msg; eval { $msg = $crypto_aead->ietf_decrypt($secret, $additional_data, $nonce_ietf, $key); }; if ( $@ ) { warn "Message forged!"; } else { print "Decrypted message: $msg\n"; }
When supported by the CPU, AES256-GCM is the fastest AEAD cipher available in this library.
AEAD
If portability is a concern, use default "ChaCha20/Poly1305 MAC" cipher.
if ( $crypto_aead->aes256gcm_is_available ) { print "Can use AES256-GCM!\n"; }
Returns true if the current CPU supports AES256-GCM implementation.
my $key = $crypto_aead->aes256gcm_keygen();
The length of the $key equals "AES256GCM_KEYBYTES".
NOTE: if AES256-GCM is not available this method croaks.
my $precal_key = $crypto_aead->aes256gcm_beforenm( $key );
Applications that encrypt several messages using the same key can gain a little speed by expanding the AES key only once, via the precalculation interface.
Returns Crypt::NaCl::Sodium::aead::aes256gcmstate object which encapsulates the expanded key.
Crypt::NaCl::Sodium::aead::aes256gcmstate
NOTE: the returned object provides following methods to allow securing the access to the expanded key:
$precal_key->lock();
When called makes the state inaccessible. It cannot be read or written, but the data are preserved.
$precal_key->unlock();
When called makes the state accessible for read access only.
if ( $precal_key->is_locked ) { $precal_key->unlock; }
Returns true if the $precal_key object is locked, false otherwise.
$precal_key
my $nonce = $crypto_aead->aes256gcm_nonce();
The length of the nonce equals "AES256GCM_NPUBBYTES".
my $counter = 121; my $nonce = $crypto_aead->aes256gcm_nonce($counter); $nonce =~ /^121\0+$/ or die;
my $secret = $crypto_aead->aes256gcm_encrypt($msg, $additional_data, $nonce, $key);
The length of the $secret is at most equal to the length of $msg + "AES256GCM_ABYTES".
my $secret = $crypto_aead->aes256gcm_encrypt_afternm($msg, $additional_data, $nonce, $precal_key);
Same as above but uses precalculated key (as returned by "aes256gcm_beforenm").
my $msg; eval { $msg = $crypto_aead->aes256gcm_decrypt($secret, $additional_data, $nonce, $key); }; if ( $@ ) { warn "Message forged!"; } else { print "Decrypted message: $msg\n"; }
The length of the $msg is at most equal to the length of $secret - "AES256GCM_ABYTES".
my $msg; eval { $msg = $crypto_aead->aes256gcm_decrypt_afternm($secret, $additional_data, $nonce, $precal_key); }; if ( $@ ) { warn "Message forged!"; } else { print "Decrypted message: $msg\n"; }
my $nonce_length = $crypto_aead->NPUBBYTES;
Returns the length of nonce used by "ChaCha20/Poly1305 MAC" methods.
my $nonce_length = $crypto_aead->IETF_NPUBBYTES;
Returns the length of nonce used by IETF-compatible "ChaCha20/Poly1305 MAC" methods.
my $nonce_length = $crypto_aead->AES256GCM_NPUBBYTES;
Returns the length of nonce used by "AES256-GCM" methods.
my $key_length = $crypto_aead->KEYBYTES;
Returns the length of key used by "ChaCha20/Poly1305 MAC" methods.
my $key_length = $crypto_aead->AES256GCM_KEYBYTES;
Returns the length of key used by "AES256-GCM" methods.
my $additional_bytes = $crypto_aead->ABYTES;
Returns the maximum of number of additional bytes added to encrypted messages used by "ChaCha20/Poly1305 MAC" methods.
my $additional_bytes = $crypto_aead->AES256GCM_ABYTES;
Returns the maximum of number of additional bytes added to encrypted messages used by "AES256-GCM" methods.
crypto_aead for encryption by default uses ChaCha20 stream cipher and Poly1305 MAC for authentication.
crypto_aead
Google has selected those algorithms as a replacement for RC4 in OpenSSL, and shortly afterwards it has been added to OpenSSH.
The AES256-GCM algorithm has been recommended by NIST and is a part of the TLS 1.2 ciphers.
NIST
TLS 1.2
Data::BytesLocker - guarded data storage
ChaCha, a variant of Salsa20
The Poly1305-AES message-authentication code
ChaCha20 and Poly1305 based Cipher Suites for TLS
AES Galois Counter Mode (GCM) Cipher Suites for TLS
An Interface and Algorithms for Authenticated Encryption
Alex J. G. Burzyński <ajgb@cpan.org>
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.
To install Crypt::NaCl::Sodium, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Crypt::NaCl::Sodium
CPAN shell
perl -MCPAN -e shell install Crypt::NaCl::Sodium
For more information on module installation, please visit the detailed CPAN module installation guide.