Randomness in the browser

Basics

How crypto.getRandomValues differs from Math.random, why the latter must never make passwords, and how to check it yourself.

A password generator in a browser invites a reasonable doubt: where does the randomness come from, and is it rigged? The question is a fair one, and — unlike most claims about security — the answer can be checked.

Two different generators

The browser has two, and they must not be confused.

Math.random()crypto.getRandomValues
PurposeGames, animation, shuffling a listSecrets: passwords, keys, tokens
SourceAn internal algorithm in the browserThe operating system's generator
PredictabilityA few outputs reveal the restCannot be reconstructed from its outputs
Fit for a passwordNoYes
The difference is not visible “by eye”: both sequences look equally random. What differs is resistance to reconstruction.

Where the system gets randomness

The operating system collects unpredictable events: interrupt timings, noise from devices, a hardware source in the processor. From these it maintains a pool that is constantly stirred.

The browser invents nothing of its own — it simply asks the system for the number of bytes it needs. So the quality of the generator in a browser is the quality of your operating system's generator, not a separate property of the browser.

Why a simple modulo will not do

Suppose you need a character from an alphabet of 62 and the generator returns a byte from 0 to 255. Taking the remainder modulo 62 looks sensible — but 256 does not divide evenly by 62.

In the remainder, the first few values come up four times each while the rest come up three. The early characters of the alphabet start appearing more often, and the entropy ends up lower than calculated.

The fix is called rejection: values in the leftover “tail” that does not fit a whole number of alphabet repetitions are simply discarded and a new one requested. It is slower by fractions of a microsecond, and the distribution is exactly uniform. That is how the generator on this site works.

How to check it yourself

  1. Look at the page source

    The scripts are not minified beyond recognition: in the generator file you can see that the system source is what gets called.

  2. Open the Network tab in developer tools

    Generate a password and confirm there are no requests to the server. A password cannot leak to a place it is never sent.

  3. Turn off the internet and try again

    The most vivid check of all: the generator keeps working. Which means everything is computed in the browser.

Copied