JavaScriptMath.random()
函数旨在返回单个 IEEE 浮点值n,使得 0 ≤ n < 1。众所周知(或至少应该)众所周知,输出不是密码安全的。大多数现代实现使用很容易被破坏的XorShift128+算法。由于人们在需要更好的随机性时错误地使用它并不少见,为什么浏览器不将其替换为 CSPRNG?我知道Opera 就是这样做的*, 至少。我能想到的唯一理由是 XorShift128+ 比 CSPRNG 更快,但在现代(甚至不是那么现代)计算机上,使用 ChaCha8 或 AES-CTR 每秒输出数百兆字节将是微不足道的。这些通常足够快,以至于优化的实现可能仅受系统内存速度的限制。即使是未优化的 ChaCha20 实现在所有架构上都非常快,而 ChaCha8 的速度是其两倍以上。
我知道它不能被重新定义为 CSPRNG,因为该标准明确不保证适用于加密使用,但浏览器供应商自愿这样做似乎没有不利之处。它将减少大量 Web 应用程序中的错误的影响,而不会违反标准(它只要求输出是四舍五入的IEEE 754数字)、降低性能或破坏与 Web 应用程序的兼容性。
编辑:一些人指出,这可能会导致人们滥用此功能,即使标准规定您不能依赖它来实现加密安全。在我看来,有两个相反的因素决定了使用 CSPRNG 是否会带来净安全收益:
错误的安全感- 本来会使用为此目的而设计的功能的人数,例如
window.crypto
,决定使用Math.random()
它,因为它恰好在他们的预期目标平台上是加密安全的。Opportunistic security - 不了解更多信息并
Math.random()
无论如何都使用敏感应用程序的人数,这些应用程序可以避免自己的错误。显然,最好对他们进行教育,但这并不总是可行的。
可以肯定的是,可以避免自己犯错的人数将大大超过陷入虚假安全感的人数。
* 正如 CodesInChaos 指出的那样,由于 Opera 基于 Chromium,这不再适用。
几个主要浏览器都有错误报告,建议用加密安全的替代方法替换此功能,但没有一个建议的安全更改落地:
改变的论点基本上与我的一致。反对它的论点从降低微基准测试的性能(在现实世界中几乎没有影响)到误解和神话,例如随着时间的推移 CSPRNG 会随着更多随机性的产生而变得更弱的错误想法。最后,Chromium 创建了一个全新的加密对象,Firefox 用 XorShift128+ 算法替换了他们的 RNG。该Math.random()
功能仍然是完全可预测的。