阶段二哈希与认证 — 真随机数是密码学的根基。密钥生成、 nonce、盐值都需要不可预测的随机源。硬件 TRNG 利用物理噪声产生真随机数。
密码学中的随机数必须满足:
环形振荡器是 FPGA 上最常用的熵源。奇数个反相器首尾相连形成振荡,由于热噪声和电源抖动,频率和相位具有随机性。
// 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
典型 TRNG 架构:多个环形振荡器采样 → 异或合并 → 后处理(von Neumann 或 SHA 压缩):
// 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
TRNG 的输出必须通过统计测试验证其随机性:
| 测试 | 检测目标 |
|---|---|
| 频率测试 | 0 和 1 的比例 |
| 游程测试 | 连续 0/1 序列长度分布 |
| 块内频率测试 | 子块中 0/1 比例 |
| 累积和测试 | 随机游走偏差 |
| 谱测试 | 周期性特征 |
| 近似熵测试 | 可预测性 |
| 线性复杂度测试 | LFSR 可预测性 |
// 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!");
# 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 偏重面积和能效,服务器偏重吞吐量。