Math.random(): Is it Truly Random or Just a Clever Illusion?

·

3 min read

Randomness has always intrigued humanity, and in the realm of computer science, generating random numbers plays a crucial role in various applications such as simulations and gaming.

What really is randomness?

According to dictionary.com,

"randomness is the apparent or actual lack of definite pattern or predictability in information."

In essence, real randomness is anything that cannot be predicted.

Lets study the coin toss. It is an example of a chaotic system — outcome depends on a lot of factors like force, wind drift, air resistance. If you knew all the factors and accurate values of each, you could predict with high probability what the result of the toss will be.

That is to say, if you know all the initial conditions of a chaotic system, you can model the outcome of the system (because it is determinate).
We can logically agree that randomness is basically ignorance of the initial conditions of a chaotic system. ("... apparent lack of definite pattern in information.")

We know that the computer generate random numbers for example by using the Math.random() method in javascript, but these numbers aren't truly random because computers are determinant machines. Every code was written by a person and its output is dependent on an initial value(seed value) and an algorithm to generate the next number and so on. As discussed in the previous paragraph, it is possible to model the outcome of the system if you know all the initial conditions — so, we can agree that the computer does not generate a true random number. These numbers are called Pseudorandom numbers and the libraries used are called Pseudorandom number generators(PRNGs)

How does the Math.random() work?
Javascript runs on chrome and node by the V8 engine. This V8 engine is maintained by Google and open-source. The Math.random() implementation is based on an algorithm that looks something like this:

uint32_t state0 = 1;
uint32_t state1 = 2;
uint32_t mwc1616() { state0 = 18030 (state0 & 0xFFFF) + (state0 >> 16); state1 = 30903 (state1 & 0xFFFF) + (state1 >> 16); return state0 << 16 + (state1 & 0xFFFF); }

Since we know this algorithm, a model to predict the numbers can be created and the initial values of Math.random() sequence can be passed to the model as arguments to predict the subsequent numbers.

How to improve security?

The initial value is called the seed value and it should be often changed to reduce predictability.
For example, random.org offers almost true random numbers to anyone on the internet. It chooses its seed value from atmospheric noise, which is always changing and — for many purposes is better than the pseudo-random number algorithms typically used in computer programs.

Since Math.random() does not provide cryptographically secure random numbers, they are not used for security. Mozilla docs recommend using window.crypto.getRandomValues() method and other cryptographically secure pseudorandom number generators instead.