--- Crypt-Spritz/Spritz.pm 2015/01/10 07:19:24 1.5 +++ Crypt-Spritz/Spritz.pm 2015/01/10 09:36:01 1.8 @@ -1,6 +1,6 @@ =head1 NAME -Crypt::Spritz - Spritz stream cipher/hash/MAC/AEAD/CSPRNG module +Crypt::Spritz - Spritz stream cipher/hash/MAC/AEAD/CSPRNG family =head1 SYNOPSIS @@ -12,6 +12,10 @@ my $cipher = new Crypt::Spritz::Cipher::XOR $key, $iv; $ciphertext = $cipher->crypt ($cleartext); + my $cipher = new Crypt::Spritz::Cipher $key, $iv; + $ciphertext = $cipher->encrypt ($cleartext); + # $cleartext = $cipher->decrypt ($ciphertext); + my $hasher = new Crypt::Spritz::Hash; $hasher->add ($data); $digest = $hasher->finish; @@ -20,15 +24,22 @@ $hasher->add ($data); $mac = $hasher->finish; + my $prng = new Crypt::Spritz::PRNG $entropy; + $prng->add ($additional_entropy); + $keydata = $prng->get (32); + my $aead = new Crypt::Spritz::AEAD::XOR $key; $aead->nonce ($counter); $aead->associated_data ($header); $ciphertext = $aead->crypt ($cleartext); $mac = $aead->mac; - my $prng = new Crypt::Spritz::PRNG $entropy; - $prng->add ($additional_entropy); - $keydata = $prng->get (32); + my $aead = new Crypt::Spritz::AEAD $key; + $aead->nonce ($counter); + $aead->associated_data ($header); + $ciphertext = $aead->encrypt ($cleartext); + # $cleartext = $aead->decrypt ($ciphertext); + $mac = $aead->mac; =head1 DESCRIPTION @@ -48,8 +59,8 @@ unproven in the field (as of this writing, the cipher was just a few months old), so it can't be called production-ready. -All the usual caveats regarding stream ciphers apply - never repeat -your key, never repeat your nonce and so on - you should have some basic +All the usual caveats regarding stream ciphers apply - never repeat your +key, never repeat your nonce and so on - you should have some basic understanding of cryptography before using this cipher in your own designs. @@ -57,11 +68,13 @@ and safer, a number of convenience classes are provided for typical end-user tasks: - encryption - Crypt::Spritz::Cipher::XOR + random number generation - Crypt::Spritz::PRNG hashing - Crypt::Spritz::Hash message authentication - Crypt::Spritz::MAC + encryption - Crypt::Spritz::Cipher::XOR + encryption - Crypt::Spritz::Cipher authenticated encryption - Crypt::Spritz::AEAD::XOR - random number generation - Crypt::Spritz::PRNG + authenticated encryption - Crypt::Spritz::AEAD =cut @@ -69,7 +82,7 @@ use XSLoader; -$VERSION = '0.0'; +$VERSION = '0.1'; XSLoader::load __PACKAGE__, $VERSION; @@ -122,6 +135,12 @@ Initialises the Spritz state again, throwing away the previous state. +=item $another_spritz = $spritz->clone + +Make an exact copy of the spritz state. This method can be called on all +of the objects in this module, but is documented separately to give some +cool usage examples. + =item $spritz->update # Update =item $spritz->whip ($r) # Whip @@ -137,8 +156,8 @@ =item $spritz->absorb ($I) # Absorb -Absorbs the given data into the state (usually used for key material, nonces, IVs -messages to be hashed and so on). +Absorbs the given data into the state (usually used for key material, +nonces, IVs messages to be hashed and so on). =item $spritz->absorb_stop # AbsorbStop @@ -161,71 +180,67 @@ =back -=head2 THE Crypt::Spritz::Cipher::XOR CLASS +=head2 THE Crypt::Spritz::PRNG CLASS -This class implements stream encryption/decryption. It doesn't implement -the standard Spritz encryption but the XOR variant (called B -in the paper). +This class implements a Pseudorandom Number Generatore (B), +sometimes also called a Deterministic Random Bit Generator (B). In +fact, it is even cryptographically secure, making it a B. -The XOR variant should be as secure as the standard variant, but -doesn't have separate encryption and decryaption functions, which saves -codesize. IT is not compatible with standard Spritz encryption, however - -drop me a note if you want that implemented as well. +Typical usage as a random number generator involves creating a PRNG +object with a seed of your choice, and then fetching randomness via +C: -Typical use for encryption I decryption (code is identical for -decryption, you simply pass the encrypted data to C): + # create a PRNG object, use a seed string of your choice + my $prng = new Crypt::Spritz::PRNG $seed; - # create a cipher - $salt can be a random string you send - # with your message, in clear, a counter (best), or empty if - # you only want to encrypt one message with the given key. - # 16 or 32 octets are typical sizes for the key, for the salt, - # use whatever you need to give a unique salt for every - # message you encrypt with the same key. + # now call get as many times as you wish to get binary randomness + my $some_randomness = $prng->get (17); + my moree_randomness = $prng->get (5000); + ... - my $cipher = Crypt::Spritz::Cipher::XOR $key, $salt; +Typical usage as a cryptographically secure random number generator is to +feed in some secret entropy (32 octets/256 bits are commonly considered +enough), for example from C or C, and then +generate some key material. - # encrypt a message in one or more calls to crypt + # create a PRNG object + my $prng = new Crypt::Spritz::PRNG; - my $encrypted; + # seed some entropy (either via ->add or in the constructor) + $prng->add ($some_secret_highly_entropic_string); - $encrypted .= $cipher->crypt ("This is"); - $encrypted .= $cipher->crypt ("all very"); - $encrypted .= $cipher->crypt ("secret"); + # now call get as many times as you wish to get + # hard to guess binary randomness + my $key1 = $prng->get (32); + my $key2 = $prng->get (16); + ... - # that's all + # for long running programs, it is advisable to + # reseed the PRNG from time to time with new entropy + $prng->add ($some_more_entropy); =over 4 -=item $cipher = new Crypt::Spritz::Cipher::XOR $key[, $iv] - -Creates a new cipher object usable for encryption and decryption. The -C<$key> must be provided, the initial vector C<$IV> is optional. - -Both C<$key> and C<$IV> can be of any length. Typical lengths for the -C<$key> are 16 (128 bit) or 32 (256 bit), while the C<$IV> simply needs to -be long enough to distinguish repeated uses of tghe same key. - -=item $encrypted = $cipher->crypt ($cleartext) - -=item $cleartext = $cipher->crypt ($encrypted) +=item $prng = new Crypt::Spritz::PRNG [$seed] -Encrypt or decrypt a piece of a message. This cna be called as many times -as you want, and the message can be split into as few or many pieces as -required without affecting the results. +Creates a new random number generator object. If C<$seed> is given, then +the C<$seed> is added to the internal state as if by a call to C. -=item $cipher->crypt_inplace ($cleartext_or_ciphertext) +=item $prng->add ($entropy) -Same as C, except it I. +Adds entropy to the internal state, thereby hopefully making it harder +to guess. Good sources for entropy are irregular hardware events, or +randomness provided by C or C. -=item $constant_32 = $cipher->keysize +The design of the Spritz PRNG should make it strong against attacks where +the attacker controls all the entropy, so it should be safe to add entropy +from untrusted sources - more is better than less if you need a CSPRNG. -=item $constant_64 = $cipher->blocksize +For use as PRNG, of course, this matters very little. -These methods are provided for L compatibility and simply -return C<32> and C<64>, respectively. +=item $octets = $prng->get ($length) -Note that it is pointless to use Spritz with L, as Spritz is -not a block cipher and already provides an appropriate mode. +Generates and returns C<$length> random octets as a string. =back @@ -267,6 +282,35 @@ Typical digest lengths are 16 and 32, corresponding to 128 and 256 bit digests, respectively. +=item $another_hasher = $hasher->clone + +Make an exact copy of the hasher state. This can be useful to generate +incremental hashes, for example. + +Example: generate a hash for the data already fed into the hasher, by keeping +the original hasher for further C calls and calling C on a C. + + my $intermediate_hash = $hasher->clone->finish; + +Example: hash 64KiB of data, and generate a hash after every kilobyte that +is over the full data. + + my $hasher = new Crypt::Spritz::Hash; + + for (0..63) { + my $kib = "x" x 1024; # whatever data + + $hasher->add ($kib); + + my $intermediate_hash = $hasher->clone->finish; + ... + } + +These kind of intermediate hashes are sometimes used in communications +protocols to protect the integrity of the data incrementally, e.g. to +detect errors early, while still having a complete hash at the end of a +transfer. + =back @@ -315,6 +359,119 @@ Typical digest lengths are 16 and 32, corresponding to 128 and 256 bit digests, respectively. +=item $another_hasher = $hasher->clone + +Make an exact copy of the hasher state. This can be useful to +generate incremental macs, for example. + +See the description for the C method for some +examples. + +=back + + +=head2 THE Crypt::Spritz::Cipher::XOR CLASS + +This class implements stream encryption/decryption. It doesn't implement +the standard Spritz encryption but the XOR variant (called B +in the paper). + +The XOR variant should be as secure as the standard variant, but +doesn't have separate encryption and decryaption functions, which saves +codesize. IT is not compatible with standard Spritz encryption, however - +drop me a note if you want that implemented as well. + +Typical use for encryption I decryption (code is identical for +decryption, you simply pass the encrypted data to C): + + # create a cipher - $salt can be a random string you send + # with your message, in clear, a counter (best), or empty if + # you only want to encrypt one message with the given key. + # 16 or 32 octets are typical sizes for the key, for the salt, + # use whatever you need to give a unique salt for every + # message you encrypt with the same key. + + my $cipher = Crypt::Spritz::Cipher::XOR $key, $salt; + + # encrypt a message in one or more calls to crypt + + my $encrypted; + + $encrypted .= $cipher->crypt ("This is"); + $encrypted .= $cipher->crypt ("all very"); + $encrypted .= $cipher->crypt ("secret"); + + # that's all + +=over 4 + +=item $cipher = new Crypt::Spritz::Cipher::XOR $key[, $iv] + +Creates a new cipher object usable for encryption and decryption. The +C<$key> must be provided, the initial vector C<$IV> is optional. + +Both C<$key> and C<$IV> can be of any length. Typical lengths for the +C<$key> are 16 (128 bit) or 32 (256 bit), while the C<$IV> simply needs to +be long enough to distinguish repeated uses of tghe same key. + +=item $encrypted = $cipher->crypt ($cleartext) + +=item $cleartext = $cipher->crypt ($encrypted) + +Encrypt or decrypt a piece of a message. This can be called as many times +as you want, and the message can be split into as few or many pieces as +required without affecting the results. + +=item $cipher->crypt_inplace ($cleartext_or_ciphertext) + +Same as C, except it I. + +=item $another_cipher = $cipher->clone + +Make an exact copy of the cipher state. This can be useful to cache states +for reuse later, for example, to avoid expensive key setups. + +While there might be use cases for this feature, it makes a lot more sense +for C and C, as they allow +you to specify the IV/nonce separately. + +=item $constant_32 = $cipher->keysize + +=item $constant_64 = $cipher->blocksize + +These methods are provided for L compatibility and simply +return C<32> and C<64>, respectively. + +Note that it is pointless to use Spritz with L, as Spritz is +not a block cipher and already provides an appropriate mode. + +=back + + +=head2 THE Crypt::Spritz::Cipher CLASS + +This class is pretty much the same as the C +class, with two differences: first, it implements the "standard" Spritz +encryption algorithm, and second, while this variant is easier to analyze +mathematically, there is little else to recommend it for, as it is slower, +and requires lots of code duplication code. + +So unless you need to be compatible with another implementation that does +not offer the XOR variant, stick to C. + +All the methods from C are available, except +C, which has been replaced by separate C and C +methods: + +=over 4 + +=item $encrypted = $cipher->encrypt ($cleartext) + +=item $cleartext = $cipher->decrypt ($encrypted) + +Really the same as C, except you need separate +calls and code for encryption and decryption. + =back @@ -402,7 +559,7 @@ generate the same randomness multiple times (randomness can be very hard to get especially on embedded devices). -=item $aead->associated_data ($data)( +=item $aead->associated_data ($data) Provide the associated data (cleartext data to be authenticated but not encrypted). This method I be called I C and I @@ -421,7 +578,7 @@ =item $cleartext = $cipher->crypt ($encrypted) -Encrypt or decrypt a piece of a message. This cna be called as many times +Encrypt or decrypt a piece of a message. This can be called as many times as you want, and the message can be split into as few or many pieces as required without affecting the results, with one exception: All except the last call to C needs to pass in a multiple of C<64> octets. The @@ -431,70 +588,53 @@ Same as C, except it I. -=back +=item $another_cipher = $cipher->clone +Make an exact copy of the cipher state. This can be useful to cache states +for reuse later, for example, to avoid expensive key setups. -=head2 THE Crypt::Spritz::PRNG CLASS +Example: set up a cipher state with a key, then clone and use it to +encrypt messages with different nonces. -This class implements a Pseudorandom Number Generatore (B), -sometimes also called a Deterministic Random Bit Generator (B). In -fact, it is even cryptographically secure, making it a B. + my $cipher = new Crypt::Spritz::AEAD::XOR $key; -Typical usage as a random number generator involves creating a PRNG -object with a seed of your choice, and then fetching randomness via -C: - - # create a PRNG object, use a seed string of your choice - my $prng = new Crypt::Spritz::PRNG $seed; + my $message_counter; - # now call get as many times as you wish to get binary randomness - my $some_randomness = $prng->get (17); - my moree_randomness = $prng->get (5000); - ... - -Typical usage as a cryptographically secure random number generator is to -feed in some secret entropy (32 octets/256 bits are commonly considered -enough), for example from C or C, and then -generate some key material. + for my $message ("a", "b", "c") { + my $clone = $cipher->clone; + $clone->nonce (pack "N", ++$message_counter); + $clone->associated_data (""); + my $encrypted = $clone->crypt ($message); + ... + } - # create a PRNG object - my $prng = new Crypt::Spritz::PRNG; +=back - # seed some entropy (either via ->add or in the constructor) - $prng->add ($some_secret_highly_entropic_string); - # now call get as many times as you wish to get - # hard to guess binary randomness - my $key1 = $prng->get (32); - my $key2 = $prng->get (16); - ... +=head2 THE Crypt::Spritz::AEAD CLASS - # for long running programs, it is advisable to - # reseed the PRNG from time to time with new entropy - $prng->add ($some_more_entropy); +This class is pretty much the same as the C +class, with two differences: first, it implements the "standard" Spritz +encryption algorithm, and second, while this variant is easier to analyze +mathematically, there is little else to recommend it for, as it is slower, +and requires lots of code duplication code. + +So unless you need to be compatible with another implementation that does +not offer the XOR variant, stick to C. + +All the methods from C are available, except +C, which has been replaced by separate C and C +methods: =over 4 -=item $prng = new Crypt::Spritz::PRNG [$seed] +=item $encrypted = $cipher->encrypt ($cleartext) -Creates a new random number generator object. If C<$seed> is given, then -the C<$seed> is added to the internal state as if by a call to C. +=item $cleartext = $cipher->decrypt ($encrypted) -=item $prng->add ($entropy) - -Adds entropy to the internal state, thereby hopefully making it harder -to guess. Good sources for entropy are irregular hardware events, or -randomness provided by C or C. - -The design of the Spritz PRNG should make it strong against attacks where -the attacker controls all the entropy, so it should be safe to add entropy -from untrusted sources - more is better than less if you need a CSPRNG. - -For use as PRNG, of course, this matters very little. - -=item $octets = $prng->get ($length) - -Generates and returns C<$length> random octets as a string. +Really the same as C, except you need separate +calls and code for encryption and decryption, but you have the same +limitations on usage. =back