一文详解安全随机数

本文分享自华为云社区《【安全攻防】深入浅出实战系列专题-安全随机数》,作者: 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方法都是生成的真随机数,缺点是因为每次都是真随机数,性能较低,会有阻塞性问题。常见几个参数的对比如下:

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",...)

从JDK 9开始,新增了由Sun提供的符合NIST SP 800 90-A标准的DRBG伪随机数产生器,包括HASH-DRBG、HMAC-DRBG、CTR-DRBG三种,且适用于各种OS,符合公司密码算法相关要求,在使用JDK 9

及以上版本时,推荐优先使用该方式生成安全随机数。该方式生成随机数是兼顾安全跟效率周期补种真随机数方式的封装,所以在高频生成安全随机数的场景中可以使用该方式。

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

小结一下:

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

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

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

实战验证

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

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

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

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

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

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

点击关注,第一时间了解华为云新鲜技术~

相关推荐
qyhua4 小时前
【Linux运维实战】彻底修复 CVE-2011-5094 漏洞
linux·运维·安全
Andya_net5 小时前
网络安全 | 深入了解 X.509 证书及其应用
服务器·安全·web安全
骥龙12 小时前
2.8、权限的终极目标:提权与持久化
安全·网络安全
SuperherRo14 小时前
JS逆向-安全辅助项目&Yakit热加载&魔术方法&模版插件语法&JSRpc进阶调用&接口联动
javascript·安全·yakit·jsrpc·热加载
梵得儿SHI15 小时前
Java 反射机制深度剖析:性能与安全性的那些坑
java·开发语言·安全·反射·动态代理·性能·反射机制
来旺16 小时前
互联网大厂Java面试全解析及三轮问答专项
java·数据库·spring boot·安全·缓存·微服务·面试
Brianna Home17 小时前
博客安全攻防演练:从攻击者视角构筑铜墙铁壁
网络·数据库·安全·oracle
施嘉伟18 小时前
SQL Server安全配置全面检查与优化方案
数据库·安全
Andya_net19 小时前
网络安全 | SSL/TLS 证书文件格式详解:PEM、CRT、CER、DER、PKI、PKCS12
安全·web安全·ssl
newxtc1 天前
【昆明市不动产登记中心-注册安全分析报告】
人工智能·安全