Crypt::NaCl::Sodium::stream - Stream ciphers (XSalsa20, ChaCha20, Salsa20, AES-128-CTR)
version 1.0.8.0
use Crypt::NaCl::Sodium qw( :utils ); my $crypto_stream = Crypt::NaCl::Sodium->stream(); my ($key, $nonce, $random_bytes, $secret, $decrypted_msg); my $msg = "Secret message"; ## XSalsa20 ######## # generate secret key $key = $crypto_stream->keygen(); # generate nonce $nonce = $crypto_stream->nonce(); # generate 256 bytes from $nonce and $key $random_bytes = $crypto_stream->bytes( 256, $nonce, $key ); # encrypt $secret = $crypto_stream->xor($msg, $nonce, $key); # decrypt $decrypted_msg = $crypto_stream->xor($secret, $nonce, $key); ## ChaCha20 ######## # generate secret key $key = $crypto_stream->chacha20_keygen(); # generate nonce $nonce = $crypto_stream->chacha20_nonce(); # generate 256 bytes from $nonce and $key $random_bytes = $crypto_stream->chacha20_bytes( 256, $nonce, $key ); # encrypt $secret = $crypto_stream->chacha20_xor($msg, $nonce, $key); # decrypt $decrypted_msg = $crypto_stream->chacha20_xor($secret, $nonce, $key); ## Salsa20 ######## # generate secret key $key = $crypto_stream->salsa20_keygen(); # generate nonce $nonce = $crypto_stream->salsa20_nonce(); # generate 256 bytes from $nonce and $key $random_bytes = $crypto_stream->salsa20_bytes( 256, $nonce, $key ); # encrypt $secret = $crypto_stream->salsa20_xor($msg, $nonce, $key); # decrypt $decrypted_msg = $crypto_stream->salsa20_xor($secret, $nonce, $key); ## AES-128-CTR ######## # generate secret key $key = $crypto_stream->aes128ctr_keygen(); # generate nonce $nonce = $crypto_stream->aes128ctr_nonce(); # generate 256 bytes from $nonce and $key $random_bytes = $crypto_stream->aes128ctr_bytes( 256, $nonce, $key ); # encrypt $secret = $crypto_stream->aes128ctr_xor($msg, $nonce, $key); # decrypt $decrypted_msg = $crypto_stream->aes128ctr_xor($secret, $nonce, $key);
The crypto_stream provides XSalsa20, ChaCha20, Salsa20 and AES-128 stream ciphers which can be used to generate pseudo-random data from a key and nonce, or as building blocks for implementing custom constructions, but they are not alternatives to Crypt::NaCl::Sodium::secretbox.
crypto_stream
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 generated key must be distributed in secret.
The default stream cipher is XSalsa20.
XSalsa20 is a stream cipher based upon Salsa20 but with a much longer nonce: 192 bits instead of 64 bits.
XSalsa20 uses a 256-bit key as well as the first 128 bits of the nonce in order to compute a subkey. This subkey, as well as the remaining 64 bits of the nonce, are the parameters of the Salsa20 function used to actually generate the stream.
Like Salsa20, XSalsa20 is immune to timing attacks and provides its own 64-bit block counter to avoid incrementing the nonce after each block.
But with XSalsa20's longer nonce, it is safe to generate nonces using "nonce" for every message encrypted with the same key without having to worry about a collision.
crypto_stream exposes XSalsa20 with 20 rounds as the default algorithm.
my $key = $crypto_stream->keygen();
Helper method to generate a XSalsa20 random key to be used by $crypto_stream.
$crypto_stream
The length of the $key equals "KEYBYTES".
$key
NOTE: keep the key confidential.
Returns Data::BytesLocker object.
my $nonce = $crypto_stream->nonce();
Helper method to generate a random nonce to be used by $crypto_stream.
The length of the nonce equals "NONCEBYTES".
If initial value has been passed as the argument, it will then padded with null bytes.
null
my $counter = 121; my $nonce = $crypto_stream->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. It is large enough that the randomly generated nonces have negligible risk of collision.
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.
# stream of random bytes my $bytes = $crypto_stream->bytes($num_of_bytes, $nonce, $key);
Generates unpredictable sequence of $num_of_bytes bytes using given $nonce and $key.
$num_of_bytes
$nonce
The length of the $bytes equals the value of $num_of_bytes.
$bytes
# encryption my $secret = $crypto_stream->xor($msg, $nonce, $key); # decryption my $decrypted_msg = $crypto_stream->xor($secret, $nonce, $key);
Encrypts/decrypts the message using given $nonce and $key.
The length of the $secret/$decrypted_msg is equal to the length of $msg/$secret.
$secret/$decrypted_msg
$msg/$secret
# encryption my $secret = $crypto_stream->xor_ic($msg, $nonce, $ic, $key); # decryption my $decrypted_msg = $crypto_stream->xor_ic($secret, $nonce, $ic, $key);
xor_ic is similar to "xor" function and encrypts/decrypts the message using given $nonce and $key, but adds the ability to set the initial value of the block counter to a non-zero value, $ic.
xor_ic
$ic
This permits direct access to any block without having to compute the previous ones.
ChaCha20 is a stream cipher developed by Daniel J. Bernstein that expands a 256-bit key into 2^64 randomly accessible streams, each containing 2^64 randomly accessible 64-byte (512 bits) blocks. It is a variant of Salsa20 with better diffusion.
ChaCha20 doesn't require any lookup tables and avoids the possibility of timing attacks.
Internally, ChaCha20 works like a block cipher used in counter mode. It uses a dedicated 64-bit block counter to avoid incrementing the 64-bit nonce after each block.
Methods that use IETF-compatible extended nonce (96-bit) and a 32-bit counter are also available as "chacha20_ietf_nonce", "chacha20_ietf_bytes", "chacha20_ietf_xor" and "chacha20_ietf_xor_ic".
IETF
my $key = $crypto_stream->chacha20_keygen();
Helper method to generate a ChaCha20 random key to be used by $crypto_stream.
The length of the $key equals "CHACHA20_KEYBYTES".
NOTE: this method can be used to generate keys used in original version of ChaCha20 and the IETF-compatible.
ChaCha20
my $nonce = $crypto_stream->chacha20_nonce();
The length of the nonce equals "CHACHA20_NONCEBYTES".
my $counter = 121; my $nonce = $crypto_stream->chacha20_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.
Bacause the nonce is 64 bits long, in order to prevent nonce reuse, if a key is being reused, it is recommended to increment the previous nonce instead of generating a random nonce every time a new stream is required.
my $nonce_ietf = $crypto_stream->chacha20_ietf_nonce();
Same as above but generates an IETF-compatible extended nonce.
The length of the nonce equals "CHACHA20_IETF_NONCEBYTES".
# stream of random bytes my $bytes = $crypto_stream->chacha20_bytes($num_of_bytes, $nonce, $key);
# stream of random bytes my $bytes = $crypto_stream->chacha20_ietf_bytes($num_of_bytes, $nonce_ietf, $key);
Same as above but uses an IETF-compatible extended nonce.
# encryption my $secret = $crypto_stream->chacha20_xor($msg, $nonce, $key); # decryption my $decrypted_msg = $crypto_stream->chacha20_xor($secret, $nonce, $key);
# encryption my $secret = $crypto_stream->chacha20_ietf_xor($msg, $nonce_ietf, $key); # decryption my $decrypted_msg = $crypto_stream->chacha20_ietf_xor($secret, $nonce_ietf, $key);
# encryption my $secret = $crypto_stream->chacha20_xor_ic($msg, $nonce, $ic, $key); # decryption my $decrypted_msg = $crypto_stream->chacha20_xor_ic($secret, $nonce, $ic, $key);
chacha20_xor_ic is similar to "chacha20_xor" function and encrypts/decrypts the message using given $nonce and $key, but adds the ability to set the initial value of the block counter to a non-zero value, $ic.
chacha20_xor_ic
# encryption my $secret = $crypto_stream->chacha20_ietf_xor_ic($msg, $nonce_ietf, $ic, $key); # decryption my $decrypted_msg = $crypto_stream->chacha20_ietf_xor_ic($secret, $nonce_ietf, $ic, $key);
Salsa20 is a stream cipher developed by Daniel J. Bernstein that expands a 256-bit key into 2^64 randomly accessible streams, each containing 2^64 randomly accessible 64-byte (512 bits) blocks.
Salsa20 doesn't require any lookup tables and avoids the possibility of timing attacks.
Internally, Salsa20 works like a block cipher used in counter mode. It uses a dedicated 64-bit block counter to avoid incrementing the nonce after each block.
Although the best known attack against Salsa20/8 is not practical, the full-round (20 rounds) version provides a highest security margin while still being fast enough for most purposes.
Faster, reduced-rounds versions of "salsa20_bytes" and "salsa20_xor" are also available.
my $key = $crypto_stream->salsa20_keygen();
Helper method to generate a Salsa20 random key to be used by $crypto_stream.
The length of the $key equals "SALSA20_KEYBYTES".
my $nonce = $crypto_stream->salsa20_nonce();
The length of the nonce equals "SALSA20_NONCEBYTES".
my $counter = 121; my $nonce = $crypto_stream->salsa20_nonce($counter); $nonce =~ /^121\0+$/ or die;
# stream of random bytes my $bytes = $crypto_stream->salsa20_bytes($num_of_bytes, $nonce, $key);
Salsa20 reduced to 12 rounds:
# stream of random bytes using Salsa20/12 my $bytes = $crypto_stream->salsa2012_bytes($num_of_bytes, $nonce, $key);
See "salsa20_bytes" for details.
Salsa20 reduced to 8 rounds:
# stream of random bytes using Salsa20/8 my $bytes = $crypto_stream->salsa208_bytes($num_of_bytes, $nonce, $key);
# encryption my $secret = $crypto_stream->salsa20_xor($msg, $nonce, $key); # decryption my $decrypted_msg = $crypto_stream->salsa20_xor($secret, $nonce, $key);
# encryption using Salsa20/12 my $secret = $crypto_stream->salsa2012_xor($msg, $nonce, $key); # decryption using Salsa20/12 my $decrypted_msg = $crypto_stream->salsa2012_xor($secret, $nonce, $key);
See "salsa20_xor" for details.
# encryption using Salsa20/8 my $secret = $crypto_stream->salsa208_xor($msg, $nonce, $key); # decryption using Salsa20/8 my $decrypted_msg = $crypto_stream->salsa208_xor($secret, $nonce, $key);
# encryption my $secret = $crypto_stream->salsa20_xor_ic($msg, $nonce, $ic, $key); # decryption my $decrypted_msg = $crypto_stream->salsa20_xor_ic($secret, $nonce, $ic, $key);
salsa20_xor_ic is similar to "salsa20_xor" function and encrypts/decrypts the message using given $nonce and $key, but adds the ability to set the initial value of the block counter to a non-zero value, $ic.
salsa20_xor_ic
crypto_stream provides a software bitsliced implementation of AES-128 in counter mode written by Peter Schwabe and Emilia Käsper, which resists all cache timing attacks.
Unless using AES is a requirement, you should consider "XSalsa20" or "ChaCha20" instead.
my $key = $crypto_stream->aes128ctr_keygen();
Helper method to generate a AES-128-CTR random key to be used by $crypto_stream.
The length of the $key equals "AES128CTR_KEYBYTES".
my $nonce = $crypto_stream->aes128ctr_nonce();
The length of the nonce equals "AES128CTR_NONCEBYTES".
my $counter = 121; my $nonce = $crypto_stream->aes128ctr_nonce($counter); $nonce =~ /^121\0+$/ or die;
# stream of random bytes my $bytes = $crypto_stream->aes128ctr_bytes($num_of_bytes, $nonce, $key);
# encryption my $secret = $crypto_stream->aes128ctr_xor($msg, $nonce, $key); # decryption my $decrypted_msg = $crypto_stream->aes128ctr_xor($secret, $nonce, $key);
my $nonce_length = $crypto_stream->NONCEBYTES;
Returns the length of nonce used by "XSalsa20" methods.
my $key_length = $crypto_stream->KEYBYTES;
Returns the length of key used by "XSalsa20" methods.
my $nonce_length = $crypto_stream->CHACHA20_NONCEBYTES;
Returns the length of nonce used by "ChaCha20" methods.
my $key_length = $crypto_stream->CHACHA20_KEYBYTES;
Returns the length of key used by "ChaCha20" methods.
my $nonce_length = $crypto_stream->SALSA20_NONCEBYTES;
Returns the length of nonce used by "Salsa20" methods.
my $key_length = $crypto_stream->SALSA20_KEYBYTES;
Returns the length of key used by "Salsa20" methods.
my $nonce_length = $crypto_stream->AES128CTR_NONCEBYTES;
Returns the length of nonce used by "AES-128-CTR" methods.
my $key_length = $crypto_stream->AES128CTR_KEYBYTES;
Returns the length of key used by "AES-128-CTR" methods.
crypto_stream stream ciphers, viewed as a functions of the nonce for a uniform random key, are designed to meet the standard notion of unpredictability.
This means that an attacker cannot distinguish this function from a uniform random function. Consequently, if a series of messages is encrypted by *_xor() methods with a different nonce for each message, the ciphertexts are indistinguishable from uniform random strings of the same length.
*_xor()
crypto_stream does not make any promises regarding the resistance to "related-key attacks". It is the caller's responsibility to use proper key-derivation functions.
Data::BytesLocker - guarded data storage
Crypt::NaCl::Sodium::secretbox
The security of the cipher block chaining message authentication code
Extending the Salsa20 nonce - the paper introducing XSalsa20
ChaCha, a variant of Salsa20
ChaCha20 and Poly1305 for IETF Protocols
Faster and Timing-Attach Resistant AES-GCM
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.