NAME

Crypt::NaCl::Sodium::stream - Stream ciphers (XSalsa20, ChaCha20, Salsa20, AES-128-CTR)

VERSION

version 0.08

SYNOPSIS

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);

DESCRIPTION

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.

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.

METHODS

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.

keygen

my $key = $crypto_stream->keygen();

Helper method to generate a XSalsa20 random key to be used by $crypto_stream.

The length of the $key equals "KEYBYTES".

NOTE: keep the key confidential.

Returns Data::BytesLocker object.

nonce

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.

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.

Returns Data::BytesLocker object.

bytes

# 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.

The length of the $bytes equals the value of $num_of_bytes.

Returns Data::BytesLocker object.

xor

# 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.

Returns Data::BytesLocker object.

xor_ic

# 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.

This permits direct access to any block without having to compute the previous ones.

The length of the $secret/$decrypted_msg is equal to the length of $msg/$secret.

Returns Data::BytesLocker object.

ChaCha20

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 nonce after each block.

chacha20_keygen

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: keep the key confidential.

Returns Data::BytesLocker object.

chacha20_nonce

my $nonce = $crypto_stream->chacha20_nonce();

Helper method to generate a random nonce to be used by $crypto_stream.

The length of the nonce equals "CHACHA20_NONCEBYTES".

If initial value has been passed as the argument, it will then padded with null bytes.

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.

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.

Returns Data::BytesLocker object.

chacha20_bytes

# stream of random bytes
my $bytes = $crypto_stream->chacha20_bytes($num_of_bytes, $nonce, $key);

Generates unpredictable sequence of $num_of_bytes bytes using given $nonce and $key.

The length of the $bytes equals the value of $num_of_bytes.

Returns Data::BytesLocker object.

chacha20_xor

# encryption
my $secret = $crypto_stream->chacha20_xor($msg, $nonce, $key);

# decryption
my $decrypted_msg = $crypto_stream->chacha20_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.

Returns Data::BytesLocker object.

chacha20_xor_ic

# 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.

This permits direct access to any block without having to compute the previous ones.

The length of the $secret/$decrypted_msg is equal to the length of $msg/$secret.

Returns Data::BytesLocker object.

Salsa20

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.

salsa20_keygen

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".

NOTE: keep the key confidential.

Returns Data::BytesLocker object.

salsa20_nonce

my $nonce = $crypto_stream->salsa20_nonce();

Helper method to generate a random nonce to be used by $crypto_stream.

The length of the nonce equals "SALSA20_NONCEBYTES".

If initial value has been passed as the argument, it will then padded with null bytes.

my $counter = 121;
my $nonce = $crypto_stream->salsa20_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.

Returns Data::BytesLocker object.

salsa20_bytes

# stream of random bytes
my $bytes = $crypto_stream->salsa20_bytes($num_of_bytes, $nonce, $key);

Generates unpredictable sequence of $num_of_bytes bytes using given $nonce and $key.

The length of the $bytes equals the value of $num_of_bytes.

Returns Data::BytesLocker object.

salsa2012_bytes

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.

salsa208_bytes

Salsa20 reduced to 8 rounds:

# stream of random bytes using Salsa20/8
my $bytes = $crypto_stream->salsa208_bytes($num_of_bytes, $nonce, $key);

See "salsa20_bytes" for details.

salsa20_xor

# encryption
my $secret = $crypto_stream->salsa20_xor($msg, $nonce, $key);

# decryption
my $decrypted_msg = $crypto_stream->salsa20_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.

Returns Data::BytesLocker object.

salsa2012_xor

Salsa20 reduced to 12 rounds:

# 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.

salsa208_xor

Salsa20 reduced to 8 rounds:

# 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);

See "salsa20_xor" for details.

salsa20_xor_ic

# 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.

This permits direct access to any block without having to compute the previous ones.

The length of the $secret/$decrypted_msg is equal to the length of $msg/$secret.

Returns Data::BytesLocker object.

AES-128-CTR

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.

aes128ctr_keygen

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".

NOTE: keep the key confidential.

Returns Data::BytesLocker object.

aes128ctr_nonce

my $nonce = $crypto_stream->aes128ctr_nonce();

Helper method to generate a random nonce to be used by $crypto_stream.

The length of the nonce equals "AES128CTR_NONCEBYTES".

If initial value has been passed as the argument, it will then padded with null bytes.

my $counter = 121;
my $nonce = $crypto_stream->aes128ctr_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.

Returns Data::BytesLocker object.

aes128ctr_bytes

# stream of random bytes
my $bytes = $crypto_stream->aes128ctr_bytes($num_of_bytes, $nonce, $key);

Generates unpredictable sequence of $num_of_bytes bytes using given $nonce and $key.

The length of the $bytes equals the value of $num_of_bytes.

Returns Data::BytesLocker object.

aes128ctr_xor

# encryption
my $secret = $crypto_stream->aes128ctr_xor($msg, $nonce, $key);

# decryption
my $decrypted_msg = $crypto_stream->aes128ctr_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.

Returns Data::BytesLocker object.

CONSTANTS

NONCEBYTES

my $nonce_length = $crypto_stream->NONCEBYTES;

Returns the length of nonce used by "XSalsa20" methods.

KEYBYTES

my $key_length = $crypto_stream->KEYBYTES;

Returns the length of key used by "XSalsa20" methods.

CHACHA20_NONCEBYTES

my $nonce_length = $crypto_stream->CHACHA20_NONCEBYTES;

Returns the length of nonce used by "ChaCha20" methods.

CHACHA20_KEYBYTES

my $key_length = $crypto_stream->CHACHA20_KEYBYTES;

Returns the length of key used by "ChaCha20" methods.

SALSA20_NONCEBYTES

my $nonce_length = $crypto_stream->SALSA20_NONCEBYTES;

Returns the length of nonce used by "Salsa20" methods.

SALSA20_KEYBYTES

my $key_length = $crypto_stream->SALSA20_KEYBYTES;

Returns the length of key used by "Salsa20" methods.

AES128CTR_NONCEBYTES

my $nonce_length = $crypto_stream->AES128CTR_NONCEBYTES;

Returns the length of nonce used by "AES-128-CTR" methods.

AES128CTR_KEYBYTES

my $key_length = $crypto_stream->AES128CTR_KEYBYTES;

Returns the length of key used by "AES-128-CTR" methods.

SECURITY MODEL

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.

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.

SEE ALSO

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.