In 2014 an exploit was discovered in Firefox for Android that allowed malicious applications access to sensitive user data. The cause? An unfortunately predictable PRNG called Math.random().
If youāre using Node.js (or any other JavaScript environment) in your stack today, the same Math.random() function is your default PRNG.
Donāt worry, though. Weāve got your back.
Hereās a breakdown of exactly where Math.random() goes astray, and some possible PRNG alternatives you can use to make your projects more secure.
Thereās really nothing random about Math.random(). By definition, PRNGs generate numbers deterministically based on a set of initial seed value: they can only approximate randomness. While there are PRNGs that come a stoneās throw from true randomness (weāll get to those), Math.random() is widely regarded as sub-par.
What does this mean?
There is a chance that the ārandomlyā generated values produced by JavaScriptās baked-in PRNG will be repeated (or, under the wrong circumstances, could be predicted by an adversary). For scenarios that involve random selectionāa simple dice game, or for internal QA testing where thereās less emphasis on unique session ID values and cryptographyāthis can be frustrating.
But in the event youāre currently using Math.random() where unique values are criticalāto create unique session IDs, generate values across active users, or for encryptionāthere could be major security implications.
Luckily, for these security-centered scenarios you have the option of cryptographically secure pseudorandom number generators (CSPRNGs). These are designed to resist a would-be attackerās ability to identify the seed value and predict subsequent outputs in a sequence.
Since security isnāt the only place where random number generation is necessary, itās important to understand the non-cryptographic alternatives to Math.random(). And because JavaScriptās default PRNG is found wanting in virtually every measurable categoryāfrom predictability to statistical quality to speedāwe absolutely recommend upgrading.
With that in mind, weāve put together this list of more powerful, easy-to-implement PRNGs for you to use in your application:
Xorshift random number generators create sequences by ārepeatedly taking the exclusive of a number with a bit shifter version of itself.ā It passes more statistical tests than Math.random() and, because of the way it structures sequences, itās much faster.
According to the (in no way biased) chart below, PCG random number generators are the cream of the crop. Theyāre difficult to predict, extremely fast, compact, and statistically excellent.
The Mersenne Twister is the most widely-used PRNG; itās the default in Python, R, Ruby, and a slew of other languages. Why JavaScript isnāt one of them is a mystery. Downsides? Itās not very fast (especially when compared to Xorshift and PCG) and takes up a ton of space.
While the random number generators listed above are invariably better than Math.random(), their lack of a cryptographic component ultimately renders them inferior to CSPRNGs when used for security.
By default, the Node.js library contains crypto.randomBytes(), a CSPRNG that uses entropy from the underlying operating system to create near-true randomness. For example, on Linux crypto.randomBytes() takes the entropy from /dev/urandom, and generates random bytes which can be used to create secure pseudorandom numbers.
Stacked up against Math.random(), crypto.randomBytes() looks even more impressive: it generates a table of unique possible random values on each call compared to a static table generated only once by Math.random().
While Math.random() isnāt as powerful a PRNG as Xorshift, PCG, or the Mersenne Twister, it does still generate pseudorandom numbers. If you arenāt using your PRNG to create and track sessions or for some other application in which an increased chance of recurring values could be cataclysmic, Math.random() could make sense.
That being said, any of the other three PRNGs would be better: theyāre faster, more powerful, more efficient. And, in a security context, not even these options will cut it: the cryptographic alternative is a necessity.