tim.qfs has asked for the wisdom of the Perl Monks concerning the following question:

EDIT: I have edited the script in this post to make it comply with strict and warnings. I have also changed the documentation to reflect some new information I have learned about the "use" command.

Hi Monks

I have managed to create what I believe is a pretty much bullet-proof TRNG using a Perl script. I challenge you all to examine it in detail to see if you can find any vulnerabilities. I would be very interested to know what you think and to know the results if you test it on your systems.

Here is the script:

sub TRNGrand { (my $range) = @_; #This Perl subroutine almost instantly outputs a true random #number between zero and $range inclusive to 15 decimal places. # #If you are considering purchasing a hardware TRNG, save your #money and use this script instead. # #The author has only tested this subroutine on the Windows OS #and therefore does not know if it works on Unix. # #Unfortunately, the Perl "bignum" module and associated modules #can break this subroutine so if you are writing a Perl script #which uses these modules, please put the "use bignum;" command #and associated commands somewhere after the text of this #subroutine. use Time::HiRes qw(gettimeofday); my $decimalplace; my $bitstring; my $binaryplace; my @loopcount; my $loopcountsgroupA; my $loopcountsgroupB; my $runnumber; my $x8microsecondschanges; my $previousx8microseconds; my $seconds; my $microseconds; my $x8microseconds; my $bit; my $bitstring; my $decimaldigit; my $decimaldigits; my $decimalplace; $decimalplace = 1; until ($decimalplace == 15) { $bitstring = ""; for ($binaryplace = 0; $binaryplace <= 3; $binaryplace++) { @loopcount = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); $loopcountsgroupA = 0; $loopcountsgroupB = 0; until ($loopcountsgroupA ne $loopcountsgroupB) { for ($runnumber = 0; $runnumber <= 32; $runnumber++) { $x8microsecondschanges = 0; $previousx8microseconds = "null"; until ($x8microsecondschanges == 2) { ($seconds,$microseconds) = gettimeofday; $x8microseconds = int($microseconds / 8); if($previousx8microseconds ne "null" && $x8microseconds ne $previousx8microseconds) { $x8microsecondschanges++; } $previousx8microseconds = $x8microseconds; if($x8microsecondschanges == 1) {$loopcount[$runnumber]++;} } } $loopcountsgroupA = $loopcount[1]+$loopcount[3]+$loopcount[6]+$loopcount[8]+ $loopcount[9]+$loopcount[11]+$loopcount[14]+$loopcount[16]+ $loopcount[18]+$loopcount[20]+$loopcount[21]+$loopcount[23]+ $loopcount[26]+$loopcount[28]+$loopcount[29]+$loopcount[31]; $loopcountsgroupB = $loopcount[2]+$loopcount[4]+$loopcount[5]+$loopcount[7]+ $loopcount[10]+$loopcount[12]+$loopcount[13]+$loopcount[15]+ $loopcount[17]+$loopcount[19]+$loopcount[22]+$loopcount[24]+ $loopcount[25]+$loopcount[27]+$loopcount[30]+$loopcount[32]; } if($loopcountsgroupA < $loopcountsgroupB) {$bit = 0;} else {$bit = 1;} $bitstring = "$bitstring$bit"; } $decimaldigit = unpack("N",pack("B32",substr("0"x32 .$bitstring,-32))); if($decimaldigit < 10) { $decimaldigits = "$decimaldigits$decimaldigit"; $decimalplace++; } } if($range eq "") {$range = 1;} return "0.$decimaldigits" * $range; }

Replies are listed 'Best First'.
Re: New software TRNG
by Corion (Patriarch) on Jan 29, 2014 at 15:00 UTC
Re: New software TRNG
by hdb (Monsignor) on Jan 29, 2014 at 15:01 UTC

    For any random number generator it is important to know its statistical properties. Can you please elaborate a bit for your generator? For example, does it generate uniformly distributed numbers over the given range? What is the expected value (or average over many trials)? Are consecutively drawn numbers independent/uncorrelated?

      It works by counting the number of for-loop cycles per eight microseconds several times and dividing the counts into two groups. A bit (0 or 1) is then determined by which group wins. A draw means "try again". This process is repeated for each bit.

      I have tested it and it does produce results which are fairly uniform and because of the way it operates, the results are theoretically independent of each other.

        Is the exclusive use in the function of variables that are non-local-ized globals an essential source of the entropy it supplies? If so, please be aware that entropy may "leak" from the function and make the operation of any program employing it very random indeed. If not, please consider using lexical (my) variables.

        I wanted to give it a try but as I run all my scripts under strict and warnings it did not compile.

Re: New software TRNG
by LanX (Saint) on Jan 29, 2014 at 15:11 UTC
    Please link to older discussions when posting follow-ups:

    see also TRNG Perl script query

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: New software TRNG
by GrandFather (Saint) on Jan 29, 2014 at 22:36 UTC

    Note that use doesn't work the way you think it does. use statements are processed at compile time before the script is executed so there is no a sense in which 'use this subroutine ... before issuing the "use bignum;"' is applicable.

    If the code changes take longer than the time saved, it's fast enough already.
      Hi GrandFather Thank you very much for your post. I have done some experimentation and have changed the comments in the script to reflect what I found out.

        Update: Argh! tye is right. My understanding of bignum was flawed - bignum doesn't work like most modules and even a detailed read of the documentation doesn't make that obvious. As tim.qfs points out in his reply changing where the 'use bignum;' statement is does alter the code generated at compile time.

        But you still don't understand the compile/execute nature of Perl script execution and how that affects 'use' statements. All the use statements are executed before any of the script is executed (except where BEGIN blocks are used, but don't go there until you really know what you are doing). Moving the 'use' statements around does not affect the fact that modules loaded using 'use' are loaded before the script executes.

        There are several ways to fix that. One way would be to put your sub in a module and have it do the number generation when loaded. Another way is to use require to load bignum. Best of all is to identify the nasty interaction and fix your code so that the presence of bignum doesn't matter. It would be interesting to know what the effect of bignum is on your code as that may point to a weakness in your code that will bite in other contexts.

        If the code changes take longer than the time saved, it's fast enough already.