iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Random Numbers (CSPRNG)

Random number generation: when Math.random is fine and when it is dangerous. CSPRNGs in every major language, and how to test that your randomness is genuine.

Crypto — random number generation

EXAMPLE
# ===== Two kinds of random =====
# PRNG (Math.random, mt19937)
#   Deterministic given the seed. Fast. Predictable.
#   Use for: games, shuffles, simulations, fake data.
#
# CSPRNG (crypto.randomBytes, secrets.token_bytes, /dev/urandom)
#   Unpredictable to attackers without the seed.
#   Use for: tokens, session IDs, keys, salts, nonces, anything security-related.

# Mixing them up is the most common crypto bug in app code.

# ===== When you MUST use CSPRNG =====
# - Session tokens / cookies
# - Password reset / email verification tokens
# - API keys
# - Cryptographic keys + nonces
# - Salt for password hashing
# - CSRF tokens
# - Two-factor codes (TOTP secrets)
# - 'Random' URLs (signed S3 URLs, share links)

# ===== Per-language quick reference =====

# Node.js:
import { randomBytes, randomUUID, randomInt } from 'node:crypto';
randomBytes(32).toString('hex');     // 64-char hex token
randomUUID();                        // v4 UUID, CSPRNG-backed
randomInt(0, 100);                   // CSPRNG int

# Python:
import secrets
secrets.token_hex(32)                # CSPRNG hex
secrets.token_urlsafe(32)            # URL-safe base64
secrets.choice([1, 2, 3])

# Go:
import ("crypto/rand"; "encoding/hex")
b := make([]byte, 32); rand.Read(b); hex.EncodeToString(b)

# Rust:
use rand::rngs::OsRng;
use rand::RngCore;
let mut b = [0u8; 32]; OsRng.fill_bytes(&mut b);

# Java:
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] b = new byte[32]; sr.nextBytes(b);

# C#:
using System.Security.Cryptography;
var b = RandomNumberGenerator.GetBytes(32);

# Ruby:
require 'securerandom'
SecureRandom.hex(32)

# PHP:
random_bytes(32);          // CSPRNG, throws on failure
random_int(0, 100);

# ===== UUID notes =====
# v4 UUID is random; some libraries use CSPRNG, some PRNG. Verify.
# Node randomUUID, Python uuid.uuid4 (CSPRNG), Java UUID.randomUUID (CSPRNG since 6+)

# ===== Testing your randomness =====
# Quick distribution sanity check:
python -c "import secrets; print({i: 0 for i in range(10)} | {})"
# Use dieharder / TestU01 for serious testing if rolling your own RNG.

# ===== Patterns to internalise =====
# - Default to the CSPRNG; never Math.random for security
# - 32-byte tokens (256 bits) are the safe baseline for opaque IDs
# - randomBytes -> hex / base64url for display
# - Salts: at least 16 bytes, unique per record

# ===== Pitfalls =====
# - Math.random() for session IDs -> predictable; account takeover risk
# - Re-seeding a CSPRNG with predictable data -> reduces entropy
# - Using time + pid as a 'random' seed -> predictable
# - Generating tokens in a loop without re-seeding entropy on long-running daemons

Why it matters

Use the CSPRNG. Math.random is for games; tokens deserve crypto.randomBytes. Every modern language has a one-liner — randomBytes, secrets.token_hex, SecureRandom, RandomNumberGenerator. Pick 32 bytes as the safe default and never look back.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Use a CSPRNG. Never Math.random / rand for security.
// Node:    crypto.randomBytes(n) / crypto.randomUUID()
// Browser: crypto.getRandomValues(new Uint8Array(n))
// Python:  secrets.token_bytes(n)
// PHP:     random_bytes(n) / random_int(0, 100)
Try it Yourself »

Exercise

Node API for secure random bytes.

crypto. (32)

Test yourself

Q1. In Node, secure random bytes come from…
Q2. In the browser, use…
Q3. In Python, use…

Discussion

Loading…