持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
前言
在 JavaScript 中, 通常使用 Math.random 获取随机数;然而在 MDN中,备注着这么一句话:
也就是说,Math.random 虽然能够满足大多数需要使用随机数的场景,但是不够安全,不能用于处理一些和安全有关的需求。
为何 Math.random 不够安全
根据网络上的资料,Math.random 的实现是基于 XorShift128+算法实现的。
这种算法的随机数并不是在使用时就已经生成的,而是在环境初始化或者缓存的随机数用完时,会生成一个随机数的cache。
也就是说,每次使用的随机数其实在一开始就已经存在了,在使用时将其取出而已,如果把随机数的缓存进行更改,那么,随机,就将变成可控的,随机也就失去了意义。
参考文章。
使用 Crypto.getRandomValues() 代替
这个方法与 Math.random 相比,它是在调用时才生成随机数的数组,然后使用者从数组获取某一个随机数使用,不用担心被篡改了随机数缓存。同时,因为没有使用缓存,所以 Crypto.getRandomValues() 的性能是比 Math.random 要差一些的。
使用时,比 Math.random 复杂一点;首先,它的参数是 typedArray,也只能是 typedArray,传入其他数组会报错,无法执行代码;第二,它返回的是一个随机数的数组,需要从数据里面取出数据才能使用。
可以封装成如下函数来模拟 Math.random:
function getSafeRandom (): number {
return crypto.getRandomValues(new Uint8Array(1))[0] / 256
}
代码中 crypto.getRandomValues(new Uint8Array(1))[0] 表示从 0 ~ 256 随机去一个数字,然后除以 256 缩小其最终取值的值域,将返回一个从 0 ~ 1 之中的数字。