使用_mm_aeskeygenassist_si128匹配AES参考扩展密钥问题
解决AES-NI生成rk[1]不匹配的问题
我来帮你解决用Intel AES-NI intrinsics生成正确的AES扩展密钥rk[1]的问题。首先,我们需要严格对应FIPS 197的密钥扩展步骤,同时正确使用AES-NI的指令。
正确的代码实现
以下是生成目标rk[1]的完整代码片段:
#include <wmmintrin.h> #include <emmintrin.h> #include <stdio.h> void print128(__m128i val) { unsigned char *bytes = (unsigned char*)&val; for (int i = 15; i >= 0; i--) { printf("%02X ", bytes[i]); } printf("\n"); } int main() { // 初始密钥:2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c // 注意:_mm_set_epi8的参数是从最高字节到最低字节(字节15到字节0) __m128i rk0 = _mm_set_epi8(0x3c, 0x4f, 0xcf, 0x09, 0x88, 0x15, 0xf7, 0xab, 0xa6, 0xd2, 0xae, 0x28, 0x16, 0x15, 0x7e, 0x2b); printf("初始密钥rk[0]: "); print128(rk0); // 生成辅助temp值,Rcon[1]对应立即数0x01 __m128i temp = _mm_aeskeygenassist_si128(rk0, 0x01); // 执行密钥扩展的移位和异或操作 __m128i rk1 = _mm_xor_si128(rk0, _mm_slli_si128(rk0, 4)); rk1 = _mm_xor_si128(rk1, _mm_slli_si128(rk1, 4)); rk1 = _mm_xor_si128(rk1, _mm_slli_si128(rk1, 4)); rk1 = _mm_xor_si128(rk1, temp); printf("生成的rk[1]: "); print128(rk1); // 目标rk[1]: A0 FA FE 17 88 54 2C B1 23 A3 39 39 2A 6C 76 05 return 0; }
关键步骤解释
正确加载初始密钥
_mm_set_epi8的参数顺序是从最高字节(寄存器的位127-120)到最低字节(位7-0),这样才能保证寄存器中的密钥字节顺序和FIPS 197定义的一致(大端顺序)。如果直接按内存小端加载,会导致密钥字节顺序颠倒,后续计算全部错误。
使用
_mm_aeskeygenassist_si128生成辅助值- 这个指令会对输入密钥的最高32位(对应FIPS中的w3)执行三个操作:
RotWord:将32位字的字节循环左移1位(如09 cf 4f 3c→cf 4f 3c 09)SubWord:用AES S盒替换每个字节- 与
Rcon[1](0x01000000)异或
- 第二个参数传入
0x01对应第一轮扩展的Rcon值,这是关键,传入错误的Rcon值会导致结果不匹配。
- 这个指令会对输入密钥的最高32位(对应FIPS中的w3)执行三个操作:
移位与异或组合生成完整轮密钥
- 单独的
_mm_aeskeygenassist_si128只生成了扩展所需的辅助temp值,我们需要通过三次左移4字节(_mm_slli_si128)和异或操作,将初始密钥的各个部分与temp组合,最终得到完整的rk[1]。这一步对应FIPS 197中w[i] = w[i-4] XOR temp的递归计算逻辑。
- 单独的
运行这段代码后,你会得到与目标完全匹配的rk[1]:A0 FA FE 17 88 54 2C B1 23 A3 39 39 2A 6C 76 05。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

