Skip to content

Weak randomness (RNG)

A huge amount of security depends on unpredictable random numbers: keys, IVs/nonces, session tokens, password resets, OTPs, identifiers. When the generator is weak or predictable, the attacker predicts those values and breaks the system without touching the cryptography itself.

Standard PRNG (rand(), Math.random(), mt_rand, java.util.Random)
fast but PREDICTABLE: given enough output, the state is recovered and the rest predicted
NEVER for anything security-related
CSPRNG (cryptographically secure)
/dev/urandom, getrandom(), secrets (Python), crypto.randomBytes (Node),
SecureRandom (Java), RNGCryptoServiceProvider/.NET
designed so output is unpredictable even knowing previous outputs
Predictable seed seed = time() or PID -> small seed space -> brute force
Non-crypto PRNG for tokens session/reset tokens generated with rand()/Mersenne Twister
-> recover the state and predict future/past tokens
Insufficient entropy at boot IoT/VM devices generate keys with little entropy
-> REPEATED or factorable KEYS across devices
Predictable or fixed nonce/IV breaks CTR/GCM/CBC (see crypto-sym)
Repeated k in (EC)DSA reusing the nonce 'k' when signing REVEALS the private key
# MT19937 (used by PHP's mt_rand, Python's random, Math.random in many runtimes):
# with 624 consecutive 32-bit outputs you reconstruct the internal state and predict everything
# tool: randcrack (Python)
from randcrack import RandCrack
rc = RandCrack()
for v in observed_624: rc.submit(v)
rc.predict_randint(0, n) # next "random" value
# real application: predictable tokens/IDs -> account takeover, OTP bypass
# if two signatures use the SAME k: with both signatures (r,s1),(r,s2) and the messages
# you solve for k and then the PRIVATE KEY. Historic case: PS3 (Sony) signed with a fixed k.
# detection: the same r value in two distinct signatures = repeated k
# large-scale studies of public RSA keys on the Internet found keys sharing a prime
# (GCD between moduli != 1) from weak RNG at router/IoT boot -> trivial factorization
  • randcrack (MT19937), language-specific PRNG crackers, sage/z3 to model.
  • openssl/msieve/yafu for the factoring part; token analysis with Burp Sequencer (session randomness quality).
  • Always use a CSPRNG from the system for keys, IVs/nonces, tokens, resets, and OTPs (secrets, crypto.randomBytes, SecureRandom).
  • Unique nonce/k per operation (or deterministic signing RFC 6979 in ECDSA); random IV.
  • Ensure sufficient entropy at boot (hardware RNG, don’t generate keys on first boot without entropy).
  • Long (≥128-bit), opaque tokens; audit with Burp Sequencer.
  • Debian OpenSSL (CVE-2008-0166): a patch cut entropy → predictable SSH/SSL keys worldwide.
  • PS3 / fail0verflow (2010): ECDSA with a fixed k revealed Sony’s signing key.
  • Mining your Ps and Qs (2012): RSA/DSA keys factorable via shared primes (weak RNG in IoT).
  • Numerous predictable-reset-token bugs from using a non-cryptographic PRNG.
  • Identify what uses randomness (tokens, resets, OTP, IV/nonce, keys)
  • Non-cryptographic PRNG (rand/mt_rand/Math.random)?
  • Collect outputs and try prediction (randcrack for MT19937)
  • Tokens/IDs: sequential or predictable? (Burp Sequencer)
  • ECDSA/DSA signatures: repeated r value? → reused k
  • RSA keys: shared primes (GCD)? (low entropy)
  • Verify CSPRNG and RFC 6979 use in the defense