radiantmatrix has asked for the wisdom of the Perl Monks concerning the following question:

I have searched CPAN and Google for far too long. I am looking for a Perl module that implements a PRNG algorithm that is considered cryptographically secure (e.g. Fortuna, ISAAC), but haven't had any luck.

I am willing to develop this myself (and try to get it into CPAN), but I'm afraid I lack sufficient knowledge of the languages the reference implementations are written in. The reference for ISAAC is in C, but it relies on bit-shifting behaviour I don't know how to duplicate in Perl.

I realize that things like Crypt::Random exist, but they rely on access to either /dev/random or the EGD, neither of which I can count on for this application (in fact, they are likely not to be there). I'm also familiar with Math::TrulyRandom, but while this may be good randomness for statistical use, it may not be strong enough for cryptography -- and I lack the ability to test its stregth for those purposes. Much better to go with an accepted secure algorithm.

So, I'm looking for something extant that is reasonably self-contained. Failing that, I'm hoping someone can point me to an algorithm with explanation that is sufficient for me to develop an implementation.

If I do end up implementing this, it is my full intention to share my results with CPAN, if I can get my employer to sign off on it (likely).

Of course, I'm open to alternative solutions... My goal is to provide a CSPRNG for use in a web application that encrypts data for later transmission. The encryption algorithm is selectable from several standards (3DES, Blowfish, AES, and a few others, maybe) -- all of the implementations of these require secure PRNG's to work in a secure manner, and in my case, without access to /dev/random or an Entropy Gathering Daemon (EGD).

Does anyone know where I can find either a ready-made module or a description of a secure PRNG algorithm in sufficient detail that I can implement it myself?

Update: I neglected to mention one of my requirements, a good CSPRNG algorithm is one thing, but I also need a cross-platform way of seeding it. The ISAAC code, for example, defaults to the same seed unless you explicitly seed it. Add to this question, what is a good method for gaining a 32-bit seed value?

Update: I now have preliminary code for the ISAAC-based CSPRNG as a module named Crypt::Random::ISAAC that contains a drop-in replacement for Perl's rand(). It is not done, but it is usable -- I still must decide on a truly good method for picking a random seed than the method I used. I've uploaded the code to the Code Catacombs: Crypt::Random::ISAAC - secure random number generator. Thanks to all of you for your help, and especially to Roy Johnson and hv for pointing me to easily-implementable code.

Yoda would agree with Perl design: there is no try{}

  • Comment on Cryptographically Secure Psuedorandom Number Genergator - PRNG?

Replies are listed 'Best First'.
Re: Cryptographically Secure Psuedorandom Number Genergator - PRNG?
by BrowserUk (Patriarch) on Jun 10, 2005 at 00:27 UTC

    Math::Random::MT is a very well documented and tested PRNG with an extremely long periodicity. Unfortunately, the reference links within the modules POD are no longer valid, but google will find a zillion references including this one.

    Of course, like any PRNG, it does generate a known sequence for a given seed, so the trick is to chose a seed at random. Time of day (in milliseconds), process number and various other things can be used, but they are at least to some extent inferable. A possibility would be to randomly pick a file from a directory and then a random offset within that file and then unpack 4 bytes at that location as a number and use that to seed MT.

    #!perl -slw use strict; use Math::Random::MT qw[ rand srand ];; my @files = glob '*';; my $file = $files[ rand @files ]; open RND, '<', $file or die $!; my $slurp = do{ local $/; <RND> }; close RND; my $seed = unpack 'N', substr $slurp, rand( length $slurp - 4 ), 4; srand $seed; print rand for 1 .. 100;

    With a suitable choice of directory that includes some binary images, especially if the contents of the directory change, the random choice of seed drawn this way should be pretty unpredictable. From then on, the sequence produced by MT is about as unpredicatable as PRNGs get.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Cryptographically Secure Psuedorandom Number Genergator - PRNG?
by Roy Johnson (Monsignor) on Jun 09, 2005 at 20:04 UTC
    If you've got usable C, couldn't you Inline::C it?

    ISAAC source


    Caution: Contents may have been coded under pressure.

      That page itself links to a perl version of the ISAAC code: http://burtleburtle.net/bob/rand/randperl.txt.

      But the code is trivial enough that exposing the C code via an XS or Inline module should be a pretty straightforward path to retaining the speed of C if that's an issue.

      Hugo

        Aha! Thank you! I'm working producing a module for that code that can provide a drop-in replacement to the default rand(). I will probably publish it in the Monestary first, then work on submitting to CPAN (which will be a new experience for me, and so might take some time).

        As I mention in my new update to the parent node, however, I also need a cross-platform (at least *NIX and Win) method to generate a seed. For ISAAC specifically, I would want at least one and no more than 256 32-bit values with which to seed the PRNG. Any thoughts?

        Yoda would agree with Perl design: there is no try{}

Re: Cryptographically Secure Psuedorandom Number Genergator - PRNG?
by dynamo (Chaplain) on Jun 09, 2005 at 19:48 UTC
    If you don't want to use /dev/random or EGD, you are going to have to emulate their functionality yourself using some other source of 'truly' random source data - perhaps the timing of network requests, or keystrokes (but realize that each of these things is far from totally random and account for it - for example, instead of storing the raw data, calculate a profile of 'typical' data, and generate your randomness from moment-by-moment variation from that profile). Something has to come from the non-deterministic land of humans to make randomness possible in the deterministic land of machines. A major reason to use digital computers in the first place is to eliminate random variation in functional output from circuit noise and that kind of thing. When randomness does affect the operations of a computer outside the context of an EGD/dev/random type mechanism, that machine is broken.

    Find variance in nature and bring it into your computer. Emulate the interface to /dev/random or EGD. Then, use the accepted (and already written) secure algorithms in CPAN that rightfully require this functionality.

    - paul

    "A fool and his freedom are soon parted"
    -RMS

Re: Cryptographically Secure Psuedorandom Number Genergator - PRNG?
by davies (Monsignor) on Jun 10, 2005 at 07:49 UTC
    A few years back, I was involved with something that needed PRNGs, and I found the Mersenne Twister. The home page, including the academic article describing it, is here. I hope that will tell you if it is secure enough for your purposes. I then looked to see if a Perl implementation existed, and then worked out that it was what BrowserUK was talking about. So I suppose my only contribution to this is to act as his echo, and to provide the full name of the PRNG!

    Regards,

    John Davies
      Mersenne Twister is a great PRNG, but not a Cryptographically Secure PRNG. See the Mersenne Twister homepage. There is, unfortunately, a big difference between PRNGs that are statistically random enough for mathematics purposes, and PRNGs that are random in the right ways for cryptography.

      Yoda would agree with Perl design: there is no try{}

        Ahem. From the homepage you linked (my emphasis):

        Caution: Mersenne Twister is basically for Monte-Carlo simulations - it is not cryptographically secure "as is". Please read FAQ.

        And from the FAQ:

        Want to use for cryptography.

        Mersenne Twister is not cryptographically secure. (MT is based on a linear recursion. Any pseudorandom number sequence generated by a linear recursion is insecure, since from sufficiently long subsequence of the outputs, one can predict the rest of the outputs.)

        To make it secure, you need to use some Secure Hashing Algorithm with MT. For example, you may gather every eight words of outputs, and compress them into one word (thus the length of the output sequence is 1/8 of the original one).

        It is meaningful to replace linear generators like LFSR with MT.

        2002-version can receive an array of integer as a seed, and it fits to this usage.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Cryptographically Secure Psuedorandom Number Genergator - PRNG?
by Anonymous Monk on Jun 10, 2005 at 20:39 UTC
    No PRNG is ever CS. Proof: If you know the seed, you know all values. If you don't know the seed where does it come from? From a PRNG? Same problem applies. From a truly random source? This source would be better CS. Else it could be worked out. Then why the PRNG? From a secret key? Where does that come from?

      Your proof demonstrates only that no PRNG is truly random: we already know this, and that's why it's called a Psuedo-random number generator.

      Cryptographically Secure means that the randomness has no easily discernable pattern, and has a very long period -- that is, you don't start demonstrating any pattern until a whole lot of numbers have been generated.

      Gathering entropy from a random (or "random enough") source for seeding doesn't make for a better source of random numbers; gathering entropy is time-intensive, but if we only do it once and then use a CSPRNG to generate further PR values, you end up with reasonable performance. Besides, you use the seed and then throw it away; as long as no one can derive the seed (with ISAAC, it is 256 32-bit values, so it's tough to brute-force), it's fantasically hard to duplicate the string of random values.

      I strongly suggest that you research CSPRNG tech -- yes, it isn't as good as using a hardware RNG (or a Lava Lamp) as a source of entropy, but it is a good enough simulation that the numbers generated are random enough for cryptography. Not every application can implement a true RNG.

      Yoda would agree with Perl design: there is no try{}