java 伪随机数安全性

真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等。这样的随机数发生器叫做物理性随机数发生器,虽然很可靠,但是使用计算机很难实现,它们的缺点是技术要求比较高。

在实际应用中往往使用伪随机数就足够了。这些数列看似是随机的数,实际上它们是通过一个固定的、可以重复的计算方法产生的。计算机产生的随机数有很长的周期性。它们不真正地随机,因为它们实际上是可以计算出来的,但是它们具有类似于随机数的统计特征。这样的发生器叫做伪随机数发生器。

伪随机数又有强弱之分。强伪随机数一般是指相对难以猜解的随机数,比如服务器占用的内存数量作为随机数;而弱伪随机数是指相对容易猜解的随机数呢,典型的例子是当前的时间戳等。

C、C++、Java等程序语言和软件中都有对应的随机数生成函数或者类。以我们最常用的Java语言为例,强伪随机数RNG实现java.security.SecureRandom类,该类使用临时文件夹中大小,线程休眠时间等的值作为随机数种子;而弱伪随机数实现PRNG java.util.Random类,默认使用当前时间作为种子,并且采用线性同余法计算下一个随机数。

Random r = new Random(10000); //10000作为seed,默认使用当前时间作为seed
for (int i=0;i<5;++i)
{
  System.out.println(r.nextInt());
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

以上这段代码,无论你怎么跑都会打印出以下结果:

-498702880
-858606152
1942818232
-1044940345
1588429001
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

这是一个稳定的结果。这就是由于线性同余法带来的后果。那么,在我们的程序,如果使用Random类生成一个随机数,事实上很容易通过上一个产生的随机数来推断下一个随机数。

接下来,我们来分析一些常用的随机数应用场景,并且分析一下出错的原因。

很多账号体系都有一个找回密码功能,找回密码时给手机发送的验证码,给邮箱发送的验证码或者重置密码链接,以上种种都使用了伪随机数。

下面以某网站通过邮箱重置密码链接找回密码为例,通过页面操作之后,会在密保邮箱中发现以下重置密码的链接:

http://www.xxx.com/findpwd/setpwdfromemail?vc=2ABB36620A927644607491393EF0D5EF&u=xxx%40gmail.com
 
 
  • 1
  • 1

通过分析,我们发现,vc=2ABB36620A927644607491393EF0D5EF是一串md值,解开之后值是1339744000,是个unix时间戳!那么可以猜测,用户取回密码时产生一个时间戳与帐号绑定,那么修改这个用户密码只需知道这个时间戳就可以。况且,一般服务器时间都是跟标准时间同步,也就是说unix时间戳是可以预测的。我们可以通过暴力破解遍历当前标准时间+一个网络延迟来进行暴力破解。

伪随机数的应用里,验证码是另外一种典型应用。对于安全而言,验证码是一个非常有效的保护机制和人机区分机制,可以保障口令不被暴力破解,可以防止刷票,刷屏,重复提交恶意数据等。除了作为验证码之外,类似的应用还存在于一些活动的优惠券或者兑换码,如果兑换码设计不当,很容易被破解而破坏活动的公平性。

总结一下,使用随机数的场景需要注意以下几点: 
不要使用时间戳作为随机数 
保证不同用处的随机数使用不同的种子 
对于安全性要求高的随机数,使用强伪随机数产生

转载自:伪随机数安全性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值