第11课:真随机数生成器

阶段二哈希与认证 — 真随机数是密码学的根基。密钥生成、 nonce、盐值都需要不可预测的随机源。硬件 TRNG 利用物理噪声产生真随机数。

1. 随机数的密码学要求

密码学中的随机数必须满足:

2. 硬件熵源

2.1 环形振荡器(Ring Oscillator)

环形振荡器是 FPGA 上最常用的熵源。奇数个反相器首尾相连形成振荡,由于热噪声和电源抖动,频率和相位具有随机性。

✅Verilator验证通过
// ring_oscillator.v - 环形振荡器(3级)
// 注意:Verilator 会将环路优化掉,实际使用需加 (* keep *)
module ring_oscillator (
    output wire osc_out
);

    wire stage0, stage1;

    // 3级反相器链,形成自激振荡
    // 实际 FPGA 中需要使用 (* keep *) 防止综合优化
    assign stage0 = ~osc_out;   // 第一级
    assign stage1 = ~stage0;    // 第二级
    assign osc_out = ~stage1;   // 第三级(输出反馈到输入)

endmodule

2.2 TRNG 架构

典型 TRNG 架构:多个环形振荡器采样 → 异或合并 → 后处理(von Neumann 或 SHA 压缩):

✅Verilator验证通过
// trng_ro.v - 基于环形振荡器的 TRNG
module trng_ro #(
    parameter NUM_OSC = 8,          // 环形振荡器数量
    parameter POST_PROCESS = 1      // 启用后处理
)(
    input  wire         clk,        // 系统时钟
    input  wire         rst_n,
    input  wire         enable,
    output reg          random_valid,
    output reg  [31:0]  random_data
);

    // 采样寄存器
    reg [NUM_OSC-1:0] osc_samples;
    reg [NUM_OSC-1:0] osc_prev;
    reg [NUM_OSC-1:0] osc_xor;     // 相邻采样异或(提取抖动)

    // 简化模型:用 LFSR 模拟环形振荡器输出
    // 实际硬件中,这里连接到真实的环形振荡器
    reg [NUM_OSC-1:0] lfsr_state;
    integer i;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            lfsr_state <= 8'hAC;  // 任意初始值
        end else if (enable) begin
            // 模拟 8 个独立振荡器的相位漂移
            for (i = 0; i < NUM_OSC; i = i + 1) begin
                lfsr_state[i] <= lfsr_state[i] ^ (lfsr_state[(i+3)%NUM_OSC] ^
                                 lfsr_state[(i+5)%NUM_OSC]);
            end
        end
    end

    // 采样和异或
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            osc_samples <= 0;
            osc_prev <= 0;
            osc_xor <= 0;
        end else begin
            osc_samples <= lfsr_state;
            osc_xor <= osc_samples ^ osc_prev;
            osc_prev <= osc_samples;
        end
    end

    // 异或合并所有振荡器输出
    wire raw_bit = ^osc_xor;

    // Von Neumann 后处理器
    reg prev_raw;
    reg [1:0] vn_state;
    reg [31:0] accum;
    reg [5:0] bit_cnt;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            random_valid <= 0;
            random_data <= 0;
            accum <= 0;
            bit_cnt <= 0;
            prev_raw <= 0;
            vn_state <= 0;
        end else if (enable) begin
            random_valid <= 0;
            case (vn_state)
                2'd0: begin
                    prev_raw <= raw_bit;
                    vn_state <= 2'd1;
                end
                2'd1: begin
                    // Von Neumann: 01→输出0, 10→输出1, 00/11→丢弃
                    if (prev_raw != raw_bit) begin
                        accum[bit_cnt] <= raw_bit;
                        bit_cnt <= bit_cnt + 1;
                        if (bit_cnt == 31) begin
                            random_data <= accum;
                            random_valid <= 1;
                            bit_cnt <= 0;
                        end
                    end
                    vn_state <= 2'd0;
                end
                default: vn_state <= 2'd0;
            endcase
        end
    end

endmodule

3. NIST 随机性测试

TRNG 的输出必须通过统计测试验证其随机性:

测试检测目标
频率测试0 和 1 的比例
游程测试连续 0/1 序列长度分布
块内频率测试子块中 0/1 比例
累积和测试随机游走偏差
谱测试周期性特征
近似熵测试可预测性
线性复杂度测试LFSR 可预测性

4. TRNG 安全性考量

⚠️ 安全红线
✅Verilator验证通过
// trng_health.v - TRNG 健康检测模块
module trng_health (
    input  wire clk,
    input  wire rst_n,
    input  wire raw_bit,
    input  wire bit_valid,
    output wire health_ok,      // 健康状态
    output wire alarm           // 报警信号
);

    // 重复计数测试:检测连续相同位的数量
    reg [3:0] rep_count;
    reg       last_bit;
    reg       rep_alarm;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rep_count <= 0;
            last_bit <= 0;
            rep_alarm <= 0;
        end else if (bit_valid) begin
            if (raw_bit == last_bit) begin
                rep_count <= rep_count + 1;
                if (rep_count >= 12)  // NIST 建议:连续 12 个以上相同位报警
                    rep_alarm <= 1;
            end else begin
                rep_count <= 1;
                last_bit <= raw_bit;
            end
        end
    end

    // 自相关测试:检测输出序列的自相关性
    reg [31:0] shift_reg;
    reg [7:0]  autocorr_count;
    reg        autocorr_alarm;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            shift_reg <= 0;
            autocorr_count <= 0;
            autocorr_alarm <= 0;
        end else if (bit_valid) begin
            shift_reg <= {shift_reg[30:0], raw_bit};
            // 检测与 8 步前的相关性
            if (raw_bit == shift_reg[23])  // 8步延迟
                autocorr_count <= autocorr_count + 1;
            else
                autocorr_count <= 0;
            if (autocorr_count >= 16)
                autocorr_alarm <= 1;
        end
    end

    assign health_ok = ~rep_alarm & ~autocorr_alarm;
    assign alarm = rep_alarm | autocorr_alarm;

endmodule

1. 在 FPGA 上实现环形振荡器 TRNG,用逻辑分析仪捕获原始输出,运行 NIST 测试套件。

2. 比较不同数量环形振荡器(4、8、16)的统计质量。

3. 实现基于 SHA-256 的后处理器:将 512 位原始熵压缩为 256 位高质量随机数。

4. 思考:如果攻击者可以通过激光故障注入使某个环形振荡器停振,TRNG 的熵如何变化?

🏆 成就解锁:熵之源

你已掌握硬件真随机数生成器的设计:环形振荡器熵源、采样与合并、Von Neumann 后处理和健康检测。真随机数是密码系统的根基!

获得徽章:🎲 ENTROPY_SOURCE

💡 扩展阅读与参考资源

🔧 实践环境搭建

推荐使用以下工具链进行课程实践:

# 安装 Verilator
sudo apt install verilator

# 安装 Icarus Verilog(可选)
sudo apt install iverilog

# 安装 GTKWave(波形查看器)
sudo apt install gtkwave

# 验证安装
verilator --lint-only --version
iverilog -V

📊 性能指标对比

密码学硬件实现的关键性能指标:

这些指标之间通常存在 trade-off,设计时需根据应用场景权衡。

📚 本课知识图谱

本课涉及的核心概念和技术关系:

💡 调试技巧

Verilog 仿真调试的常用方法:

// 调试示例
initial begin
    $dumpfile("sim.vcd");
    $dumpvars(0, uut);
end

// 断言验证
assert property (@(posedge clk) valid |-> data !== 'x)
    else $error("Invalid data when valid!");

🔧 Verilator 编译仿真完整流程

# 1. 语法检查
verilator --lint-only module.v

# 2. 创建 C++ 测试主函数
cat > sim_main.cpp << 'EOF'
#include "Vmodule.h"
#include "verilated.h"
int main(int argc, char** argv) {
    Verilated::commandArgs(argc, argv);
    Vmodule* top = new Vmodule;
    top->clk = 0; top->rst_n = 0;
    top->eval();
    top->rst_n = 1;
    for (int i = 0; i < 100; i++) {
        top->clk = !top->clk;
        top->eval();
    }
    delete top;
    return 0;
}
EOF

# 3. 编译
verilator -cc module.v --exe sim_main.cpp
make -C obj_dir -f Vmodule.mk

# 4. 运行
./obj_dir/Vmodule

📖 推荐阅读

⚖️ 性能评估框架

密码硬件的性能评估维度:

指标单位说明
面积GE / LUT等效门数或查找表数量
频率MHz最大时钟频率
吞吐量Gbps每秒处理的数据量
延迟周期数从输入到输出的周期
能效pJ/bit每比特能耗
面积效率Gbps/GE单位面积吞吐量

不同应用场景对指标优先级不同:IoT 偏重面积和能效,服务器偏重吞吐量。