Random number generation

From
wikipedia:Random number generation
:
A random number generator (RNG) is a computational or physical device designed to generate a sequence of numbers or symbols that lack any pattern, i.e. appear random.
Generation of random data is crucial for several applications like making cryptographic keys (e.g. for
data-at-rest encryption
),
securely wiping disks
, running encrypted
Software access points
.
Kernel built-in RNG
Note
the Linux RNG has been improved significantly in recent years, with many changes occurring in the 4.x and 5.x kernel series.  As such, much information that exists about it is outdated.  This page describes the current implementation and behavior, applicable to modern kernels including Arch Linux's
officially supported kernels
.
The Linux kernel's built-in RNG
produces cryptographically secure pseudorandom data.  It works by collecting
entropy
from various sources, such as hardware RNGs, interrupts, and CPU-based jitterentropy.  No single entropy source is relied on exclusively.  The entropy is extracted using the
BLAKE2s cryptographic hash function
and used to seed a set of
ChaCha20
CRNGs (Cryptographic Random Number Generators) that provide the actual random data.  Entropy continues to be collected, and the CRNGs are periodically reseeded, as long as the kernel is running.
The Linux RNG provides three interfaces for userspace to get random data:
The
getrandom(2)
system call
/dev/random
/dev/urandom
Historically,
/dev/random
was considered to provide stronger random numbers than
/dev/urandom
.  However, the behavior of
/dev/random
and
/dev/urandom
has significantly converged over time, and on x86-64 systems they are now equivalent.  Since Arch Linux only supports x86-64,
/dev/random
and
/dev/urandom
are equivalent on Arch Linux.  (This is true because the presence of the
RDTSC instruction
on all x86-64 CPUs means that the
CPU-based jitterentropy algorithm
will always be able to generate entropy, not to mention that most x86-64 CPUs also support
RDRAND
.)
On other architectures (specifically, architectures that do not have a fast cycle counter), there is one remaining difference between the two:
/dev/random
blocks until the kernel has estimated that the CRNGs are properly initialized, whereas
/dev/urandom
does not.  Therefore, in the general case, users and applications should still follow the traditional guidance of using
/dev/random
when generating long-term cryptographic keys, or use
getrandom(2)
which by default behaves similarly to
/dev/random
.
Note that because
/dev/random
no longer aims to provide true random data, but rather "just" cryptographically secure random data (which is sufficient for all real-world use cases), reading from it no longer causes the kernel's entropy pool to deplete.  Therefore,
/proc/sys/kernel/random/entropy_avail
should always contain 256, which is the size of a ChaCha20 key in bits.  Historical documentation that expected larger values in this file, or expected the user to take actions if the value was getting "too low", can be disregarded.
Alternatives
Applications that do not need cryptographically secure random numbers can simply use a non-cryptographic random number generator, for example
random(3)
.
For applications that do need cryptographically secure random numbers, there generally is no need for anything other than the kernel's RNG.  Historically, the kernel's RNG was fairly slow and did not take advantage of as many entropy sources as it could have.  However, it has since been improved to provide ~400 MB/s throughput on x86-64 and to take advantage of more entropy sources.  Even for cases that need fairly high throughput random numbers, such as
securely wiping a disk
, simply reading from
/dev/urandom
works fine.
Cases where it could make sense to not use the kernel's RNG directly include:
In rare cases, applications need cryptographically secure random numbers with a
very
high throughput, or with a very low latency where the overhead of a system call would not be tolerable.  A userspace CRNG can solve this problem.  Userspace CRNGs should be seeded from the kernel's RNG to ensure that they are at least as secure as the kernel's RNG, modulo considerations such as reseeding.
Some applications work in domains where there is already a well-established API for generating cryptographically secure random numbers using a userspace CRNG.  For example, when an application is using
OpenSSL
, it may make sense to use OpenSSL's
RAND_bytes(3)
.  When an application is written in Java, it may make sense to use
java.security.SecureRandom
.  Usually, the userspace CRNGs underlying these APIs are automatically seeded using the kernel's RNG.
If you would like to use additional entropy sources that are not already incorporated into the kernel's RNG, it might make sense to not use the kernel's RNG directly.  For example,
Haveged
can provide random data generated using jitterentropy.  If possible, additional entropy sources should not replace the kernel's RNG, but rather be used in conjunction with it by seeding a userspace CRNG from both the additional entropy source and the kernel's RNG.  It is also possible to write additional entropy to
/dev/random
to cause it to be incorporated into the kernel's RNG, though it may take up to 60 seconds for this to take effect due to the kernel's CRNG reseeding schedule.  Note: the kernel already uses
RDSEED
and other hardware random number generators as entropy sources.
See also
Kernel RNG improvements:
random: replace non-blocking pool with a Chacha20-based CRNG
- introduced the ChaCha20 CRNG (2016)
random: try to actively add entropy rather than passively wait for it
- made CPU-based jitterentropy be used as a fallback (2019)
Removing the Linux /dev/random blocking pool
- made
/dev/random
use a CRNG, just like
/dev/urandom
, and not try to provide "true" randomness (2020)
Random number generator enhancements for Linux 5.17 and 5.18
(2022)
random: use simpler fast key erasure flow on per-cpu keys
- simplified and optimized the CRNG design (2022)
random: do not pretend to handle premature next security model
- made new entropy be used more quickly (2022)
random: opportunistically initialize on /dev/urandom reads
- made
/dev/urandom
as safe as
/dev/random
on x86 (2022)
Randomness
- A popular science article explaining different RNGs
ENT
- A simple program for testing random sequences (entropy, Chi square test, Monte Carlo, correlation, etc.)
An Analysis of OpenSSL's Random Number Generator
- Paper on RNG reseeding risks in OpenSSL functionality