3. 真随机数发生器(TRNG)

真随机数发生器,圈里人常叫它 TRNG。这东西在硬件安全里有多重要?我打个比方——如果你的密钥是用伪随机数生成的,那攻击者只要猜中你的种子,整个系统就裸奔了。TRNG 不一样,它从物理世界的噪声里“挤”出随机性,理论上不可预测。

我做过好几个安全芯片的项目,每次评审时 TRNG 都是被盯得最紧的模块。为什么?因为设计不好,它就是个摆设。今天咱们把 TRNG 的原理、振荡器实现、熵源评估和健康测试掰开揉碎了讲。

3.1 TRNG 原理

TRNG 的核心思想很简单:从物理过程中提取随机性。这些物理过程包括热噪声、抖动、亚稳态、量子效应等等。关键是要保证这些源头的熵——也就是不可预测性——足够高。

一个典型的 TRNG 架构分三步:

  1. 熵源:产生原始随机信号,比如振荡器相位抖动
  2. 采样/量化:把模拟的随机信号转成数字比特
  3. 后处理:消除偏差,提取均匀随机比特

重要概念:TRNG 的“真”体现在熵源是物理的,不是算法生成的。但物理源可能受温度、电压、老化影响,所以必须做健康测试。

你可能会问:为什么不用软件随机数生成器?嗯,软件 RNG 本质上是确定性算法,只要知道状态就能复现。TRNG 的随机性来自物理世界,攻击者没法通过数学推导来预测。

3.2 基于振荡器的 TRNG 设计

振荡器 TRNG 是工业界最常用的方案之一。原因?实现简单,面积小,功耗低。我最早接触 TRNG 时,用的就是这种结构。

基本思路是这样的:

  • 用两个振荡器,一个慢速,一个快速
  • 慢速振荡器的抖动作为随机源
  • 快速振荡器作为采样时钟
  • 采样结果就是随机比特

但这里有个坑——如果两个振荡器频率相关,随机性会大打折扣。我曾经在一个项目里发现,由于版图布局不当,两个振荡器通过电源耦合产生了相关性,采样结果出现明显的周期性。后来我们加了独立的 LDO 供电才解决。

下面是一个经典的振荡器 TRNG 结构图:

基于振荡器的 TRNG 结构图 基于振荡器的 TRNG 结构 慢速振荡器 (抖动源) 快速振荡器 (采样时钟) D 触发器 (采样单元) 后处理 (去偏/提取) 随机比特输出 设计要点: 1. 两个振荡器必须独立,避免频率锁定或耦合 2. 慢速振荡器的抖动幅度要大于采样时钟周期 3. 后处理环节不能引入确定性偏差

设计时要注意几个关键参数:

参数 推荐范围 说明
慢速振荡器频率 1-10 MHz 太低则输出速率慢,太高则抖动不足
快速振荡器频率 50-500 MHz 至少比慢速高一个数量级
采样后处理 Von Neumann 或哈希 消除 0/1 偏差

个人经验:我习惯在振荡器环路上加一个可调延迟单元。这样可以在测试时微调频率,找到抖动最大的工作点。量产时再固定下来。

3.3 熵源评估

熵源评估是 TRNG 设计里最容易被忽视的环节。很多人觉得“有抖动就行”,但实际不是这样。熵不够的 TRNG,输出的随机数质量很差。

评估熵源,我主要看三个指标:

  • 最小熵(Min-Entropy):最保守的熵估计,假设攻击者知道分布但不知道具体值
  • 香农熵(Shannon Entropy):平均信息量,常用于理论分析
  • 相关性:相邻比特之间的依赖程度

具体怎么测?我常用的方法是:

  1. 采集大量原始采样数据(至少 1M 比特)
  2. 做 NIST SP 800-22 统计测试
  3. 计算自相关函数,看有没有周期性
  4. 用压缩算法(如 gzip)看压缩率,理想随机数压缩率接近 0%

注意:熵源评估必须在芯片工作的全温度范围(-40°C 到 125°C)和全电压范围内进行。我见过一个案例,常温下熵源表现很好,但高温下振荡器抖动急剧下降,随机数质量严重退化。

这里有一个简单的熵计算示例:

// 假设采样了 N 个比特,其中 1 的个数为 M
// 最小熵计算
p = M / N
min_entropy = -log2(max(p, 1-p))

// 如果 p = 0.5,min_entropy = 1 比特/比特
// 如果 p = 0.6,min_entropy = 0.737 比特/比特
// 如果 p = 0.9,min_entropy = 0.152 比特/比特

你看,偏差越大,熵损失越严重。所以后处理不是可选项,是必选项。

3.4 健康测试

健康测试是 TRNG 的“看门狗”。芯片运行时,环境可能变化,老化可能发生,攻击者可能尝试注入干扰。健康测试就是确保 TRNG 始终在安全状态下工作。

我参与的一个安全芯片项目,TRNG 健康测试占了整个 TRNG 模块 40% 的面积。当时有人觉得浪费,后来我们发现,在电磁干扰下,振荡器频率会漂移,如果没有健康测试,输出的随机数质量会悄悄下降。

健康测试通常分两层:

层级 测试内容 触发条件
在线测试 连续监测熵源状态 每次输出随机数前
离线测试 全功能统计测试 上电时或定期触发

在线测试我建议做这几项:

  • 频率监测:检查振荡器频率是否在允许范围内
  • 重复计数:连续相同比特的数量不能超过阈值
  • 自适应比例:滑动窗口内 1 的比例不能偏离 0.5 太远

离线测试则更全面,包括 NIST 测试套件中的频数测试、游程测试、块内频数测试等。这些测试计算量大,不适合每次输出都做,但上电自检时必须跑一遍。

关键点:健康测试的阈值设置要平衡安全性和可用性。阈值太严,芯片频繁报警无法使用;阈值太松,安全风险增加。我一般参考 NIST SP 800-90B 的推荐值,再根据工艺角仿真调整。

最后说一个实战中的教训。有一次,我们的 TRNG 在实验室测试全部通过,但客户现场反馈说随机数生成器频繁报错。排查后发现,客户的环境温度比我们测试时高了 15°C,振荡器频率漂移超出了健康测试的阈值。从那以后,我要求所有 TRNG 的健康测试阈值必须覆盖全温度范围,并且留 20% 的余量。

嗯,TRNG 的设计就是这样——原理不复杂,但细节决定成败。从熵源选择到健康测试,每一步都要扎实。下次你们设计 TRNG 时,记得把健康测试当作安全防线,而不是可有可无的附加功能。