Math.random()函数返回一个0~1之间的伪随机浮点数,其在V8中的实现原理是这样的:
为了保证足够的性能,Math.random()随机数并不是实时生成的,而是直接生成一组随机数(64个),并放在缓存中,当这一组随机数取完之后再重新生成一批,放在缓存中。
由于 Math.random()
的底层算法是公开的(xorshift128+ 算法),V8 源码可见,因此,是可以使用其他语言模拟的,这就导致,如果攻击者知道了当前随机生成器的状态,那就可以知道缓存中的所有随机数,那就很容易匹配与破解。
Crypto.getRandomValues()
和 Math.random()
方法的区别在于,getRandomValues()
方法的随机种子生成器更加的无序,例如系统层面的无序源(有些硬件自带随机种子)。
然后不同浏览器下 getRandomValues()
方法生成的随机数可能是有区别的。
以及 getRandomValues()
方法的底层实现是没有缓存的,随机数都是实时生成的,因此,性能上是要比 Math.random()
差的,因此,如果是高并发的场景,同时随机数仅仅是用做随机,与安全和金钱不相关,请使用 Math.random()
而不是 getRandomValues()
。
就 Web 前端而言,必须要使用 getRandomValues()
方法的场景很少,不过由于纯前端几乎不存在所谓的高并发,因此使用 getRandomValues()
方法也是可以的。