if (-e "/dev/random"){ .... } else { .... }
To generate a nice seed where you don't have /dev/random, you can do a checksum on your environment. Here are some sources of bits that are not random, but hard to reproduce:
- concatenate keys and values of %ENV{}
- process id, ppid
- current time
- process table
- disk statistics
- network interface report, especially if it can list counters
- inode number of $0, and arguments if any
- names of arguments, if any
- strings coming out of the memory allocator (allocate some references, stringify them)
Once you have a big string you can pipe it through a compression or cipher algorithm, just to distribute bits across 8bit space evenly, and use unpack to count the sum (see examples in perldoc).
/dev/random collects entropy from drivers, timers, and so forth, so essentially you're doing a cheap emulation of that.
If you get something nice, make a module out of it: Entropy::Gather::Win32 or something.
| [reply] [d/l] |
Some excellent ideas, which I am pursuing. Any idea on how to (reasonably quickly) determine if I got good seed values (i.e. are they random enough)? I don't have enough of a math background, I guess.
Larry Wall is Yoda: there is no try{}
The Code that can be seen is not the true Code
| [reply] |
ent measures entropy in byte streams
| [reply] |
For information on getting cryptographically secure random data on Win32 see here and RtlGenRandom, and Re: Random Numbers under XP: Translating XS to Win32::API for how to access it from Perl.
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.
| [reply] [d/l] |
I looked into these, and they seem to work rather well. I considered adding them to this module, but there were a few things that made me decide, ulimately, not to:
- RtlGenRandom is available only in W2K and WinXP; and there are rumours that it will not be available in the next generation(s) of Windows. There are still a great many Win98 installations out there.
- If I use /dev/random for UNIX and RtlGenRandom on Windows, I've solved two OS issues. That's great for my current project, but the personal goal I had when developing this module is to be general-purpose and platform-independant. I wish to avoid special cases when possible.
- I see this module as an alternative to OS-based PRNG's. If someone is developing a tool that requires a good PRNG, I would expect them to use the best PRNG for the job. In other words, I want to leave it to the end developer to, say, prefer /dev/random first, RtlGenRandom, then this module if neither of the former are available.
- The seed doesn't need to be very random, just hard to guess or duplicate based on general information about the system (the pid and/or the current time are bad, since loggers can guess this information closely enough to significantly narrow a brute-force search). The seeder I have now is so-so in this regard: it should stop anyone who doesn't have root-access to the machine from guessing the seed.
- If you already have a good PRNG, you don't need this module anyway. ;-)
In short, I envision the use of this module like:
my $prng;
if ( -f '/dev/random' ) {
$prng = sub { get_rand_from_file('/dev/random', shift) };
}
elsif ( ## Find out if RtlGenRandom works ## ) {
$prng = \&rtlGenRandom_rand;
}
else {
require Crypt::Random::ISAAC;
$prng = \&Crypt::Random::ISAAC::rand;
}
I do appreciate your pointing me to those references, though, as they will help with performance on a project that is Win2k-only.
<-radiant.matrix->
Larry Wall is Yoda: there is no try{} (ok, except in Perl6; way to ruin a joke, Larry! ;P)
The Code that can be seen is not the true Code
| [reply] [d/l] |