GM/T 0005-2012 随机性检测实战:15 项统计测试全流程解析

国密算法 · 2026-10-16 · 12 阅读

在国密算法的实际应用中,随机数的质量直接决定了系统的安全性。SM2 签名需要随机数 k,SM4 加密需要 IV 和初始向量,密钥生成过程同样依赖高质量的随机数。如果随机数存在偏差或规律,攻击者可能通过统计分析推断出密钥。

GM/T 0005-2012《随机性检测规范》正是解决这一问题的核心标准。它规定了密码应用中随机数质量的检测方法,包含 14 项统计测试,涵盖了从频率检测到游程分析、从矩阵秩检测到扑克测试等多个维度。

本文将逐一解读这 15 项测试,并提供完整的 Python 实现代码,帮助开发者在实际项目中验证随机数质量。

1. 标准概述

GM/T 0005-2012 由国家密码管理局发布,是密码应用中随机数检测的强制性标准。标准规定了随机数序列的质量评估方法,适用于基于 SM2/SM3/SM4 等国密算法的系统。

1.1 标准适用范围

  • 密钥生成:SM2 签名密钥对生成中的随机数 k
  • 初始化向量:SM4 加密模式中的 IV
  • 盐值生成:PBKDF2 中的 salt
  • nonce 生成:TLS 握手中的 nonce

1.2 检测流程概述

标准规定的检测流程分为三步:

  • 采样:从待测随机数源中抽取长度为 n 的二进制序列
  • 测试:依次执行 14 项统计测试
  • 判定:根据 P 值和阈值判断随机数序列是否合格

2. 14 项统计测试详解

2.1 频率测试(Monobit Frequency Test)

目的:检测序列中 0 和 1 的比例是否接近 50%。

原理:计算序列中 1 的个数 N₁,若序列长度 n 足够大,则 N₁ 应近似服从二项分布 B(n, 0.5)。

公式:

CODE
S_n = Σ(2·b_i - 1)  (将 0/1 映射为 -1/+1)
S_n / √n < 1.96(置信度 95%)

判定:P 值 ≥ 0.01 为合格。

代码实现:

2.2 游程测试(Runs Test)

目的:检测序列中游程(连续相同比特)的分布是否符合随机性。

原理:计算游程总数 V_obs,若序列随机,则游程数应近似服从正态分布。

公式:

CODE
V_obs = 序列中游程总数
μ = 1 + 2·N₁·N₀ / n
σ² = 2·N₁·N₀·(2·N₁·N₀ - n) / (n²·(n-1))
P = erfc(|V_obs - μ| / (σ·√2))

代码实现:

2.3 扑克测试(Poker Test)

目的:检测固定长度块中比特组合的分布均匀性。

原理:将序列分成 m 位一组,统计各组合出现次数,用卡方检验判断分布均匀性。

公式:

CODE
χ² = Σ(O_i - E_i)² / E_i
其中 E_i = n / 2^m

代码实现:

2.4 游程最大宽度测试(Longest Run of Ones in a Block Test)

目的:检测序列中连续 1 的最大游程长度分布是否合理。

原理:将序列分成若干块,每块中统计最长连续 1 的长度,用卡方检验判断分布是否符合理论值。

代码实现:

2.5 串行测试(Serial Test)

目的:检测序列中 m 位子序列的出现频率是否均匀。

原理:统计所有可能的 m 位组合出现次数,用卡方检验判断均匀性。

代码实现:

2.6 游程测试(扩展版)

检测不同块大小下的游程分布,增强对周期性模式的敏感性。

代码实现:

2.7 矩阵秩测试(Matrix Rank Test)

目的:检测序列构成的矩阵是否满秩。

原理:将比特序列排成矩阵,计算矩阵的秩。若随机数质量良好,矩阵应为满秩的概率约为 0.35。

代码实现:

2.8 通用序列测试(Universal Statistical Test)

目的:用线性复杂度检测序列的随机性。

原理:序列的线性复杂度应近似为 n/2。用 Berlekamp-Massey 算法计算线性复杂度。

代码实现:

2.9 离散傅里叶变换测试(Discrete Fourier Transform Test)

目的:检测序列的频谱特性,识别周期性成分。

原理:计算序列的 DFT 幅度谱,若随机,则各频率分量幅度应近似指数分布。

代码实现:

2.10 非重叠模板匹配测试(Non-overlapping Template Matching Test)

目的:检测特定模式的出现频率是否符合预期。

原理:统计指定模板在序列中出现的次数,用泊松分布判断是否符合。

代码实现:

2.11 重叠模板匹配测试(Overlapping Template Matching Test)

与 2.10 类似,但允许模板重叠匹配。

代码实现:

代码实现:

2.12 游程测试(三进制游程)

检测连续相同比特的分布,特别关注长游程。

2.13 压缩测试(Compression Test)

目的:利用压缩算法检测序列的熵。

原理:若序列可压缩,则存在冗余,非随机。

代码实现:

2.14 伪随机数测试(Linear Complexity Over Subsequences)

检测子序列的线性复杂度分布。

代码实现:

代码实现:

2.15 平均游走测试(Cumulative Sums Test)

目的:检测随机游走的路径是否偏离原点。

原理:将序列映射为 ±1,计算累积和,若偏离过大则非随机。

代码实现:

3. 完整检测框架

将上述测试整合为统一的检测框架:

4. 实际应用指南

4.1 密评场景下的随机数检测

在密码应用安全性评估中,GM/T 0005 的检测要求如下:

检测对象要求
SM2 签名随机数 k必须通过全部 14 项测试
SM4 加密 IV至少通过频率测试和游程测试
密钥生成随机数全部通过
Salt 生成通过频率测试即可

4.2 常见问题排查

问题 1:频率测试失败

原因:随机数源存在偏差,如硬件 RNG 未充分校准。

解决:

  • 检查硬件 RNG 的熵源是否稳定
  • 增加后处理(如 HMAC-DRBG)
  • 更换 RNG 设备
问题 2:游程测试失败

原因:序列中存在周期性或自相关。

解决:

  • 使用更高质量的熵源
  • 增加 Whiteninɡ 处理
问题 3:线性复杂度测试失败

原因:序列中存在可预测的模式。

解决:

  • 检查 RNG 的实现是否合规
  • 使用 NIST SP 800-90A 标准算法

4.3 性能建议

在实际部署中,建议采用以下策略:

  • 在线检测:仅运行频率测试和游程测试(快速筛查)
  • 离线检测:运行全部 14 项测试(深度验证)
  • 定期检测:每季度或更换 RNG 时执行完整检测

5. 标准引用与参考

  • GM/T 0005-2012《随机性检测规范》,国家密码管理局
  • NIST SP 800-22《A Statistical Test Suite for Random and Pseudorandom Number Generators for Cryptographic Applications》
  • ISO/IEC 18031-1:2018《Random bit generation》

6. 总结

GM/T 0005-2012 为密码应用中的随机数质量提供了系统化的检测框架。通过 14 项统计测试,可以全面评估随机数的质量,发现潜在的偏差和模式。

在实际工程中,建议将随机数检测作为密钥生成、初始化向量配置等环节的必要步骤,确保密码系统的底层安全性。


相关实践文章: