Random Number Generation Explained
A practical guide to random number generation covering PRNGs, CSPRNGs, entropy, seeds, random integers and decimals, security-sensitive applications and common implementation mistakes.
Random numbers are used in far more places than games and simulations. Modern applications rely on random values for session identifiers, API keys, password-reset tokens, cryptographic operations, randomized algorithms, testing, sampling, simulations and many other tasks.
However, not every kind of randomness is suitable for every purpose. A random number generated for a game does not necessarily need the same properties as a random value used as an authentication token. In security-sensitive applications, the distinction between ordinary pseudo-randomness and cryptographically secure randomness is critical.
This guide explains how random number generation works, what pseudo-random number generators and cryptographically secure random number generators are, why seeds matter, what entropy means and how to choose an appropriate random source for a particular task.
What Is a Random Number?
A random number is a value produced according to some probability distribution where the outcome cannot be reliably determined in advance from the information available to the observer.
In practice, software cannot simply ask a computer to produce a mathematically perfect random number from nothing. Instead, random-number systems use algorithms, internal state and, in some cases, physical sources of unpredictable environmental data.
The exact meaning of random therefore depends on the application. A simulation may require values that follow a particular statistical distribution. A game may need unpredictable outcomes from the player's perspective. A security system may require values that an attacker cannot feasibly predict.
True Randomness vs Pseudo-Randomness
Random number generation is commonly divided into two broad categories: true or physical randomness and pseudo-random number generation.
| Type | Basic idea | Typical use |
|---|---|---|
| Physical randomness | Uses measurements of physical phenomena | Entropy sources and specialized hardware |
| PRNG | Uses a deterministic algorithm and internal state | Games, simulations, testing and randomized algorithms |
| CSPRNG | Uses cryptographic algorithms and unpredictable system entropy | Tokens, keys, sessions and security-sensitive values |
A CSPRNG is still algorithmic and therefore deterministic internally, but it is designed so that its outputs remain computationally unpredictable without access to the generator's internal state and required secret information.
What Is a PRNG?
PRNG stands for Pseudo-Random Number Generator. A PRNG is an algorithm that produces a sequence of values that appears random according to relevant statistical properties.
seed → PRNG state → value → updated state → value → updated stateThe important word is pseudo. Given the same initial state or seed and the same algorithm, a deterministic PRNG can produce the same sequence again.
This property is extremely useful. Reproducibility is often desirable in simulations, automated tests and debugging because developers can recreate the same sequence of values.
Why PRNGs Are Useful
- They are usually fast.
- They can generate very large numbers of values.
- Their sequences can be reproducible.
- They are useful for simulations and randomized algorithms.
- They can provide good statistical distributions.
A good PRNG is not automatically a bad generator. It is simply designed for a different problem than a cryptographically secure generator.
Why Ordinary PRNGs Should Not Be Used for Security
Many ordinary PRNGs are designed around speed and statistical quality rather than resistance to prediction attacks. If an attacker can observe enough output or infer the generator's state, future values may become predictable.
const value = Math.random();JavaScript's Math.random() is intended for general-purpose pseudo-random values, not for generating secrets. It should not be used for password-reset tokens, session identifiers, API keys, authentication challenges or cryptographic keys.
What Is a CSPRNG?
CSPRNG stands for Cryptographically Secure Pseudo-Random Number Generator. A CSPRNG is designed to produce output that is computationally difficult to predict even when an attacker knows the algorithm and may have observed previous outputs.
Modern operating systems provide cryptographic randomness facilities that applications can access through standard APIs. These systems collect entropy from multiple sources and use cryptographic algorithms to generate random-looking output.
The application normally does not need to implement the underlying generator itself. Using the operating system or runtime's established cryptographic random API is generally safer than designing a custom random algorithm.
JavaScript Secure Randomness
Web applications can use the Web Crypto API to obtain cryptographically strong random values.
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);The returned bytes can then be encoded into hexadecimal, Base64url or another suitable representation depending on how the value will be stored or transmitted.
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);
const token = Array.from(bytes, byte =>
byte.toString(16).padStart(2, "0")
).join("");For security-sensitive applications, using the platform's established cryptographic APIs is preferable to implementing a custom PRNG.
Node.js Secure Randomness
Node.js provides cryptographic random functionality through its crypto APIs.
import { randomBytes } from "node:crypto";
const token = randomBytes(32).toString("hex");This approach produces a cryptographically strong random byte sequence suitable for many security-sensitive token-generation tasks.
What Is Entropy?
Entropy is a measure of uncertainty. In the context of random-number generation, more entropy generally means that there are more possible unpredictable outcomes available to the system.
For a uniformly distributed random value with N equally likely possibilities, the information content can be expressed as log₂(N) bits.
For example, a single uniformly random bit has two possible outcomes, 0 and 1, corresponding to one bit of entropy. Four independent random bits can represent 16 equally likely combinations and therefore provide four bits of entropy.
1 bit → 2 possible values
2 bits → 4 possible values
4 bits → 16 possible values
8 bits → 256 possible valuesEntropy Is Not the Same as Length
A long string is not necessarily highly random. If its contents are predictable, the string may contain very little effective entropy despite having many characters.
20260929153000000000000000000000The value above is long, but much of it may be predictable if it represents a timestamp followed by fixed characters. A shorter value generated from a strong random source can contain significantly more useful entropy.
Alphabet Size and Random Strings
When random numbers are encoded as strings, the alphabet affects how much information each character can represent.
| Alphabet | Approximate information per character |
|---|---|
| Binary | 1 bit |
| Hexadecimal | 4 bits |
| Base32 | 5 bits |
| Base64 | 6 bits |
| 62-character alphanumeric alphabet | About 5.95 bits |
This is why a 32-character hexadecimal string and a 32-character alphanumeric string do not represent the same number of possible values.
What Is a Seed?
A seed is an initial value used to initialize the state of a deterministic pseudo-random number generator.
seed → deterministic sequence of pseudo-random valuesIf the same PRNG algorithm receives the same seed and starts from the same state, it can produce the same sequence. This makes seeds extremely useful for reproducible simulations and tests.
Why Reproducible Randomness Is Useful
Suppose a simulation produces a rare bug after generating thousands of random events. If the random sequence can be reproduced from a known seed, developers can rerun the simulation and investigate the same sequence of events.
The same technique is useful in testing machine-learning experiments, procedural generation, game development and statistical simulations.
const rng = createSeededGenerator(12345);
const first = rng();
const second = rng();
const third = rng();The exact seeded-generator API varies by library. The important concept is that the seed makes the pseudo-random sequence reproducible.
Why Predictable Seeds Are Dangerous
A predictable seed can make an otherwise complicated pseudo-random sequence predictable. Using the current time, process ID or another easily guessed value as the seed is therefore inappropriate for security-sensitive random values.
Random Integer Generation
Many applications need a random integer within a range rather than a raw random byte sequence.
const min = 1;
const max = 100;
const value =
Math.floor(Math.random() * (max - min + 1)) + min;This pattern is useful for ordinary non-security-sensitive applications, but it should not be used when the generated value controls authentication, authorization, secrets or other security-sensitive behavior.
Random Integer Bias
Generating a random integer in a range requires more care than simply taking a random byte and applying a remainder operation. If the source space is not evenly divisible by the target range, some results can become more likely than others.
const value = randomByte % 10;If randomByte can contain 256 equally likely values, 256 is not evenly divisible by 10. Some digits would therefore occur more frequently than others.
A secure range generator can solve this problem using rejection sampling: values outside an evenly divisible portion of the source range are discarded and regenerated.
Cryptographically Secure Random Integers
Modern runtimes provide APIs or libraries that can generate secure random integers within ranges without requiring developers to implement rejection sampling manually.
When the integer affects security decisions, use a well-tested cryptographic API rather than adapting an ordinary Math.random() formula.
Random Decimal Numbers
Random decimal values are commonly used in simulations, visualization, testing and other applications where continuous-looking values are useful.
const value = Math.random();This produces a pseudo-random floating-point value according to the runtime's implementation. For ordinary simulation or UI purposes, this can be perfectly appropriate.
For security-sensitive applications, however, do not assume that a random-looking decimal is suitable simply because it came from a random function. Use an appropriate cryptographic API when unpredictability matters.
Uniform Distribution
A uniform distribution means that outcomes within the defined range have equal probability, subject to the precision and representation of the generator.
Uniform randomness is useful for many tasks, but not every application needs a uniform distribution. Scientific simulations and statistical models often require distributions such as normal, exponential or Poisson.
Random Numbers From Other Distributions
A PRNG usually produces values from a base distribution, often uniform. Algorithms can then transform those values into other statistical distributions.
| Distribution | Example use |
|---|---|
| Uniform | Random selection and general simulation |
| Normal | Statistical models and simulations |
| Exponential | Waiting-time models |
| Poisson | Event-count simulations |
Randomness in Games
Games commonly use pseudo-random number generators because performance and reproducibility can be more important than cryptographic unpredictability.
A game may use a seeded PRNG so that the same game state produces the same sequence of events. This can be useful for replays, deterministic simulations and debugging.
If the random outcome has real-world monetary value or can be exploited to gain an advantage, the requirements may be substantially different and cryptographically secure randomness may become important.
Randomness in Simulations
Scientific and engineering simulations frequently need reproducible pseudo-random sequences. Researchers can store the seed and rerun the same experiment later.
This is one reason PRNGs remain important despite the existence of cryptographically secure generators. Security is not always the primary requirement.
Randomness in Testing
Randomized tests can explore a much larger set of inputs than a small collection of manually written test cases.
const input = generateRandomTestData();
expect(processInput(input)).toSatisfyTheContract();For reliable debugging, randomized tests should usually record the seed or generated input so a failing case can be reproduced.
Randomness in Cryptography
Cryptographic systems rely heavily on unpredictable random values. Keys, nonces, initialization values, salts, challenges and tokens can all depend on secure randomness.
A weakness in random-number generation can undermine an otherwise mathematically sound cryptographic system. Historically, failures in entropy collection or predictable random generators have resulted in serious security vulnerabilities.
Randomness for Password Reset Tokens
Password-reset links commonly contain a random token that proves possession of a previously issued recovery capability.
https://example.com/reset?token=RANDOM_SECRET_VALUESuch tokens should be generated using cryptographically secure randomness and should expire after a limited period. They should also be invalidated after successful use when the application design permits it.
Randomness for Session IDs
Session identifiers are bearer credentials in many web applications. If an attacker can guess a valid session ID, they may be able to impersonate the associated user.
For this reason, session identifiers should use a cryptographically secure random source and sufficient entropy. A predictable PRNG or timestamp-based value is inappropriate.
Randomness for API Keys
API keys should also be generated from a cryptographically secure source. A sufficiently long random secret makes brute-force guessing impractical when combined with appropriate rate limiting and key management.
import { randomBytes } from "node:crypto";
const apiKey = randomBytes(32).toString("base64url");The API key should be treated as a secret after generation. It should not be unnecessarily exposed in client-side code, logs or URLs.
Randomness and UUIDs
Random-number generation is also used inside some identifier formats. UUID v4, for example, uses randomly generated bits as the primary source of uniqueness.
This does not mean that every UUID is appropriate for every security purpose. A UUID can be a useful identifier without being treated as an authentication credential.
Entropy vs Collision Resistance
Entropy and collision resistance are related but should not be treated as identical concepts. Entropy describes uncertainty in the generated value, while collision resistance concerns the likelihood that two independently generated values are equal.
A system can be designed with a large identifier space and still have poor security if its generator is predictable. Conversely, a value can be difficult to predict without necessarily being suitable for a particular cryptographic protocol.
Hardware Random Number Generators
Some systems include hardware components capable of measuring physical phenomena that provide unpredictable data. Examples can include electronic noise or other physical processes.
Operating systems can collect and manage entropy from hardware and software sources before exposing a standardized cryptographic random interface to applications.
Application developers generally do not need to access hardware randomness directly. Relying on the operating system's cryptographic randomness facility is usually the safer abstraction.
Why You Usually Should Not Build Your Own CSPRNG
Designing a secure random-number generator requires expertise in cryptography, entropy management, state handling and resistance to prediction attacks.
Established operating-system and runtime APIs have already solved these problems and are maintained as part of the platform's security infrastructure.
Random Seed Generators
A random seed generator can be useful when you need an unpredictable starting point for a reproducible or configurable PRNG-based process.
However, whether the seed itself needs to be secret depends on the application. A simulation seed can be intentionally public, while a seed used as part of a security-sensitive protocol must be handled according to the protocol's security requirements.
Random Number Generation in the Browser
Browser applications have access to two conceptually different sources: Math.random() for ordinary pseudo-random values and the Web Crypto API for cryptographically secure random values.
const ordinary = Math.random();
const secureBytes = new Uint8Array(16);
crypto.getRandomValues(secureBytes);The correct choice depends on what the value is used for. Do not use the secure API merely because every random number is a security problem, but do not use Math.random() when unpredictability is a security requirement.
Random Number Generation in Next.js Applications
Next.js applications can generate random values on both the server and client, but security-sensitive values should generally be created in a trusted server-side environment.
For example, a server can generate a password-reset token, store an appropriate representation and send only the required token to the user. A browser should not be responsible for generating an authentication secret that the server is expected to trust.
Randomness and Server-Side Rendering
Random values generated during server rendering can cause a different value to be produced during client hydration if the same computation runs again. This can create hydration mismatches in frameworks such as React and Next.js.
Random values that are part of stable rendered content should therefore be generated and passed deliberately rather than regenerated independently on the server and client.
Randomness in Distributed Systems
Distributed systems often need independent services to generate identifiers without coordinating every operation through one central server.
Cryptographically strong random values or carefully designed distributed ID formats can provide sufficiently large identifier spaces so independent generation remains practical.
Time-ordered identifiers such as UUID v7, ULID and KSUID add another option when ordering is important.
Common Random Number Generation Mistakes
Using Math.random() for Security
This is one of the most common mistakes in JavaScript applications. Math.random() is useful for ordinary random behavior but is not intended to generate secrets.
Using Timestamps as Random Values
A timestamp can provide a unique-looking value in some limited situations, but it contains highly predictable information. It should not be used as a replacement for secure randomness.
Adding Randomness to a Predictable Value
Appending a few random characters to a timestamp does not automatically make the result secure. The security properties depend on the entropy and generation method of the random component.
Using Too Few Random Bits
A token with only a small number of possible values can be brute-forced even if every value is generated uniformly. Security-sensitive tokens need enough entropy for the threat model and expected lifetime.
Modulo Bias
Mapping random values to a smaller range with a simple modulo operation can produce a non-uniform distribution when the source range is not evenly divisible by the target range.
Reusing Random State Incorrectly
A PRNG's internal state must be managed correctly. Accidentally copying, resetting or reusing state can cause repeated sequences and undermine the assumptions made by the application.
Confusing Randomness With Security
A value can look random without providing meaningful security. Security requires considering the generator, entropy source, attacker knowledge, token lifetime, rate limiting, storage and the surrounding protocol.
How to Choose a Random Generator
| Requirement | Recommended approach |
|---|---|
| Game effect | Ordinary PRNG |
| Simulation | Seeded PRNG when reproducibility is useful |
| Random test data | PRNG with recorded seed |
| Random UI behavior | Ordinary PRNG |
| Session token | CSPRNG |
| Password-reset token | CSPRNG |
| API key | CSPRNG |
| Cryptographic key material | Cryptographic randomness through an established API |
| Database identifier | UUID, UUID v7, ULID or another appropriate ID generator |
A Practical Checklist
- Determine whether the value is security-sensitive.
- If security matters, use a CSPRNG provided by the platform.
- Estimate how many possible values the generator can produce.
- Consider collision probability for identifiers.
- Choose an appropriate distribution for simulations.
- Use a reproducible seed when deterministic testing is useful.
- Avoid predictable seeds for security-sensitive values.
- Avoid modulo bias when mapping secure random values into ranges.
- Do not expose secrets unnecessarily in URLs or logs.
- Do not implement a custom cryptographic random generator unless there is a specialized reason.
Random Number Generation vs Random ID Generation
Random numbers and random identifiers overlap but are not identical problems. A random-number generator may be designed to produce values from a statistical distribution, while an ID generator is usually concerned with uniqueness, representation and sometimes ordering.
| Task | Important property |
|---|---|
| Simulation | Statistical distribution and reproducibility |
| Random selection | Uniformity or required distribution |
| Database ID | Uniqueness and storage/index behavior |
| Session token | Unpredictability and entropy |
| API key | Unpredictability, entropy and secret handling |
Frequently Asked Questions
What is the difference between PRNG and CSPRNG?
A PRNG is a deterministic algorithm designed to produce statistically useful pseudo-random sequences. A CSPRNG is specifically designed so that its output is computationally difficult to predict and is therefore appropriate for security-sensitive values.
Is Math.random() secure?
No. Math.random() is intended for ordinary pseudo-random behavior and should not be used to generate passwords, session tokens, API keys or other security-sensitive secrets.
What is entropy in random number generation?
Entropy describes uncertainty or information content. For equally likely outcomes, the number of entropy bits corresponds to the base-2 logarithm of the number of possible outcomes.
How many random bits does a secure token need?
There is no single universal number. The appropriate amount depends on the threat model, token lifetime, rate limiting, attack surface and the required security margin. Security-sensitive tokens should be generated using a cryptographically secure random source.
Should I use a random seed for security?
A predictable seed is not suitable for security. Security-sensitive systems should rely on a cryptographic random source rather than attempting to construct security from a manually selected seed.
Why is modulo bias a problem?
If the source range cannot be divided evenly by the desired range, a simple modulo operation makes some outputs more likely than others. Secure range generators can avoid this with techniques such as rejection sampling.
Can random numbers be reproduced?
Yes. Seeded PRNGs are specifically designed for reproducibility. The same algorithm and seed can produce the same sequence, which is useful for simulations, tests and debugging.
Helpful Randomness Tools
A Random Number Generator is useful for ordinary integer or range-based random values, while a Random Decimal Generator can produce random decimal values for simulations, testing and other non-security-sensitive tasks.
For security-sensitive values, use a Secure Random Generator designed around cryptographically strong randomness. An Entropy Calculator can help estimate the amount of information available in an identifier or random string, while a Random Seed Generator is useful when a reproducible PRNG-based process needs a fresh seed.
Conclusion
Random number generation is not one single technology. Ordinary PRNGs, seeded generators and cryptographically secure random generators solve different problems.
For games, simulations, testing and many ordinary application features, a conventional PRNG can provide excellent performance and useful reproducibility. For sessions, password-reset tokens, API keys and cryptographic operations, the application should use a cryptographically secure random source provided by the operating system or runtime.
Entropy, identifier-space size, collision probability, distribution and unpredictability all matter, but they answer different questions. Understanding those differences makes it much easier to choose an appropriate generator instead of treating every random-looking value as equivalent.
The most important rule is simple: use ordinary pseudo-randomness when you need statistical randomness, speed or reproducibility, and use cryptographically secure randomness whenever an attacker must not be able to predict the generated value.