← All Tools

Math.random() vs crypto.getRandomValues() — How to Calculate Password Entropy

Guide · Last verified Aug 28, 2026

There are two ways to generate a "random string" in a browser: Math.random() and crypto.getRandomValues(). Both look like they produce the same kind of unpredictable output, but for anything security-sensitive — passwords, API keys — the difference between them matters a great deal.

1. The fundamental difference between the two APIs

Math.random() uses the JS engine's internal pseudorandom number generator (PRNG). It's fast, and it's perfectly fine for game shuffles, UI animation, or random sampling. But this PRNG was never designed to be unpredictable — several security studies have shown that if you know (or can reconstruct) its internal state, or you observe enough of its output, you can in theory work backward to predict future values. That's why official documentation, including MDN, explicitly warns against using Math.random() anywhere security matters.

crypto.getRandomValues(), on the other hand, is part of the Web Crypto API and draws from the operating system's cryptographically secure pseudorandom number generator (CSPRNG). Because it's seeded from real hardware entropy sources (mouse movement, timing jitter, dedicated random-number hardware, and the like), it's designed so that no amount of observed output lets you predict the next value. This is the one you must use when generating tokens, passwords, or encryption keys.

How this tool actually implements it: checking the source code of the Random String Generator confirms it uses crypto.getRandomValues(arr). It's built the correct (secure) way rather than with Math.random(), so strings it generates are safe to use as passwords or API keys.

2. What entropy is, and how to calculate it

A password's "strength" is commonly expressed as a value called entropy. The formula is simple.

Entropy (bits) = log₂(charset size) × string length

For example, with uppercase + lowercase letters + digits (62 characters: 26 a-z + 26 A-Z + 10 0-9), each character carries log₂(62) ≈ 5.95 bits of entropy. To hit the widely used practical security benchmark of "128-bit entropy" (considered comfortably resistant to brute-force attacks for the foreseeable future), you'd need:

128 ÷ 5.95 ≈ 21.5 → at least 22 characters.

3. Charset size changes how many characters you need

CharsetSizeEntropy per characterLength needed for 128 bits
Lowercase only (a-z)26≈4.7 bits≈28 chars
Upper + lower + digits62≈5.95 bits≈22 chars
Upper + lower + digits + symbols≈94≈6.55 bits≈20 chars

Adding special characters enlarges the charset, which raises the entropy per character, so you can hit the same security level with a shorter string. Conversely, sticking to lowercase-only means you need a much longer string to reach the same 128 bits.

4. Practical guidance

Frequently Asked Questions

Q. Has Math.random() actually been broken in practice?

A. Yes. Multiple security studies have reconstructed the internal state of specific JS engines' Math.random() from enough observed output samples and predicted subsequent outputs. The real-world difficulty of such an attack varies by situation, but since the API was never designed to guarantee unpredictability in the first place, it isn't recommended for security purposes.

Q. Does crypto.getRandomValues() work in every browser?

A. Yes — the Web Crypto API is a standard supported by every modern browser (Chrome, Firefox, Safari, Edge). It's available over HTTPS (or on localhost).

Q. Are there cases where you'd want more than 128 bits of entropy?

A. Long-lived master keys or highly sensitive encryption keys sometimes call for 256 bits. But for ordinary passwords, session tokens, and API keys, 128 bits is widely accepted as a practically sufficient standard.

Q. What's the actual entropy of the 32-character strings this tool generates?

A. With the 62-character upper+lower+digit set at 32 characters, that's 32 × 5.95 ≈ 190 bits — comfortably above the 128-bit benchmark.