Randomness in Cryptography: True Random Sources, Entropy, and Pseudorandom Generators Explained

Emin MuhammadiEmin Muhammadi
13 min read

Randomness is a word you hear in everyday life and in headlines about security breaches, but it hides subtle technical meaning. In cryptography, randomness is the backbone of secret keys, tokens, and nonces; when randomness fails, systems fail.

What “random” really means

In everyday terms, randomness is unpredictability. A coin toss feels random because you cannot reliably predict whether it will land heads or tails. Technically, randomness combines unpredictability with lack of bias. A truly random source gives outcomes that cannot be predicted better than by chance and that follow expected frequencies. If you can forecast future outputs better than chance, the source is not random in the cryptographic sense.

A hand rolling two twenty-sided dice on a wooden surface.

To make these ideas precise, cryptographers use the mathematical notion of entropy, which quantifies how much uncertainty or “surprise” a source produces on average. Formally, for a discrete random variable X that takes values x with probabilities p(x), Shannon entropy is written as H(X) = –Σ p(x) log₂ p(x). Entropy is measured in bits and has an intuitive interpretation: one bit of entropy equals the uncertainty of a fair coin toss. For a fair coin, the calculation is straightforward and instructive. Each outcome has probability 0.5, so H = –[0.5·log₂(0.5) + 0.5·log₂(0.5)]. The logarithm log₂(0.5) equals –1, so the inner products are 0.5·(–1) = –0.5 and another –0.5; their sum is –1.0, and the negative of that is 1.0. Thus, a fair coin toss carries exactly 1.0 bit of entropy.

The practical consequence for security is clear: when cryptographers say a source is “random,” they mean that it resists feasible prediction and that its entropy content is well understood and sufficient for the intended use. Entropy estimates guide decisions about seed sizes and key strengths because the number of bits of entropy roughly corresponds to the logarithm of the attacker’s search space. If a key is intended to provide 128 bits of security, the secret material used to derive that key should contain comparable entropy; otherwise, an attacker’s effective effort to brute force or guess the secret is reduced. In short, unpredictability and lack of bias are two sides of the same coin (pun intended), and entropy is the rigorous tool cryptographers use to measure how secure that coin toss really is.

True randomness from the physical world

Computers are deterministic machines and cannot produce true randomness by themselves, so cryptographers and engineers turn to the messy, noisy processes of the physical world when they need genuine unpredictability. Physical randomness comes from measurements of phenomena that are fundamentally difficult (or impossible) to predict in practice: thermal agitation of electrons in a resistor, the microscopic timing of photons striking a photodiode, the discrete and memoryless events of radioactive decay, or the constant hiss of atmospheric radio noise. Each of these phenomena produces signals that, when observed through sensitive electronics, look like irregular fluctuations rather than the smooth, repeatable patterns that a CPU naturally generates. That irregularity is what we want: entropy that an attacker cannot reproduce or control without physically accessing the device or altering the environment.

Real-world hardware random number generators include not only discrete sensors but entire subsystems engineered for robustness. Designs typically include analog front-ends to amplify noise, high-resolution analog-to-digital converters to sample it, and digital conditioners to remove bias. They also include run-time health checks and continuous statistical monitoring so that the system can detect sensor failures, saturation, or an unexpected shift in distribution and fail safely. For embedded devices or virtual machines that may have limited entropy at startup, engineers add entropy pooling and conservative seeding strategies to avoid predictable initial states, because low entropy at boot time has been the root cause of several high-profile cryptographic failures.

Hardware RNGs are not immune to attack. An attacker with physical access can alter the environment (apply heat, inject signals, or clamp supply voltages) to bias the source, and even remote attackers can sometimes exploit shared hardware effects or firmware flaws to influence entropy. Side-channel leaks can reveal partial state, and subtle implementation bugs can turn an ostensibly random process into a predictable one. Mitigations include sensor redundancy, tamper-evident packaging, continuous self-tests, and cryptographic post-processing that assumes part of the input may be under adversarial control while still extracting usable randomness from the uncontaminated portion.

A wall display of colorful lava lamps is visible through a glass window with "Cloudflare" printed on it.

Cloudflare’s “lava lamp” setup is one of the most fun and concrete examples of how engineers turn physical chaos into cryptographic strength. At a high level the idea is simple: film analog, hard-to-predict phenomena, convert the imagery into bits, mix that with other entropy sources, and feed the result into a cryptographically secure pseudorandom generator that helps seed keys and other security-critical values. Cloudflare publicly documented the system (called LavaRand) and how the camera feed is processed and mixed into their production randomness pool.

The lava-lamp story actually has roots before Cloudflare. The notion of using chaotic visual patterns to harvest entropy goes back to projects like Lavarand from the 1990s and later LavaRnd, which showed that inexpensive webcams and chaotic scenes can produce useful true randomness when properly digitized and post-processed. Cloudflare adopted and industrialized that concept; they point a camera at about a hundred lava lamps in their San Francisco lobby and capture frames continuously, taking advantage of the lamps’ complex, heat-driven fluid dynamics to supply unpredictable variation.

Technically, the pipeline is capture, digitize, condition, and mix. The camera captures images; the pixel data and small sensor noise become raw entropy. That raw data is not used directly. Instead the images are converted into bitstreams, deterministic artifacts and obvious biases are removed, and the result is cryptographically conditioned (for example by hashing or other extractors) before it is mixed into an entropy pool and used to seed or reseed a CSPRNG. Cloudflare’s public posts describe these steps and emphasize that the lava lamps are only one source in a multi-source design: the lamp feed is combined with kernel-level sources and other independent hardware sensors to reduce the risk any single source can be predicted or subverted.

The approach has practical benefits and limitations. The benefit is real, high-quality entropy that is hard for a remote attacker to predict. The practical limitations are bandwidth and engineering complexity: camera-based schemes produce entropy at limited rates compared with purely electronic TRNGs, require careful analog and software conditioning, and must run continuous health checks to detect stuck pixels, saturated sensors, or other failures. Designers must assume someone might attempt to bias or observe a physical source, so robust mixing with other independent entropy sources and careful entropy estimation are essential. Cloudflare’s public write-ups and journalists’ interviews discuss the tradeoffs and the precautions taken to keep the system trustworthy.

If you want an approachable demonstration you can try at home: point a webcam at a chaotic visual scene (moving shadows, fire, water ripples, or even a desktop lava lamp), capture short bursts of frames, compute a cryptographic hash of each frame, and treat the hashes as seed material for a local PRNG. For any practical security deployment, however, you need conservative entropy estimation, hardware and software safeguards, mixing of multiple independent sources, and preferably a vetted RNG design rather than a DIY system for critical uses.

Pseudorandomness: how deterministic algorithms imitate randomness

A pseudorandom number generator (PRNG) is a deterministic algorithm that stretches a small chunk of true randomness, called a seed, into a long sequence of values that look random to observers who do not know the seed. The core idea is simple but powerful: instead of relying on expensive or slow physical measurements for every random bit, a system captures a modest amount of entropy once, feeds it into a carefully designed algorithm, and then produces many bits that are suitable for ordinary use. Because the process is deterministic, anyone who knows the seed or the algorithm’s full internal state can reproduce the entire output stream exactly; the security goal of cryptographic designs is therefore to make the internal state infeasible to recover from observing outputs.

Not all PRNGs are created equal. For many applications statistical appearance is enough: the outputs should pass a variety of randomness tests and have long periods so patterns do not repeat within the expected runtime. Mersenne Twister is a classic example used widely for such nonsecurity use cases because it has excellent statistical qualities and a very long period. However, statistical quality alone does not imply security. A generator can pass many statistical tests and still be trivial to predict if an attacker learns its state or if the algorithm has structural weaknesses.

Cryptographically secure PRNGs, or CSPRNGs, add a stronger requirement: even with access to a large amount of output, an attacker should not be able to predict future outputs or recover previous internal state within feasible computational limits. One formal way to state this requirement is the next-bit unpredictability property: no efficient adversary, given the first k bits of the generator’s output, can predict bit k+1 with probability significantly better than one half. A variety of practical CSPRNG constructions realize this property under standard cryptographic assumptions. Two common construction patterns are block-cipher-based counter mode, where a secret key encrypts an increasing counter to produce output blocks, and stream-cipher or hash-based designs, where keyed primitives are used to mix state and generate bits.

Seeding and reseeding are central operational issues. A CSPRNG is only as strong as its seed: if the seed lacks sufficient entropy, the output provides a false sense of security. Good practice takes a conservative approach to entropy estimation, collects seed material from multiple independent sources when possible, and reseeds the CSPRNG periodically or on specific events (for example, when new hardware entropy becomes available, or after a long uptime). Reseeding helps limit the damage if the internal state is ever partially exposed, because later reseeds restore unpredictability for future outputs. Designers also consider forward secrecy and backward secrecy: forward secrecy prevents an attacker who learns the current state from reconstructing past outputs, and backward secrecy (also called recovery) ensures that after reseeding, previous state compromise does not imply future compromise.

Practical CSPRNGs are implemented in many libraries and operating system primitives. Examples you may encounter include HMAC or hash-based DRBGs, AES-CTR or AES-CBC based DRBGs, and stream cipher constructions such as ChaCha20 used as generators. Standards and well-reviewed implementations matter; reinventing your own generator is risky because subtle mathematical or implementation flaws can create catastrophic predictability. Real-world incidents underline this risk: a tiny change in how an operating system seeded its randomness or a single removed line of code has previously reduced effective entropy and allowed attackers to guess supposedly secret keys. Another infamous controversy involved a standardized DRBG whose parameters sparked suspicion of a potential backdoor; that episode taught the community to prefer transparent, auditable constructions and to avoid obscure defaults without scrutiny.

Performance, state size, and period are practical trade-offs. A generator intended for heavy simulation workloads favors very long period and high throughput; a generator intended for cryptographic key material places a stronger emphasis on provable unpredictability and secure state management, possibly tolerating higher computational cost. State compromise extensions and health checks are engineering features that help; implementations often zeroize state on shutdown, mix in unpredictable inputs from system events, and run continuous statistical sanity checks to detect sensor failure or stuck outputs.

Linear Congruential Generator

PRNGs are fast, reproducible, and resource-efficient, making them ideal for simulations, games, and randomized algorithms. For security, though, a PRNG must be cryptographically secure. Using a non-cryptographic PRNG for keys, tokens, or session identifiers can lead to predictable secrets and catastrophic breaches. Historical security incidents frequently trace back to insufficiently random seeds or the misuse of standard library PRNGs for sensitive purposes.

A linear congruential generator (LCG) is one of the oldest and simplest pseudorandom number generators. It is defined by a single recurrence relation that updates an internal integer state and emits the next value as that state (or a function of it). The recurrence looks compact and innocent:

Here m is the modulus, a the multiplier, c the increment, and X0 the seed. Despite the short formula, the LCG illustrates many of the fundamental trade-offs between simplicity, performance, statistical quality, and security.

Understanding why an LCG sometimes works well and sometimes fails begins with its parameters. The modulus mmm sets the numeric range of outputs: each Xn lies in the set {0,1,…,m−1}. The multiplier a and increment c determine how the sequence moves around that range. If c is zero, the generator is called a multiplicative LCG; if c is nonzero it is called mixed. The seed X0​ determines the specific sequence you will get; two different seeds can lead to the same eventual cycle or to different cycles depending on parameters.

Beyond period, LCGs exhibit other structural weaknesses that limit their usefulness. One intuitive problem is that output points from an LCG in multiple dimensions lie on a relatively small number of hyperplanes. If you take successive output values and form tuples such as (Xn,Xn+1,Xn+2), those points do not fill the 3D space uniformly but instead fall on parallel planes. This lattice structure is formalized by the spectral test, which measures how well the generator fills multiple-dimensional space; LCGs frequently score poorly on this test unless parameters are carefully tuned. Another practical problem arises when the modulus mmm is a power of two, a very common implementation choice because modular reduction is then very cheap in binary machines. In that case low-order bits of the generated numbers have particularly short periods and poor randomness properties; the least significant bit simply toggles if a and c are odd, making low bits unsuitable for direct use without further processing.

Nevertheless, LCGs remain useful in contexts that do not require cryptographic unpredictability. Their implementation is tiny, they are fast, and when properly parameterized they can provide repeatable pseudorandom streams that are good enough for many simulations and nonsecurity randomness needs. Classic textbooks and libraries historically used carefully chosen LCG parameters (for example, values recommended by early numerical libraries) to balance period and statistical behavior. Even so, more modern general-purpose generators such as the Mersenne Twister, PCG (Permuted Congruential Generator), and Xoshiro/XSAdd families outperform simple LCGs in statistical tests while retaining speed and convenience; those generators address many of the lattice and low-bit problems by combining linear recurrences with nonlinear output transformations.

If you want to experiment with an LCG, a short Python implementation illustrates the idea and helps you observe its properties in practice. The following snippet implements a simple LCG and demonstrates the cycle detection logic:

def lcg(a, c, m, seed, n):
    x = seed
    for _ in range(n):
        x = (a * x + c) % m
        yield x

"""
Example parameters
prints [3, 7, 6, 4, 0, 1, 3, 7, 6, 4]
"""
a, c, m, seed = 2, 1, 9, 1
print(list(lcg(a, c, m, seed, 10)))

That output shows the short repeating cycle. To check for period exhaustively, iterate until the state repeats and count steps, but be careful with large moduli: naive period detection can be slow if mmm is large.

In practice, if you must use an LCG in production for nonsecurity tasks, choose parameters with care and be aware of the generator’s documented limitations. Prefer a large odd modulus (often a large prime or an odd number with few small prime factors) and multipliers that meet known theoretical criteria for long periods. Avoid using raw low-order bits from power-of-two moduli. Consider combining the LCG output with a nonlinear post-processing step to reduce lattice artifacts, or better yet use a modern generator designed to provide better statistical guarantees for the same or similar computational cost.

The linear congruential generator is an elegant and historically important algorithm: it is easy to understand, cheap to compute, and it teaches fundamental lessons about pseudorandomness. Its linearity, however, is also its fundamental limitation. For simulation, visualization, and educational experiments it is a useful tool and a clean introduction to pseudorandom generators; for cryptography and high-stakes randomness it is the wrong tool and should be replaced by a vetted CSPRNG or a modern high-quality PRNG.

Conclusion

Randomness underlies everything in cryptography. True physical sources provide the raw unpredictability, and cryptographic pseudorandom generators convert that unpredictability into practical, high-volume randomness suitable for secure systems. Developers should always use platform CSPRNGs for secrets, validate entropy sources on constrained devices, and avoid the temptation to roll their own generators. When randomness is done right, your cryptography stands on firm ground; when it is done poorly, the rest of the system is at risk.

0
Subscribe to my newsletter

Read articles from Emin Muhammadi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Emin Muhammadi
Emin Muhammadi

Software & QA Engineer, Cybersec enthusiast. Website https://eminmuhammadi.com