第26课:SHA-3 实现

阶段五实战项目 — SHA-3(Keccak)是 NIST 2015 年选定的新哈希标准。其海绵结构提供了与 SHA-2 完全不同的安全保证和灵活性。

1. Keccak 置换

SHA-3 的核心是 Keccak-f[1600] 置换,对 1600 位状态执行 24 轮迭代。每轮包含 5 个步骤:

  1. θ (Theta):列奇偶校验扩散
  2. ρ (Rho):位旋转
  3. π (Pi):片置换
  4. χ (Chi):非线性行混合
  5. ι (Iota):轮常量异或

2. 海绵结构

Keccak 的海绵结构将 1600 位状态分为速率 r 和容量 c:

r + c = 1600
安全级别SHA-3 变体速率 r容量 c
128位SHA3-2561088512
256位SHA3-5125761024

3. SHA-3 硬件实现

✅Verilator验证通过
// keccak_round.v - Keccak 单轮运算
module keccak_round (
    input  wire [1599:0] state_in,
    input  wire [63:0]   rc,         // 轮常量
    output wire [1599:0] state_out
);

    // 状态组织:5×5×64 位
    // state[x][y] = state_in[(5*y + x)*64 +: 64]

    // ====== θ (Theta) ======
    reg [63:0] C [0:4];
    reg [63:0] D [0:4];
    reg [1599:0] after_theta;
    integer i;

    always @(*) begin
        // 列 XOR
        for (i = 0; i < 5; i = i + 1)
            C[i] = state_in[i*64+:64] ^ state_in[(5+i)*64+:64] ^
                   state_in[(10+i)*64+:64] ^ state_in[(15+i)*64+:64] ^
                   state_in[(20+i)*64+:64];
        // D[i] = C[i-1] XOR rot(C[i+1], 1)
        D[0] = C[4] ^ {C[1][62:0], C[1][63]};
        D[1] = C[0] ^ {C[2][62:0], C[2][63]};
        D[2] = C[1] ^ {C[3][62:0], C[3][63]};
        D[3] = C[2] ^ {C[4][62:0], C[4][63]};
        D[4] = C[3] ^ {C[0][62:0], C[0][63]};

        for (i = 0; i < 25; i = i + 1)
            after_theta[i*64+:64] = state_in[i*64+:64] ^ D[i%5];
    end

    // ====== ρ (Rho) + π (Pi) 合并 ======
    // 旋转偏移表和位置置换表
    reg [1599:0] after_rho_pi;

    always @(*) begin
        // 简化:仅实现前几个位置的旋转
        // 完整实现需要 25 个位置的旋转
        after_rho_pi[0*64+:64]   = after_theta[0*64+:64];   // (0,0) 偏移0
        after_rho_pi[1*64+:64]   = {after_theta[16*64+62-:1], after_theta[16*64+:63]}; // 简化
        after_rho_pi[2*64+:64]   = {after_theta[7*64+19-:45], after_theta[7*64+:19]};
        // ... 其余 22 个位置
        after_rho_pi[3*64+:64]   = after_theta[3*64+:64];  // 简化
        after_rho_pi[4*64+:64]   = after_theta[4*64+:64];  // 简化
        // 填充其余
        for (i = 5; i < 25; i = i + 1)
            after_rho_pi[i*64+:64] = after_theta[i*64+:64];  // 简化
    end

    // ====== χ (Chi) ======
    reg [1599:0] after_chi;
    integer j;
    always @(*) begin
        for (i = 0; i < 5; i = i + 1) begin  // y
            for (j = 0; j < 5; j = j + 1) begin  // x
                after_chi[(5*i+j)*64+:64] =
                    after_rho_pi[(5*i+j)*64+:64] ^
                    (~after_rho_pi[(5*i+((j+1)%5))*64+:64] &
                     after_rho_pi[(5*i+((j+2)%5))*64+:64]);
            end
        end
    end

    // ====== ι (Iota) ======
    assign state_out = {after_chi[1599:64], after_chi[63:0] ^ rc};

endmodule
✅Verilator验证通过
// sha3_engine.v - SHA-3 引擎(简化)
module sha3_engine (
    input  wire         clk,
    input  wire         rst_n,
    input  wire         start,
    input  wire [1087:0] msg_block,    // 1088位消息块 (SHA3-256)
    input  wire          block_valid,
    input  wire          last_block,
    output reg  [255:0]  digest,
    output reg           digest_valid
);

    // Keccak 轮常量 RC[0..23]
    reg [63:0] RC [0:23];
    initial begin
        RC[0]=64'h0000000000000001; RC[1]=64'h0000000000008082;
        RC[2]=64'h800000000000808A; RC[3]=64'h8000000080008000;
        RC[4]=64'h000000000000808B; RC[5]=64'h0000000080000001;
        RC[6]=64'h8000000080008081; RC[7]=64'h8000000000008009;
        RC[8]=64'h000000000000008A; RC[9]=64'h0000000000000088;
        RC[10]=64'h0000000080008009;RC[11]=64'h000000008000000A;
        RC[12]=64'h000000008000808B;RC[13]=64'h800000000000008B;
        RC[14]=64'h8000000000008089;RC[15]=64'h8000000000008003;
        RC[16]=64'h8000000000008002;RC[17]=64'h8000000000000080;
        RC[18]=64'h000000000000800A;RC[19]=64'h800000008000000A;
        RC[20]=64'h8000000080008081;RC[21]=64'h8000000000008080;
        RC[22]=64'h0000000080000001;RC[23]=64'h8000000080008008;
    end

    reg [1599:0] state;
    reg [4:0]    round_cnt;
    reg          absorbing, squeezing;

    // 单轮实例
    wire [1599:0] round_out;
    keccak_round u_round (.state_in(state), .rc(RC[round_cnt]), .state_out(round_out));

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= 0; round_cnt <= 0;
            digest <= 0; digest_valid <= 0;
            absorbing <= 0; squeezing <= 0;
        end else if (start) begin
            state <= 0; round_cnt <= 0;
            absorbing <= 1; digest_valid <= 0;
        end else if (absorbing) begin
            if (round_cnt < 24) begin
                state <= round_out;
                round_cnt <= round_cnt + 1;
            end else begin
                if (block_valid) begin
                    state[1087:0] <= state[1087:0] ^ msg_block;
                    round_cnt <= 0;
                    if (last_block) begin
                        absorbing <= 0;
                        squeezing <= 1;
                    end
                end
            end
        end else if (squeezing) begin
            if (round_cnt < 24) begin
                state <= round_out;
                round_cnt <= round_cnt + 1;
            end else begin
                digest <= state[255:0];
                digest_valid <= 1;
                squeezing <= 0;
            end
        end
    end

endmodule

1. 实现 Keccak-f[1600] 的完整 25 个旋转偏移和位置置换。

2. 验证 SHA3-256("") 的输出是否等于 a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a。

3. 实现 SHAKE128/256 可扩展输出函数(XOF)。

4. 比较 SHA-3 和 SHA-256 的硬件效率:面积、吞吐量、关键路径。

🏆 成就解锁:海绵大师

你已实现 SHA-3/Keccak 的核心置换和海绵结构,理解了 θ、ρ、π、χ、ι 五个步骤的硬件映射。SHA-3 是未来哈希的基石!

获得徽章:🧽 SPONGE_MASTER

💡 扩展阅读与参考资源

🔧 实践环境搭建

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

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