The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Bytes::Random::Secure - Perl extension to generate cryptographically-secure random bytes.

SYNOPSIS

    use Bytes::Random::Secure qw(
        random_bytes random_bytes_base64 random_bytes_hex
    );

    my $bytes = random_bytes(32); # A string of 32 random bytes.
    
    my $bytes_as_base64 = random_bytes_base64(57);

    my $bytes_as_hex = random_bytes_hex(8);

DESCRIPTION

Bytes::Random::Secure provides three functions that can be used anytime you need a string (or MIME Base64 representation, or hex-digits representation) of a specific number of random bytes.

This module can be a drop-in replacement for Bytes::Random, with the primary enhancement of using a much higher quality random number generator to create the random data. The random number generator comes from Math::Random::Secure, and is suitable for cryptographic purposes, including the generation of random salt or random secrets.

In addition to providing random_bytes(), this module also provides two functions not found in Bytes::Random: random_bytes_base64(), and random_bytes_hex.

RATIONALE

It's impossible to predict what uses others might find for any given module, but this author has the following use cases:

  • Generating random salt to be hashed along with passphrases (and stored alongside them) to prevent rainbow table attacks.

  • Generating a secret that can be hashed along with a cookie's session content to prevent cookie forgeries.

  • Generating raw cryptographic-quality pseudo-random data sets for testing or sampling.

EXPORTS

By default random_bytes is the only function exported. Optionally random_bytes_base64, random_bytes_hex, and random_bytes_qp may be exported.

FUNCTIONS

random_bytes( $number_of_bytes )

Returns a string containing as many random bytes as requested.

random_bytes_base64

    my $random_bytes_b64           = random_bytes_base64( $num_bytes );
    my $random_bytes_b64_formatted = random_bytes_base64( $num_bytes, $eol );

Returns a MIME Base64 encoding of the string of $number_of_bytes random bytes. Note, it should be obvious, but is worth mentioning that a base64 encoding of base256 data requires more digits to represent the bytes requested. The actual number of digits required, including padding is 4(n/3). Furthermore, the Base64 standard is to add padding to the end of any string for which length % 57 is a non-zero value.

If an $eol is specified, the character(s) specified will be used as line delimiters after every 76th character. The default is qq{\n}. If you wish to eliminate line-break insertions, specify an empty string: q{}.

random_bytes_hex

    my $random_bytes_as_hex = random_bytes_hex( $num_bytes );

Returns a string of hex digits representing the string of $number_of_bytes random bytes.

Again, it should be obvious, but is worth mentioning that a hex (base16) representation of base256 data requires two digits for every byte requested. So length( random_bytes_hex( 16 ) ) will return 32, as it takes 32 hex digits to represent 16 bytes. Simple stuff, but better to mention it now than forget and set a database field that's too narrow.

random_bytes_qp

    my $random_bytes_qp           = random_bytes_qp( $num_bytes );
    my $random_bytes_qp_formatted = random_bytes_qp( $num_bytes, $eol );

Produces a string of $num_bytes random bytes, using MIME Quoted Printable encoding (as produced by MIME::QuotedPrint's encode_qp function. The default configuration uses \n as a line break after every 76 characters, and the "binmode" setting is used to guarantee a lossless round trip. If no line break is wanted, pass an empty string as $eol.

CONFIGURATION

Bytes::Random::Secure intentionally Keeps it Simple. There is nothing to configure, and you don't get the opportunity to hamper the byte stream's quality by picking your own (possibly less secure) seed or seed-generator. It was a lot of work finding a reliable one, and if you don't like it, just go use Math::Random::ISAAC directly (or get in touch with me and we can discuss whether your method might be a better choice globally). ;)

If you really have the need to feel useful, install Math::Random::ISAAC::XS. Bytes::Random::Secure's random number generator uses Math::Random::ISAAC. That module implements the ISAAC algorithm in pure Perl. However, if you install Math::Random::ISAAC::XS, you get the same algorithm implemented in C/XS, which will provide better performance. If you need to produce your random bytes more quickly, simply install Math::Random::ISAAC::XS, and it will be used automatically.

CAVEATS

It's easy to generate weak pseudo-random bytes. It's also easy to think you're generating strong pseudo-random bytes when really you're not. It's hard to generate strong (ie, secure) random bytes in a way that works across a wide variety of platforms. A primary goal for this module is to provide cryptographically secure pseudo-random bytes. A secondary goal is to provide a simple user experience (thus reducing the propensity for getting it wrong). A terciary goal (and one that will never be permitted to compromise the primary goal) is to minimize the dependencies required to achieve the primary and secondary goals.

To re-iterate: We want secure random bytes, we want ease of use, and if we can get both while minimizing the dependencies, that would be nice, but is not a requirement.

This module steals some code from Math::Random::Secure. That module is an excellent resource, but implements a broader range of functionality than is needed here. So we just borrowed some code from it, and some of its dependencies.

The primary source of random data in this module comes from the excellent Math::Random::ISAAC. Unfortunately, to be useful and secure, even Math::Random::ISAAC needs a cryptographically sound seed, which we derive from Crypt::Random::Source. Neither of those modules are light on dependencies. The situation becomes even more difficult in a Win32 environment, where Crypt::Random::Source needs the Crypt::Random::Source::Strong::Win32 plug-in, which is even heavier in external dependencies.

The result is that the cost of getting cryptographically strong random bytes on most platforms is a heavy dependency chain, and the cost of getting them in a windows platform is about twice as heavy of a dependency chain as on most other platforms. If you're a Win32 user, and you cannot justify the dependency chain, look elsewhere. On the other hand, if you're looking for a secure random bytes solution that "just works" portably (and are willing to live with the fact that the dependencies are heavier for Windows users), you've come to the right place.

Patches that improve the Win32 situation without compromising the module's primary and secondary goals, and without growing the dependencies for *nix users are certainly welcome.

AUTHOR

David Oswald <davido [at] cpan (dot) org>

BUGS

Please report any bugs or feature requests to bug-bytes-random-secure at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Bytes-Random-Secure. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Bytes::Random::Secure

You can also look for information at:

ACKNOWLEDGEMENTS

Mojolicious for providing the motivation from its "App secret". Bytes::Random for providing a starting-point for this module. Math::Random::Secure for providing an excellent random number tool.

LICENSE AND COPYRIGHT

Copyright 2012 David Oswald.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.