第三章 真随机数发生器(TRNG)设计:熵源原理、NIST测试与后处理

各位同学,今天我们来聊聊真随机数发生器。说实话,TRNG 是芯片安全里最容易被低估的模块。很多人觉得随机数嘛,软件调个库就行。但真正做安全芯片的人都知道——没有好的硬件熵源,整个加密体系就是纸糊的

我参与过的几个安全芯片项目,流片回来发现随机数质量不过关,最后查出来都是熵源设计有坑。今天我就把这些坑一个一个讲清楚。

3.1 熵源原理:随机性从哪来?

真随机数的核心,是物理世界的不可预测性。芯片里常用的熵源主要有两种:振荡器采样热噪声

3.1.1 振荡器采样法

这个方法很直观。你想想看,两个振荡器频率不同,用慢的时钟去采快的时钟,每次采到的相位都不一样。这个相位差就是随机性的来源。

我习惯用环形振荡器来做。结构很简单:奇数个反相器首尾相连,就能振荡起来。但要注意——振荡器的频率不能太稳定。如果电源噪声被滤得太干净,振荡器反而变得太规律,随机性就差了。

关键设计参数:

  • 慢时钟频率:1-10 MHz
  • 快时钟频率:100-500 MHz
  • 采样点数:至少 1000 个周期

我曾经在一个项目里,为了省功耗把振荡器电流压得太低,结果频率抖动几乎消失,生成的随机数全是 0101 交替。嗯,那次教训挺深刻的。

3.1.2 热噪声法

热噪声是电阻里电子的随机运动产生的。这个噪声非常小,通常只有微伏级别。需要先放大,再通过比较器转换成数字信号。

我个人更偏爱热噪声法,因为它的随机性更「物理」。振荡器采样说到底还是数字电路的行为,而热噪声是真正的量子效应。

实战建议:热噪声放大器要远离数字模块。我见过一个设计,放大器旁边跑着 1GHz 的时钟,结果热噪声全被串扰淹没了。后来把放大器挪到芯片角落,单独加屏蔽环,效果立竿见影。

3.2 TRNG 的 NIST SP 800-22 测试

随机数好不好,不能靠感觉。NIST SP 800-22 是业界标准测试套件,包含 15 项统计测试。我挑几个最关键的讲讲。

测试项目 检测目标 通过标准
频率测试 0 和 1 的比例是否均衡 P-value > 0.01
游程测试 连续相同位的长度是否异常 P-value > 0.01
块内频率测试 局部区域的 0/1 分布 P-value > 0.01
离散傅里叶变换测试 是否存在周期性模式 P-value > 0.01

测试流程其实不复杂。你生成 1 百万比特的随机数序列,跑一遍 NIST 的测试程序。每个测试会输出一个 P-value,大于 0.01 就算通过。

但这里有个坑——一次通过不代表永远通过。我建议至少跑 100 组测试,看通过率。NIST 的要求是 100 组里至少 96 组通过。

注意:测试数据必须在芯片实际工作条件下采集。温度和电压变化都会影响随机数质量。我曾经在 25°C 下测试全通过,结果到 85°C 时一半测试都挂了。后来加了温度补偿电路才解决。

3.3 后处理与去偏技术

原始熵源输出的比特流,通常有偏置(bias)和相关性。说白了就是 0 比 1 多,或者相邻位之间有依赖。这时候就需要后处理。

3.3.1 冯·诺依曼去偏器

这个算法很经典。它把比特流分成两位一组:

  • 01 → 输出 0
  • 10 → 输出 1
  • 00 或 11 → 丢弃

这样做的好处是,不管原始偏置多大,输出都是无偏的。但代价是吞吐率会下降,最坏情况下只有原始速率的 25%。

// 冯·诺依曼去偏器 Verilog 实现
module von_neumann_debiaser (
    input clk,
    input rst_n,
    input raw_bit,
    output reg debiased_bit,
    output reg valid
);

reg [1:0] shift_reg;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        shift_reg <= 2'b00;
        valid <= 1'b0;
    end else begin
        shift_reg <= {shift_reg[0], raw_bit};
        if (shift_reg == 2'b01) begin
            debiased_bit <= 1'b0;
            valid <= 1'b1;
        end else if (shift_reg == 2'b10) begin
            debiased_bit <= 1'b1;
            valid <= 1'b1;
        end else begin
            valid <= 1'b0;
        end
    end
end

endmodule

3.3.2 哈希后处理

如果对随机性要求更高,可以用哈希函数做后处理。比如 SHA-256 或 AES。把原始比特流分组,每组 256 比特,哈希后取前 128 比特。

哈希的好处是能消除所有统计偏差,还能压缩数据。但代价是功耗和面积都大。我一般只在需要高安全等级的场景用哈希后处理,比如金融安全芯片。

我的经验:去偏器和哈希可以组合使用。先用冯·诺依曼去偏器去掉大部分偏置,再用哈希做最终处理。这样既保证了随机性,又控制了功耗。

3.4 知识体系总览

下面这张图是我自己整理的 TRNG 设计知识框架,你可以对照着看:

TRNG 设计知识体系 熵源 振荡器采样 热噪声放大 量子效应 后处理 冯·诺依曼去偏 哈希压缩 消除相关性 NIST 测试 15 项统计测试 P-value 分析 通过率验证 设计流程要点: 1. 选择熵源类型(振荡器 vs 热噪声) 2. 设计模拟前端(放大器、比较器) 3. 实现数字采样与后处理逻辑 4. 跑 NIST 测试,迭代优化 5. 全温全压验证,确保鲁棒性 「随机数质量 = 熵源 × 后处理 × 测试验证」

3.5 避坑指南

最后,我把自己踩过的坑总结一下:

  • 熵源不能太干净:电源噪声不是敌人,适当引入反而能增加随机性
  • 测试要覆盖全工况:低温、高温、低压、高压,每个组合都要测
  • 后处理不是万能的:如果熵源本身质量太差,再好的后处理也救不了
  • 面积和功耗要权衡:哈希后处理虽然好,但面积可能是冯·诺依曼的 10 倍

好了,这一章的内容就到这里。TRNG 设计是个需要反复迭代的过程,别指望一次就能搞定。多跑测试,多分析数据,慢慢就能找到感觉。


专注资料整理