Crypt::Random::TESHA2 - Random numbers using timer/schedule entropy
This module implements userspace voodoo entropy. You should use a proper O/S supplied entropy source such as /dev/random or the Win32 Crypt API.
# Nothing exported by default use Crypt::Random::TESHA2 qw(random_bytes random_values irand rand); # Get 64 random bytes my $seed_string = random_bytes(64); # Get 16 random 32-bit values my @seeds = random_values(16); # Get a 32-bit random integer (value between 0 and 4294967295 inclusive) my $i = irand(); # rand, like system rand, with 32 bits of randomness. my $r1 = rand(); # floating point in range [0,1). my $r2 = rand(1000); # floating point in range [0,1000). # croak if installation determined we couldn't generate enough entropy use Crypt::Random::TESHA2 ':strong'; # No warnings even if we are a weak source use Crypt::Random::TESHA2 ':weak'; # Ask for yourself die "No key for you!" unless Crypt::Random::TESHA2::is_strong();
Generate random numbers using entropy gathered from timer / scheduler jitter.
This can be used to generate non-pseudorandom data to seed a PRNG (e.g.
rand, Math::Random::MT, etc.) or CSPRNG (e.g. AES-CTR or Math::Random::ISAAC). You may use it directly or as part of a random source module that first checks for O/S randomness sources.
Only Perl CORE modules are used, making this very portable. However, systems must have a high resolution timer and support
usleep from Time::HiRes.
At installation time, measurements are taken of the estimated entropy gathered by the timer differences. If the results indicated we could not get good results, then the module will consider itself "weak". On the first use of any of the functions that return randomness (e.g. random_bytes), the module will carp about not being a strong randomness source. However, two special options, ":strong" and ":weak" may be given to the importer to change this behavior. If ":strong" is used, then the module will croak. If ":weak" is used, then no carp will be generated. The function
is_strong can be used at any time for finer control. Note that this should be an unusual case, and neither flag has any effect if the module considers itself strong.
Takes an integer and returns a string of that size filled with random data.
Takes an integer and returns an array containing that many random 32-bit integers. The values will be in the range [0,4294967295] (all 32-bit values are possible).
Returns a single random 32-bit integer in the range [0,4294967295].
Returns a random float greater than or equal to 0 and less than the value of the argument. If no argument is given or the argument is zero, 1 is used. This has an identical API as system rand, though of course there is no associated srand function. The result has 32 bits of randomness.
Returns 0 if the installation procedure determined that not enough entropy could be gathered on this system. Returns 1 if it was able. If 0 is returned, then the bytes returned may be no better than a CSPRNG using a convoluted time-based reseed every bit.
The underlying entropy gathering is done using timing differences between usleep calls. We wrap usleep calls of varying intervals along with some Perl hash processing inside microsecond timer calls. The two values are xored. This is the raw entropy source. Eight of these, along with the current time, are fed to a SHA-256 which can be added to an entropy pool.
Measurements of the raw timer entropy (just the timing differences -- no hashes, time, counters, xors, or entropy pool) on systems I have available indicate 1.5 to 4 bits of entropy per usleep. The installation procedure does a measurement of the 0-order entropy gathered from the raw timing process, halves it, limits to the range 1/8 - 7/8, and uses that as the estimated entropy gathered.
The actual output random bytes are generated by an entropy pool that uses SHA-512 or SHA-256. This adds data as needed from the above method, then extracts bits as needed to make the output bytes (again using a cryptographic hash and a counter, which means the entropy pool is not exposed).
The result will easily pass most stream randomness tests (e.g. FIPS-140, ENT, TestU01 Rabbit), but that is a given based on the last entropy pool stage, so this just shows we provide decorrelated output, not that we make a good seed.
Note that pretty much every limitation of this module will apply to Math::TrulyRandom, which many non-cryptographers still think is cryptographically secure (it's recommended in both the perl core documentation as well as Math::Random::ISAAC). If you think that module is great for your application, then you should be happy with this one. Probably happier since this is more portable, doesn't hang infinitely, runs much faster, and generates better output on most systems.
As mentioned in the Warnings section, this generates userspace entropy -- what most people used until the waning years of the 20th century. We should not have to do this on modern systems that have well designed APIs to get randomness from multiple entropy pools, all managed by production code. In other words,
Performance is slow (about 10,000 times slower than Math::Random::ISAAC::XS), making this something best to be used to seed a PRNG or CSPRNG, rather than using directly. On newer Linux systems and Win32 it runs about 10,000 bits per second. Cygwin runs about 1000 bits per second. Older systems will run slower of course, such as an old HPPA system I use that runs at 40 bits/s. Much of the time is spent sleeping.
Gathering entropy with this method depends on high resolution timers. If the timers have low resolution, especially if we had a system with very fast yield turnaround, then we would gather very little entropy. One of the tests tries to determine this, but it isn't perfect. As with all such userspace systems, you should check that it works before using it for anything critical. RFC4086 section 3.4 discusses a few of the pitfalls of using portable clock-based software, and section 3.6 discusses the desire for multiple entropy sources.
Because of the use of SHA-2 hashes along with an entropy pool using a counter, the output stream will pass randomness tests (e.g. FIPS-140, ENT, TestU01 Rabbit) even if there is no underlying entropy. The installation measurements should indicate whether this is happening, but it doesn't measure everything.
Dana Jacobsen <firstname.lastname@example.org>
Copyright 2012-2013 by Dana Jacobsen <email@example.com>
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
The software is provided "AS IS", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.