Every password, encryption key, session token, and 2FA secret you rely on begins life as a string of random numbers. That's an awkward foundation, because computers are the least random objects humans have ever built: given the same inputs, a CPU produces the same outputs, every time, by design. "Random" on a deterministic machine has to be engineered, and the engineering splits into two very different tiers - Generators that merely look random, and generators that are unpredictable to an adversary. Confusing the two has broken real systems: lotteries, casinos, Bitcoin wallets, and an entire Linux distribution's cryptography. This article explains how each tier works, where the raw randomness actually comes from, and why the distinction decides whether your passwords are safe.
Two jobs that both get called "random"
The word "random" hides two different engineering requirements. A Monte Carlo simulation or a video game needs numbers that are statistically random - Evenly spread, uncorrelated, passing tests like the diehard suite - And it needs billions of them, fast. Whether an observer could predict the next one is irrelevant; nobody attacks a raindrop animation.
Security has the opposite priority. A password generator produces a few dozen values per use - Speed is irrelevant - But an attacker who can predict the next output, or reconstruct previous ones, gets your password without cracking anything. Statistical randomness is table stakes; the actual requirement is unpredictability against a motivated adversary who knows exactly which algorithm you're using.
Pseudorandom number generators (PRNGs) serve the first job. Cryptographically secure pseudorandom number generators (CSPRNGs) serve the second. Both are deterministic algorithms stretching a starting value - The seed - Into a long output stream. The difference is what happens when someone hostile studies that stream.
How an ordinary PRNG works - And how it's beaten
A classic PRNG is a small state machine. Take the Mersenne Twister, long the default in Python, PHP, and countless libraries: it holds an internal state of 624 32-bit words, and each output is a lightly-scrambled read from that state. It has a colossal period and excellent statistical behavior, which is why simulations love it.
It is also gloriously predictable. Observe 624 consecutive outputs and you can reconstruct the entire internal state with straightforward arithmetic - From there you can generate every future output and rewind past ones. Simpler generators fall even faster: a linear congruential generator (the old C rand()) can be solved from a handful of outputs. And if a developer seeds any PRNG with the current time - The classic srand(time(0)) - An attacker who knows roughly when a token was generated can brute-force the seed in seconds, because there are only a few million plausible timestamps.
These aren't theoretical parlor tricks. Researchers have cloned slot-machine PRNGs from filmed spins, predicted "random" lottery picks, and drained cryptocurrency wallets whose keys came from JavaScript's Math.random(). The pattern repeats: the algorithm's output looked perfectly random to its authors, and perfectly transparent to anyone who modeled its state.
What makes a CSPRNG different
A CSPRNG makes two additional promises, both defined against an attacker with full knowledge of the algorithm:
- Next-bit unpredictability. Given every bit produced so far, no feasible computation predicts the next bit meaningfully better than a coin flip.
- State-compromise resistance. If an attacker somehow captures the internal state, they still can't reconstruct the outputs that came before (and the generator can recover secrecy going forward by mixing in fresh entropy).
Designs achieving this are built from the same primitives as encryption itself - Typically a cipher or hash run in counter mode, like the ChaCha20-based generator inside the Linux kernel or the AES-CTR construction NIST standardizes in SP 800-90A. Breaking the generator's unpredictability would mean breaking the underlying cipher, the same math protecting the data (see AES-256 explained for how much safety margin that implies).
Every mainstream platform ships one: /dev/urandom and getrandom() on Linux, SecRandomCopyBytes on Apple platforms, BCryptGenRandom on Windows, crypto.getRandomValues() in browsers, and secrets in Python. The practical rule for developers fits in a sentence: if a human will ever depend on the value being secret, it must come from the platform CSPRNG - Never Math.random(), never rand(), never a homemade shuffle.
Where entropy actually comes from
A CSPRNG is still deterministic - Its unpredictability has to be imported from the physical world through its seed. Operating systems run an entropy pool for exactly this purpose, continuously stirring in measurements that no outside observer can reproduce: nanosecond-scale timing jitter between keystrokes, mouse movements, disk and network interrupts, and thermal noise. Modern CPUs add dedicated hardware - Intel and AMD's RDRAND/RDSEED instructions sample electrical noise from circuits designed to be metastable - And the kernel folds that in as one source among many rather than trusting it alone.
The pool's job is to accumulate enough genuine unpredictability - Measured in bits of entropy, the same unit used to score password strength in password entropy explained - To seed the CSPRNG beyond any attacker's ability to guess. Past roughly 256 bits of accumulated entropy, the generator can safely produce output forever; the danger zone is early boot on freshly-imaged devices, when routers and IoT gadgets have seen almost no events to measure. Research scanning the internet has repeatedly found embedded devices sharing RSA keys because they all generated them in that entropy-starved first second of life.
A perfect algorithm seeded with a guessable value is a guessable system. Randomness quality is decided at the seed, not in the math that stretches it.
The hall of shame: when randomness failed
The catastrophic failures in this field were almost never broken ciphers - They were broken randomness feeding perfect ciphers.
| Incident | What went wrong | Consequence |
|---|---|---|
| Debian OpenSSL (2006–2008) | A patch accidentally gutted the entropy seeding, leaving ~32,767 possible states | Every SSH and SSL key generated on Debian systems for two years was enumerable |
| Dual_EC_DRBG (2007–2014) | NIST-standardized CSPRNG with constants widely believed to hide an NSA backdoor | Whoever held the trapdoor could predict output; RSA Security had shipped it as a default |
| Android SecureRandom flaw (2013) | Improper seeding on some Android versions produced repeated values | Bitcoin wallets computed duplicate signature nonces; funds were stolen from live wallets |
| Time-seeded generators (perennial) | srand(time(0)) and cousins in web apps and games |
Password-reset tokens and "random" draws brute-forced from timestamps |
| Entropy-starved embedded devices (2012 study) | Keys generated at first boot with nearly empty entropy pools | Tens of thousands of routers and devices found sharing or factoring-related RSA keys |
Two lessons repeat. First, randomness failures are silent: the Debian bug shipped for two years because weak keys look exactly like strong keys. Second, the blast radius is total - An attacker who can regenerate your randomness doesn't bypass your security so much as become you.
What this means for your passwords
For anyone who isn't writing cryptographic code, the practice reduces to a few habits.
Let a CSPRNG-backed tool pick your secrets. Our password generator draws every character from crypto.getRandomValues() - The browser's CSPRNG - Locally on your device; the same source drives the site's UUID generator and its other token tools. The full pipeline from random bits to characters is walked through in how random password generators work.
Never generate secrets with your head or your keyboard. Humans are miserable entropy sources: asked to "type randomly," we alternate hands, favor home-row keys, and produce patterns crackers model explicitly. Keyboard-mash passwords score far below their length suggests.
Judge dice as hardware randomness. Physical dice are a legitimate TRNG, which is why Diceware passphrases are respected practice - Five honest dice rolls per word yields exactly 12.9 bits each, no software trust required. A passphrase generator reproduces the scheme with the CSPRNG doing the rolling.
Be suspicious of "random" in unmaintained software. Old forum software, hobby projects, and legacy embedded gear are where time-seeded tokens and Math.random() session IDs still live. Password-reset links from such systems are the weak point, not your password. Sites also depend on server-side randomness for the salts that protect stored passwords - A story told in salts and peppers - So a platform's RNG hygiene quietly shapes how survivable its next breach is.
FAQ
What's the practical difference between a PRNG and a CSPRNG?
A PRNG produces statistically random-looking numbers fast, but its future output can be computed from its past output or its seed. A CSPRNG guarantees that even an attacker who knows the algorithm and has watched its output can't predict the next bit. Simulations and games want PRNGs; passwords, keys, and tokens must use CSPRNGs.
Is /dev/urandom safe for generating keys and passwords?
Yes - On any modern OS, /dev/urandom (or better, the getrandom() call) is the correct, CSPRNG-backed source once the system has been seeded. The old advice to prefer blocking /dev/random reflects a decades-old design that current kernels have replaced. The only genuine caveat is generating keys in the first moments of a freshly-imaged embedded device's first boot.
Can true randomness exist on a computer at all?
Deterministic circuits can't create it, but computers can measure physical randomness: thermal and electrical noise, interrupt timing jitter, and dedicated hardware like RDSEED. Operating systems mix many such sources into an entropy pool and use it to seed a CSPRNG, which then stretches those genuinely random bits into unlimited safe output.
Are online password generators trustworthy, given all this?
The design to look for is client-side generation from the browser's crypto.getRandomValues(), which runs a CSPRNG on your own device - The site never sees the result. That's how our generator works. Be wary of any tool that generates secrets on a server, uses Math.random(), or has no stated source of randomness at all.
Why do keyboard-mashed passwords fail if they feel random?
Human motor patterns are heavily biased: alternating hands, home-row clustering, and repeated trigrams appear at rates cracking tools model directly. A mashed 12-character string can carry fewer effective entropy bits than a truly random 8-character one. Randomness you can feel yourself producing is randomness an algorithm can predict.