C AES-GCM对ESP数据包的解密不起作用
我正在尝试解密用AES128-GCM12加密的ESP数据包。我使用c openssl库进行解密。但解密结果是错误的 我使用了两个Linux18.04虚拟机,用strongswan IPsec模拟ESP数据包。我捕获了ESP数据包,并在解密函数中打印了所有变量C AES-GCM对ESP数据包的解密不起作用,c,openssl,aes,aes-gcm,evp-cipher,C,Openssl,Aes,Aes Gcm,Evp Cipher,我正在尝试解密用AES128-GCM12加密的ESP数据包。我使用c openssl库进行解密。但解密结果是错误的 我使用了两个Linux18.04虚拟机,用strongswan IPsec模拟ESP数据包。我捕获了ESP数据包,并在解密函数中打印了所有变量 static void\u aes\u gcm\u decrypt(uint8\u t*有效载荷、uint16\u t有效载荷、uint8\u t*密钥、uint16\u t密钥、uint8\u t*iv、uint8\u t iv\u le
static void\u aes\u gcm\u decrypt(uint8\u t*有效载荷、uint16\u t有效载荷、uint8\u t*密钥、uint16\u t密钥、uint8\u t*iv、uint8\u t iv\u len、uint8\u t*icv\u len、uint8\u t*aad、uint8\u t aad){
EVP_CIPHER_CTX*CTX;
int outlen;
uint8_t突发[1024];
int-rv;
const EVP_CIPHER*密码;
//忽略盐
键长度-=4;
开关(钥匙){
案例16:密码=EVP_aes_128_gcm();中断;
案例24:cipher=EVP_aes_192_gcm();中断;
案例32:cipher=EVP_aes_256_gcm();中断;
默认:中断;
}
打印十六进制(“原始有效载荷”,有效载荷,有效载荷长度);
打印十六进制(“键”,键,键);
打印十六进制(“iv”,iv,iv_len);
打印十六进制(“icv”,icv,icv_len);
打印十六进制(“aad”,aad,aad_len);
ctx=EVP_CIPHER_ctx_new();
//选择密码
EVP_DecryptInit_ex(ctx,密码,NULL,密钥,iv);
//设置IV长度,省略96位
EVP_密码_CTX_ctrl(CTX,EVP_ctrl_GCM_集合_IVLEN,iv_len,NULL);
//指定键和IV
EVP_DecryptInit_ex(ctx,NULL,NULL,key,iv);
//零个或多个用于指定任何AAD的调用
EVP_解密更新(ctx、NULL和outlen、aad、aad_len);
//解密明文
执行副总裁解密更新(ctx、EXBUF和outlen、有效载荷、有效载荷);
打印十六进制(“解密的负载”,EXPUF,outlen);
执行副总裁密码、CTX、CTR(CTX、执行副总裁控制、GCM、设置标签、icv、icv);
rv=执行副总裁(ctx、icv和outlen);
printf(“标记验证%s\n”,rv>0?“成功!”:“失败!”);
无密码(CTX)的执行副总裁;
}
这是我捕获的数据包
04:51:57.347960 IP (tos 0x0, ttl 64, id 48604, offset 0, flags [DF], proto ESP (50), length 136)
pc2 > 10.10.10.100: ESP(spi=0xc08247f5,seq=0x2), length 116
0x0000: 0011 2233 4401 0800 2758 2898 0800 4500
0x0010: 0088 bddc 4000 4032 538b 0a0a 0a65 0a0a
0x0020: 0a64 c082 47f5 0000 0002 7a2b 37d7 160c
0x0030: 853c 870d 1119 5a34 9d95 e597 be6a 8bc7
0x0040: 2037 a1f7 ba02 1ef2 a0be de5e 5406 a5b1
0x0050: 0e03 c463 c235 5c45 9b51 6734 1f28 e364
0x0060: 2b36 470b 64da bfa3 1a68 f209 94aa 44b0
0x0070: 9131 ffe0 12f1 9208 3a7b aa95 da51 bafd
0x0080: 31cd 3d0a 8733 56e0 ae0d d7b5 13fe 8c5e
0x0090: 96d8 598d a74f
这是我的打印变量
original payload(88):
0x0000: 870d 1119 5a34 9d95 e597 be6a 8bc7 2037
0x0010: a1f7 ba02 1ef2 a0be de5e 5406 a5b1 0e03
0x0020: c463 c235 5c45 9b51 6734 1f28 e364 2b36
0x0030: 470b 64da bfa3 1a68 f209 94aa 44b0 9131
0x0040: ffe0 12f1 9208 3a7b aa95 da51 bafd 31cd
0x0050: 3d0a 8733 56e0 ae0d
key(16):
0x0000: 1a0f cccc 0315 2b58 1b1a 02ea 3664 485f
iv(8):
0x0000: 7a2b 37d7 160c 853c
icv(12):
0x0000: d7b5 13fe 8c5e 96d8 598d a74f
aad(8):
0x0000: c082 47f5 0000 0002
decrypted_payload(88):
0x0000: 860c 9110 87c6 db5a c40a a592 f862 b8ea
0x0010: b476 3be6 0881 06d4 ad11 eb2a 2e1c 698d
0x0020: a803 2417 8ffb 7130 444d 4fc8 b402 c602
0x0030: 1a0b 031b b89a 4ddb 707b f920 04ea 48c5
0x0040: 5424 5a9b bb34 a88a 08ee 2556 5532 3419
0x0050: 2621 19e6 f4e1 72b2
Tag Verify Failed!
解密的有效负载应该是某个ICMP数据包。但这是错误的!
解密方法是否错误,或者变量是否错误地进入数据包?- 如果当前的8字节IV(ESP-IV,见下文)为: 替换为以下12字节IV(Nonce/AES-GCM-IV,见下文):
- 解密的消息是:
45 00 00 54 8e 07 40 00 40 01 82 da 0a 00 0b 64 0a 00 0a 64 08 00 04 f2 28 7d 00 01 ed 10 0b 5d 00 00 00 00 0e 4f 05 00 00 00 00 00 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 01 02 02 04
- 说明:根据第8.1节的说明,AES-128-GCM-ESP的密钥有20个字节。前16个字节是AES-128-GCM密钥,最后4个字节是salt。nonce由salt(4字节)和ESP-IV(8字节)组成,因此大小为12字节。当前值为AES-GCM-IV。有关ESP-IV和AES-GCM-IV之间差异的解释,请参见第2节。在当前代码中,ESP-IV用作AES-GCM-IV,这是错误的。如果nonce用作AES-GCM-IV,则解密成功
- salt的4个字节可以强制执行以下操作:
它们应与20字节AES-128-GCM-ESP密钥的最后4个字节相对应b3 0d e6 26
-方法包含一个小缺陷,但在gcm模式下不会产生任何后果。然而,该方法应修改如下:\u aes\u gcm\u decrypt
在... EVP_DecryptUpdate(ctx, outbuf, &outlen, payload, payload_len); int plaintext_len = outlen; // added EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, icv_len, icv); rv = EVP_DecryptFinal_ex(ctx, outbuf + outlen, &outlen); // modified plaintext_len += outlen; // added ...
中存储解密消息的长度。启用填充时解密可能最后一个未完全填充的块。由于GCM模式不使用填充,因此错误不起作用。但是,存储在明文\u len
中的解密消息的长度在当前代码中丢失,另请参阅outlen
b3 0d e6 26
...
EVP_DecryptUpdate(ctx, outbuf, &outlen, payload, payload_len);
int plaintext_len = outlen; // added
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, icv_len, icv);
rv = EVP_DecryptFinal_ex(ctx, outbuf + outlen, &outlen); // modified
plaintext_len += outlen; // added
...