Why Random Number Generators Aren't Always Random
Miscellaneous - 6 min read - Published 2026-09-06
Computers are deterministic machines - the same instructions given the same inputs always produce the same output. That makes "generate a random number" a strange request in a literal sense, and how software actually handles it reveals two genuinely different kinds of randomness with very different guarantees.
Pseudo-Random: Fast, Deterministic, Predictable in Principle
Most everyday randomness - shuffling a playlist, rolling a dice in a simple game, JavaScript's Math.random() - comes from a pseudo-random number generator (PRNG). A PRNG starts from a "seed" value and runs it through a deterministic mathematical formula to produce a sequence of numbers that looks statistically random (passes tests for randomness) but is entirely reproducible if you know the seed and the formula. This is by design: PRNGs are built for speed and statistical distribution, not unpredictability against someone deliberately trying to guess or reconstruct the sequence.
Cryptographically Secure: Slower, But Actually Unpredictable
A cryptographically secure pseudo-random number generator (CSPRNG) is built for a different goal entirely: even someone who knows the algorithm and has seen previous outputs should not be able to predict the next one. CSPRNGs draw their initial randomness from genuinely unpredictable physical sources the operating system collects - tiny variations in hardware timing, mouse movement, disk activity - making the sequence's starting point itself unpredictable, not just the formula that extends it.
Why the Difference Actually Matters
For a dice roll in a casual game, a predictable-in-principle PRNG is completely fine - nobody's incentive structure involves reverse-engineering your game's random seed. But the exact same PRNG used to generate a password, an encryption key, or a session token creates a genuine vulnerability: if an attacker can determine or narrow down the seed (sometimes surprisingly feasible, since many PRNGs seed from something as guessable as the current time), they can predict supposedly-random security values, defeating the whole point of using randomness for security in the first place.
How to Tell Which One You're Using
In a browser, `Math.random()` is a plain PRNG - fine for games, dice, and shuffling, never appropriate for anything security-related. `crypto.getRandomValues()` (part of the Web Crypto API) is a real CSPRNG, backed by the operating system's secure randomness source, and is what any password generator, key generator, or token generator should be using under the hood.