Introduction

Ask your computer for a random number and it answers instantly. But computers are deterministic machines: given the same inputs they always produce the same outputs. How can they produce anything genuinely random?

The honest answer is: they usually can't. Most programs use a pseudorandom number generator (PRNG) — a deterministic formula whose output looks random without actually being so. Feed it the same starting value (the seed) and you get the identical sequence every time.

That is fine for simulations, games and shuffling playlists. It becomes a serious problem the moment the output needs to be unpredictable — like generating a cryptographic key or a one-time password. Predictable "randomness" has caused real-world security disasters that exposed millions of users to attack.

Understanding the difference between statistically random and cryptographically unpredictable is one of the most practically important distinctions in all of computing.

Predict the PRNG

The demo below runs a linear congruential generator (LCG) — the simplest well-known PRNG — and shows you each output one at a time.

<p class="hint">{{hint}}</p>
<div id="stream" class="stream"></div>
<div class="status" id="status">{{press_next_to_start}}</div>
<div class="btns">
  <button id="btn-next" type="button">{{btn_next}}</button>
  <button id="btn-reveal" type="button" class="ghost">{{btn_reveal}}</button>
  <button id="btn-predict" type="button" class="ghost" disabled>{{btn_predict}}</button>
  <button id="btn-reset" type="button" class="ghost">{{btn_reset}}</button>
</div>
<div id="state-box" class="state-box hidden">
  <span class="state-label">{{state_label}}</span>
  <span id="state-val" class="state-val"></span>
  <span class="state-label" style="margin-top:.35rem">{{next_formula}}</span>
</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .7rem; line-height: 1.5; }
code { background: #eef1f4; padding: .1em .35em; border-radius: 4px; font-size: .85em; }
.stream { display: flex; flex-wrap: wrap; gap: 6px; min-height: 56px; margin: .4rem 0; align-items: flex-start; }
.num-chip { padding: .3rem .55rem; border-radius: 8px; font: 700 14px ui-monospace, monospace;
            background: #e8eef3; color: #1d3557; border: 1px solid #cdd9e3; transition: background .2s; }
.num-chip.predicted { background: #fdefc9; color: #7a4f00; border-color: #e3c96e; }
.num-chip.confirmed { background: #d4f0dc; color: #0a6627; border-color: #6fcb8e; }
.status { font-size: .95rem; font-weight: 600; margin: .5rem 0; min-height: 1.5em; }
.status.ok { color: #0a7d33; }
.status.bad { color: #c92f3c; }
.status.info { color: #1d3557; }
.btns { display: flex; gap: .45rem; flex-wrap: wrap; }
button { font: 600 13px system-ui; padding: .42rem .85rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
button:disabled { opacity: .4; cursor: default; }
.state-box { margin-top: .8rem; padding: .6rem .8rem; background: #fff8e6; border: 1px solid #e3c96e;
             border-radius: 8px; display: flex; flex-direction: column; gap: .15rem; }
.state-box.hidden { display: none; }
.state-label { font-size: .8rem; color: #7a4f00; }
.state-val { font: 700 1.1rem ui-monospace, monospace; color: #7a4f00; }
// Code not found

Notice what happens when you click Reveal state: you can see the internal seed that drives the whole sequence. Once you know it, you can predict every future number — click Predict next to confirm. This is exactly what an attacker does when a system leaks or reuses enough PRNG output: they recover the state and from then on the "random" numbers are as predictable as a clock.

The Real Complexity

There are three very different things that people call "random numbers," and confusing them has caused real disasters.

1. Pseudorandom (PRNG)

A PRNG like the Mersenne Twister (Matsumoto & Nishimura, 1998) passes every standard statistical test — chi-square, autocorrelation, the TestU01 suite. Its period is 2199372^{19937} − 1. Yet it is entirely deterministic. After observing just 624 consecutive 32-bit outputs, an attacker can fully reconstruct the internal state and predict all future values. Python's random, PHP's mt_rand and Java's Random all use it.

2. Cryptographically secure (CSPRNG)

A CSPRNG must pass the next-bit test: no polynomial-time algorithm should predict the next bit with probability significantly better than 1/2, assuming standard hardness conjectures. Examples: ChaCha20-based generators (Linux /dev/urandom, Windows BCryptGenRandom), HMAC-DRBG (NIST SP 800-90A). Even if you see all previous outputs, the next bit looks genuinely unpredictable.

3. True randomness

Physical entropy — thermal noise, radioactive decay, quantum shot noise — is the only source of actual unpredictability. Devices like /dev/random harvest it; dedicated hardware ICs (Intel RDRAND) sample chip-level noise. True entropy is precious and rate-limited; it seeds CSPRNGs rather than generating output directly.

Where things go wrong

Real failures happen at the boundary. In 2012, researchers found that millions of RSA and DSA public keys generated by embedded devices shared prime factors — the devices had too little entropy at boot time, so their "random" seeds collided. The keys looked different but were mathematically related. The attack, called ROCA (Return of Coppersmith's Attack), compromised smart cards, TPMs and VPN appliances worldwide.

The Debian OpenSSL bug (2006–2008) accidentally replaced a genuine entropy source with a predictable process ID — reducing the PRNG seed space to just 32,768 values. Every "secure" key generated on Debian during those two years could be brute-forced in seconds.

Related reading: the unpredictability requirements here connect directly to factoring and discrete logarithms, the hard problems that underpin most public-key cryptography.

Where It Matters

Randomness shows up everywhere, but the required quality varies enormously:

  • Cryptographic keys and nonces: must be truly unpredictable. A weak PRNG here is catastrophic — it is exactly how the 2012 RSA key-collision attack worked.
  • Monte Carlo simulation: PRNGs suffice. Scientific computing (climate models, particle physics) runs billions of draws; statistical quality matters, cryptographic unpredictability does not.
  • Games and procedural generation: a seeded PRNG is often a feature — reproducible worlds, shareable seeds, deterministic replays.
  • Statistical sampling and A/B testing: quality PRNGs prevent biased samples; the seed must be chosen carefully to avoid correlations between test groups.
  • Lotteries and gambling: regulated systems use hardware true-random sources or certified CSPRNGs; a predictable generator would let players win every time.
  • Machine learning: weight initialization and data shuffling use PRNGs; reproducibility (fixed seeds) is valued for experiment repeatability.

The P vs NP question lurks here too: CSPRNGs are secure only if certain problems (like factoring) are genuinely hard. If P = NP, every CSPRNG collapses.

Conclusion

Your computer's random numbers are the output of a formula — deterministic, reproducible and, in the wrong hands, entirely predictable. For simulations and games that is fine; for cryptographic keys it is a disaster waiting for the right attacker.

The distinction matters because the history of computing is littered with systems that used a fast PRNG where they needed a secure CSPRNG, and paid for it in compromised keys, broken protocols and leaked secrets. True entropy — physical noise harvested by the hardware — is the scarce resource that underpins every cryptographic guarantee.

The next time a website logs you in with a "random" token, or your phone encrypts a file, somewhere a CSPRNG seeded by real physical entropy is quietly doing the work that keeps the secret a secret. Whether that seed had enough entropy to begin with is the question that has broken — and will break again — systems that assumed it.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/random-number-generation/Content licensed under CC BY-NC 4.0.