The JavaScript Math.random()
function is designed to return a single IEEE floating point value n such that 0 ≤ n < 1. It is (or at least should be) widely known that the output is not cryptographically secure. Most modern implementations use the XorShift128+ algorithm which can be easily broken. As it is not at all uncommon for people to mistakenly use it when they need better randomness, why do browsers not replace it with a CSPRNG? I know that Opera does that*, at least. The only reasoning I could think of would be that XorShift128+ is faster than a CSPRNG, but on modern (and even not so modern) computers, it would be trivial to output hundreds of megabytes per second using ChaCha8 or AES-CTR. These are often fast enough that a well-optimized implementation may be bottlenecked only by the system's memory speed. Even an unoptimized implementation of ChaCha20 is extremely fast on all architectures, and ChaCha8 is more than twice as fast.
I understand that it could not be re-defined as a CSPRNG as the standard explicitly gives no guarantee of suitability for cryptographic use, but there seems to be no downside to browser vendors doing it voluntarily. It would reduce the impact of bugs in a large number of web applications without violating the standard (it only requires the output be round-to-nearest-even IEEE 754 numbers), decreasing performance, or breaking compatibility with web applications.
EDIT: A few people have pointed out that this could potentially cause people to abuse this function even if the standard says you cannot rely on it for cryptographic security. In my mind, there are two opposing factors that determine whether or not using a CSPRNG would be a net security benefit:
False sense of security - The number of people who otherwise would use a function designed for this purpose, such as
window.crypto
, decide instead to useMath.random()
because it happens to be cryptographically secure on their intended target platform.Opportunistic security - The number of people who don't know any better and use
Math.random()
anyway for sensitive applications who would be protected from their own mistake. Obviously, it would be better to educate them instead, but this is not always possible.
It seems safe to assume that the number of people who would be protected from their own mistakes would greatly exceed the number of people who are lulled into a false sense of security.
* As CodesInChaos points out, this is no longer true now that Opera is based off of Chromium.
Several major browsers have had bug reports suggesting to replace this function with a cryptographically-secure alternative, but none of the suggested secure changes landed:
Chromium thread: https://bugs.chromium.org/p/chromium/issues/detail?id=45580
Firefox thread: https://bugzilla.mozilla.org/show_bug.cgi?id=322529
The arguments for the change essentially match mine. The arguments against it vary from reduced performance on microbenchmarks (with little impact in the real world) to misunderstandings and myths, such as the incorrect idea that a CSPRNG gets weaker over time as more randomness is generated. In the end, Chromium created an entirely new crypto object, and Firefox replaced their RNG with the XorShift128+ algorithm. The Math.random()
function remains fully predictable.