4

Let's say I need to generate a key, I have these three options as to where to get random data:

  • Yubikey (gpg-connect-agent 'SCD RANDOM 16384' /bye)
  • /dev/random
  • Combine bytes from the 2 sources

My question is: how do I determine which source is better?

P.S.

Also, any information about how Yubikeys generate random data is appreciated... I guess it has to be some true random number generator based on some physical process (?)

DimanNe
  • 151
  • 1
  • 4

2 Answers2

9

You should typically use the OS CSPRNG, which would be /dev/urandom or /dev/random. The reason is that the OS CSPRNG is typically secure, well-audited, and widely used, and on most modern desktop, laptop, and server systems, there is plenty of entropy to be had to reseed the generator periodically (usually including an on-chip TRNG). It is also typically very fast. Once we have 256 bits of entropy in a CSPRNG, we believe that's more than sufficient to generate all the data we need on a system, so a properly seeded /dev/urandom or /dev/random should be sufficient.

Another reason this should be sufficient is that the OS CSPRNG is what every other piece of software you use on your system uses. Thus, if it were insecure, all of your TLS sessions would be insecure, all of your temporary file names would be predictable, and all of the memory addresses on your system would also be predictable (leading to easy attacks on things like ASLR). We believe all the algorithms used in, say, Linux's CSPRNG are cryptographically secure and suitable for purpose, so there's no reason to think that there's any attack better than brute force.

Note that on modern Linux (5.18 and above), both /dev/urandom and /dev/random are completely identical when the CSPRNG has been properly seeded.

The YubiKey option is dependent on the hardware and firmware; it doesn't work on all YubiKeys. I also expect that it's going to be a little difficult to generate 16384 bytes quickly using a TRNG unless it also uses a DRBG (like Intel's on-chip TRNG). Since most modern machines already include the output of a TRNG (often RDRAND) in the CSPRNG anyway, there isn't much benefit to using a YubiKey here, and it's much less portable than using the OS CSPRNG, so I'd stick with the OS source.

bk2204
  • 3,564
  • 7
  • 12
5

Let's say I need to generate a key, I have these three options as to where to get random data:

  • Yubikey (gpg-connect-agent 'SCD RANDOM 16384' /bye)
  • /dev/random
  • Combine bytes from the 2 sources

There is a better option: You can write data from your Yubikey to /dev/random, and then read from /dev/urandom (or use getentropy).

On the system you are designing where you know there is a Yubikey and you know gpg-connect-agent will work to talk to it and so on, you can get data from the Yubikey and write it to /dev/random to incorporate it into the system's entropy pool and affect subsequent system RNG output before running applications that need entropy. Every major Unixish operating system supports this—for example, Linux, FreeBSD, NetBSD, OpenBSD, illumos. That will help your key generation application and all other applications you're using on the same system.

Then, after you have done that in your system, your application software should always just use /dev/urandom (or getentropy, on more recent systems) so that they generate keys based on all the entropy sources gathered by the system, including your Yubikey output, keystroke timings, environmental sensors, other hardware RNGs like RDRAND or TPM, and so on. Applications should never read from the legacy /dev/random interface for key generation; the idea that reading from /dev/random is better is a myth, and you should just use /dev/urandom, and even the Linux man page now calls /dev/random a legacy interface and advises against it. (You can write your Yubikey's output to /dev/urandom too, instead of to /dev/random, if you like.)


There is also another interface from Linux, getrandom, which is unnecessarily complicated and confusing with a variety of flags to choose between incoherent and inconsistently implemented behavior. But as long as you engineer your system to feed samples from an unpredictable process—e.g., your Yubikey—into /dev/random before applications generate keys, there is no security difference between the various different ways to use it. So you should just use getentropy anyway.