Cryptographers are certainly not responsible for this superstitious nonsense.
Think about this for a moment: whoever wrote the /dev/random manual page seems to
simultaneously believe that
(1) we can't figure out how to deterministically expand one 256-bit /dev/random
output into an endless stream of unpredictable keys (this is what we need from
urandom), but
(2) we _can_ figure out how to use a single key to safely encrypt many messages
(this is what we need from SSL, PGP, etc.).
For a cryptographer this doesn't even pass the laugh test.
Is the argument here simply that a properly encrypted message should look like randomness? And as a result we should be able to turn something non-random into randomness?There are people that assume that both: 1 - 256 bits aren't enough entropy to create a long chain of random numbers in a CSPRNG; 2 - 256 bits (after adjusting for known attacks) are enough entropy to encrypt a long chain of data in a symmetric cryptography algorithm.
Since encryption and creating random numbers are normally the same operation, 256 can't be both enough and not enough.
I don't know if SSL even supports symmetric encryption with more than 256 bits of entropy. I've certainly never seen it.
His basic point is that we can use the 256-bit random output as the key for a stream cipher, and voilà you have yourself an endless stream of unpredictable keys. And if you don't believe that, then in what sense do you trust the stream cipher?
There can be benefits from depending on non-portable implementation details but also significant drawbacks.
The author keeps coming back to this fact, but I don't understand how it negates any of the arguments in favour of using /dev/random. What does it matter if the numbers are ultimately coming out of the same PRNG? I don't see how this negates the "self-healing" property of /dev/random or any of the other advantages. It seems like the author is really just saying, "/dev/urandom is probably good enough".
The idea that a lot of people get from that is that urandom is not much better than Mersenne twister, while /dev/random is the real thing.
And yes, you're right, the argument is precisely "computational security is good enough".
By the way, /dev/urandom is also self-healing.
Which other advantages of /dev/random might be there, apart from the cold boot case?
In the end, it boils down to: Why not use /dev/urandom and get good enough security, instead of insecurity.
I think this is a key point that the article is missing. Silent security failures are very, very bad. Blocking will at least provide assertion that either things are as expected, or the issue will be detected early.
Linux's /dev/urandom happily gives you not-so-random numbers before the kernel even had the chance to gather entropy. When is that? At system start, booting the computer.
I invite you to read the article, because there's more.
https://github.com/torvalds/linux/blob/master/drivers/char/r...
The operation is explained starting on line 52. The 2 paragraphs starting on line 78 explain the relationship behind the entropy estimator and the CSPRNG (It relies on SHA-1).
> As more and more random bytes are requested [from /dev/urandom] without giving time for the entropy pool to recharge, this will result in random numbers that are merely cryptographically strong
https://github.com/torvalds/linux/blob/master/drivers/char/r...
The one thing I still don't like about /dev/urandom is this: urandom's proponents say that it only fails on first boot, because modern linux distros capture entropy to seed urandom on following boots.
This means that in order for /dev/urandom to be ok, I have to depend on specific functionality of both the kernel and the linux distribution. In contrast, /dev/random is (arguably) harder for the distro to mess up, as it's primarily a function of the kernel.
Given the number of times distros have screwed up crypto, what are the odds that this will someday matter in the real world?
There is work on fixing this problem (or, at least, improving the situation) on Ubuntu: http://blog.dustinkirkland.com/2014/02/random-seeds-in-ubunt...
But rewinding and restoring to a previous save point? What's the harm in keeping the seed?
Or if the change in semantics is too onerous, a new /dev/drandom (delayed-random) could do this.
This is like saying that using consistent databases for things that require consistency is also "wrong", because the developer is going to add some ludicrous poorly-implemented caching layer in front on production as the performance dips, leading you to have a poorly-controlled inconsistent system anyway. It's an argument I appreciate, but one that indicates a deeper problem of developers thinking they can fix things they can't.
...and that's the only argument in the entire document for why /dev/random is bad: everything else is a justification for why /dev/urandom should be considered a reasonable alternative to /dev/random, most of which is difficult to confirm or deny unless you are a cryptographer. I mean, from a naive standpoint, it would sound like "putting all your eggs in one basket" could lead you to a problem, but how would I know, right?
Helpfully, the article claims to quote cryptographers on the matter. However, and this pretty much damns this article for me: he takes these quotes out of context. If you read the original sources, Daniel Bernstein makes it clear that /dev/urandom is broken on Linux (more on this later), and Thomas Pornin was responding to a user that was simply trying to get unique random values (where /dev/urandom is obvious).
As for Thomas Ptacek's emphatic "use /dev/urandom" repetition, his article was about people attempting to use user-land replacements for the kernel implementations, not people who were using /dev/random. In essence, he's trying to make the argument that people shouldn't be so afraid of /dev/urandom so as to use something clearly worse. He does state that /dev/random is overrated, but correctly points out its flaws.
Back to this article: after a ton of argumentation that the people suggesting that there is a key difference between /dev/random and /dev/urandom are inherently being misleading, the author gets around to quoting a section of the man page that sounds perfectly reasonable, and even is willing to cede that there is no issue using /dev/random for those use cases. I think the author is just mad because some service is slow. :/
Now, here's what I'll leave you with: an argument why this author's article is not just wrong but promoting beliefs that are actively harmful, an argument that can I hope can be believed even if you aren't a cryptographer and does not rely on me being a cryptographer: its an argument based on practical concerns only, with a demonstration of the problem not just in theory, but that happened to real people/developers.
[edit: Apparently, I misremembered this Android issue, so when I pulled sources for it I ended up with something that is not actually an issue with /dev/urandom. I have added details on a different situation where /dev/urandom actually was the culprit, but the argument isn't quite as strong. I was hoping for an argument that anyone would believe without invoking even a single hypothetical, but sadly I screwed up: I'm sorry for the confusion :/. I think the new example still makes a strong, though not impervious, point.]
So, if the author got his way, then all source code everywhere would be referencing /dev/urandom instead of /dev/random for all use cases (including "long-lived keys"). However, the author also admits that /dev/urandom "isn't perfect", and that on Linux it never blocks, even when it really should. It is then claimed that the correct solution to this problem is that you should seed virtual machines with entropy before using them.
Look: that just isn't always possible. I say this not from theory, but from the trenches of information security. On Android, some poor developer made java.security.SecureRandom use /dev/urandom. This meant that all Java libraries that rely on random numbers were getting ones from urandom, even when they claimed that they wanted "cryptographically strong" ones. Put short: the author's dream come true, codified into the library.
Sadly, users expect to be able to use Android devices soon after they boot, the user is not in control of the entropy sources, and the people who build the kernel drivers for these devices often didn't include enough entropy sources to fill the pool faster. This meant that all of this code was now broken: instead of blocking until "seriously-random numbers" could be generated, it would get "reasonably random-looking ones".
This is not a theoretical issue: people built bitcoin wallet applications sitting on top of these APIs, and some of the people using those wallets ended up with bitcoin addresses secured by keys that were painfully predictable across usages on different devices (the specific concern people bring up using /dev/urandom!). This was looked into, traced back to this design flaw, and Google even commented on the situation.
[edit: For clarity, this is the part that is wrong; as pointed out in the author's rebuttle to my comment, SecureRandom was actually doing something ludicrous here--the kind of thing that Thomas Ptacek was angry about ;P--and thereby Google's own article, which I had pulled up as a source for something I had apparently misremembered, claims that developers could consider using /dev/random or /dev/urandom to replace it.]
http://android-developers.blogspot.com/2013/08/some-securera...
[edit: Thankfully, there is another situation I can cite: the attack on routers from a year or two ago that involved low-entropy keys that were generated at boot. It is the same issue, but what makes this a weaker argument is that the user is now the developer, and the developer is actually in control of the device and could have fixed the entropy pool as stated by both this author and by Daniel Berstein's full comment.]
[edit:]
So, in this new example, the key issue is that a bunch of embedded systems--routers and firewalls from companies such as Cisco--were generating keys to secure their configuration portals and administrator consoles using /dev/urandom. This was done, on first boot (when there would be no entropy available), and the result was that many RSA keys were generating the exact same input prime numbers. If you are trying to factor a large semi-prime, and you have another large semi-prime that shares a factor, you can break it apart very easily with simple math.
Some researchers went through to determine why this happened, and their conclusion was that reliance by library developers on /dev/urandom, being used on devices and at moments where /dev/urandom didn't end up working very well, was the "root cause" of the issue, and made a recommendation to library developers that usage of less secure mechanisms should be a non-default option and that any tradeoffs in its selection should be clearly documented, lest security be contingent on factors that do not immediately seem related to security.
https://factorable.net/weakkeys12.extended.pdf
> In the final component of our study, we experimentally explore the root causes of these vulnerabilities by investigating several of the most common open-source software components from the population of vulnerable devices (Section 5). Based on the devices we identified, it is clear that no one implementation is solely responsible, but we are able to reproduce the vulnerabilities in plausible software configurations. Every software package we examined relies on /dev/urandom to generate cryptographic keys; however, we find that Linux’s random number generator (RNG) can exhibit a boot-time entropy hole that causes urandom to produce deterministic output under conditions likely to occur in headless and embedded devices. In experiments with OpenSSL and Dropbear SSH, we show how repeated output from the system RNG can lead not only to repeated long-term keys but also to factorable RSA keys and repeated DSA ephemeral keys due to the behavior of application-specific entropy pools.
> When we disabled entropy sources that might be unavailable on a headless or embedded device, the Linux RNG produced the same predictable stream on every boot. The only variation we observed over 1,000 boots was the position in the stream where sshd read from urandom.
> On stock Ubuntu systems, these risks are somewhat mitigated: TLS keys must be generated manually, and OpenSSH host keys are generated during package installation, which is likely to be late in the install process, giving the system time to collect sufficient entropy. However, on the Fedora, Red Hat Enterprise Linux (RHEL), and CentOS Linux distributions, OpenSSH is installed by default, and host keys are generated on first boot. We experimented further with RHEL 5 and 6 to determine whether host keys on these systems might be compromised, and observed that sufficient entropy had been collected at the time of key generation (due to greater disk activity than with Ubuntu Server) by a slim margin. We believe that most server systems running these distributions are safe, particularly since they likely have multiple cores and gather additional entropy from physical concurrency. However, it is possible that other distributions and customized installations do not collect sufficient entropy on startup and generate weak keys on first boot.
> For library developers: Default to the most secure configuration. Both OpenSSL and Dropbear default to using /dev/urandom instead of /dev/random, and Dropbear defaults to using a less secure DSA signature randomness technique even though a more secure technique is available as an option. In general, cryptographic libraries should default to using the most secure mechanisms available. If the library provides fallback options, the documentation should make the trade-offs clear.
[/edit]
Of course, this is covered by the idea that these devices were not properly configured; but that's kind of the point, right? What everyone is saying about /dev/urandom is that it isn't guaranteed to produce anything "seriously" random; it happens to, most of the time, on most operating systems, produce something incredibly random, but some times, on some operating systems, it might produce something that is barely random at all.
This means that if everyone switches to using /dev/urandom in their code, a ton of libraries are going to work on some systems, and not on others; they might work on a properly configured server, but not on an Android device, or might work on one cloud provider, but not another... this is insane... if I download "secure off-the-record messaging implementation library for Linux", am I going to expect it to fail like this?
Certainly, the developers this article seems to believe are both common and acting reasonably enough to be worked around by people writing code--the ones who are supposedly going around patching random() out their libraries ;P--are not going to realize their code isn't secure, or that they they need to configure their kernel or operating system distribution to make it secure; but this is even going to burn the people reasonable enough to download code and not try to hack it :/.
[edit: And, to close the earlier edit: clearly the people who were building these embedded routers didn't realize these tradeoffs. The author of this article is thereby asking developers to be cognizant of how these different pseudo-random number generators operate and design their entire systems in ways that will make specific sub-components, components they probably don't understand well and "just want to be secure", continue to work correctly under potentially-modified assumptions. While they technically can do this--unlike the sadly-flawed Android argument I wanted to make, where users and developers had no control--this seems like a much higher bar than keeping people from taking random() and patching it out entirely due to a performance benefit, and comes down to a simple heuristic.]
Let me rebut two points that kind of irk me:
You claim that the Android problem that bit several Bitcoin wallets was due to java.security.SecureRandom using /dev/urandom.
That is mistaken, as the blog posting you gave clearly shows:
"Developers who use JCA for key generation, signing or random number generation should update their applications to explicitly initialize the PRNG with entropy from /dev/urandom or /dev/random."
So, in their opinion, /dev/urandom is fine.
Furthermore you claim that I've taken quotes out of context.
I was aware that there is the danger of misunderstanding these people's point of view, so I emailed all three of them, right when I put this web page up some days ago, specifically asking them if they felt that I might be misrepresenting them or if they are otherwise unhappy about me using their names.
Of those three two replied (both very quickly).
Daniel Bernstein replied very shortly with "Seems reasonable.", but noted that he disagrees with the "more entropy cannot hurt" point. That's why I added the little sidebar with a link to his blog posting.
Thomas Pornin seems to have taken the time to really read the article, he wrote "That's a fine page. I like it.", noted a mistake in the boot scripts section (that I have fixed) and suggested some additional points to discuss (which I did not put on the page).
Off-topic remark: All in all I was really fascinated how easy it is to get in touch with those highly-respected people, and how respectful they treat "us normals". :-)
Once urandom is seeded, there is absolutely no security benefit to using /dev/random, for any cryptographic application, anywhere. urandom is a stream cipher engine generating a keystream whose keys are entropy events. Keystreams don't (in practical terms) "run out of key", and urandom outputs don't "run out of entropy".
Time and time again, ignorant and lazy human beings are the enablers of security breaches. You can blame humans all you want, but if systems aren't designed with such human factors in mind, they simply won't work in the real world.
Look: that just isn't always possible. I say this not from theory, but from the trenches of information security.
I'd have to say that you're confusing "not possible" with "hasn't been done yet." Manufacturers have been flashing unique identifiers and even completely individually customized firmware as part of the assembly line process for decades now. (I know of one Fortune 500 manufacturer that can automatically customize virtually every engine controller's firmware.) Considering how foundational good CSPRNG are to cryptosystems and how cheap such resources are now, I'd say that this is one situation where there should be government regulations. How about a regulation mandating generous initial entropy pools in all computing devices that will be encrypting end user data? That doesn't cover all situations where insufficient entropy can cause harm, and such regulations would ultimately be much more complicated than my 3 paragraph comment might seem to suggest, but it would be a good start. (Yes, embedded devices are going to complicate this a lot, I know.)
The security field needs to start using some of the same pragmatic strategies the NTSB uses to prevent plane crashes. We can't just stand around wishing programmers know more about crypto and security. We need to put measures in place that actually work.
There were problems with routers with too little entropy, but unless you are the person implementing the code which initializes the router's keys after the first boot, you still should not use blocking.
I guess the simplest rule is: 1) If you are programming something which is to be used as a normal program, on the normal computer, use /dev/urandom. 2) If you are responsible for developing the device or virtual device which doesn't have valid entropy sources after the first boot, do consult somebody in the know how you can provide the needed initial entropy. After it's there, use /dev/urandom.
In short, I really don't know where using /dev/random regularly is a good practice.
We as a technical community and we as a society need to start using the same stances and strategies that governments and agencies like the NTSB use to prevent accidents. When planes crashed in the wooly pioneering days of aviation, people probably stood around sadly tsk-tsking someone's failure to recognize a stall. Today, the NTSB conducts root cause analyses and the industry takes concrete steps to prevent future mishaps. (Like equipment that detects stall and warns the pilot.)
In this case, why don't we simply have classes of devices that are expected to implement crypto for end-users, and require them to be built with generous entropy pools? (To head-off the expected smart-asses: Each one gets their own unique one, of course.)
(EDIT: An analogy: What if you knew that pilots all had conflicting opinions on how to fly and maintain a plane, with constant acrimonious debates, and where some large swathe of all pilots simply were operating on misinformation? Would you fly? Would you expect lots more crashes? Now ask yourself what the situation is like with computer security, where knowledgeable people expect security to always be broken.)
Intel added a generous entropy source to their processors. The result is that nobody trusts it as a single entropy source, and /dev/random blocks anyway. Also, we are learning that using it only as an added source may also be harmful, and maybe we should ignore it completely.
I don't think this'll have any simple solution, although the idea of a CSPRNG that may block only at boot is interesting.
For example, on Solaris from random(7D):
The /dev/random and /dev/urandom files are suitable
for applications requiring high quality random numbers
for cryptographic purposes.
...
While bytes produced by the /dev/urandom interface are
of lower quality than bytes produced by /dev/random, they
are nonetheless suitable for less demanding and shorter
term cryptographic uses such as short term session keys,
paddings, and challenge strings.
In short, on Solaris, you can use either one although you are encouraged to only use /dev/urandom for specific cases.Of course that probably only only counts if an external or local unprivileged entity manages to become informed of the random source's internal state. If the attacker has direct access to the kernel's state then they probably have access to influence (or at least monitor) the incoming entropy such that they can stay informed of the full internal state.
There is a point in some attacks beyond which your only half way guaranteed solution is the metaphorical orbital nuke platform.
You don't need access to the machine.
This would make sure that distro vendors don't even get a chance to mess initial seeding at boot time. It will also force vendors of embedded or "cloud" distributions (eg. Ubuntu's AWS images) to find a way to pre-seed the images to reduce the initial boot times.
Unfortunately there is such a huge amount of software that depends on this particular difference between /dev/random and /dev/urandom that I don't see the change happening soon.
/dev/urandom is a pseudo random number generator, a PRNG,
while /dev/random is a “true” random number generator.
Fact: Both /dev/urandom and /dev/random are using the exact same CSPRNG (a cryptographically secure pseudorandom number generator). They only differ in very few ways that have nothing to do with “true” randomness.
What? So it is a myth, then why is the line started with: "fact"? This a commonly believed myth
Fact: This is the real factThe assumption here is that the initial state can't be guessed, i guess you would rather use /dev/random for that, even if it blocks. Now be careful with the initialization step of your favorite crypto library, most inconsistencies /fishy tricks do happen right here !
Also another issue is that that such a random number generator introduces locks; I have a small program that encrypts everything with RSA, and uses multiprocessing to speed up the process; RSA encryption is supposed to use padding schema that needs to generate random numbers, so it locks, however you don't have this problem with decryption - that's where it counts because RSA decryption is much slower than encryption.
here is my project: http://mosermichael.github.io/cstuff/all/projects/2014/02/24...
haveged, /dev/random