4 ms·
The root problem here is the notion that you need to choose between "strong and slow" randomness vs. "weak and fast" randomness. If every language's random() wa
by nemo1618 6y ago
The root problem here is the notion that you need to choose between "strong and slow" randomness vs. "weak and fast" randomness. If every language's random() was strong and fast, most developers would never have to think about it.
"Strong" randomness is often too slow because every time you ask for new entropy, you make a syscall. The solution is to use 32 bytes of strong randomness to seed a userspace CSPRNG. You can generate gigabytes of secure entropy per second in userspace. If you need deterministic entropy, just use the same seed.
This isn't a one-size-fits-all solution, of course. If you only need to generate a few keys now and then, it's marginally safer to make a separate syscall for each of them. If you're targeting some tiny SoC, then sure, use xorshift instead. But what we care about is the common case, and right now the common case is a developer choosing the weak, deterministic RNG because it's faster and has a more convenient API and the secure RNG says "for cryptographic purposes" and well this usecase doesn't seem like cryptography, it's just a simple load balancer...
That decision should never need to be made.
- moonchild 6y ago> The solution is to use 32 bytes of strong randomness to seed a userspace CSPRNG All cryptographic randomness generation should be performed by the kernel. You always have to think about security because if you don't think about security you're going to get hacked. By all means, name the insecure randomness generation function ‘insecure_random’. It does help. But secure-by-default helps you only marginally because when building secure software you don't get to just use the defaults; you have to think about what they're doing. You have to (for example) know and think about timing attacks even if you're using a cryptographic primitives library that's hardened against them, because it's really easy to introduce timing dependence into your own code and none of Daniel Bernstein or Tanja Lange’s careful designs will save you.
- nemo1618 6y agoThat's fair. There's no silver bullet for security. But we should not let the perfect be the enemy of the good. Everyone writing non-trivial systems should have some understanding of security; but the more components we make secure-by-default, the less those developers need to learn.
- repsilat 6y ago> You can generate gigabytes of secure entropy per second in userspace. I haven't thought about this before, so please have patience: I guess the "secure" qualifier does a lot of work in this sentence? That there's 32 bytes of "true entropy", but "secure entropy" is theoretically weaker but practically just as strong with reasonable assumptions about an attacker's computing resources. So I'd guess the "secure" qualifier must mean something like "given any quantity of derived pseudorandom information, the seed bytes can't be efficiently deduced? Pretty neat. (I had a knee-jerk disagreement until I re-read your post and saw that you said "32 bytes", not "32 bits". Quite plausible -- and cool -- that we have a good solution with just a small amount more seed randomness though.)
- nemo1618 6y agoCorrect -- the RNG output does not reveal anything about its input, just like the output of a strong cipher does not reveal anything about its input. djb has a good article on the subject: https://blog.cr.yp.to/20170723-random.html https://blog.cr.yp.to/20170723-random.html I've implemented his "fast-key-erasure CSPRNG" in Go: https://github.com/lukechampine/frand https://github.com/lukechampine/frand
- smcameron 6y agoThere is no such thing as fast enough.