In fact both the MacOS X man page, and the Linux man page, are afflicted with the same disease, which is that they talk of entropy as if it was some sort of gasoline, which is consumed upon usage.
In reality, this does not work so. Entropy is a measure of what a system could have been. In both Linux and Mac OS X, there is an internal "entropy pool", namely a set of bits which have been filled from hardware events. These events are supposed to be non-predictable or measurable by attackers, so the pool, at any time, may have accumulated "n bits of entropy", meaning that if the attacker wanted to guess the pool contents, then he would need, on average, 2n-1 tries. This pool is then extended into an arbitrarily long stream of pseudorandom bytes with a cryptographically secure PRNG.
Suppose that you have a pool with n bits of entropy. Now generate one gigabyte of data with the PRNG, seeded with that pool. What is the pool entropy after the generation ? Still n bits ! Indeed, the pool could still have 2n possible contents, and an attacker trying to guess the pool contents is not helped in any way by having obtained the gigabyte of pseudorandom bytes. Why is that so ? Because the cryptographically secure PRNG is cryptographically secure. That's exactly what is meant by "cryptographically secure": output "looks random" and cannot be predicted with higher probability than that of guessing the internal state, even if previous output has been observed in large quantities.
However, for some reason, both the Mac OS X and Linux man page writers are apparently convinced that the randomness somehow degrades upon usage. This would make some sort of sense if the PRNG was weak and leaked information about the pool; but you would not want to use such a PRNG anyway. In other words, when someone writes "the output from /dev/(u)random
loses quality after some time", he is implicitly telling you "the PRNG is broken and leaks data".
Fortunately, even if the man page writers are somewhat fuzzy in their heads about what entropy is, the implementations are better. To ensure security, what is needed is that the entropy pool gets at some point to a decent level of entropy (128 bits are enough); from that point and until the machine is next rebooted, /dev/urandom
will yield high-quality randomness which is perfectly appropriate for all practical usages, including, yeah, generating long-term PGP or SSH keys. The tricky point is to ensure that no randomness is extracted before that moment of optimal entropiness.
When the machine boots up, the pool is empty. Then hardware events are gathered, continuously. FreeBSD is a Unix-like operating system which does everything right in that respect:
- The OS maintains an "entropy estimate" of how much entropy it has gathered since boot time.
- If the entropy estimate is below a given threshold,
/dev/random
will block and refuse to produce pseudo-alea. It will wait until some decent entropy has been gathered.
- Once the threshold has been reached,
/dev/random
will happily produce gigabytes of pseudorandomness, without ever blocking.
/dev/urandom
is an alias on /dev/random
.
This behaviour is nice and good: don't output bad randomness, but don't refuse to output tons of randomness when it can be done safely. Mac OS X imported a lot of kernel code from FreeBSD, so we may imagine that Mac OS X behaves like FreeBSD in that respect (this should be checked by inspecting the source code).
Linux is not as good, but not so bad either. On Linux:
/dev/random
uses an entropy estimator, and (through flawed reasoning, as explained above) decreases this estimate when random bytes are output. /dev/random
blocks when the estimate is below a given threshold.
/dev/urandom
never blocks.
So /dev/urandom
does the Right Thing, except right after boot: /dev/urandom
may accept to produce pseudorandom bytes even if the entropy pool is still too shallow (i.e. too "predictable" by the attacker). To avoid this problem, Linux distributions apply a nifty fix: they save a random seed for next boot. When the machine boots, it injects that file into the pool, then produces a new file, to be injected upon next boot. This mechanism reduces the window of "poor entropy" to the very first boot, when the OS was first installed. Afterwards, /dev/urandom
is properly seeded, will produce high-quality randomness, and will never block.
To sum up, just use /dev/urandom
. It is fine, despite the millenarist prophecies of some man page writers; even on Linux, where a window of "low entropy" theoretically exists, distribution vendors apply corrective mechanisms.
(Note, though, that not all Linux derivatives may be fixed, in particular embedded systems. Generating an entropy seed file for next boot works only as long as there is a writable filesystem; this is not necessarily the case for embedded systems.)