Posted by Synopsys Editorial Team on August 25, 2016
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().
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?
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.
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.
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 NodeJS 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 byMath.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.