3

I need to use a cryptographically strong (certification requirement), which is of high quality (pass industry standard randomness tests) reasonably performant (see below) PRNG.

Originally, I assumed it would run on the latest Ubuntu LTS, and planned to read from /dev/urandom since, according to my information, as of kernel version 5.18 it seemed to tick all the boxes.

Performance-wise, running { timeout --foreground 1s cat /dev/urandom; } | wc -c on an M1 Mac (for reference) achieved ~450MB/s throughput, and I got similar results from an x86-64 Ubuntu 22.04.2 LTS VM.

A C++ program that read 40kB chunks achieved an even higher ~1GB/sec throughput, but I could not run compile and run an executable on it (though I assume that the ratio between the shell command and executable would be similar).

However, it turned out that it will be deployed on Amazon Linux 2 (kernel version 5.10) running in a VM, which means that the algorithmic and performance improvements to the RNG will not be available.

My questions are:

  • Will /dev/urandom on kernel 5.10 running on a VM still satisfy the original requirements, that is: provide cryptographically strong pseudo-random numbers that also pass industry standard randomness tests with a throughput of at least 1MB/sec?

I did not have access to the environment in question, but trying several online shells with earlier kernel versions produced inconsistent results: on a couple of systems (kernel 5.4, and kernel 5.15) I got the same throughput from /dev/random and /dev/urandom, which according to my understanding implies the same quality, but on another system (also kernel 5.4), /dev/random blocked and gave results between 0-200B/s (that's bytes, without a prefix), suggesting that /dev/urandom's quality was degraded (unless I misunderstood something).

However, according to Phoronix, "with Linux 5.6 /dev/random behaves more like /dev/urandom now for polling RNG data in user-space. The changed behavior causes /dev/random to behave the same as /dev/urandom except for reads being blocked until the CRNG (the Linux cryptographic-strength random number generator) is ready. Meanwhile /dev/urandom will continue to serve its best data but never block.", so the tests above with kernel 5.4 are probably not valid for this case.

So it looks like I might get away with it, but I'm not sure.

  • If it turns out that using the random pseudo-files is not an option, what are the alternatives that would tick the checkboxes above? Will OpenSSL's RAND_Bytes fit the bill?
1
  • in addition to urandom implementation, it's still possible to save/load random seed, run haveged, etc. so if you have doubts regarding the kernel ability to collect entropy in a virtualized environment, you can just add your own entropy to the mix. as for the performance, you'll just have to benchmark it yourself. Commented Jun 19, 2023 at 8:34

1 Answer 1

5

As I understand it, /dev/urandom was already backed by a good enough CSPRNG even in 5.4 (it was ported to use ChaCha20 in 4.8, with both devices backed by the same CSPRNG).

The bigger focus of the later changes was not the improvements to the RNG itself (though plenty of those did occur) but the recognition that the CSPRNG was in fact good enough, and the resulting removal of the "blocking due to entropy accounting" behavior for /dev/random, specifically because it was agreed that the CSPRNG was good enough to not need it.

So in other words, yes, according to my understanding /dev/urandom on 5.10 will be as high-quality as /dev/random, after its CSPRNG has been initialized – though it does not provide userspace any indication whether that has happened or not.

A better choice might be the getrandom(2) syscall (available since 3.something), which appears to provide "best of both worlds" (aka the new 5.18 /dev/random behavior) – with 0 specified as flags, it will block if the CSPRNG is not yet ready, but will not block afterwards.

Though, a userspace CSPRNG will always be faster due to lack of context switching – it's very common to use /dev/urandom or getrandom() to seed e.g. the OpenSSL RAND_bytes() or whatever else your cryptography library of choice provides. (I believe modern OpenSSL 3.0 will call getrandom() automatically so you don't need to manually seed it.)

(Side note: I tested pv /dev/urandom > /dev/null on various nearby x86 servers, from Westmere to Comet Lake, plus a VPS on ARM64 Ampere Altra for good measure, and they all reach the same 300–400 MB/s.)

/dev/random blocked and gave results between 0-200B/s (that's bytes, without a prefix), suggesting that /dev/urandom's quality was degraded (unless I misunderstood something).

I believe the whole point of the recent changes is the recognition that /dev/urandom's quality doesn't degrade if it's backed by a good CSPRNG, and that the accounting that /dev/random did was meaningless (hence its removal in 5.6).

2
  • Thank you for the helpful answer! I would appreciate a pointer to some "official" source that I can refer to.
    – Alex O
    Commented Jun 20, 2023 at 3:02
  • 1
    I don't really have much in terms of sources, except for e192be9d9a30 as the initial /dev/urandom CSPRNG switchover (note "we don't pretend to track entropy usage […] anymore"). (And the next commit being relevant to performance: 1e7f583af67b.) Finally, 30c08efec888 for the v5.6 random-urandom merge that you found mentioned in Phoronix. Commented Jun 20, 2023 at 4:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .