Randomness and RNG

PRNG vs CSPRNG vs TRNG: the three tiers of random

Not all 'random' is the same. We separate the three tiers — PRNG, CSPRNG, TRNG — with plain-language analogies, real examples (Mersenne Twister, ChaCha20, hardware noise), and the jobs each is built for.

"Random number generator" covers three very different machines. Confusing them is how projects end up drawing prizes with a generator built for video-game dust particles. Here are the three tiers, what actually separates them, and where each one belongs.

Tier 1 — PRNG: the photographed deck

A pseudo-random number generator is a deterministic formula. You give it a starting value (the seed), and it churns out a sequence that looks random but is completely fixed by that seed. Same seed, same sequence, every time.

The honest analogy: a deck of cards that was shuffled once, photographed, and is now dealt in order. Every deal looks unpredictable to someone at the table — but anyone holding the photograph knows every card that is coming.

The classic example is the Mersenne Twister, published by Matsumoto and Nishimura in 1998 and for decades the default generator in Python, R, PHP and many scientific libraries. Its numbers are superb by statistical measures — its period is 2^19937 − 1, a number with over 6,000 digits. And yet its own authors' documentation states plainly that it is not cryptographically secure: observe 624 consecutive outputs and you can reconstruct the internal state and predict everything that follows. The photograph leaks.

The same applies to xorshift128+, the engine behind JavaScript's Math.random() — we walk through its published state-recovery attack in why Math.random() must never draw a lottery.

Where PRNGs belong: simulations, games, procedural graphics, statistical sampling — anywhere you need lots of plausible randomness fast, and reproducibility from a seed is a feature (re-running a simulation) rather than a flaw. Our draw simulator is a legitimate use: it models millions of hypothetical draws where speed matters and nobody wins money on the outcome.

Tier 2 — CSPRNG: the deck behind a one-way lock

A cryptographically secure PRNG is still deterministic underneath — but with two properties the first tier lacks:

  1. Forward secrecy of the pattern: even if you record enormous amounts of output, computing the internal state should be as hard as breaking a modern cipher.
  2. Protected, replenished seeding: the state is fed from unpredictable physical events and kept secret, and is regularly stirred with fresh entropy.

Analogy: the deck is still dealt by a machine, but the machine's memory sits behind a lock that scrambles everything you can see. Watching cards come out tells you nothing usable about the cards still inside — not because there is no pattern, but because extracting the pattern is computationally out of reach.

Modern CSPRNGs are built from the same primitives as encryption. The Linux kernel's random pool, for instance, generates its output with the ChaCha20 stream cipher — the design change is documented in LWN's "Replacing /dev/urandom", and ChaCha20 itself is specified in RFC 8439. Predicting the generator's next output would mean breaking ChaCha20, a cipher trusted to protect a large share of the world's internet traffic.

Where CSPRNGs belong: passwords, session tokens, encryption keys — and any draw where someone has an incentive to predict the outcome. When your browser runs our number generator, the numbers come from crypto.getRandomValues(), which is the operating system's CSPRNG surfaced to the web page (details here).

Tier 3 — TRNG: no deck at all

A true random number generator doesn't compute anything. It measures a physical process that is unpredictable at the level of physics: thermal noise in a resistor, jitter between oscillators, radioactive decay timing, quantum optics.

Analogy: instead of dealing from any deck, you flip a real coin — the outcome isn't stored anywhere in advance, not even in principle.

Real examples: Intel CPUs since 2012 include a hardware entropy source behind the RDRAND/RDSEED instructions, documented in Intel's Digital Random Number Generator guide — thermal noise sampled, conditioned and served to software. The engineering discipline around such devices is codified in NIST SP 800-90B, the standard for validating entropy sources.

TRNGs have their own honest weaknesses: they are slow compared to computation, the raw physical measurements are usually biased (more 1s than 0s, correlations from the circuit) and must be post-processed, and a failing or sabotaged sensor can silently degrade. That is why real systems use TRNGs to feed CSPRNGs rather than serve numbers directly: physics supplies unpredictability, cryptography supplies speed and robustness. That layered design is exactly what sits under getrandom() on Linux and BCryptGenRandom on Windows.

Where TRNGs belong: seeding everything else; standalone certified gambling hardware; lab work needing physical randomness. Ball machines in televised lottery draws are, in a sense, the oldest TRNGs in the business — mechanical chaos as entropy source (can physics predict a draw?).

The one-table summary

Tier Determined by a seed? Predictable from outputs? Speed Typical use
PRNG (Mersenne Twister, xorshift128+) Yes Yes — published attacks Fastest Simulations, games
CSPRNG (ChaCha20-based, OS pools) Yes, but state is secret and refreshed No, barring a cipher break Fast Keys, tokens, fair draws
TRNG (hardware noise) No seed — physical measurement No, but needs conditioning Slow Seeding, certified hardware

The tiers are not "bad, good, best" — they are different tools. The failure mode that matters for a lottery site is using tier 1 where tier 2 is required. Every fairness claim on this site is built on tier 2 randomness with the bias mathematically removed — the full construction is in how we built an unbiased generator, and how certifiers audit such systems is in certified RNGs and testing labs.

Try it yourself

Keep reading

Sources

Last verified: 2026-08-29