到底要不要用伪随机数?

作者:vkvi 来源:ITPOW(原创) 日期:2017-1-19

我们现在经常在用伪随机数,比如 rand() 方法,就是一个伪随机数。什么是伪随机数呢?就是说这个随机数是人为按照一定算法出来的,具有可预测性,如果我们拿这个伪随机数作为 token,去获取重要资源,就有可能被人猜出来,别人就可能仿冒 token。

如上,就是我随便写的一个随机数算法,虽然有待优化,但是各语言的伪随机数算法原理就是这么回事,基于一个 Seed,除了第一次 Seed 不确定外,第二次、第三次都可以推算得出结果。

这时有人会说,那我每次使用 Next 之前都初始化一下 Seed,这样就预测不到结果了吧?

的确不那么好猜了,但是我们要知道由于 Seed 初始化是基于当前时间的(目前都是类似做法),所以我们可以预测到一个范围,比如前面是毫秒,那么 Seed 无非就是 0-999 这 1000 个数,那么猜 1 次就有 1/1000 机率猜中,如果我猜得非常快,极短时间内可以猜 1000 次,那么必定会猜出来。

这时有人会说,那我不用毫秒,用更细的纳秒,这样被猜中的机率就更小了?

是的。但是如果产生随机数,非常频繁,比如每毫秒产生 1 个,虽然我们种子用的是纳秒,被人猜中的机率也是 1/1000,同时提高猜的频率,同样很容易猜出来。

有人说,以上都是你的理论,能不能有个实例?看看一个例子吧:

由于执行速度很快,new Random() 使用的种子(即当前时间)只变过一次,所以上面试图产生 1000 个随机数,却只有 2 个不重复的数(如果你的计算机够快,可能只会产生 1 个)。

所以伪随机数安不安全,要不要用,得根据我们的应用需求、我们的产生频率、能猜多快来决定。

那么什么是真随机数呢?计算机能不能产生呢?

关于“真随机数”,要看这个定义怎么看,反正我觉得一般来说是统计学上的随机,计算机要产生这样的随机数,往往不光是用时间作 Seed,还要加入更多因素,比如噪音、温度、鼠标输入等,尽量增加随机性,但是在我看来,这也仅仅是增加了 Seed 复杂度,并没有改变本质。但是从应用级上来说,要安全得多,比如以前猜 1 亿次就有可能猜中 1 次,现在猜 1000000 亿次才有可能猜中 1 次。

所以,不必一杆子打死,要考虑实际应用。

相关阅读

相关文章