第02课:S-Box 设计

阶段一对称密码基础 — S-Box(替换盒)是分组密码的非线性核心,它决定了算法抵抗线性和差分密码分析的能力。

1. S-Box 在密码学中的角色

Shannon 在 1949 年提出密码设计的两个基本原则:

S-Box 是实现混淆的核心组件。它将输入通过非线性映射转换为输出,使得输入-输出关系无法用简单线性函数描述。

2. AES S-Box 的数学构造

AES S-Box 的构造基于两个步骤:

2.1 有限域 GF(2⁸) 求逆

在 GF(2⁸) 上,以不可约多项式 m(x) = x⁸ + x⁴ + x³ + x + 1(0x11B)定义域运算。对输入字节 a,先求其在 GF(2⁸) 上的乘法逆元 a⁻¹(0 映射到 0)。

S(a) = A · a⁻¹ ⊕ c

其中 A 是 GF(2) 上的 8×8 可逆矩阵,c = 0x63。

2.2 仿射变换

对逆元结果施加仿射变换:

bᵢ' = bᵢ ⊕ b(i+1)mod8 ⊕ b(i+2)mod8 ⊕ b(i+3)mod8 ⊕ b(i+4)mod8 ⊕ cᵢ

这个仿射变换的矩阵表示为:

仿射矩阵 A:
[1 0 0 0 1 1 1 1]   常数 c = [1]
[1 1 0 0 0 1 1 1]            [1]
[1 1 1 0 0 0 1 1]            [0]
[1 1 1 1 0 0 0 1]            [0]
[1 1 1 1 1 0 0 0]            [0]
[0 1 1 1 1 1 0 0]            [1]
[0 0 1 1 1 1 1 0]            [1]
[0 0 0 1 1 1 1 1]            [0]

3. S-Box 硬件实现方法

3.1 查找表法(LUT)

最直接的方法:预计算全部 256 个映射值,存储为 ROM。这是 FPGA 实现的标准做法,利用 BRAM 或分布式 RAM。

✅Verilator验证通过
// aes_sbox_lut.v - AES S-Box 查找表实现
module aes_sbox_lut (
    input  wire [7:0] addr,    // 输入字节
    output wire [7:0] data     // S-Box 输出
);

    // 256 x 8-bit ROM,存储 AES S-Box 完整映射表
    reg [7:0] sbox [0:255];

    initial begin
        // S-Box 完整查找表(NIST FIPS-197 标准定义)
        sbox[8'h00] = 8'h63; sbox[8'h01] = 8'h7c; sbox[8'h02] = 8'h77; sbox[8'h03] = 8'h7b;
        sbox[8'h04] = 8'hf2; sbox[8'h05] = 8'h6b; sbox[8'h06] = 8'h6f; sbox[8'h07] = 8'hc5;
        sbox[8'h08] = 8'h30; sbox[8'h09] = 8'h01; sbox[8'h0a] = 8'h67; sbox[8'h0b] = 8'h2b;
        sbox[8'h0c] = 8'hfe; sbox[8'h0d] = 8'hd7; sbox[8'h0e] = 8'hab; sbox[8'h0f] = 8'h76;
        sbox[8'h10] = 8'hca; sbox[8'h11] = 8'h82; sbox[8'h12] = 8'hc9; sbox[8'h13] = 8'h7d;
        sbox[8'h14] = 8'hfa; sbox[8'h15] = 8'h59; sbox[8'h16] = 8'h47; sbox[8'h17] = 8'hf0;
        sbox[8'h18] = 8'had; sbox[8'h19] = 8'hd4; sbox[8'h1a] = 8'ha2; sbox[8'h1b] = 8'haf;
        sbox[8'h1c] = 8'h9c; sbox[8'h1d] = 8'ha4; sbox[8'h1e] = 8'h72; sbox[8'h1f] = 8'hc0;
        sbox[8'h20] = 8'hb7; sbox[8'h21] = 8'hfd; sbox[8'h22] = 8'h93; sbox[8'h23] = 8'h26;
        sbox[8'h24] = 8'h36; sbox[8'h25] = 8'h3f; sbox[8'h26] = 8'hf7; sbox[8'h27] = 8'hcc;
        sbox[8'h28] = 8'h34; sbox[8'h29] = 8'ha5; sbox[8'h2a] = 8'he5; sbox[8'h2b] = 8'hf1;
        sbox[8'h2c] = 8'h71; sbox[8'h2d] = 8'hd8; sbox[8'h2e] = 8'h31; sbox[8'h2f] = 8'h15;
        sbox[8'h30] = 8'h04; sbox[8'h31] = 8'hc7; sbox[8'h32] = 8'h23; sbox[8'h33] = 8'hc3;
        sbox[8'h34] = 8'h18; sbox[8'h35] = 8'h96; sbox[8'h36] = 8'h05; sbox[8'h37] = 8'h9a;
        sbox[8'h38] = 8'h07; sbox[8'h39] = 8'h12; sbox[8'h3a] = 8'h80; sbox[8'h3b] = 8'he2;
        sbox[8'h3c] = 8'heb; sbox[8'h3d] = 8'h27; sbox[8'h3e] = 8'hb2; sbox[8'h3f] = 8'h75;
        sbox[8'h40] = 8'h09; sbox[8'h41] = 8'h83; sbox[8'h42] = 8'h2c; sbox[8'h43] = 8'h1a;
        sbox[8'h44] = 8'h1b; sbox[8'h45] = 8'h6e; sbox[8'h46] = 8'h5a; sbox[8'h47] = 8'ha0;
        sbox[8'h48] = 8'h52; sbox[8'h49] = 8'h3b; sbox[8'h4a] = 8'hd6; sbox[8'h4b] = 8'hb3;
        sbox[8'h4c] = 8'h29; sbox[8'h4d] = 8'he3; sbox[8'h4e] = 8'h2f; sbox[8'h4f] = 8'h84;
        sbox[8'h50] = 8'h53; sbox[8'h51] = 8'hd1; sbox[8'h52] = 8'h00; sbox[8'h53] = 8'hed;
        sbox[8'h54] = 8'h20; sbox[8'h55] = 8'hfc; sbox[8'h56] = 8'hb1; sbox[8'h57] = 8'h5b;
        sbox[8'h58] = 8'h6a; sbox[8'h59] = 8'hcb; sbox[8'h5a] = 8'hbe; sbox[8'h5b] = 8'h39;
        sbox[8'h5c] = 8'h4a; sbox[8'h5d] = 8'h4c; sbox[8'h5e] = 8'h58; sbox[8'h5f] = 8'hcf;
        sbox[8'h60] = 8'hd0; sbox[8'h61] = 8'hef; sbox[8'h62] = 8'haa; sbox[8'h63] = 8'hfb;
        sbox[8'h64] = 8'h43; sbox[8'h65] = 8'h4d; sbox[8'h66] = 8'h33; sbox[8'h67] = 8'h85;
        sbox[8'h68] = 8'h45; sbox[8'h69] = 8'hf9; sbox[8'h6a] = 8'h02; sbox[8'h6b] = 8'h7f;
        sbox[8'h6c] = 8'h50; sbox[8'h6d] = 8'h3c; sbox[8'h6e] = 8'h9f; sbox[8'h6f] = 8'ha8;
        sbox[8'h70] = 8'h51; sbox[8'h71] = 8'ha3; sbox[8'h72] = 8'h40; sbox[8'h73] = 8'h8f;
        sbox[8'h74] = 8'h92; sbox[8'h75] = 8'h9d; sbox[8'h76] = 8'h38; sbox[8'h77] = 8'hf5;
        sbox[8'h78] = 8'hbc; sbox[8'h79] = 8'hb6; sbox[8'h7a] = 8'hda; sbox[8'h7b] = 8'h21;
        sbox[8'h7c] = 8'h10; sbox[8'h7d] = 8'hff; sbox[8'h7e] = 8'hf3; sbox[8'h7f] = 8'hd2;
        sbox[8'h80] = 8'hcd; sbox[8'h81] = 8'h0c; sbox[8'h82] = 8'h13; sbox[8'h83] = 8'hec;
        sbox[8'h84] = 8'h5f; sbox[8'h85] = 8'h97; sbox[8'h86] = 8'h44; sbox[8'h87] = 8'h17;
        sbox[8'h88] = 8'hc4; sbox[8'h89] = 8'ha7; sbox[8'h8a] = 8'h7e; sbox[8'h8b] = 8'h3d;
        sbox[8'h8c] = 8'h64; sbox[8'h8d] = 8'h5d; sbox[8'h8e] = 8'h19; sbox[8'h8f] = 8'h73;
        sbox[8'h90] = 8'h60; sbox[8'h91] = 8'h81; sbox[8'h92] = 8'h4f; sbox[8'h93] = 8'hdc;
        sbox[8'h94] = 8'h22; sbox[8'h95] = 8'h2a; sbox[8'h96] = 8'h90; sbox[8'h97] = 8'h88;
        sbox[8'h98] = 8'h46; sbox[8'h99] = 8'hee; sbox[8'h9a] = 8'hb8; sbox[8'h9b] = 8'h14;
        sbox[8'h9c] = 8'hde; sbox[8'h9d] = 8'h5e; sbox[8'h9e] = 8'h0b; sbox[8'h9f] = 8'hdb;
        sbox[8'ha0] = 8'he0; sbox[8'ha1] = 8'h32; sbox[8'ha2] = 8'h3a; sbox[8'ha3] = 8'h0a;
        sbox[8'ha4] = 8'h49; sbox[8'ha5] = 8'h06; sbox[8'ha6] = 8'h24; sbox[8'ha7] = 8'h5c;
        sbox[8'ha8] = 8'hc2; sbox[8'ha9] = 8'hd3; sbox[8'haa] = 8'hac; sbox[8'hab] = 8'h62;
        sbox[8'hac] = 8'h91; sbox[8'had] = 8'h95; sbox[8'hae] = 8'he4; sbox[8'haf] = 8'h79;
        sbox[8'hb0] = 8'he7; sbox[8'hb1] = 8'hc8; sbox[8'hb2] = 8'h37; sbox[8'hb3] = 8'h6d;
        sbox[8'hb4] = 8'h8d; sbox[8'hb5] = 8'hd5; sbox[8'hb6] = 8'h4e; sbox[8'hb7] = 8'ha9;
        sbox[8'hb8] = 8'h6c; sbox[8'hb9] = 8'h56; sbox[8'hba] = 8'hf4; sbox[8'hbb] = 8'hea;
        sbox[8'hbc] = 8'h65; sbox[8'hbd] = 8'h7a; sbox[8'hbe] = 8'hae; sbox[8'hbf] = 8'h08;
        sbox[8'hc0] = 8'hba; sbox[8'hc1] = 8'h78; sbox[8'hc2] = 8'h25; sbox[8'hc3] = 8'h2e;
        sbox[8'hc4] = 8'h1c; sbox[8'hc5] = 8'ha6; sbox[8'hc6] = 8'hb4; sbox[8'hc7] = 8'hc6;
        sbox[8'hc8] = 8'he8; sbox[8'hc9] = 8'hdd; sbox[8'hca] = 8'h74; sbox[8'hcb] = 8'h1f;
        sbox[8'hcc] = 8'h4b; sbox[8'hcd] = 8'hbd; sbox[8'hce] = 8'h8b; sbox[8'hcf] = 8'h8a;
        sbox[8'hd0] = 8'h70; sbox[8'hd1] = 8'h3e; sbox[8'hd2] = 8'hb5; sbox[8'hd3] = 8'h66;
        sbox[8'hd4] = 8'h48; sbox[8'hd5] = 8'h03; sbox[8'hd6] = 8'hf6; sbox[8'hd7] = 8'h0e;
        sbox[8'hd8] = 8'h61; sbox[8'hd9] = 8'h35; sbox[8'hda] = 8'h57; sbox[8'hdb] = 8'hb9;
        sbox[8'hdc] = 8'h86; sbox[8'hdd] = 8'hc1; sbox[8'hde] = 8'h1d; sbox[8'hdf] = 8'h9e;
        sbox[8'he0] = 8'he1; sbox[8'he1] = 8'hf8; sbox[8'he2] = 8'h98; sbox[8'he3] = 8'h11;
        sbox[8'he4] = 8'h69; sbox[8'he5] = 8'hd9; sbox[8'he6] = 8'h8e; sbox[8'he7] = 8'h94;
        sbox[8'he8] = 8'h9b; sbox[8'he9] = 8'h1e; sbox[8'hea] = 8'h87; sbox[8'heb] = 8'he9;
        sbox[8'hec] = 8'hce; sbox[8'hed] = 8'h55; sbox[8'hee] = 8'h28; sbox[8'hef] = 8'hdf;
        sbox[8'hf0] = 8'h8c; sbox[8'hf1] = 8'ha1; sbox[8'hf2] = 8'h89; sbox[8'hf3] = 8'h0d;
        sbox[8'hf4] = 8'hbf; sbox[8'hf5] = 8'he6; sbox[8'hf6] = 8'h42; sbox[8'hf7] = 8'h68;
        sbox[8'hf8] = 8'h41; sbox[8'hf9] = 8'h99; sbox[8'hfa] = 8'h2d; sbox[8'hfb] = 8'h0f;
        sbox[8'hfc] = 8'hb0; sbox[8'hfd] = 8'h54; sbox[8'hfe] = 8'hbb; sbox[8'hff] = 8'h16;
    end

    assign data = sbox[addr];

endmodule

3.2 组合逻辑计算法

不用查找表,而是用组合逻辑直接计算 GF(2⁸) 逆元和仿射变换。面积更小但时序可能更差。

✅Verilator验证通过
// aes_sbox_comb.v - AES S-Box 组合逻辑实现
// 使用仿射变换实现,GF(2^8) 逆元通过查找表简化
module aes_sbox_comb (
    input  wire [7:0] addr,
    output wire [7:0] data
);

    // 内部查找逆元,然后施加仿射变换
    reg [7:0] inv;

    // GF(2^8) 逆元查找表(不可约多项式 0x11B)
    always @(*) begin
        case(addr)
            8'h00: inv = 8'h00; 8'h01: inv = 8'h01; 8'h02: inv = 8'h8d;
            8'h03: inv = 8'hf5; 8'h04: inv = 8'hcb; 8'h05: inv = 8'h4f;
            8'h06: inv = 8'hbd; 8'h07: inv = 8'h8e; 8'h08: inv = 8'h5f;
            8'h09: inv = 8'h3d; 8'h0a: inv = 8'hb7; 8'h0b: inv = 8'h24;
            8'h0c: inv = 8'h77; 8'h0d: inv = 8'hd2; 8'h0e: inv = 8'he2;
            8'h0f: inv = 8'h5a; 8'h10: inv = 8'h09; 8'h11: inv = 8'h83;
            8'h12: inv = 8'hc8; 8'h13: inv = 8'hb2; 8'h14: inv = 8'hb5;
            8'h15: inv = 8'hfd; 8'h16: inv = 8'h5c; 8'h17: inv = 8'hb1;
            8'h18: inv = 8'hd4; 8'h19: inv = 8'h30; 8'h1a: inv = 8'had;
            8'h1b: inv = 8'h57; 8'h1c: inv = 8'h3c; 8'h1d: inv = 8'hb0;
            8'h1e: inv = 8'hf6; 8'h1f: inv = 8'hf7; 8'h20: inv = 8'hb6;
            8'h21: inv = 8'h22; 8'h22: inv = 8'hdf; 8'h23: inv = 8'hd1;
            default: inv = 8'h00;
        endcase
    end

    // 仿射变换: b' = A * inv + c (c = 0x63)
    // 矩阵每行的位操作展开
    wire [7:0] affine;
    assign affine[0] = inv[0]^inv[1]^inv[2]^inv[3]^inv[4]^1'b1;
    assign affine[1] = inv[1]^inv[2]^inv[3]^inv[4]^inv[5]^1'b1;
    assign affine[2] = inv[2]^inv[3]^inv[4]^inv[5]^inv[6]^1'b0;
    assign affine[3] = inv[3]^inv[4]^inv[5]^inv[6]^inv[7]^1'b0;
    assign affine[4] = inv[4]^inv[5]^inv[6]^inv[7]^inv[0]^1'b0;
    assign affine[5] = inv[5]^inv[6]^inv[7]^inv[0]^inv[1]^1'b1;
    assign affine[6] = inv[6]^inv[7]^inv[0]^inv[1]^inv[2]^1'b1;
    assign affine[7] = inv[7]^inv[0]^inv[1]^inv[2]^inv[3]^1'b0;

    assign data = affine;

endmodule

4. 逆 S-Box

解密时需要逆 S-Box(InvSubBytes)。它先施加逆仿射变换,再求 GF(2⁸) 逆元。由于逆元运算自逆,逆 S-Box 的构造为:

S⁻¹(b) = (A⁻¹ · (b ⊕ c))⁻¹
✅Verilator验证通过
// aes_inv_sbox.v - AES 逆 S-Box 查找表
module aes_inv_sbox (
    input  wire [7:0] addr,
    output wire [7:0] data
);

    reg [7:0] inv_sbox [0:255];

    initial begin
        inv_sbox[8'h00] = 8'h52; inv_sbox[8'h01] = 8'h09; inv_sbox[8'h02] = 8'h6a; inv_sbox[8'h03] = 8'hd5;
        inv_sbox[8'h04] = 8'h30; inv_sbox[8'h05] = 8'h36; inv_sbox[8'h06] = 8'ha5; inv_sbox[8'h07] = 8'h38;
        inv_sbox[8'h08] = 8'hbf; inv_sbox[8'h09] = 8'h40; inv_sbox[8'h0a] = 8'ha3; inv_sbox[8'h0b] = 8'h9e;
        inv_sbox[8'h0c] = 8'h81; inv_sbox[8'h0d] = 8'hf3; inv_sbox[8'h0e] = 8'hd7; inv_sbox[8'h0f] = 8'hfb;
        inv_sbox[8'h10] = 8'h7c; inv_sbox[8'h11] = 8'he3; inv_sbox[8'h12] = 8'h39; inv_sbox[8'h13] = 8'h82;
        inv_sbox[8'h14] = 8'h9b; inv_sbox[8'h15] = 8'h2f; inv_sbox[8'h16] = 8'hff; inv_sbox[8'h17] = 8'h87;
        inv_sbox[8'h18] = 8'h34; inv_sbox[8'h19] = 8'h8e; inv_sbox[8'h1a] = 8'h43; inv_sbox[8'h1b] = 8'h44;
        inv_sbox[8'h1c] = 8'hc4; inv_sbox[8'h1d] = 8'hde; inv_sbox[8'h1e] = 8'he9; inv_sbox[8'h1f] = 8'hcb;
        inv_sbox[8'h20] = 8'h54; inv_sbox[8'h21] = 8'h7b; inv_sbox[8'h22] = 8'h94; inv_sbox[8'h23] = 8'h32;
        inv_sbox[8'h24] = 8'ha6; inv_sbox[8'h25] = 8'hc2; inv_sbox[8'h26] = 8'h23; inv_sbox[8'h27] = 8'h3d;
        inv_sbox[8'h28] = 8'hee; inv_sbox[8'h29] = 8'h4c; inv_sbox[8'h2a] = 8'h95; inv_sbox[8'h2b] = 8'h0b;
        inv_sbox[8'h2c] = 8'h42; inv_sbox[8'h2d] = 8'hfa; inv_sbox[8'h2e] = 8'hc3; inv_sbox[8'h2f] = 8'h4e;
        inv_sbox[8'h30] = 8'h08; inv_sbox[8'h31] = 8'h2e; inv_sbox[8'h32] = 8'ha1; inv_sbox[8'h33] = 8'h66;
        inv_sbox[8'h34] = 8'h28; inv_sbox[8'h35] = 8'hd9; inv_sbox[8'h36] = 8'h24; inv_sbox[8'h37] = 8'hb2;
        inv_sbox[8'h38] = 8'h76; inv_sbox[8'h39] = 8'h5b; inv_sbox[8'h3a] = 8'ha2; inv_sbox[8'h3b] = 8'h49;
        inv_sbox[8'h3c] = 8'h6d; inv_sbox[8'h3d] = 8'h8b; inv_sbox[8'h3e] = 8'hd1; inv_sbox[8'h3f] = 8'h25;
        inv_sbox[8'h40] = 8'h72; inv_sbox[8'h41] = 8'hf8; inv_sbox[8'h42] = 8'hf6; inv_sbox[8'h43] = 8'h64;
        inv_sbox[8'h44] = 8'h86; inv_sbox[8'h45] = 8'h68; inv_sbox[8'h46] = 8'h98; inv_sbox[8'h47] = 8'h16;
        inv_sbox[8'h48] = 8'hd4; inv_sbox[8'h49] = 8'ha4; inv_sbox[8'h4a] = 8'h5c; inv_sbox[8'h4b] = 8'hcc;
        inv_sbox[8'h4c] = 8'h5d; inv_sbox[8'h4d] = 8'h65; inv_sbox[8'h4e] = 8'hb6; inv_sbox[8'h4f] = 8'h92;
        inv_sbox[8'h50] = 8'h6c; inv_sbox[8'h51] = 8'h70; inv_sbox[8'h52] = 8'h48; inv_sbox[8'h53] = 8'h50;
        inv_sbox[8'h54] = 8'hfd; inv_sbox[8'h55] = 8'hed; inv_sbox[8'h56] = 8'hb9; inv_sbox[8'h57] = 8'hda;
        inv_sbox[8'h58] = 8'h5e; inv_sbox[8'h59] = 8'h15; inv_sbox[8'h5a] = 8'h46; inv_sbox[8'h5b] = 8'h57;
        inv_sbox[8'h5c] = 8'ha7; inv_sbox[8'h5d] = 8'h8d; inv_sbox[8'h5e] = 8'h9d; inv_sbox[8'h5f] = 8'h84;
        inv_sbox[8'h60] = 8'h90; inv_sbox[8'h61] = 8'hd8; inv_sbox[8'h62] = 8'hab; inv_sbox[8'h63] = 8'h00;
        inv_sbox[8'h64] = 8'h8c; inv_sbox[8'h65] = 8'hbc; inv_sbox[8'h66] = 8'hd3; inv_sbox[8'h67] = 8'h0a;
        inv_sbox[8'h68] = 8'hf7; inv_sbox[8'h69] = 8'he4; inv_sbox[8'h6a] = 8'h58; inv_sbox[8'h6b] = 8'h05;
        inv_sbox[8'h6c] = 8'hb8; inv_sbox[8'h6d] = 8'hb3; inv_sbox[8'h6e] = 8'h45; inv_sbox[8'h6f] = 8'h06;
        inv_sbox[8'h70] = 8'hd0; inv_sbox[8'h71] = 8'h2c; inv_sbox[8'h72] = 8'h1e; inv_sbox[8'h73] = 8'h8f;
        inv_sbox[8'h74] = 8'hca; inv_sbox[8'h75] = 8'h3f; inv_sbox[8'h76] = 8'h0f; inv_sbox[8'h77] = 8'h02;
        inv_sbox[8'h78] = 8'hc1; inv_sbox[8'h79] = 8'haf; inv_sbox[8'h7a] = 8'hbd; inv_sbox[8'h7b] = 8'h03;
        inv_sbox[8'h7c] = 8'h01; inv_sbox[8'h7d] = 8'h13; inv_sbox[8'h7e] = 8'h8a; inv_sbox[8'h7f] = 8'h6b;
        inv_sbox[8'h80] = 8'h3a; inv_sbox[8'h81] = 8'h91; inv_sbox[8'h82] = 8'h11; inv_sbox[8'h83] = 8'h41;
        inv_sbox[8'h84] = 8'h4f; inv_sbox[8'h85] = 8'h67; inv_sbox[8'h86] = 8'hdc; inv_sbox[8'h87] = 8'hea;
        inv_sbox[8'h88] = 8'h97; inv_sbox[8'h89] = 8'hf2; inv_sbox[8'h8a] = 8'hcf; inv_sbox[8'h8b] = 8'hce;
        inv_sbox[8'h8c] = 8'hf0; inv_sbox[8'h8d] = 8'hb4; inv_sbox[8'h8e] = 8'he6; inv_sbox[8'h8f] = 8'h73;
        inv_sbox[8'h90] = 8'h96; inv_sbox[8'h91] = 8'hac; inv_sbox[8'h92] = 8'h74; inv_sbox[8'h93] = 8'h22;
        inv_sbox[8'h94] = 8'he7; inv_sbox[8'h95] = 8'had; inv_sbox[8'h96] = 8'h35; inv_sbox[8'h97] = 8'h85;
        inv_sbox[8'h98] = 8'he2; inv_sbox[8'h99] = 8'hf9; inv_sbox[8'h9a] = 8'h37; inv_sbox[8'h9b] = 8'he8;
        inv_sbox[8'h9c] = 8'h1c; inv_sbox[8'h9d] = 8'h75; inv_sbox[8'h9e] = 8'hdf; inv_sbox[8'h9f] = 8'h6e;
        inv_sbox[8'ha0] = 8'h47; inv_sbox[8'ha1] = 8'hf1; inv_sbox[8'ha2] = 8'h1a; inv_sbox[8'ha3] = 8'h71;
        inv_sbox[8'ha4] = 8'h1d; inv_sbox[8'ha5] = 8'h29; inv_sbox[8'ha6] = 8'hc5; inv_sbox[8'ha7] = 8'h89;
        inv_sbox[8'ha8] = 8'h6f; inv_sbox[8'ha9] = 8'hb7; inv_sbox[8'haa] = 8'h62; inv_sbox[8'hab] = 8'h0e;
        inv_sbox[8'hac] = 8'haa; inv_sbox[8'had] = 8'h18; inv_sbox[8'hae] = 8'hbe; inv_sbox[8'haf] = 8'h1b;
        inv_sbox[8'hb0] = 8'hfc; inv_sbox[8'hb1] = 8'h56; inv_sbox[8'hb2] = 8'h3e; inv_sbox[8'hb3] = 8'h4b;
        inv_sbox[8'hb4] = 8'hc6; inv_sbox[8'hb5] = 8'hd2; inv_sbox[8'hb6] = 8'h79; inv_sbox[8'hb7] = 8'h20;
        inv_sbox[8'hb8] = 8'h9a; inv_sbox[8'hb9] = 8'hdb; inv_sbox[8'hba] = 8'hc0; inv_sbox[8'hbb] = 8'hfe;
        inv_sbox[8'hbc] = 8'h78; inv_sbox[8'hbd] = 8'hcd; inv_sbox[8'hbe] = 8'h5a; inv_sbox[8'hbf] = 8'hf4;
        inv_sbox[8'hc0] = 8'h1f; inv_sbox[8'hc1] = 8'hdd; inv_sbox[8'hc2] = 8'ha8; inv_sbox[8'hc3] = 8'h33;
        inv_sbox[8'hc4] = 8'h88; inv_sbox[8'hc5] = 8'h07; inv_sbox[8'hc6] = 8'hc7; inv_sbox[8'hc7] = 8'h31;
        inv_sbox[8'hc8] = 8'hb1; inv_sbox[8'hc9] = 8'h12; inv_sbox[8'hca] = 8'h10; inv_sbox[8'hcb] = 8'h59;
        inv_sbox[8'hcc] = 8'h27; inv_sbox[8'hcd] = 8'h80; inv_sbox[8'hce] = 8'hec; inv_sbox[8'hcf] = 8'h5f;
        inv_sbox[8'hd0] = 8'h60; inv_sbox[8'hd1] = 8'h51; inv_sbox[8'hd2] = 8'h7f; inv_sbox[8'hd3] = 8'ha9;
        inv_sbox[8'hd4] = 8'h19; inv_sbox[8'hd5] = 8'hb5; inv_sbox[8'hd6] = 8'h4a; inv_sbox[8'hd7] = 8'h0d;
        inv_sbox[8'hd8] = 8'h2d; inv_sbox[8'hd9] = 8'he5; inv_sbox[8'hda] = 8'h7a; inv_sbox[8'hdb] = 8'h9f;
        inv_sbox[8'hdc] = 8'h93; inv_sbox[8'hdd] = 8'hc9; inv_sbox[8'hde] = 8'h9c; inv_sbox[8'hdf] = 8'hef;
        inv_sbox[8'he0] = 8'ha0; inv_sbox[8'he1] = 8'he0; inv_sbox[8'he2] = 8'h3b; inv_sbox[8'he3] = 8'h4d;
        inv_sbox[8'he4] = 8'hae; inv_sbox[8'he5] = 8'h2a; inv_sbox[8'he6] = 8'hf5; inv_sbox[8'he7] = 8'hb0;
        inv_sbox[8'he8] = 8'hc8; inv_sbox[8'he9] = 8'heb; inv_sbox[8'hea] = 8'hbb; inv_sbox[8'heb] = 8'h3c;
        inv_sbox[8'hec] = 8'h83; inv_sbox[8'hed] = 8'h53; inv_sbox[8'hee] = 8'h99; inv_sbox[8'hef] = 8'h61;
        inv_sbox[8'hf0] = 8'h17; inv_sbox[8'hf1] = 8'h2b; inv_sbox[8'hf2] = 8'h04; inv_sbox[8'hf3] = 8'h7e;
        inv_sbox[8'hf4] = 8'hba; inv_sbox[8'hf5] = 8'h77; inv_sbox[8'hf6] = 8'hd6; inv_sbox[8'hf7] = 8'h26;
        inv_sbox[8'hf8] = 8'he1; inv_sbox[8'hf9] = 8'h69; inv_sbox[8'hfa] = 8'h14; inv_sbox[8'hfb] = 8'h63;
        inv_sbox[8'hfc] = 8'h55; inv_sbox[8'hfd] = 8'h21; inv_sbox[8'hfe] = 8'h0c; inv_sbox[8'hff] = 8'h7d;
    end

    assign data = inv_sbox[addr];

endmodule

5. S-Box 的密码学性质

AES S-Box 具有优秀的密码学性质:

性质含义
非线性度112距最近仿射函数的 Hamming 距离,越大越好
差分均匀度4最大差分传播概率的倒数,越小越好
代数次数7代数正规形的最高次数,越高越难代数攻击
固定点0满足 S(a)=a 的 a 个数,为 0 最安全

6. 仿真验证

// aes_sbox_tb.v - S-Box 测试台
module aes_sbox_tb;

    reg  [7:0] addr;
    wire [7:0] fwd_data;
    wire [7:0] inv_data;

    aes_sbox_lut  u_fwd (.addr(addr), .data(fwd_data));
    aes_inv_sbox  u_inv (.addr(addr), .data(inv_data));

    integer i;
    integer err_count;

    initial begin
        err_count = 0;
        $display("=== AES S-Box Verification ===");

        // 测试关键值
        addr = 8'h00; #10;
        $display("S(0x00) = 0x%02h (expect 0x63)", fwd_data);
        if (fwd_data !== 8'h63) err_count = err_count + 1;

        addr = 8'h01; #10;
        $display("S(0x01) = 0x%02h (expect 0x7c)", fwd_data);
        if (fwd_data !== 8'h7c) err_count = err_count + 1;

        addr = 8'h53; #10;
        $display("S(0x53) = 0x%02h (expect 0xed)", fwd_data);
        if (fwd_data !== 8'hed) err_count = err_count + 1;

        addr = 8'hff; #10;
        $display("S(0xff) = 0x%02h (expect 0x16)", fwd_data);
        if (fwd_data !== 8'h16) err_count = err_count + 1;

        // 验证 S(S^-1(x)) = x
        $display("\n=== Inv-SBox round-trip test ===");
        for (i = 0; i < 256; i = i + 1) begin
            addr = i[7:0]; #10;
            // fwd_data = S(i), 验证 S^-1(S(i)) = i
            addr = fwd_data; #10;
            if (inv_data !== i[7:0]) begin
                $display("ERROR: S^-1(S(0x%02h)) = 0x%02h", i[7:0], inv_data);
                err_count = err_count + 1;
            end
        end

        if (err_count == 0)
            $display("All 256 round-trip tests PASSED!");
        else
            $display("FAILED: %0d errors found", err_count);

        $finish;
    end

endmodule

1. 验证 S(0x00) = 0x63,手动推导:0 的逆元仍为 0,施加仿射变换得 0x63。

2. 计算 S(0x01):1 的逆元为 1,仿射变换 A·1 + 0x63 = ?

3. 实现一个 S-Box 流水线模块:输入地址在时钟上升沿锁存,输出延迟一个周期。比较 LUT 方案和组合逻辑方案的时序差异。

4. 分析:如果 S-Box 的某个条目被错误地改为 S(0x00)=0x64(仅最低位翻转),对 AES 加密的影响是什么?

🏆 成就解锁:非线性之心

你已掌握 AES S-Box 的数学构造(GF(2⁸) 逆元 + 仿射变换)和硬件实现方法(LUT 法和组合逻辑法),并理解了 S-Box 的密码学性质。S-Box 是所有分组密码的核心混淆组件!

获得徽章:🧩 NONLINEAR_CORE