In 2012, a team of researchers from the University of Michigan, the University of California San Diego, and Centrum Wiskunde & Informatica in Amsterdam analyzed the RSA public keys of 7.1 million TLS certificates and 6.2 million SSH hosts. They found that 0.2% of TLS certificates and 1.1% of SSH hosts shared a prime factor with at least one other key. These keys were trivially factorable – not because RSA was broken, but because the devices generating them had insufficient randomness. Routers, embedded systems, and virtual machines that generated keys immediately after boot, before entropy pools had accumulated, produced keys with predictable prime factors. A single shared factor between two 1024-bit RSA moduli allows factoring both in microseconds.

This was not an isolated incident. It was a symptom of the single most common failure mode in deployed cryptography: broken randomness.

The Debian OpenSSL bug (2008) reduced the seed entropy to 15 bits (32,768 possible values) for two years, affecting every key generated on Debian and Ubuntu systems. The PlayStation 3 ECDSA implementation reused a random nonce, allowing recovery of Sony’s private signing key. The Android SecureRandom vulnerability (2013) produced predictable outputs that compromised Bitcoin wallets. The RSA BSAFE library shipped with the Dual_EC_DRBG backdoor for years before the Snowden revelations confirmed it was a deliberate NSA insertion.

Every one of these failures was a randomness failure. The ciphers were fine. The protocols were fine. The random numbers were not.

What Cryptographic Randomness Requires

A cryptographic random number generator must produce output that is:

Unpredictable. Given any number of previously generated outputs, an adversary cannot predict the next output with probability better than random guessing. Formally, no polynomial-time algorithm can distinguish the output from a truly random sequence with non-negligible advantage.

Unbiased. Each bit of output has equal probability of being 0 or 1, and bits are independent of each other.

Non-reproducible. Even if the internal state is compromised at some point, past outputs cannot be reconstructed (forward secrecy), and future outputs become unpredictable once new entropy is mixed in (recovery/break-in resistance).

These requirements are stricter than what most applications need. A video game’s random number generator needs to be “fair” but not unpredictable – a determined player who reverse-engineers the seed can predict outcomes, but the consequences are trivial. A cryptographic RNG must resist adversaries with arbitrary computational resources (up to the assumed hardness of the underlying primitives), because the consequences of prediction are key recovery, forgery, and decryption.

Entropy Sources

True randomness must come from physical processes. Software is deterministic – a program that receives the same inputs always produces the same outputs. Entropy sources bridge the gap between the deterministic world of computation and the unpredictable world of physics.

Hardware Sources

Thermal noise. Johnson-Nyquist noise in resistors produces voltage fluctuations proportional to temperature and resistance. Sampling these fluctuations with an ADC produces random bits. Intel’s RDRAND instruction uses thermal noise in the processor die.

Shot noise. The discrete nature of electric current (individual electron arrivals) produces random fluctuations detectable in semiconductor junctions. This is the basis of several dedicated hardware random number generators.

Radioactive decay. The timing of individual nuclear decay events is governed by quantum mechanics and is fundamentally unpredictable. Geiger counter-based random number generators sample the inter-event timing. The HotBits service at Fourmilab has generated random bits from radioactive decay since 1996.

Photonic noise. Quantum random number generators (QRNGs) exploit quantum phenomena such as vacuum fluctuations, photon arrival times, or beam-splitter decisions. ID Quantique’s Quantis QRNG achieves generation rates of 16 Mbps and is certified by multiple national standards bodies. A 2023 survey by Herrero-Collantes and Garcia-Escartin identified over 30 commercially available QRNG devices.

Software Entropy Sources

Operating systems harvest entropy from unpredictable system events:

  • Interrupt timing. The precise timing of hardware interrupts (disk I/O, network packets, keyboard events) is influenced by physical factors (disk seek time, network latency, keystroke dynamics) that are unpredictable at the bit level.
  • Jitter. CPU clock jitter – the variation in timing of identical instructions across executions – is caused by thermal effects, cache behavior, and pipeline stalls. The Jitterentropy library, developed by Stephan Mueller, extracts entropy from CPU jitter and is used in the Linux kernel.
  • Environmental noise. Mouse movements, microphone input, camera frames, and sensor readings (accelerometer, gyroscope) provide entropy on devices with these peripherals.

The Linux Entropy Model

Linux maintains an entropy pool fed by hardware interrupts, disk events, and input devices. The pool is a 4096-bit state that is mixed using a cryptographic hash function.

Historically, Linux provided two interfaces: /dev/random (which blocked when the estimated entropy was low) and /dev/urandom (which never blocked but was seeded from the same pool). The blocking behavior of /dev/random was based on an entropy estimation model that the cryptographic community widely considered flawed – once the pool is seeded with sufficient entropy (typically 256 bits), the CSPRNG produces output indistinguishable from random, and blocking provides no additional security.

Since Linux 5.6 (2020), /dev/random no longer blocks once the CSPRNG is initialized, effectively making it equivalent to /dev/urandom. The getrandom() system call, introduced in Linux 3.17, provides the recommended interface: it blocks until the CSPRNG is initialized (preventing early-boot entropy starvation) and then returns output without blocking.

Cryptographically Secure Pseudorandom Number Generators (CSPRNGs)

Hardware entropy sources are slow. A QRNG producing 16 Mbps cannot supply the gigabits per second of random data needed by a busy TLS server. CSPRNGs stretch a small seed of true randomness into an unlimited stream of pseudorandom output.

CTR_DRBG (NIST SP 800-90A)

CTR_DRBG uses AES in counter mode as the core generator. An internal state (V, Key) is maintained. To generate output:

  1. Increment V.
  2. Compute output block = AES_Key(V).
  3. Periodically reseed by mixing new entropy into (V, Key).

CTR_DRBG with AES-256 is the most widely deployed CSPRNG in commercial cryptographic modules. It is the default in OpenSSL, the Windows CNG (Cryptography Next Generation) library, and most FIPS 140-validated modules. Its security reduces to the security of AES: if AES is a pseudorandom permutation, CTR_DRBG output is computationally indistinguishable from random.

HMAC_DRBG

HMAC_DRBG uses HMAC (Hash-based Message Authentication Code) as the core primitive. It maintains a key K and a value V:

  1. V = HMAC_K(V)
  2. Output = V
  3. K = HMAC_K(V || 0x00 || additional_input)
  4. V = HMAC_K(V)

HMAC_DRBG’s security reduces to the security of the underlying hash function. It is used in RFC 6979 for deterministic ECDSA nonce generation – the construction that prevents the nonce-reuse vulnerability that broke the PS3.

ChaCha20-Based CSPRNGs

The BSDs (FreeBSD, OpenBSD, NetBSD) and the Linux kernel (since 4.8) use ChaCha20 as the core CSPRNG. ChaCha20’s design – a 256-bit key, a 64-bit counter, and a 96-bit nonce processed through 20 rounds of quarter-round operations – is naturally suited to stream generation. The arc4random() function in modern BSDs wraps ChaCha20 with automatic reseeding from the kernel entropy pool.

ChaCha20 has no known timing side channels in software implementations (unlike AES without AES-NI), making it a safer choice for platforms without hardware AES support.

The Dual_EC_DRBG Backdoor

In 2006, NIST published SP 800-90A, specifying four pseudorandom number generators. One of them, Dual_EC_DRBG, was based on elliptic curve points. The generator’s state update function computed:

s_{i+1} = x(s_i * P)
output_i = x(s_i * Q)

where P and Q are fixed elliptic curve points on the P-256 curve.

In 2007, Dan Shumow and Niels Ferguson presented at the Crypto rump session, observing that if someone knew the discrete logarithm e such that Q = e * P, they could recover the internal state from a small number of output bits. The relationship between P and Q was not explained in the standard – the points were simply given without derivation.

In 2013, the Snowden documents confirmed that the NSA had deliberately inserted the backdoor. RSA Security (the company, not the algorithm) had made Dual_EC_DRBG the default in their BSAFE library, reportedly after receiving a $10 million contract from the NSA.

The impact was significant: NIST withdrew Dual_EC_DRBG from SP 800-90A in 2014. The episode permanently altered the cryptographic community’s relationship with government-standardized algorithms and reinforced the principle that algorithm constants must have verifiable derivations (“nothing-up-my-sleeve” numbers).

The Web Crypto API: Randomness in the Browser

Modern browsers provide cryptographic randomness through the Web Crypto API’s crypto.getRandomValues() function. This function fills a typed array with random bytes sourced from the operating system’s CSPRNG:

const iv = new Uint8Array(12);
crypto.getRandomValues(iv);

The function is synchronous, available in all modern browsers, and backed by the OS entropy pool (CryptGenRandom on Windows, /dev/urandom or getrandom() on Linux, SecRandomCopyBytes on macOS). The Web Crypto API specification requires that the output be cryptographically random, and browser implementations are regularly audited.

For AES-256-GCM encryption in Stealth Cloud’s client-side architecture, crypto.getRandomValues() generates initialization vectors (IVs) and key material. The security of every encrypted message depends on the quality of this randomness – a predictable IV in GCM mode leads to nonce reuse, which collapses the authentication guarantee and can reveal the encryption key.

Common Failures and Their Consequences

Insufficient entropy at boot (2012 key factoring study). Embedded devices generating keys before the entropy pool is seeded produce predictable keys. The study found 64,000 vulnerable TLS certificates and 108,000 vulnerable SSH hosts.

Nonce reuse in ECDSA. The ECDSA signature algorithm requires a random nonce k for each signature. If the same k is used twice with the same private key, the private key can be recovered algebraically. This is not a theoretical concern: the Sony PS3 hack (2010), multiple Bitcoin wallet compromises, and the Java SecureRandom vulnerability all exploited nonce reuse. Deterministic nonce generation (RFC 6979) eliminates this class of failure entirely.

VM snapshot and fork. Virtual machines that are snapshotted and cloned carry identical CSPRNG states. If the CSPRNG is not reseeded after fork, cloned VMs produce identical random sequences. This affected Amazon EC2 instances and was addressed by adding VM-fork-aware reseeding to Linux’s random number generator.

Process fork without reseeding. Similar to VM snapshots, a Unix fork() duplicates the process’s CSPRNG state. If both parent and child generate random numbers without reseeding, they produce identical outputs. OpenSSL addressed this by checking the PID on each call and reseeding after fork.

Testing Randomness

How do you verify that a random number generator produces good output?

Statistical test suites. NIST SP 800-22 defines 15 statistical tests (frequency, runs, spectral, entropy, etc.) applied to a sequence of bits. The Dieharder suite provides more aggressive tests. TestU01 (L’Ecuyer and Simard) is the most comprehensive, with over 100 tests in its “Big Crush” battery.

These tests detect statistical bias but cannot detect cryptographic weakness. A generator that passes all statistical tests may still be predictable to an adversary who knows the algorithm. Statistical tests are necessary but not sufficient.

Formal analysis. The security of a CSPRNG should be provably reducible to the hardness of a well-studied problem. CTR_DRBG’s security reduces to AES. HMAC_DRBG’s security reduces to the hash function. Formal analysis provides confidence that the generator is secure assuming its underlying primitive is secure.

Health monitoring. Production systems continuously monitor the output of hardware RNGs for anomalies (stuck bits, bias, correlation). If a health check fails, the system falls back to software entropy sources or enters a fail-safe state.

The Stealth Cloud Perspective

Stealth Cloud’s client-side encryption generates a new AES-256-GCM key and a fresh 96-bit IV for every message. The security of this construction depends entirely on the quality of the randomness provided by the browser’s Web Crypto API. A predictable key is no key at all. A reused IV in GCM mode is a catastrophic failure.

The zero-knowledge architecture amplifies this dependency. Because the server never sees plaintext and cannot verify client-side encryption quality, the client must be solely responsible for generating strong random values. There is no server-side safety net. If the client’s entropy source is compromised, the server has no mechanism to detect the weakness – the ciphertext looks the same regardless of whether the key was generated from 256 bits of entropy or from a predictable seed.

This is why Stealth Cloud’s key management design relies exclusively on the Web Crypto API rather than implementing custom random number generation. The Web Crypto API’s getRandomValues() and generateKey() functions are implemented in native browser code, backed by OS-level entropy sources, and continuously tested by the security teams of every major browser vendor. Custom JavaScript RNG implementations, no matter how carefully designed, cannot match this assurance.

Randomness is the foundation on which every other cryptographic primitive stands. Flawed randomness does not weaken security incrementally. It destroys it categorically. The history of cryptographic failures teaches one lesson above all others: the cipher is rarely the problem. The random number generator is.