Skip to content

Good Randomness

CSPRNG · seeds · why a guessable key is no key

See why looking random is not enough. Compare a key generated by the browser with one generated from a four-digit PIN. Both pass the same checks. Try all 10,000 PINs to recover the predictable key.

Start here

Two programs make a secret key — the value a program uses to lock and unlock a message. Both keys look like nonsense. You are going to find out why a stranger can still read one of the two messages.

Real cryptography, running in your browser. Nothing is sent anywhere and nothing is stored.

What is real here, and what this demo is not

Both sources are real. The unguessable one is crypto.getRandomValues, the Web Cryptography API's own random source — the same one your browser uses to make its own keys. The predictable one is ChaCha20, the stream cipher in TLS 1.3 and WireGuard, implemented in this repository and checked against the published test vectors in RFC 8439. It is given a bad starting point on purpose.

A toy generator would have been easier to write and would have taught the wrong thing: you would have concluded that the generator was the problem, and walked away believing a respectable algorithm would have saved you. The lesson is the seed, not the algorithm.

Not production code. One thing here is deliberately not what a working system does: the predictable generator's starting point is a four-digit PIN, and its nonce is fixed at zero. Both choices are made so the recovery in Step 3 is something you can watch happen in under a second. A real system gets its starting point from the operating system, which is the fix — and the page says so rather than leaving you to infer it.

There is no entropy figure anywhere on this page and no test battery. Guessability is counted in tries, because that is the number a person can hold. If you want the measurement layer instead, that is Noise to Numbers.

Step 1 Dice, then a computer

Start with the one random source everybody already trusts, then ask what a computer does instead.

Roll some dice

Five dice. You cannot work out the next five from these, and neither can anybody else.

Now a computer, following a recipe

Give a program a word to start from, and watch what happens when you ask it twice.

Predict first — optional

A word, a date, your name. This is what the generator starts from, and it is the only thing it starts from.

Step 2 Two keys. Tell them apart.

Two keys, 32 bytes each — the same length, so neither has any advantage there. One comes from the browser's own random source; one comes from the Step 1 generator, whose starting point is a 4-digit PIN. Then the checks you would think to apply, applied to both.

Predict first — optional

Do those checks do anything at all?

A fair question. Here are the same four checks, run over a generator with a pattern you could see across a room.

Step 3 Guess the seed, take the key

The page has encrypted the same short message twice — once under each key. Only the encrypted bytes are handed to what happens below: not the keys, not the PIN, not the message.

Your guess first

Every attempt, yours or the computer's, is the same four steps: guess a PIN → rebuild the key that PIN produces → try to open the encrypted message → rejected, or opened. Nothing is compared against the real key; the message's own integrity check is what says whether a candidate worked.

Step 2's generator was started at one of these 4 PINs, picked without telling you which. Pick one and watch a single attempt go through those four steps.

Which PIN was it?

Now stop guessing

Predict first — optional

Guessing from a list of 4 was a warm-up: it showed you one attempt, and a real stranger is not handed a four-item list. What they are handed is the shape of the starting point — four digits — and there are 10,000 of those, counting the ones that begin with a zero. The page will try every one against the encrypted message and count out loud.

What this does, and does not, tell you

What each observation about a generator does and does not establish
What you can see What it establishes What it does NOT establish
The output looks random There is no pattern a check of the bytes can find Anything at all about how many keys could have been produced
The key is 256 bits long A ceiling: no more than 2256 values are possible How many were actually reachable — here, ten thousand
The algorithm is a respected one The arithmetic turning the seed into output is sound Where the seed came from, which is the whole question
The seed was hashed first The seed was spread evenly across the output Any increase in the number of possible seeds

Where this has really happened

Real TLS and SSH hosts have shipped duplicate and guessable keys, with no flaw in the cryptography and nothing visibly wrong in the keys themselves — the generators simply had too little to start from. That is the same failure as the one on this page, at the scale of the internet. Entropy Collapse is the lab that shows it.

Four questions

No score, and nothing is recorded. If one of these is awkward, the explanation is the point.

How this demo checks its own results

Everything above is this page agreeing with itself, which is not worth much alone: a build that got the cipher wrong would produce output that passed every check in Step 2. So the lab also runs a fixed set of cases published by somebody else, in your browser, on arrival.