阶段二哈希与认证 — HMAC(Hash-based Message Authentication Code)利用哈希函数和密钥提供消息认证。硬件实现需要复用 SHA-256 核心并高效处理双哈希计算。
HMAC 的核心思想是将密钥融入哈希计算:
其中:
HMAC 的安全性基于哈希函数的抗碰撞性。即使哈希函数的碰撞阻力被削弱,HMAC 可能仍然安全——这被称为"NMAC 安全性"。
HMAC 需要两次哈希调用:内层哈希和外层哈希。硬件架构选择:
// hmac_sha256.v - HMAC-SHA256 硬件实现
module hmac_sha256 (
input wire clk,
input wire rst_n,
input wire start,
input wire [255:0] key, // 256位密钥
input wire [511:0] msg_block, // 消息块
input wire msg_valid,
input wire msg_last,
output reg [255:0] mac, // HMAC 输出
output reg mac_valid
);
// 状态机
localparam IDLE = 3'd0;
localparam INNER_H = 3'd1; // 内层哈希
localparam OUTER_H = 3'd2; // 外层哈希
localparam DONE = 3'd3;
reg [2:0] state;
reg [255:0] inner_hash;
reg [255:0] hash_state;
// SHA-256 核心实例
reg sha_start, sha_block_valid, sha_last;
reg [511:0] sha_block;
wire [255:0] sha_digest;
wire sha_digest_valid;
sha256_engine u_sha (
.clk(clk), .rst_n(rst_n), .start(sha_start),
.block(sha_block), .block_valid(sha_block_valid),
.last_block(sha_last),
.digest(sha_digest), .digest_valid(sha_digest_valid)
);
// 生成 ipad 和 opad 块
// SHA-256 块大小 = 64 字节 = 512 位
// K ⊕ ipad: 每字节 K[i] ^ 0x36
// K ⊕ opad: 每字节 K[i] ^ 0x5c
reg [511:0] ipad_block, opad_block;
integer j;
always @(*) begin
for (j = 0; j < 64; j = j + 1) begin
ipad_block[j*8+7 -: 8] = key[j*4+7 -: 8] ^ 8'h36;
opad_block[j*8+7 -: 8] = key[j*4+7 -: 8] ^ 8'h5c;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE; mac <= 0; mac_valid <= 0;
sha_start <= 0; sha_block_valid <= 0; sha_last <= 0;
inner_hash <= 0;
end else begin
mac_valid <= 0;
sha_block_valid <= 0;
sha_start <= 0;
case (state)
IDLE: begin
if (start) begin
sha_start <= 1;
state <= INNER_H;
end
end
INNER_H: begin
// 先发送 ipad 块
sha_block <= ipad_block;
sha_block_valid <= 1;
sha_last <= 0;
// 然后发送消息块
if (msg_valid) begin
sha_block <= msg_block;
sha_block_valid <= 1;
sha_last <= msg_last;
end
if (sha_digest_valid && msg_last) begin
inner_hash <= sha_digest;
sha_start <= 1;
state <= OUTER_H;
end
end
OUTER_H: begin
sha_block <= opad_block;
sha_block_valid <= 1;
sha_last <= 0;
// 第二块:inner_hash 作为消息
sha_block <= {inner_hash, 256'h0};
sha_block_valid <= 1;
sha_last <= 1;
if (sha_digest_valid) begin
mac <= sha_digest;
mac_valid <= 1;
state <= IDLE;
end
end
endcase
end
end
endmodule
// 测试向量: HMAC-SHA256(key="", msg="") =
// b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad
module hmac_sha256_tb;
reg clk, rst_n, start, msg_valid, msg_last;
reg [255:0] key;
reg [511:0] msg_block;
wire [255:0] mac;
wire mac_valid;
hmac_sha256 uut (.*);
always #5 clk = ~clk;
initial begin
clk=0; rst_n=0; start=0;
#20 rst_n=1;
key = 256'h0;
start = 1; #10; start = 0;
msg_block = 512'h0; msg_valid = 1; msg_last = 1;
#10; msg_valid = 0;
wait(mac_valid);
$display("HMAC = %064h", mac);
$finish;
end
endmodule
1. 实现 HMAC-SHA256 的分块消息处理:支持任意长度的消息输入。
2. 优化:预计算 ipad 和 opad 块的哈希值(对于固定密钥),减少重复计算。
3. 分析 HMAC 的时序安全性与底层哈希函数的关系。
4. 设计一个支持多种哈希算法的 HMAC 模块(SHA-256、SHA-512),通过参数化选择。
你已掌握 HMAC 的原理和硬件实现,理解了内层/外层哈希的协同工作。HMAC 是 TLS、IPSec 等协议的核心认证组件!
获得徽章:🛡️ HMAC_GUARDIAN
推荐使用以下工具链进行课程实践:
# 安装 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 偏重面积和能效,服务器偏重吞吐量。
本课涉及的核心概念和技术关系:
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 偏重面积和能效,服务器偏重吞吐量。