HomeGuides › Secure random values

How to generate secure random values

API keys, session tokens, salts and nonces all need randomness that cannot be predicted — which is not the same as randomness that looks messy.

There are two kinds of random number generator, and mixing them up is a classic and serious mistake. An ordinary one is built for speed and statistical spread — fine for shuffling a playlist. A cryptographic one is built so that seeing past output tells an attacker nothing about future output.

Anything that has to be unguessable — a password reset token, an API key, a salt, a nonce — needs the second kind. This tool uses crypto.getRandomValues() and nothing else.

What you can generate

Why ranges are harder than they look

The obvious way to get a number from 0 to 9 is to take a random byte and use the remainder after dividing by 10. It is also subtly wrong. A byte holds 0–255; 256 does not divide by 10. Values 0–5 come up 26 times each across the range and 6–9 only 25, so the low digits are about four per cent more likely. For a dice roll, irrelevant. For anything an attacker is trying to guess, a real bias.

The fix is rejection sampling: draw, and if the value falls in the uneven tail, throw it away and draw again. Slightly slower, exactly uniform. That is what this tool does, and it is why the page says "unbiased" rather than "random".

How much randomness

For a token that must not be guessable, 16 bytes (128 bits) is the usual floor and 32 bytes (256 bits) is a comfortable answer. There is no benefit to going much beyond that, and no excuse for going below it.

Frequently asked questions

Is this suitable for production secrets?

The values come from the same cryptographic generator your browser uses for TLS, so they are suitable in quality. Whether you want to generate a production secret by pasting it out of a web page is a separate question about your own handling — for automated systems, generate secrets on the machine that will use them.

Are the values sent anywhere?

No. Everything is generated locally and nothing is transmitted.

What is wrong with using a remainder for a range?

Unless the range divides the size of the source exactly, some values come up more often than others. The tool uses rejection sampling to avoid it, which costs a negligible amount of time and removes the bias entirely.

Open the random generator →