Offered by Dead Brands
Why security randomness is a different substance from statistical randomness: CSPRNGs versus general-purpose PRNGs, where entropy actually comes from, how big tokens and UUIDs need to be, and the nonc
Use it over MCP: connect to https://mcp.deadbrands.co/hub/mcp and call skills_get with slug randomness-and-entropy.
# Randomness and Entropy Credit: SteTy — published free in the Skills Hub Why security randomness is a different substance from statistical randomness: CSPRNGs versus general-purpose PRNGs, where entropy actually comes from, how big tokens and UUIDs need to be, and the nonce/IV discipline whose violation has destroyed real systems (Sony's PS3 signing key, WEP, the 2008 Debian OpenSSL bug). Public, textbook-grade material (NIST SP 800-90, RFC 4086, RFC 9562) that any bot generating a token, key, ID, or nonce must internalize. ## Overview Almost every cryptographic failure involving "randomness" is really a predictability failure. A PRNG like JavaScript's `Math.random()`, Python's `random` module (Mersenne Twister), or Java's `java.util.Random` is designed for simulations and games: fast, statistically smooth, and fully deterministic from its seed. Observe a few outputs and the internal state can be reconstructed — V8's `Math.random()` state has been recovered from a handful of values, and Mersenne Twister state falls after 624 consecutive 32-bit outputs. A CSPRNG (cryptographically secure PRNG) is engineered so that no feasible computation predicts the next bit from previous outputs, and compromise of its current state doesn't expose past outputs. For anything security-shaped — keys, session tokens, reset links, nonces, salts, UUIDs that act as capabilities — only a CSPRNG is acceptable. ## Core Principles - **Entropy is the budget.** An n-bit value drawn uniformly from a CSPRNG carries n bits of entropy. 128 bits is the standard floor for tokens: brute-forcing 2^128 is physically infeasible. A long-looking token generated from a 32-bit seed still has only 32 bits of real entropy. - **Use the OS CSPRNG, via the right API.** Linux `getrandom(2)`/`/dev/urandom`; Windows `BCryptGenRandom`; Python `secrets` / `os.urandom`; Node `crypto.randomBytes`; browser `crypto.getRandomValues`; Java `SecureRandom`; Go `crypto/rand`. Never seed these yourself, never substitute a fast PRNG "temporarily." - **A nonce must be unique, not secret; a key must be both.** Nonces/IVs prevent identical plaintexts producing identical ciphertexts. Uniqueness per key is the requirement — secrecy is not, but predictability combined with reuse is still fatal in signature schemes. - **Never roll your own entropy collection.** Mouse-jitter and timestamp hashing schemes are how systems ship with effectively 16-bit keyspaces. ## Techniques - **Token sizing:** session tokens, API keys, password-reset tokens: ≥128 bits (16 bytes) from a CSPRNG; 256 bits is cheap insurance. Encode base64url (16 bytes → 22 chars) or hex (32 chars). Compare tokens in constant time (e.g., `hmac.compare_digest`, `crypto.timingSafeEqual`) to avoid timing oracles. - **UUIDs (RFC 9562):** - *v4* — 122 bits of CSPRNG randomness (6 bits are version/variant). Fine as an unguessable ID; sorts terribly as a database primary key. - *v7* — 48-bit Unix millisecond timestamp + 74 random bits. Time-ordered, B-tree friendly, leaks creation time. Prefer v7 for primary keys and anything humans sort by eye. - *v1* — embeds the host MAC address and timestamp; leaks when and (historically) where an ID was minted. Avoid in public URLs. - A UUID is an identifier, not automatically a credential — if it grants access, it must come from a CSPRNG (v4/v7 do, when the library uses the OS source; verify library defaults). - **Nonce/IV discipline by algorithm:** - *AES-GCM:* 96-bit nonce, unique per key. Random nonces are safe to roughly 2^32 messages per key (birthday bound); beyond that use a counter or rotate the key. Deterministic construction (fixed field + invocation counter) is the conservative choice. - *ChaCha20-Poly1305:* 96-bit nonce, same uniqueness rule; XChaCha20's 192-bit nonce makes random selection safe at any realistic volume. - *AES-CBC:* IV must be random *and unpredictable*, 128-bit, fresh per message. - *ECDSA:* the per-signature secret k must be unique and unpredictable — use deterministic RFC 6979 derivation, which removes the runtime RNG from the equation entirely. - **Rejection sampling:** when mapping random bytes to a smaller set (e.g., password characters), discard out-of-range bytes instead of using naive modulo, which biases the distribution. - **Entropy sources and health:** modern OSes seed their CSPRNG from hardware jitter, interrupt timing, and where available a hardware RNG (RDRAND, TPM). The danger window is early boot and cloned VM images — first-boot key generation on a cloned image has produced identical host keys across machines. Generate long-lived keys after boot entropy is established, and rotate keys on cloned images. ## Worked Examples - **Session token, done right:** `secrets.token_urlsafe(32)` → 256 bits of CSPRNG entropy, 43 characters. Done wrong: `random.random()` formatted as a "long decimal" — a Mersenne Twister output whose whole future sequence is recoverable. - **Debian OpenSSL, 2006–2008 (CVE-2008-0166):** a maintainer removed lines feeding uninitialized memory into OpenSSL's entropy pool to silence Valgrind warnings. The effective seed shrank to roughly the process ID — about 15–16 bits, ~32,767 possible values per key type/size. Every SSH key, TLS certificate, and OpenVPN key generated on Debian/Ubuntu in that window was enumerable and had to be blacklisted. Lesson: entropy code is the last place to "clean up" warnings you don't understand. - **Sony PS3, 2010:** Sony's ECDSA implementation used a *constant* k instead of a fresh random value per signature. With two signatures sharing k, the algebra (s₁ − s₂ = k⁻¹(m₁ − m₂)) solves for k, then for the private key itself. fail0verflow extracted Sony's root code-signing key; every PS3 ever made trusted it, and it could not be patched in software. - **WEP, 2001:** a 24-bit IV guaranteed repeats within hours on a busy network; repeated RC4 keystreams let attackers recover the key. Nonce space size is a security parameter, not a detail. ## Common Pitfalls - Using `Math.random()`, `random`, `rand()`, or `mt_rand()` for tokens, IDs, salts, or "temporary" secrets that ship. - Seeding any RNG with the current time, a PID, or a counter — all guessable. - Generating tokens client-side from a weak source and trusting their length as proof of entropy. - Reusing a GCM nonce after a process restart because the counter lived only in memory. - Truncating a strong token to 6 digits "for usability" without rate limiting (a 6-digit code has ~20 bits — it needs attempt throttling and expiry, like TOTP's). - Comparing secrets with `==`/`===` and leaking them byte-by-byte through timing. ## Practice Drills 1. Generate 1,000 "UUIDs" from a seeded general PRNG and from a CSPRNG; show that knowing the seed reproduces the PRNG set exactly, and that no seed exists for the other. 2. Compute the entropy of tokens you meet: length × log2(alphabet size) for strings, byte count × 8 for raw random — then check whether the generation method, not the format, is the real limit. 3. Write a GCM encrypt function that persists its nonce counter across restarts; then switch to XChaCha20-Poly1305 and justify the change. 4. Audit a sample codebase: grep for `Math.random`, `random.`, `rand(`, `uuid1`, `verify=False`; classify each hit as harmless or a finding. 5. Explain, in one paragraph each, why PS3, WEP, and Debian OpenSSL are the *same* root-cause failure wearing three costumes. ## When to Use and Limits - **Use it when:** a task calls for randomness and entropy, as laid out in the Techniques and Worked Examples above. - **Watch first for:** (see Common Pitfalls). - **Limits:** this is a general reference drawn from public sources; check exact values against the current standard or vendor docs before relying on them, and get expert review for production security decisions. ## Quick Reference - Security randomness APIs: Python `secrets`, Node `crypto.randomBytes`, Web `crypto.getRandomValues`, Java `SecureRandom`, Go `crypto/rand`. - Tokens/API keys/reset links: ≥128 bits CSPRNG (256 preferred), constant-time comparison. - UUID: v7 for sortable keys, v4 for pure unguessable IDs, never v1 in public. - AES-GCM: 96-bit nonce, unique per key; random nonces → rotate key before ~2^32 messages; or use XChaCha20 (192-bit nonce). - ECDSA nonces: deterministic per RFC 6979. - Forbidden for security: `Math.random`, Mersenne Twister, time/PID seeds, homegrown entropy. --- *Trademarks and copyrights mentioned belong to their respective owners. Educational reference only; not affiliated with or endorsed by them.*