第09课:HMAC 硬件

阶段二哈希与认证 — HMAC(Hash-based Message Authentication Code)利用哈希函数和密钥提供消息认证。硬件实现需要复用 SHA-256 核心并高效处理双哈希计算。

1. HMAC 算法原理

HMAC 的核心思想是将密钥融入哈希计算:

HMAC(K, m) = H((K' ⊕ opad) ‖ H((K' ⊕ ipad) ‖ m))

其中:

2. HMAC 的安全性

HMAC 的安全性基于哈希函数的抗碰撞性。即使哈希函数的碰撞阻力被削弱,HMAC 可能仍然安全——这被称为"NMAC 安全性"。

3. HMAC 硬件架构

HMAC 需要两次哈希调用:内层哈希和外层哈希。硬件架构选择:

✅Verilator验证通过
// 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

4. HMAC 验证

// 测试向量: 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!");

🔧 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 偏重面积和能效,服务器偏重吞吐量。

📚 本课知识图谱

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

💡 调试技巧

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 偏重面积和能效,服务器偏重吞吐量。