But let's quote the kernel source on the matter[1], just to be clear:
> The two other interfaces are two character devices /dev/random and /dev/urandom. /dev/random is suitable for use when very high quality randomness is desired (for example, for key generation or one-time pads), as it will only return a maximum of the number of bits of randomness (as estimated by the random number generator) contained in the entropy pool.
> The /dev/urandom device does not have this limit, and will return as many bytes as are requested. As more and more random bytes are requested without giving time for the entropy pool to recharge, this will result in random numbers that are merely cryptographically strong. For many applications, however, this is acceptable.
The real point to be made here is that, yes, /dev/random is theoretically better - but for many applications, letting /dev/random hang to wait for entropy is worse than having /dev/urandom use a CSPRNG in a way that is generally recognized to be secure.
[1]: http://repo.or.cz/w/davej-history.git/blob/d0562c8dc:/driver...
Edit:
I would like to add that the original article is talking about using /dev/urandom to generate long-lived keys, not session keys or similar. In this case, the blocking is sometimes acceptable to generate appropriate entropy, since the fact that the key is long-lived implies that you don't do this very often. The argument for /dev/urandom only holds clout when you are making a tradeoff for non-blocking behavior (which is 99% of the time). As such, there is nothing wrong with being slightly paranoid and using /dev/random if you can afford the time spent collecting entropy.
Fortunately major distros work around this bug, so it's only an issue in unusual cases, like cloud VMs.
See also http://sockpuppet.org/blog/2014/02/25/safely-generate-random...
> FreeBSD’s kernel crypto RNG doesn’t block regardless of whether you use /dev/random or urandom. Unless it hasn’t been seeded, in which case both block. This behavior, unlike Linux’s, makes sense. Linux should adopt it.
It boils down to a tricky and potentially misleading interface. Abstractions are leaky beasts, and if there are many ways to get apparently identical results, we will use the one that most closely aligns with our usual way of thinking.
Security is hard to get right. Cryptographic security depends on entropy, so getting sufficient entropy should be hard too. Right?
Maybe the default answer should be "yeah, right" instead.
[0] https://developer.apple.com/library/mac/documentation/Darwin...
[1] https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
The key to remember is that when the pool has sufficient entropy there is no difference between /dev/random and /dev/urandom, and if the pool is low then there is practically no difference between /dev/random and /dev/urandom - the quality of the PRNG means it is practically impossible to tell the difference between the two outputs (take a few thousand bits from each at a time and see if any statistical analysis can reliably tell the difference).
It is increasingly common for CPUs and/or related chipsets to have a built in TRNG so keeping the entropy pool "topped up" is getting easier by feeding the pool from those using rng-tools. The SoC RPi's are based around has an RNG that pushes out more then 500kbit/s for instance.
/dev/random and /dev/urandom both even use the same CSPRNG behind the scenes. The former tries to maintain a count of the estimated entropy, but this is a meaningless distinction. CSPRNGs can't run out of entropy (for instance, a stream cipher is essentially a non-reseeded CSPRNG that works by generating an arbitrarily long sequence of computationally random bits that can be XORed against a plaintext).
There might be a meaningful distinction if /dev/random provided "true" randomness (and could therefore be used for something like an OTP). But it doesn't. Both use the same CSPRNG algorithm.
Though practically speaking, that would probably not be acceptable in most (if not all) circumstances.
If you are that paranoid then there are inexpensive true-RNGs out there (free in fact, if your CPU or other chipsets have one that is easily accessible) which can provide enough bits for all but the larger bulk requirements (i.e. generating many keys in a short space of time). You can either use one of them specifically for the process(es) that definitely wants absolutely true random of feed its output into the standard entropy pool.
The is some genuine randomness there as the entropy sources are not (unlike the PRNG) deterministic: they take whitened fractional values from I/O timings (time between keep presses & mouse signals, and some aspects of physical drive I/O - the low bits of such timings essentially being random noise if the timer is granular enough).
/dev/urandom uses the CSPRNG in what-ever state it is in, /dev/random waits until it considered the CSPRNG to have been sufficiently randomly reseeded. In cases where the current situation is considered random enough (the pool count is high so /dev/random will not block) you will get the same value from either /dev/random or /dev/urandom.
And it seems to be implying that while use of the arc4random_buf function is platform-independent, its implementation is permitted to be platform-specific.
No. That argument is exactly why I didn't just use /dev/urandom in PyCrypto's userspace RNG when I wrote it in 2008. The result was 5 years of a catastrophic failure in certain cases where fork() is used, even though I specifically designed it to cope with fork(). If someone hadn't made that argument, PyCrypto wouldn't have had a catastrophic failure mode that went undetected for 5 years until I stumbled across it: CVE-2013-1445 http://www.openwall.com/lists/oss-security/2013/10/17/3
It is surprisingly difficult to implement a fast, reliable CSPRNG in a crypto library. There are innumerable things that can leak or corrupt your state, which compromises everything. You can leak state as a result of multithreading, fork(), signal-handling, etc., and libraries generally can't cope with that without having complicated APIs that application developers WILL misuse, causing silent security failures for end-users that go unnoticed for years. Plus, since you're still relying on /dev/urandom anyway, it really only gives you another way to fail.
Arguably, there are so few people who understand this stuff that---at least in the FOSS world---we should kill off all but one implementation, so that the few of us who collectively understand how this stuff really works can focus on that one implementation.