一文详解安全随机数

一文详解安全随机数本文分享自华为云社区 安全攻防 深入浅出实战系列专题 安全随机数 云社区 华为云 作者 MDKing 随机数的使用场景使用随机数可分类安全场景跟非安全场景 非安全场景需要生成的越快越好 安全场景使用的随机数必须足够安全 保证不能被预

欢迎大家来到IT世界,在知识的湖畔探索吧!

本文分享自华为云社区《【安全攻防】深入浅出实战系列专题-安全随机数-云社区-华为云》,作者: MDKing 。

随机数的使用场景

使用随机数可分类安全场景跟非安全场景。非安全场景需要生成的越快越好。安全场景使用的随机数必须足够安全,保证不能被预测到。

常见的非安全场景:

  • 数据的索引号、标识;
  • 文件的名称或目录;
  • UUID、用户ID、随机填充字节;

常见安全场景包括但不限于以下场景:

  • 用于密码算法用途,如生成IV、盐值、密钥等;
  • 会话标识(sessionId)的生成;
  • 挑战算法中的随机数生成;
  • 验证码的随机数生成;

密码学意义上的安全随机数

安全场景下使用的随机数必须是密码学意义上的安全随机数。

密码学意义上的安全随机数分为两类:

  • 真随机数产生器产生的随机数;
  • 以真随机数产生器产生的少量随机数作为种子的密码学安全的伪随机数产生器产生的大量随机数。

已知的可供产品使用的密码学安全的非物理真随机数产生器有:

  • Linux操作系统的/dev/random设备接口(存在阻塞问题)
  • Windows操作系统的 CryptGenRandom() 接口

我们可以看到,密码学意义上的安全随机数非指必须都为真随机数生成器生成,因为真随机数生成器产生随机数是需要资源(熵)消耗的,当资源不足时会阻塞。所以在业务使用随机数频次较低的时候可以考虑全部使用真随机数。在业务使用随机数的频次高、数量大时就必须使用兼顾安全跟效率的方式:使用伪随机数生成器作为主体生成器进行随机数生成,使用真随机数周期为其设置种子(seed)。

SecureRandom对象的生成随机数有两类方法:生成下一个随机数的方法,比如nextInt、nextBytes等;生成种子的方法,如generateSeed。

使用new SecureRandom()创建的对象的nextXXX、generateSeed方法在linux系统下随机数来源均为/dev/urandom,生成的随机数都是不安全随机数。

使用SecureRandom.getInstance(“SHA1PRNG”, “SUN”)创建的对象nextXXX生成的为不安全的随机数,generateSeed生成的为安全随机数(linux下来源为/dev/random),所以使用SHA1PRNG算法合理设置好周期补种的逻辑理论上是可行的。但是根据公司密码算法相关要求,从2023年开始将禁止使用SHA1PRNG算法生成安全随机数。

常用推荐的安全随机数用法

大的原则上不建议自己实现补种、刷新熵源等逻辑,最好直接使用JDK封装好的方法。

密码学安全的随机数用法主要有3种:

1. SecureRandom.getInstance(“NativePRNGBlocking”)

参数要配置NativePRNGBlocking,好处是非常安全,因为nextXXX、generateSeed方法都是生成的真随机数,缺点是因为每次都是真随机数,性能较低,会有阻塞性问题。常见几个参数的对比如下:

参数取值

说明

nextXXX的随机数源

generateSeed的随机数源

随机数质量

是否阻塞(没实际验证,读者自酌)

SHA1PRNG

通过系统属性和java.security的熵收集设备完成随机数生成器的初始播种。完成初始播种后,不再依赖熵收集设备

NA

NA

不安全

不阻塞

NativePRNG

完成初始播种后,仍然要从系统的熵收集设备获取随机数,这就是Native的含义。nextBytes()从/dev/urandom设备获取随机数, generateSeed()从/dev/random获取随机数。

/dev/urandom

/dev/random

较安全

取随机数不阻塞,取种可能阻塞

NativePRNGBlocking

nextBytes()和generateSeed()均从/dev/random获取随机数

/dev/random

/dev/random

最安全

很可能阻塞

NativePRNGNonBlocking

nextBytes()和generateSeed()均从/dev/urandom获取随机数

/dev/urandom

/dev/urandom

不安全

不阻塞

2. SecureRandom.getInstanceStrong()

在JDK 8中引入,主要解决getInstance在应用某些参数时不能保证取到的随机数质量足够安全的问题,简化编程。它返回每个平台上可用的最强SecureRandom实现的实例。它会调用系统上可用的最强算法,该算法由$JAVA_HOME/jre/lib/security/java.security中的securerandom.strongAlgorithms来指定。

securerandom.strongAlgorithms的默认配置一般为NativePRNGBlocking:SUN,在这种设定下 getInstanceStrong()与getInstance(“NativePRNGBlocking”)等效。

3. SecureRandom.getInstance(“DRBG”,…)

推荐写法可参考编程规范:

一文详解安全随机数

小结一下:

低频使用安全随机数的业务场景(对性能没有要求)可以使用SecureRandom.getInstance(“NativePRNGBlocking”)或者SecureRandom.getInstanceStrong()方式;

高频使用安全随机数的业务场景(对性能有要求)只能使用SecureRandom.getInstance(“DRBG”,…)方式;

上述方式都不能满足业务场景需求时,再考虑自己实现补种、补熵等逻辑(不推荐、一般也不会有)。

实战验证

我们使用SHA1PRNG类型的随机数生成器,验证设置同样的种子seed后,是否能产生同样的随机数序列。

一文详解安全随机数

执行结果如下:可以看到,不管重复执行多少次,只要初始设置的种子相同,后面的序列一定是相同、且固定的。

一文详解安全随机数

一文详解安全随机数

所以如果使用了不安全的随机数生成器实现的代码逻辑,一旦攻击者掌握了一定数量的随机数序列,就有可能推测出初始种子,从而完全预测到后续生成的随机数序列的具体内容。

如果使用真随机数设置种子(当前写法仅为示例,并非推荐写法)

一文详解安全随机数

可以看到,每次执行都有随机性,由于设置的seed是通过真随机数生成器生成的,所以不可预测。

一文详解安全随机数

一文详解安全随机数

有同学肯定好奇,真随机数生成器的速度真的有那么慢吗?我们实际验证下,使用真随机数生成器、伪随机数生成器的性能对比如下:

一文详解安全随机数

关注#华为云开发者联盟# 点击下方,第一时间了解华为云新鲜技术~

华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/88923.html

(0)
上一篇 1小时前
下一篇 1小时前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信