Join our Newsletter — 33% off our NHI Course
Home› Guides› Random Number Generation and Entropy in Security Guide:…
Guide Data Security

Random Number Generation and Entropy in Security Guide: CSPRNGs and Common Failures

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 26 October 2026 17 min read
On this page

Every key, token, nonce, session ID and API key is only as strong as the random numbers that produced it, and weak randomness fails silently. A predictable generator does not crash or log an error: it produces values that look random but can be guessed, sometimes years later, by anyone who works out how they were made. Randomness in security means unpredictability to an attacker, which is a stricter property than "looks statistically random". This guide explains entropy, the difference between ordinary and cryptographically secure generators, the NIST SP 800-90 series, the operating system and language interfaces to use, how long tokens should be, and the failures that taught the industry these lessons. It is written for developers, security engineers and reviewers who generate or audit secrets.

Key takeaways

  • Use the operating system CSPRNG through a high-level API (secrets, crypto.randomBytes, SecureRandom, crypto/rand, RandomNumberGenerator) and never a general-purpose PRNG such as Math.random(), rand() or mt_rand() for anything security relevant.
  • Entropy is the scarce input, not the output: a well-seeded CSPRNG can produce unlimited secure output, but no amount of mixing can create entropy that was never collected.
  • On Linux, prefer getrandom() or /dev/urandom; the man pages advise against /dev/random and GRND_RANDOM except for long-term key generation.
  • Size secrets by bits of entropy, not characters: at least 128 bits for session IDs and tokens, 256 bits for long-lived API keys and secrets, encoded however you like.
  • The riskiest moment is first boot: embedded devices, cloned virtual machines and fresh containers that generate keys before the kernel pool is initialised have produced most of the large-scale real-world failures.

What randomness means in security

In plain terms, a random value is secure if an attacker who knows everything about the system except the secret seed still cannot predict it better than by guessing. Statistical tests can show that output is unbiased, but RFC 4086 is explicit that passing statistical tests does not prove unpredictability. A Mersenne Twister passes many statistical tests and is still fully predictable once an attacker has observed enough of its output.

  • Entropy: a measure of unpredictability, counted in bits. A value with 128 bits of entropy has 2128 equally likely possibilities. A 32-character hex string generated from a 32-bit seed still has only 32 bits of entropy.
  • Entropy source (noise source): a physical or system process that is genuinely unpredictable, such as thermal noise, ring oscillator jitter or interrupt timing. Output is usually biased and must be conditioned. NIST SP 800-90B covers how such sources are designed and validated.
  • PRNG: a deterministic algorithm that expands a seed into a long sequence. Fast and repeatable, which suits simulations, games and testing, but its internal state can often be recovered from outputs.
  • CSPRNG or DRBG: a deterministic generator built from a cryptographic primitive (hash, HMAC, block cipher or stream cipher) so that output cannot be predicted and past output cannot be reconstructed even if some output is seen. NIST calls these Deterministic Random Bit Generators (DRBGs) in SP 800-90A.
  • RBG: NIST's term for the whole construction: an entropy source feeding a DRBG, defined in SP 800-90C.
Generator typeExamplesPredictable from output?Use for
Non-cryptographic PRNGMersenne Twister (Python random, PHP mt_rand()), Java java.util.Random, C rand(), JavaScript Math.random()Yes, often after a modest number of outputsSimulation, sampling, games, test data only
CSPRNG / DRBGHash_DRBG, HMAC_DRBG, CTR_DRBG (SP 800-90A), ChaCha20-based kernel generatorsNo, if correctly seededKeys, nonces, IVs, tokens, salts, session IDs, passwords
Hardware entropy sourceCPU instructions, TPM RNG, HSM noise sourcesNo, but may be biased or failSeeding and reseeding a DRBG, rarely used raw
Full RBGOS kernel generator, FIPS-validated module RNGNoThe interface applications should call

The NIST SP 800-90 series and entropy sources

The NIST series is the reference model most validated cryptographic modules follow, and it splits the problem into three documents.

DocumentStatusWhat it covers
SP 800-90A Rev. 1Final, June 2015 (a Rev. 2 draft is listed by NIST)DRBG mechanisms based on hash functions or block ciphers: Hash_DRBG, HMAC_DRBG and CTR_DRBG. Rev. 1 is the version from which Dual_EC_DRBG was removed.
SP 800-90BFinal, January 2018 (NIST noted errata to fix in a future update)Design principles and requirements for entropy sources, health tests and the validation tests used to estimate min-entropy.
SP 800-90CFinal, 25 September 2025How to combine 90A DRBGs with 90B entropy sources into complete RBGs, with four constructions: RBG1, RBG2, RBG3 and RBGC.

RFC 4086 (BCP 106) gives the engineering view in plainer language: collect from several uncorrelated sources, mix them with a strong cryptographic function, and remember that mixing preserves entropy but never adds it. It singles out seeding from the system clock as a serious weakness, because an attacker who knows roughly when a generator started only has to try a small set of seeds. It also notes that a few hundred bits of real entropy is enough to seed a strong generator that then produces everything else.

  • Health tests matter: an entropy source that silently fails (a stuck hardware bit, a virtualised device returning zeros) must be detected. SP 800-90B requires continuous health tests for this reason.
  • Do not trust a single source: modern kernels mix CPU instructions, interrupt timing, device data and hypervisor-supplied seed material, so the failure or subversion of one input does not leave the pool empty.

Operating system interfaces

Applications should almost never implement their own generator. The kernel or platform cryptography library already runs a seeded, reseeding CSPRNG, and every major language wraps it.

PlatformInterfaceBehaviour to know
Linux (3.17+)getrandom(buf, len, 0)Uses the urandom source; blocks until the pool is initialised at boot, then never blocks. Requests up to 256 bytes always return in full once initialised. With GRND_NONBLOCK it fails with EAGAIN instead of blocking. Always check the return value.
Linux/dev/urandomNever blocks. Before the pool is initialised it can return output the man page describes as possibly low entropy and unsuitable for cryptography. Prefer getrandom() in new code.
Linux/dev/random, getrandom(..., GRND_RANDOM)The man page advises avoiding these except for long-term key generation: they can block and add partial-read complexity without a meaningful security gain.
WindowsBCryptGenRandom(NULL, buf, len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)CNG API; the default provider implements SP 800-90 CTR_DRBG. With the system-preferred flag the algorithm handle must be NULL. The BCRYPT_RNG_USE_ENTROPY_IN_BUFFER flag is ignored from Windows 8.
macOS, iOS, OpenBSDarc4random_buf(), SecRandomCopyBytesSystem CSPRNG; the old RC4-based name is historical.

The Linux man page also gives a useful sense of scale: a 3072-bit RSA key needs only around 16 bytes of seed material, and code that reads more than 256 bits per call, or per reseed interval, suggests the surrounding cryptography is not carefully implemented.

Language APIs: secure and insecure choices

The OWASP Cryptographic Storage Cheat Sheet lists the functions to avoid and to use. This is the table reviewers and static analysis rules should enforce.

LanguageNever for securityUse
Pythonrandom modulesecrets.token_bytes(), token_hex(), token_urlsafe(), secrets.choice(), secrets.SystemRandom
Node.jsMath.random()crypto.randomBytes(), crypto.randomInt(), crypto.randomUUID()
JavaMath.random(), java.util.Random, SplittableRandom, ThreadLocalRandomjava.security.SecureRandom, UUID.randomUUID()
.NET / C#System.RandomRandomNumberGenerator
Gomath/randcrypto/rand (rand.Read, rand.Text from Go 1.24)
PHPrand(), mt_rand(), lcg_value(), uniqid(), array_rand()random_bytes(), random_int(), Random\Engine\Secure (8.2)
Rubyrand(), RandomSecureRandom
C / C++rand(), random()getrandom(2), or the platform crypto library

Details that catch experienced developers

  • Java setSeed: the SecureRandom documentation says calling setSeed before the first nextBytes stops the generator seeding itself, so the caller's seed becomes the only entropy. A fixed or time-based seed there turns SecureRandom into a predictable generator. Use getInstanceStrong() only for high-value long-lived keys; it reads the securerandom.strongAlgorithms property and may block.
  • Python token length: the secrets default size (DEFAULT_ENTROPY) is documented as subject to change, and the docs say 32 bytes (256 bits) was considered sufficient as of 2015. Pass an explicit byte count so token length is a deliberate, reviewable choice.
  • Go: crypto/rand uses getrandom(2) on Linux, arc4random_buf on Apple platforms and ProcessPrng on Windows; the documentation states Read never returns an error and Text returns at least 128 bits of randomness.
  • UUIDs are not tokens by default: OWASP notes version 1 UUIDs combine a timestamp and MAC address and are not random, and version 4 randomness depends on the implementation. Use a CSPRNG token where unpredictability matters.
  • Modulo bias: random_bytes() % n skews results when n is not a power of two. Use the library's bounded function (secrets.randbelow, crypto.randomInt, random_int) to pick PINs, codes or characters.

How much randomness: tokens, keys and identifiers

Length guidance is about entropy, not string length. Encoding changes the number of characters (hex uses 2 per byte, base64url about 1.3) but not the strength.

ValueMinimum entropyBasisExample
Session ID64 bits minimum, 128 bits recommendedOWASP Session Management Cheat Sheet: at least 64 bits; a CSPRNG producing at least 128 bits if you build your ownsecrets.token_urlsafe(16)
Server-side stored token (reset link, refresh token, opaque access token)128 bits, 160 or more preferredOWASP Session Management Cheat Sheetcrypto.randomBytes(32)
Long-lived API key or client secret256 bitsPython secrets documentation (32 bytes) and the long exposure window of non-human credentials32 random bytes plus a recognisable prefix
Symmetric key (AES-256), HMAC keyFull key lengthKey strength equals entropyGenerate inside the KMS or HSM
IV or noncePer algorithm: unique, and random where the mode requires itMode specification (for GCM, uniqueness under a key is critical)Library-generated, never reused
Salt for password hashing128 bits is commonUniqueness per passwordGenerated by the hashing library

A recognisable prefix (for example a vendor or environment tag) is not entropy, and neither is a checksum suffix. They help secret scanners find leaked keys, which is useful, but the random portion alone must meet the target. See the API Key Management Guide and the Token and Session Security Guide.

Boot time, virtual machines and containers

The large real-world randomness failures cluster around the moment a system first starts. The "Mining your Ps and Qs" study by Heninger, Durumeric, Wustrow and Halderman found 5.57% of TLS hosts and 9.60% of SSH hosts sharing public keys in a vulnerable way, and recovered RSA private keys for 0.50% of TLS hosts because their keys shared prime factors. Almost all vulnerable hosts were headless embedded devices such as routers, firewalls and management cards that generated keys on first boot with few sources of randomness, across 54 manufacturers.

  • Do not generate keys at image build time: SSH host keys, TLS keys and machine identities baked into a golden image or container image are shared by every instance. Generate them on first boot, after the RNG is initialised, or issue them from a central PKI.
  • Cloned and restored VMs: snapshotting or cloning a running VM can duplicate the guest's generator state, so two clones may produce the same "random" values until they reseed. Prefer fresh boots from images over cloning running machines, and give guests a hypervisor entropy device (virtio-rng or the cloud provider's equivalent).
  • Containers share the host kernel RNG: that is good news for entropy, but user-space generators seeded once at process start (a forked worker pool, for example) can repeat state across forks unless the library reseeds after fork().
  • Use blocking semantics at boot: getrandom() without GRND_NONBLOCK waits until the pool is ready, which is exactly what first-boot key generation needs. Code that reads /dev/urandom early in boot does not get that guarantee.

Choosing the right source

  • OS CSPRNG vs a library DRBG: the OS interface is the default for almost all applications. A separate, validated DRBG is justified when a FIPS 140-3 boundary requires it; Go, for example, routes output through an SP 800-90A Rev. 1 DRBG in FIPS 140-3 mode.
  • OS CSPRNG vs HSM or KMS: generate long-lived, high-value keys (CA keys, signing keys, KMS root keys) inside the HSM or cloud KMS so the key never exists outside the boundary. Tokens and session IDs belong in the application using the OS generator.
  • Hardware RNG on a device: TPM or secure element output is a good input to the kernel pool, but ROCA showed hardware key generation can itself be flawed. Prefer designs where keys can be regenerated and rotated.
  • Small vs large organisations: a small team gets most of the value from a lint rule banning insecure APIs and a short standard for token lengths. A large organisation also needs an inventory of who generates keys where (devices, images, CI), FIPS module requirements and a tested key regeneration plan. See the Cryptographic Inventory and CBOM Guide.

Implementing and testing a randomness standard

  1. Write the standard: one page listing approved APIs per language (the table above), minimum entropy per value type, and the rule that keys are generated in KMS or HSM where available.
  2. Find existing use: search code for insecure calls (Math.random, java.util.Random, mt_rand, rand(, import random, math/rand, System.Random) and triage each by context: flag only those producing secrets, user-facing IDs or security decisions.
  3. Enable static analysis rules in warn mode: most SAST tools ship rules mapped to CWE-338 and CWE-330. Run them in report-only mode for a sprint to measure noise, then block on new findings in pull requests.
  4. Fix and rotate: replacing the generator does not fix values already issued. Invalidate sessions, reissue tokens and API keys, and regenerate keys produced by the weak code. Debian's DSA-1571 made the same point: upgrading the package was not enough, all affected key material had to be regenerated.
  5. Check build and boot pipelines: confirm no keys are generated during image builds, and that first-boot key generation waits for the RNG.
  6. Test: unit tests should assert token length and character set, and a review should confirm that tests mocking the RNG do not leak into production configuration.
  7. Roll back safely: enforcement is a CI rule, so rollback means switching it back to warn mode; never roll back by restoring an insecure generator.

Detection and measurement

  • Duplicate key detection: scan certificate inventories and SSH host key collections for identical public keys or shared RSA factors across hosts; duplicates point to image-baked keys or boot entropy problems.
  • Token collisions: any collision of a supposedly random token or ID in production logs is a strong signal of a broken or poorly seeded generator.

Metrics that show the programme is working:

  1. Number of open SAST findings for CWE-338 and CWE-330 in security-relevant code, trending to zero.
  2. Percentage of repositories with the insecure-RNG rule enforced in CI.
  3. Count of duplicate public keys found across the estate per quarter.
  4. Percentage of long-lived API keys and client secrets meeting the 256-bit standard (from the issuing system's metadata).
  5. Percentage of high-value keys generated inside a KMS or HSM rather than on application hosts.

Where identity fits

Non-human identities are where randomness matters most and is checked least. API keys, client secrets, webhook signing secrets, service account passwords and bootstrap tokens are generated by scripts, CI jobs and vendor platforms, often once, and then live for years. A key generated with a weak PRNG keeps its weakness for the whole of that life. Generate machine credentials through the secrets manager or platform, record which generator and length were used, and prefer short-lived credentials so a flawed batch can be replaced quickly. See the Secrets Management Guide.

Framework mapping

FrameworkReferenceRelevance
NIST SP 800-53 Rev. 5SC-12 Cryptographic Key Establishment and ManagementKey generation, including the quality of random input
NIST SP 800-53 Rev. 5SC-13 Cryptographic ProtectionUse of approved cryptography, including approved RBGs
NIST CSF 2.0PR.DS-01Protection of data at rest depends on keys generated with sufficient entropy
MITRE CWECWE-330 Use of Insufficiently Random Values; CWE-338 Use of Cryptographically Weak PRNGWeakness IDs used by SAST tools and CVE records
MITRE CAPECCAPEC-59 Session Credential Falsification through PredictionAttack pattern exploiting predictable session tokens (related to CWE-330 and CWE-331)
MITRE CAPECCAPEC-485 Signature Spoofing by Key RecreationRecreating private keys from weak generation, as with Debian 2008 and ROCA
MITRE CAPECCAPEC-112 Brute ForceLow-entropy secrets shrink the search space

Common failure patterns

  • Removing the entropy by accident: a Debian-specific change to OpenSSL, shipped from version 0.9.8c-1 in September 2006 and disclosed in DSA-1571 (CVE-2008-0166) on 13 May 2008, made the generator predictable. SSH, OpenVPN, DNSSEC and X.509 keys became guessable, and CWE lists it as producing only 65,536 unique keys. Every DSA key used on an affected system had to be treated as compromised, because DSA signatures leak the key when the per-signature random value is weak.
  • Trusting a generator that cannot be audited: after reports in September 2013, NIST removed Dual_EC_DRBG from its draft SP 800-90A Rev. 1 in April 2014, citing a lack of public confidence, and told users to move to the remaining three DRBGs and to ask vendors whether their modules used it. The lesson is to prefer simple, well-analysed constructions and to keep the ability to change them. See the Crypto-Agility Guide.
  • Flawed key generation in hardware: ROCA (CVE-2017-15361) was a flaw in an Infineon RSA library used in TPM firmware and other devices that produced RSA keys weak enough to make factoring practical; affected uses included BitLocker with TPM 1.2 and YubiKey 4 PGP key generation before 4.3.5. Hardware-generated keys still need an inventory and a regeneration path.
  • Keys generated at first boot with no entropy: the Ps and Qs research showed thousands of embedded devices with factorable or shared keys. Image-baked keys and cloned VMs repeat the pattern in cloud estates.
  • General-purpose PRNGs for tokens: CWE-338 cites a PHP framework using mt_rand() for tokens (CVE-2021-3692). Password reset tokens, invite codes and API keys built on non-cryptographic generators can be predicted from a few observed values.
  • Treating identifiers as secrets: version 1 UUIDs, timestamps, database sequence IDs and hashes of predictable inputs are unique but not unpredictable, and should never act as bearer credentials.

Practitioner checklist

  • Publish an approved-API list per language and ban Math.random, java.util.Random, mt_rand, rand() and Python random for security use.
  • Enforce the ban with SAST rules for CWE-338 and CWE-330, warn first, then block new findings.
  • Set minimum entropy: 128 bits for session IDs and tokens, 256 bits for long-lived API keys and secrets, full length for keys.
  • Use getrandom() (not /dev/random) on Linux and BCryptGenRandom with the system-preferred RNG on Windows in native code.
  • Never call SecureRandom.setSeed with a fixed or time-based value before first use.
  • Generate high-value keys inside a KMS or HSM; never at image build time.
  • Give virtual machines a hypervisor entropy device and avoid cloning running VMs that hold key material.
  • Scan certificate and SSH key inventories for duplicate public keys every quarter.
  • When a weak generator is found, rotate every secret it produced, not only the code.
  • Use bounded random functions to avoid modulo bias in codes and PINs.

Standards and references

Related NHI Mgmt Group resources: Cryptography Basics Guide · API Key Management Guide · Secrets Management Guide · Cryptographic Key Management Guide · Hashing Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 26 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.