kelvin@cluxnei:~/blog$ cat entropy.md
Where a random number comes from
I built a site that draws things using earthquakes, the position of the Space Station, atmospheric noise and the quantum vacuum. The obvious question is why, given that every computer has a random function built in. The answer involves entropy, chaotic systems, and something that tends to surprise people: your computer's randomness is already physical, you just cannot verify it.
In this text
What entropy actually is
The word carries two histories. In thermodynamics, entropy measures how spread out a system's energy is. In information theory, which is the one that matters here, it measures something else: surprise.
Claude Shannon formalised this in 1948. If an event has probability
p, the surprise of seeing it happen is log₂(1/p). The
entropy of a source is the average surprise across everything it can
produce:
The unit is the bit. One bit of entropy is exactly the uncertainty of a fair coin.
Two consequences worth keeping.
Entropy is not about the value, it is about the distribution. The number 7 is no more and no less random than 4. What does or does not have entropy is the process that chose.
Bias costs bits. A fair coin gives 1 bit per flip. A coin that lands heads 90% of the time gives only 0.47 bit. It is still unpredictable, just less so, and you need more than twice the flips to extract the same amount of uncertainty.
fair coin p = 0.50 1.00 bit per flip biased coin p = 0.90 0.47 bit per flip six-sided die p = 1/6 2.58 bits per roll full byte 256 values 8.00 bits
Hold on to that idea of "bits per event". It is the ruler that will later separate a source that works from a source that is garnish.
Why a computer draws nothing
A processor is a deterministic machine. Same input, same state, same output, always. That is the most valuable thing it has: it is why software works. And it is exactly why it cannot, on its own, produce a surprise.
What rand() does is something else: it produces a sequence that
looks random from an internal state. The name for that is a
pseudo-random generator, and the classic form is a linear congruential one:
Each number is an arithmetic function of the previous one. Knowing the state, you know the whole sequence, forwards and backwards.
Which means the real entropy of a PRNG is the entropy of the seed, and nothing more. If the seed has 32 bits, the entire sequence has 32 bits of surprise, no matter whether you pull a million numbers out of it. The generator does not create uncertainty, it stretches it.
Math.random() in the browser
and rand() in C are not cryptographically secure, and their own
documentation says so. Observe enough outputs and you can reconstruct the
internal state and predict the rest. For tic-tac-toe, fine. For drawing anything
that matters, no.
Where a computer gets real entropy
Here is the part that usually goes missing from the conversation, and it is the opposite of what many people imagine.
Modern operating systems keep an entropy pool, and what
goes into it is not mathematics: it is physics. Jitter in the exact timing
between hardware interrupts. Thermal noise in dedicated circuits. CPU
instructions like RDRAND, which sample a ring oscillator whose
instability is thermal. The interval, in nanoseconds, between two packets
arriving at the network card.
That pool feeds a cryptographic generator, and the result is what you get
when you call random_bytes(), /dev/urandom or
crypto.getRandomValues().
Your computer's "digital" randomness is already real-world randomness. It just comes in through a door you cannot see.
And it is good. In randomly's code, the source representing the system CSPRNG is classified as class A, with this comment:
/** Full-entropy, unpredictable bytes. Safe to stand alone. */ case Cryptographic = 'A';
Safe to stand alone. If the goal were entropy quality alone, the whole project would be unnecessary, and it would be dishonest to pretend otherwise.
Chaos: deterministic and unpredictable at once
Before answering why go looking outside, one piece is missing: understanding why an earthquake or the atmosphere are unpredictable, if both obey perfectly deterministic physical laws.
The answer is deterministic chaos. A chaotic system is governed by exact equations, with no randomness inside at all, and still cannot be predicted in the long run. The reason is sensitivity to initial conditions: two nearly identical configurations separate exponentially.
An initial difference δ(0) grows exponentially with time. The exponent λ is the Lyapunov exponent: when it is positive, the system is chaotic.
Edward Lorenz stumbled into this in 1961, running a weather model. Restarting a simulation from the middle, he typed the values with three decimal places instead of the six the machine held. The resulting forecast diverged completely from the original. The difference was one part in a thousand.
From that comes the phrase that became a cliché and that almost nobody knows is a technical statement: the butterfly effect is not a poetic metaphor about interconnection, it is a claim about the exponential growth of error in non-linear dissipative systems.
The atmosphere is chaotic. The Earth's crust is chaotic. The geomagnetic field is chaotic. None of them is random in the strict sense, but all of them are impractical to predict, because predicting would require knowing the current state with infinite precision.
So why go looking outside
If the system CSPRNG is secure, and natural sources are only unpredictable in practice, what is the point?
The point is not quality. It is provenance.
When a site draws a winner and says "it was random", you have no way to check
anything. The bytes came from random_bytes(), and that call leaves no
trace. There is no way to tell an honest draw from a hand-picked result presented
as a draw. The trust is total and blind.
What randomly proposes is trading that for a receipt. Every result comes with the source, the instant, a plain-language account, and a link to the original data on the site of whoever published it.
value 9, 23, 8, 47, 12 source RANDOM.ORG · class A account Atmospheric radio noise, sampled in Dublin moments ago proof https://www.random.org/randomness/ instant 2026-09-14T17:31:35+00:00 latency 274 ms
You can go and check. And more importantly, the whole result is reproducible from its own URL: the token carries the generator, the parameters and the source reference, so anyone recomputes exactly the same draw. There is no database behind it; there is nowhere to tamper with a history that does not exist.
The three classes, and the one that admits it is garnish
Now the bits-per-event ruler matters again. Not every real-world source is good for the same thing, and the code sorts the ten into three categories:
A · Cryptographic Full-entropy, unpredictable bytes. Safe to stand alone.
System CSPRNG, ANU (quantum vacuum), RANDOM.ORG
B · Public High entropy at publication, but globally public afterwards.
NIST Beacon, drand, Bitcoin blocks
C · Observational Low-rate, biased, structured. Flavour, not entropy.
USGS seismic, ISS position, space weather
Look at class C. Earthquakes, the ISS and space weather are the prettiest sources in the project, and the comment in the code calls them flavour, not entropy. They produce very few bits per event, they are biased and they have structure. The ISS position is an orbit: you can compute where it will be.
Which is why there is a one-line rule governing the whole system:
mixedWithCsprng: ! $isCsprng
Everything that is not the CSPRNG itself gets mixed with it.
The earthquake chooses which of the possible results you receive. The CSPRNG makes
sure nobody can predict or reproduce that choice without the token. And every
receipt carries a mixed_with_csprng field saying exactly that, rather
than selling mysticism.
There is another field worth attention, degraded. While I was
preparing this text, one of the examples came back like this:
value 09 15 33 41 56 57 source Operating System CSPRNG · class A account Drawn from the kernel entropy pool on the server degraded true
The source I asked for did not answer, and the system fell back to the local CSPRNG. It kept working and announced the fallback in the receipt, instead of serving a result with the pretty narrative of an earthquake that never happened. That is the difference between degrading and lying.
Holding that up with ten third-party services needs a breaker. Three consecutive failures open a source's circuit for sixty seconds, and the next attempt is a probe that either restores or reopens it. The comment in the code sums up the goal better than I would:
Keeps one flaky third party from becoming our outage.
What you can do with it
There are 63 generators across six modules: numbers, words, equations, patterns, images and sound. Everything below is a real result, pulled from the live API while I was writing, each seeded by a different source.
And beyond images, the same mechanism produces things like these, which I captured along with their receipts:
passphrase helper-opossum-lion-safehouse-sensitive-washable
ISS Position · class C · over 40.69° N, 66.82° E
equation 2x² + 4x = 0 → x = -2 or x = 0
USGS · magnitude 2.2 quake, 40 km ESE of Malaga, NM
dice 9, 12, 10, 10, 14, 18
NOAA · planetary K-index 1.67, geomagnetic field quiet
The summary
Entropy is surprise, measured in bits. A deterministic computer does not manufacture surprise: it stretches the surprise it was given. The surprise it is given already comes from the physical world, through sensors you cannot see. And chaotic systems are unpredictable not because they are random, but because they amplify any uncertainty exponentially.
None of this makes random_bytes() bad. What it lacks is a
receipt. That is what I set out to build: not better randomness,
but randomness you can check, including the part where it admits to having had
help.
randomly lives at randomly.cluxnei.dev, with 63 generators, ten sources and no API keys. Every result is reproducible from its own URL. The source is on GitHub.
kelvin@cluxnei:~/blog$