随机数是隐形地基
密码应用的安全性建立在随机数之上:密钥生成、IV 与 Nonce、盐值、挑战值都依赖随机源的质量。随机数一旦可预测,密钥就可能被推算出来。判断标准很简单:密码用途必须使用密码模块或操作系统提供的密码学安全随机源,业务代码里的普通伪随机数生成器不能用于这些场景。GM/T 0005 给出了随机性检测的方法与要求。
基本信息
| 标准 | GM/T 0005《随机性检测规范》 |
|---|---|
| 依赖场景 | 密钥生成、IV 与 Nonce、盐值、挑战值、令牌 |
| 正确来源 | 密码模块内置随机源或操作系统的密码学随机源 |
| 错误来源 | 时间戳、进程号、普通伪随机数生成器 |
| 检测方式 | 对发生器的输出做统计检测(频数、游程、矩阵等) |
典型使用场景
- 密钥生成:密钥长度与随机源质量共同决定强度
- 对称加密:IV 与 Nonce 必须不可预测且不复用
- 口令存储:盐值需随机且逐用户独立
- 会话与令牌:会话标识与一次性令牌依赖强随机
- 方案评审:检查代码中是否存在弱随机调用
正确与错误示例
正确与错误示例
import secrets # 正确:密码学安全随机源
key = secrets.token_bytes(32)
nonce = secrets.token_bytes(12) # GCM 场景常用 96 位随机数
salt = secrets.token_bytes(16)
# import random # 错误:伪随机,输出可预测
# key = bytes(random.getrandbits(8) for _ in range(32))
# 错误示例:把时间戳当作随机种子或随机值
# import time; weak = str(int(time.time()))场景与要求
| 场景 | 要求 |
|---|---|
| 密钥生成 | 使用密码模块或系统随机源,长度符合算法要求 |
| IV / Nonce | 不可预测,同一密钥下不得重复 |
| 盐值 | 逐用户独立随机,长度足够 |
| 挑战值与令牌 | 单次有效,避免顺序或时间推导 |
检查与整改动作
- 代码扫描:检索 random / rand / srand 等非密码学随机调用出现在密钥与令牌相关代码的位置
- 依赖核查:确认所用的密码库版本来自官方渠道且未被打补丁替换
- 来源确认:密钥与随机数由密码模块或操作系统接口产生,而不是应用自行实现
- 送检准备:自研随机数发生器需按 GM/T 0005 做随机性检测并保留报告
- 变更复核:把随机源检查纳入上线评审清单,避免回退到旧实现
弱随机用在 GCM 的 Nonce 上后果严重:同一密钥下 Nonce 重复会直接破坏 GCM 的安全性,可能泄露明文与认证密钥。