There is a sentence in the docs on random.org explaining randomness which reads, “Essentially, PRNGs (Pseudo Random Number Generators) are algorithms that use mathematical formulae or simply precalculated tables to produce sequences of numbers that appear random”.

Appear random?! What’s more, many common languages use PRNGs in their standard random libraries, including Python, Java, Ruby, Go and many more.

I reflected on what I already knew of random numbers. Most random libraries have either the option, or requirement, to seed a random number generator so the randomness is deterministically calculated. This should have been my first clue. How could something be both random and deterministic? Poking around a few more docs, I found a big red box warning in Python’s random library which explicitly says not to use the random library for security.

Python Random Warning

So random numbers only appear random, and are not actually useful for security practices? What was happening here?

To understand PRNGs, we first need a small grasp on what it means for something to be truly random. True Random Number Generators (TRNGs) generate random numbers from physical processes or phenomena. Radioactive decay is an example of a physical occurrence which is truly random and so can be used for generating random numbers. Random.org listens to atmospheric noise with a radio. These are non-deterministic, non-repeating and so can be used for security or for gambling. Notably, these are also inefficient. Since they can’t be generated, they will be slower to compute than pseudo random numbers.

PRNGs are long sequences of numbers which are deterministic, periodic, and efficient. They depend on a seed value, and so can be reproduced. Since they’re sequences of numbers, they will repeat eventually. This is why it is recommended not to use PRNGs for security or cryptographic use cases. Lastly, because they’re generated, they are much faster to calculate than most TRNGs.

The periods for these random number generators are often so long that the pseudo-randomness is more than enough for the use cases especially given the benefits that both determinism and efficiency provide. The most commonly used PRNG is Mersenne Twister. Its period is 219937 - 1. That number has 6002 digits. For more context, the age of the universe in nanoseconds only has 26 decimal digits. Most of the time when we’re interested in random numbers, we’re interested in avoiding collisions in numbers we generate. Rest assured, as the Python library states, the appearance of randomness is more than enough for these non-security related use cases.