四、真随机数发生器(TRNG):TRNG原理、熵源采集、NIST SP 800-22随机性测试

各位好,今天我们聊一个在安全芯片里“生死攸关”的模块——真随机数发生器。说白了,TRNG就是给加密算法提供“不可预测性”的源头。你想想看,如果密钥能被猜出来,那加密再强也没用。

我个人习惯把TRNG比作“芯片的熵工厂”。它不像伪随机数发生器(PRNG)那样靠算法算出来,而是直接从物理世界中“提取”随机性。我在项目中遇到过不少因为TRNG设计不当导致安全认证失败的案例,嗯,今天就把这些坑和经验一并分享给大家。

4.1 TRNG的工作原理

TRNG的核心逻辑其实不复杂:采集物理噪声 → 数字化 → 后处理 → 输出随机比特。但每一步都有讲究。

TRNG的三大核心组件:

  • 熵源(Entropy Source):物理噪声的源头,比如热噪声、抖动噪声、亚稳态等。
  • 采样与量化电路:把模拟噪声转换成数字信号。
  • 后处理模块(Conditioning):消除偏差,提取纯随机性。

我画了一张TRNG的典型架构图,方便大家理解整个流程:

TRNG 典型架构流程图 熵源 热噪声 / 抖动 / 亚稳态 采样与量化 ADC / 比较器 / 环形振荡器 后处理 Von Neumann / 哈希 / 抽取 随机比特 健康检测模块 在线监测 / 告警 / 自复位 反馈控制 NIST SP 800-22 测试 离线验证 / 合规认证 图例: 数据路径 控制/反馈 测试接口

4.2 熵源采集——从物理世界“榨取”随机性

熵源是TRNG的命根子。我见过不少芯片,后处理做得花里胡哨,但熵源本身质量不行,最后随机数还是不过关。说白了,源头不行,后面再怎么折腾也白搭。

4.2.1 常见的熵源类型

熵源类型 原理 优点 缺点
热噪声 电阻/二极管中的电子热运动 物理本质随机,带宽高 信号微弱,易受温度影响
环形振荡器抖动 振荡器相位噪声累积 实现简单,数字友好 可能引入周期性偏差
亚稳态采样 触发器建立/保持时间违规 面积小,功耗低 对工艺电压温度敏感
量子噪声 隧穿效应/光子散粒噪声 理论上的真随机 成本高,集成难度大

我个人在工业安全芯片中最常用的是环形振荡器抖动 + 热噪声混合方案。为什么?因为单一熵源容易被攻击者建模。你想想看,如果攻击者知道了你的振荡器频率,再结合温度补偿,就有可能预测输出。混合熵源能大幅提高攻击难度。

避坑指南:我曾经在一个项目中只用了环形振荡器作为熵源,结果在高温老化测试时,振荡器频率漂移导致随机性急剧下降。后来我加了一路热噪声辅助源,并在健康检测中加入了频率漂移告警,问题才解决。

4.2.2 熵源采集电路设计要点

采集电路的设计有几个关键点,我列出来供大家参考:

  • 差分结构:尽量使用差分采样,抑制共模噪声干扰。
  • 高阻抗输入:避免负载效应影响噪声源特性。
  • 带宽匹配:采样时钟带宽要与噪声源带宽匹配,否则会丢失高频随机成分。
  • 隔离设计:数字电路开关噪声会污染模拟熵源,必须做好电源和衬底隔离。

嗯,这里要特别强调一下隔离。我在一个项目中吃过亏——数字核心和TRNG共用同一个LDO,结果每次CPU执行复杂运算时,TRNG输出的随机性就变差。后来我单独给TRNG配了一个低噪声LDO,问题才彻底解决。

4.3 后处理——把“毛坯”变成“精品”

原始熵源采集到的比特流,往往存在偏差(比如0比1多)或相关性。后处理的目的就是把这些“毛坯”数据打磨成符合密码学要求的均匀随机序列。

常用的后处理方法包括:

  • Von Neumann 校正器:通过“01”和“10”模式提取无偏比特。简单但吞吐率低。
  • 哈希函数:用SHA-256等密码学哈希对原始数据进行压缩和扩散。安全性高,但面积大。
  • 线性反馈移位寄存器(LFSR):结合熵源种子进行扩展。注意:LFSR本身是确定性的,只能作为辅助。
  • 抽取与去相关:通过降采样或异或操作消除相邻比特间的相关性。

我的推荐方案:对于工业安全芯片,我建议使用“Von Neumann + SHA-256”两级后处理。第一级快速消除静态偏差,第二级用哈希做最终提取。这样既保证了吞吐率,又达到了密码学安全级别。

4.4 NIST SP 800-22 随机性测试

TRNG做出来之后,怎么证明它“真随机”?光靠拍胸脯可不行。NIST SP 800-22就是业界公认的“试金石”。

这套测试包含15项统计测试,我挑几个重点的给大家讲讲:

测试名称 检测目标 典型失败原因
频率测试 0和1的比例是否均衡 熵源偏差、后处理不足
游程测试 连续相同比特的分布是否正常 序列存在长周期模式
块内频率测试 局部窗口内的频率偏差 低频噪声干扰
离散傅里叶变换测试 是否存在周期性成分 振荡器谐波泄漏
重叠模板匹配测试 是否存在重复模式 后处理算法缺陷
线性复杂度测试 序列是否可被LFSR预测 熵源退化

重要提醒:NIST测试通过≠绝对安全。这些测试是统计意义上的,只能排除明显的随机性缺陷。真正的安全TRNG还需要通过物理攻击测试(如温度/电压扰动、电磁注入等)。

4.4.1 测试流程与参数设置

我在实际项目中测试TRNG时,一般按以下步骤操作:

  1. 数据采集:连续采集至少1Mbit(100万比特)的TRNG输出数据。
  2. 格式转换:将二进制数据转换为NIST测试工具要求的格式(通常是ASCII 0/1字符串)。
  3. 参数配置:根据芯片应用场景设置测试参数(如块大小、模板长度等)。
  4. 批量测试:运行全部15项测试,记录P-value值。
  5. 结果判定:P-value ≥ 0.01 视为通过(显著性水平α=0.01)。

这里给出一段简单的测试脚本示例(Python调用NIST测试套件):

# 示例:使用Python调用NIST SP 800-22测试套件
import subprocess
import os

# 假设数据文件为 trng_output.bin
data_file = "trng_output.bin"
nist_tool = "./assess"  # NIST提供的测试可执行文件

# 配置测试参数
params = f"""
1  # 选择二进制文件
{data_file}
1000000  # 数据长度(比特数)
0  # 使用默认参数
1  # 运行所有测试
"""

# 执行测试
with open("input.txt", "w") as f:
    f.write(params)

subprocess.run([nist_tool, "1000000"], stdin=open("input.txt"))

# 检查结果
result_file = "experiments/AlgorithmTesting/finalAnalysisReport.txt"
if os.path.exists(result_file):
    with open(result_file) as f:
        print(f.read())
else:
    print("测试未完成,请检查数据格式")

经验之谈:我建议在芯片量产前,至少在不同温度(-40°C、25°C、85°C)和不同电压(标称±10%)下各采集一组数据做NIST测试。我曾经遇到过常温全过、高温全挂的情况——后来发现是高温下熵源噪声幅度衰减导致的。

4.5 健康检测——让TRNG“自我诊断”

TRNG在芯片运行过程中可能会因为老化、温度突变或攻击而退化。所以,在线健康检测是必不可少的。

常见的健康检测机制包括:

  • 重复计数测试:检测连续相同比特的数量是否超过阈值。
  • 自适应比例测试:动态监测0/1比例是否在允许范围内。
  • 熵率估算:实时估算当前熵源的熵值,低于阈值时告警。
  • 看门狗定时器:如果TRNG长时间未输出有效随机数,触发复位。

嗯,这里要注意:健康检测本身不能太复杂,否则会消耗大量功耗和面积。我一般用硬件实现简单的重复计数和自适应比例测试,软件层再定期做完整的NIST测试。

总结一下:TRNG设计不是“搭积木”,而是一个系统工程。熵源选型、采集电路、后处理、健康检测、NIST验证,每个环节都要精心打磨。我在项目中见过太多“看起来随机”但实际有偏的TRNG,最后在安全认证环节被卡住。希望大家能少走这些弯路。


公众号:蓝海资料掘金营,微信deep3321