实用 AI

可在线运行 AI 集合,涵盖 AI 文案生成、写作辅助、AI 绘图与照片修复、AI 配音、字幕生成、语音转录以及 AI 视频创作和数字人等多种 AI 服务

查看详情

随机数生成器Random的安全性问题

深入学习Java基础知识
2022-06-10 13:37 · 阅读时长7分钟

在Java开发中经常使用Random作为随机数的生成器,它能满足绝大多数随机数生成的需求,但是在安全性比较高的业务中要慎重使用。我们知道Random内部有一个seed属性,如果在构造方法中传入则使用传入的,否则会自动生成,seed对随机数的生成非常重要,如果两个Random的seed一样,则它们产生的随机数序列也是一样的。

加载中...

由此可见,如果我们要想破解或者说预测随机数序列,只需要得到Random对象的seed属性即可,上面提到了seed属性如果不设置的话会自动生成,下面是Random默认的构造方法。

加载中...

seedUniquifier方法会返回一个常数,而System.nanoTime()则是返回当前纳秒级别的时间戳,也就是说如果得到这个时间戳就能够得到seed值,但是这种风险还是比较小的。

Random不安全的主要是它的next方法,我们常用的nextInt,nextLong这些都是通过它生成的,next和nextInt的源码如下

加载中...

从源码中可以看出,相邻的两个随机数之间是存在某种关系,首先是oldseed和nextseed存在线性关系,然后是seed和最终生成的int随机数也存在关系。

以nextInt为例,它最终生成的int随机数是通过nextSeed右移16位得到的,我们可以将int随机数左移16位得到一个基数baseSeed,由于nextSeed在右移过程中丢失了低16位,所以baseSeed<=nextSeed<=baseSeed + 216,再通过oldSeed和nextSeed的关系,我们就可以得到上次产生随机数的seed,核心代码如下。

加载中...

下面是一个实例测试,我们可以通过Random先后得到两个int随机数,然后通过这两个随机数获取Random对象目前的seed属性值,从而推断出下一次将会产生的int随机数。

加载中...
总结

从上面可以看出,如果我们能够得到Random先后产生的两个随机数就能预测下一个随机数的值,从而引出安全问题,在对安全性要求比较高的业务场景中,我们可以使用SecureRandom来替代Random生成随机数,SecureRandom重写了next方法,即使两个SecureRandom的seed一样,它们产生的随机序列也是不一样的。

javaRandomSecureRandom随机数安全