C语言实现Rijndael S-box计算函数结果异常,请问问题出在哪里
代码错误原因
你实现的逻辑只有Rijndael S-box的仿射变换步骤,缺少了前置的GF(2⁸)有限域乘法逆元计算步骤,这是结果偏差的核心原因。
Rijndael S-box的完整计算流程为:
- 处理输入字节
b:如果b == 0x00,则中间值x = 0x00;否则计算b在GF(2⁸)(不可约多项式为x⁸+x⁴+x³+x+1,对应值0x11B)下的乘法逆元,赋值给x - 对
x执行你代码中写的仿射变换:s = x ^ ROTL8(x,1) ^ ROTL8(x,2) ^ ROTL8(x,3) ^ ROTL8(x,4) ^ 0x63,得到最终S盒输出
你测的前两个值刚好正确属于巧合:
0x00的逆元就是0x00,代入仿射变换得到结果0x63和正确值一致0x01的逆元就是0x01,代入仿射变换得到结果0x7c和正确值一致- 从
0x02开始,输入的逆元不等于原始输入值,你直接用原始输入做仿射变换,结果自然和预期不符。
正确实现示例
首先补充GF(2⁸)逆元计算函数,再整合到S盒逻辑中:
#include <stdint.h> #define ROTL8(x,shift) ((uint8_t) ((x) << shift | ((x) >> (8 - (shift))))) // GF(2^8)下乘法实现,不可约多项式0x11B uint8_t gf_mul(uint8_t a, uint8_t b) { uint8_t p = 0; uint8_t hi_bit_set; for (int i = 0; i < 8; i++) { if (b & 1) p ^= a; hi_bit_set = (a & 0x80); a <<= 1; if (hi_bit_set) a ^= 0x1B; b >>= 1; } return p; } // 求GF(2^8)下的逆元,用费马小定理:a^(2^8-2) = a^254 uint8_t gf_inv(uint8_t a) { if (a == 0) return 0; uint8_t p = 1; uint8_t exp = 254; uint8_t base = a; while (exp > 0) { if (exp & 1) p = gf_mul(p, base); base = gf_mul(base, base); exp >>= 1; } return p; } uint8_t sbox(uint8_t b) { uint8_t x = gf_inv(b); uint8_t s = x ^ ROTL8(x,1) ^ ROTL8(x,2) ^ ROTL8(x,3) ^ ROTL8(x,4) ^ 0x63; return s; }
该实现计算sbox(0x02)会得到正确结果0x77。
内容的提问来源于stack exchange,提问作者Paul Kim
相关产品推荐
相关产品推荐

