# What is a CSPRNG (secure random number generator)?

> A CSPRNG produces random values that can't be predicted even by someone who has seen earlier output. Which APIs to use for secrets, and which ones never to use.

URL: https://crunu.com/learn/csprng
Language: en
Updated: 2026-10-30

A cryptographically secure random number generator (CSPRNG) is a source of random values designed so that nobody, even after seeing any amount of its earlier output, can predict the next value or work backwards to previous ones better than by guessing, which makes it suitable for generating keys, tokens and passwords.

## Why ordinary randomness isn't enough

Most programming languages have two kinds of random function. One is fast and statistically even, meant for simulations, games and shuffling; its output can often be predicted from a few earlier values. The other is built for security. MDN marks the difference for JavaScript: `Math.random` is "a non-cryptographic source of random numbers", while `crypto.getRandomValues()` "lets you get cryptographically strong random values" ([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)).

A secret generated with the wrong one may look random and still be guessable. Unlike a weak password, nothing warns you.

## How a CSPRNG works

Real randomness from hardware events is slow and limited, so systems collect it, mix it into a seed and expand that seed with a cryptographic algorithm. MDN describes browsers the same way: implementations use "a pseudo-random number generator seeded with a value with enough entropy", and the algorithm "may vary across user agents, but is suitable for cryptographic purposes." The quality of the result depends on the seed's [entropy](https://crunu.com/learn/entropy) and on the algorithm resisting prediction.

## Which APIs to use

- **Browsers:** `crypto.getRandomValues()`. MDN also advises preferring `generateKey()` when the goal is a cryptographic key.
- **Node.js:** `crypto.randomBytes()`, which "generates cryptographically strong pseudorandom data" ([Node.js](https://nodejs.org/api/crypto.html)).
- **Python:** the `secrets` module, which "should be used in preference to the default pseudo-random number generator in the `random` module, which is designed for modelling and simulation, not security or cryptography" ([Python](https://docs.python.org/3/library/secrets.html)).
- **The command line:** `openssl rand -base64 32` prints 32 random bytes, 256 bits, from OpenSSL's CSPRNG ([OpenSSL](https://docs.openssl.org/3.0/man1/openssl-rand/)).

## Common mistakes

- **`Math.random()` or a language's default `rand`** for tokens, reset codes or keys.
- **Biased conversion.** Turning random bytes into characters with `byte % alphabetSize` makes some characters more likely unless the alphabet size divides 256. The fix is to discard bytes from the uneven tail and draw again.
- **Too few bytes.** A random 6-character string isn't a strong secret, however good the generator. See [entropy](https://crunu.com/learn/entropy).
- **Seeding by hand.** Seeding a generator with the time or a process ID throws away the protection.

## Where Crunu uses it

The **Generate** button in Crunu's environment editor creates a 40-character value of letters and digits from `crypto.getRandomValues()` in your browser. It discards bytes that would bias the result, so every character is equally likely, which gives about 238 bits. The value is created on your device and saved encrypted like any other value; the server never sees it in plain form.

*Figure: A new variable row in the payments-api production table. The name CHECKOUT_SIGNING_KEY is typed, and the Generate button has just filled the value with a random 40-character string of letters and digits, so nobody has to invent a secret. Add and Cancel finish the row.*

For values you need outside the vault, such as a framework's signing secret, the free [secret key generator](https://crunu.com/tools/secret-generator) works the same way in your browser and offers Base64, Base64URL, hex or letters and digits from 128 to 512 bits. More on handling the result: [how to share .env files with your team](https://crunu.com/guides/share-env-files-with-a-team).

## Sources

- [MDN Web Docs: Crypto.getRandomValues()](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues), checked October 30, 2026.
- [Node.js: Crypto](https://nodejs.org/api/crypto.html), checked October 30, 2026.
- [Python: secrets](https://docs.python.org/3/library/secrets.html), checked October 30, 2026.
- [OpenSSL: openssl-rand](https://docs.openssl.org/3.0/man1/openssl-rand/), checked October 30, 2026.
