What Is This?
- what is a "random number"
- when you use them
- how to make them
- how to screw up
Opening Caveats
- my opinions
- math is elided
- theory is glossed over
- probably wrong stuff
"Random Number"?
- "uniform random variable"
- one of { min, ..., max } ("range")
- equal probability of each
- non-uniform random variable?
Terms
- uniform: coin, die roll, ...
- non-uniform: letters, heights, ...
- entropy:
- log2(# options)
- entropy(random_u64()) = 64 bits
- entropy(random_u64() % 8) = 3 bits
Computer Facts
- computers are deterministic
- meaning: state S0 → state S1
- meaning: rand() in state S0 → state S1
- meaning: rand() in state S0 → V1
- aside: does a computer have 0 entropy?
"Pseudorandom"
- random: impossible to predict (*)
- pseudorandom: hard to predict?
- RNG "strength" / "goodness"
(*): even with all info
True Randomness
- thermal noise
- various electrical effects
- chaotic systems
- Quantum ™
- open q: how random are these?
- → hardware RNG
Hardware RNGs
- hardware to sample one of those things
- very slow
- "bad" randomness
- hard to assess
- sometimes not available
- ... or even present
Software RNGs (PRNGs)
- stateful object with a next() method
Software RNGs (PRNGs)
stateful object with a next() method
- function : S → (V, S)
Software RNGs (PRNGs)
stateful object with a next() method
- function : S → (V, S)
- S: "entropy pool"
- V: value
- "takes some entropy" from S (?)
PRNG Properties
- Ni uncorrelated to Ni+1
- N0 ... Ni uncorrelated to Ni+1
- retain these properties for "a while"
- note: all PRNGs are eventually periodic
- → reseeding
- fast?
Terrible RNGs
- const(S) → (N, S): N, N, N, ... (*)
- add1(S) → (S, S + 1): 0, 1, 2, ...
- direct(S) → (S0, S1...):
S0, S1, ...
Less Terrible RNGs
- linear congruential generator (LCG)
- linear feedback shift register (LFSR)
- shift-register generators
- counter-based generators
- more complex things
LCGs
- lcg(S) → (S, (aS + c) % m)
- (a, c, m) tuple defines an LCG
- with good a, c, period is m - 1
- quality critically depends on (a, c, m)!
- see: RANDU (Knuth Vol 2 § 3.3.4)
RANDU
- a = 65539, c = 0, m = 231
- RANDU(S) → (S, 65539 * S mod 231)
- 9Sn - 6Sn + 1 + Sn
+ 2 ≡ 0 mod 231 (!)
- these form neat "planes" in 3d space
- oops... for science!
LFSR
- S : a bit vector { S0, S1, ...,
Sn }
- bit(S) → Sa ⊕ Sb
⊕ ... ("taps")
- update(S, v) → { v, S0, ..., Sn -
1 }
- lfsr(S) → (bit(S), update(S, bit(S)))
- { a, b, ... } defines the LFSR
Counter-based generator
- S : (seed, counter)
- counter((s, c)) → (f(s, c), (s, c + 1))
- what's f?
- example: "Squares"
- x = y = s * c, z = y + s
- x = x2 + y; x = x2 + z; x = x2 + y
More complex stuff
- [decades of research elided]
- Mersenne Twister
- kind of a feedback shift register
- very fast
- very long period
- quite high quality
"Quality"?
- warning: math
- spectral test (for LCGs)
- statistics to the rescue
- Knuth Vol 2 § 3.3
- → diehard & dieharder
- "most runs mostly pass"
RNG security
- recover MT state with a few hundred samples
- → reproduce its output
- same for many PRNGs
- dangerous property!
- idea: "cryptographically secure" PRNG
CSPRNG
- csprng(Si) → (Vi,
Si+1)
- given V0, V1, ..., Vn, can't
predict Vn + 1
- → Vi doesn't "leak" state
- given Si, can't recover Vi-k
- → state update is one-way
General CSPRNGs
- S: (key K, counter C)
- mix(S, T): Si → S'0
- update(S): Si → Si+1
- extract(S): Si → Vi
- update() and extract() are one-way
Aside: NIST SP 800-90A
- us govt standard for "DRBGs"
- a few subtle security issues...
- Dual_EC_DRBG scandal with NSA (!)
- others still in wide use
Actual RNGs
- the time
- timings: keyboard, disk, network
- how random is this stuff?
- sidechannels?
- magical amulets?? (special hardware)
- state of the art for decades
RDRAND / RDSEED
- RNG in the CPU hardware
- CTR-DRBG seeded off "hardware"
- can you trust this?
- CrossTalk, Zen5 zero bug, NSA?
Actual CSPRNGs
- arc4random(): RC4 key stream
- Fortuna: CTR-DRBG (ish) with AES
- Windows BCryptGenRandom(): CTR-DRBG with AES
- bssl RAND_bytes(): CTR-DRBG with AES
- linux kernel: CTR-DRBG with ChaCha20
Best practices (kernel)
- "entropy pool" (CSPRNG state)
- mix "everything" into this
- attacker can't control all of it
- any unknown input adds entropy
- generate out of it as needed
Aside: /dev/{,u}random
- /dev/random: "actual entropy"
- /dev/urandom: PRNG output
- "move the mouse around" / "type"
- random blocks, urandom doesn't
- q: when to use random?
Aside: /dev/{,u}random
- /dev/random: "actual entropy"
- /dev/urandom: PRNG output
- "move the mouse around" / "type"
- random blocks, urandom doesn't
- q: when to use random?
- a: never
Best practices: user
- seed PRNG off kernel, use that
- CSPRNG ~always
- unless you know perf is critical
- just use base::RandBytes() :)
Aside: state cloning
- problem: fork() copies PRNG state
Aside: state cloning
- problem: fork() copies PRNG state
- problem: VM snapshot copies PRNG state
- reseed on every call?
- ... if we can (RDRAND / etc)
- ... or just give up
Oops #1: Debian OSSL
- CVE-2008-0166
- OpenSSL CSPRNG on Debian seeded with PID
only
- → 32,767 possible output streams
- unnoticed for years
- ~all crypto broken on such systems
- CSPRNG only as good as seed
Oops #2: PS3 DSA
- DSA uses a random nonce
- non-random nonce → leak private
key
- Sony did this
- → leaked root PS3 signing key!
- random quantities must be random
Oops #3: RSA moduli
- N = pq (p, q random primes)
- N' = pq' or N' = p'q
- gcd(N, N') = p or q
- how??
- routinely breaks 100ks of keys
Oops #4: DUHK
- ANSI X9.31 CSPRNG
- X9.31 discloses full state if you have key...
- various Fortinet devices hardcoded
key
- broke 100ks of keys
Oops #5: Android CSPRNG
- Java SecureRandom default seed: 64 bits
- disclosed in 2013
- latent for... years?
- BitCoin keys from Android broken
Oops #6: RC4 key
- key schedule: key → longer key
- ... basically a CSPRNG
- output is biased
- → Fluhrer-Mantin-Shamir
- → break WEP for wifi
- arc4random() drops stream prefix
Oops #7: Dual_EC_DRBG
- from NIST SP 800-90A
- slow, weird CSPRNG
- NSA paid RSA Security to use it
- ... then used that use to standardize it
- widely considered likely backdoored
- rejected by everyone, later de-standardized
Lessons
- rng failure cannot be tested for
- rng failure generally has no visible result
- these bugs can have unfixable consequences
- leaked user data
- decrypt-later
Lessons 2
- use a good rng
- use big-enough random values
- use constructs that don't need one
- use bssl and //crypto
- talk to security
Further reading
- Knuth Volume 2 3.3 for Math
- Cryptography Engineering Chapter 9 for Crypto
- [add yours here]