Hacker News new | past | comments | ask | show | jobs | submit login

So is GnuPG bad because it reads directly from /dev/random instead of using an interface like getrandom()? I'm naive enough to not know reading directly from /dev/random is bad and would love to know more.



The getrandom() syscall is relatively new. Before it was available, you had two choices.

Use a non-Linux OS with reasonable /dev/(u)random or use Linux with its Sophie's choice:

/dev/random will give you something that's probably good, but will block for good and bad reasons.

/dev/urandom will never block, including when the random system is totally unseeded.

GnuPG could not use /dev/urandom, since there was no indication of seeding, so it had to use /dev/random which blocks until the system is seeded and also when the entropy count of nebulous value was low. Most (all) BSDs have /dev/urandom the same as /dev/random, where it blocks until seeded and then never blocks again . This behavior is available in Linux with the getrandom() syscall, but perhaps GnuPG hasn't updated to use it? Also, there was some discussion in the last few months of changing the behavior of that syscall, which thankfully didn't happen, in favor of having the kernel generate some hopeful entropy on demand in case there is a caller blocked on random with an unseeded pool.


> This behavior is available in Linux with the getrandom() syscall, but perhaps GnuPG hasn't updated to use it?

GnuPG has been using getrandom() where available for over a year[1]. Obviously some distros may not yet have updated to a recent enough version, but it (and OpenSSL) are no longer among the offenders that cause /dev/random blocking hangs.

[1] https://lists.gnupg.org/pipermail/gnupg-announce/2018q4/0004...


So the issue is the block? I make a blocking call and another app attempts to make a call during the block and will fail if it's not expecting to wait? Is that (one of) the problem(s)?

Thanks for breaking that down for me!


So, if the random system hasn't been properly seeded, you do need to block, if you're using the random for security; especially for long term security, ex long lived keys.

The problem is, before this patch, Linux keeps track of an entropy estimate for /dev/random, and if the estimate gets too low, read requests will block. Each read reduces the estimate significantly, so something that does a lot of reads makes it hard for other programs to do any reads in a reasonable amount of time.

If you knew the system was seeded, you could use urandom instead, but there's not a great way to know. Perhaps, you could read from random the first time, and urandom for future requests in the same process... but that only helps in long running processes; also reading once from random and using it as a seed to an in-process secure random generator works almost as well. The getrandom() syscall is really the way forward, but you would need to keep old logic conditionally or accept loss of compatibility with older releases.

In summary, it's not really fair to say GnuPG is doing it wrong, when they didn't have a way to do it right.


Thanks! That makes sense. I appreciate you taking the time to break all that down.


It should have read just 16 or 32 bytes from /dev/random in order to seed its own CSPRNG (at most once per process invocation, only when first needed)


No! Per-processs CSPRNGs are a terrible idea. Fork-safety is hard. Swap-safety is hard.


I guess all programming is kinda hard, it's the nature of expectations of modern computing.

Per-process CSPRNGs are pretty common. Most programs don't fork without exec, no problem for them. Managing a per-process CSPRNG is only hard for libraries that might be used by some programs that fork without exec, and don't want to require the program to do anything right.

No! It's not hard, just don't screw it up. This is true of most things.


Why not just use getrandom() or CryptGenRandom() instead and simplify everything avoiding all those classes of bugs?

A user space CSPRNG is just a foot-gun waiting to go off.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: