C AES-GCM ESP数据包解密不起作用

时间:2019-06-20 03:59:14

标签: c openssl aes aes-gcm evp-cipher

我正在尝试解密用AES128-GCM12加密的ESP数据包。我使用c openssl库进行解密。但是解密结果是错误的!

我使用了两个Linux 18.04 VM来模拟带有Strongswan IPsec的ESP数据包。我捕获了ESP数据包,并将所有变量打印在解密函数中。

Sub AllWorkbooks()

   Dim MyFolder As String
   Dim MyFile As String
   Dim wbk As Workbook

On Error Resume Next

Application.ScreenUpdating = False

With Application.FileDialog(msoFileDialogFolderPicker)

.Title = "Please select a folder"

.Show

.AllowMultiSelect = False

   If .SelectedItems.Count = 0 Then

MsgBox "You did not select a folder"

      Exit Sub

   End If

MyFolder = .SelectedItems(1) & "\"

End With

MyFile = Dir(MyFolder)

Do While MyFile <> “”

   Set wbk = Workbooks.Open(Filename:=MyFolder & MyFile)


UnMergeFill


wbk.Close savechanges:=True

MyFile = Dir

Loop

Application.ScreenUpdating = True

End Sub


Call Sub UnMergeFill()

Dim cell As Range, joinedCells As Range

For Each cell In ThisWorkbook.ActiveSheet.UsedRange
    If cell.MergeCells Then
        Set joinedCells = cell.MergeArea
        cell.MergeCells = False
        joinedCells.Value = cell.Value
    End If
Next

End Sub

'''

这是我捕获的包裹。

static void _aes_gcm_decrypt(uint8_t* payload, uint16_t payload_len, uint8_t* key, uint16_t key_len, uint8_t* iv, uint8_t iv_len, uint8_t* icv, uint8_t icv_len, uint8_t* aad, uint8_t aad_len) {
    EVP_CIPHER_CTX *ctx;
    int outlen;
    uint8_t outbuf[1024];
    int rv;
    const EVP_CIPHER *cipher;

    // Ignore salt
    key_len -= 4;
    switch(key_len) {
        case 16: cipher = EVP_aes_128_gcm(); break;
        case 24: cipher = EVP_aes_192_gcm(); break;
        case 32: cipher = EVP_aes_256_gcm(); break;
        default: break;
    }

    print_hex("original payload", payload, payload_len);
    print_hex("key", key, key_len);
    print_hex("iv", iv, iv_len);
    print_hex("icv", icv, icv_len);
    print_hex("aad", aad, aad_len);

    ctx = EVP_CIPHER_CTX_new();
    // Select cipher
    EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv);
    // Set IV length, omit for 96 bits
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL);
    // Specify key and IV
    EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv);
    // Zero or more calls to specify any AAD
    EVP_DecryptUpdate(ctx, NULL, &outlen, aad, aad_len);
    // Decrypt plaintext
    EVP_DecryptUpdate(ctx, outbuf, &outlen, payload, payload_len);
    print_hex("decrypted_payload", outbuf, outlen);

    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, icv_len, icv);
    rv = EVP_DecryptFinal(ctx, icv, &outlen);

    printf("Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!");
    EVP_CIPHER_CTX_free(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

解密后的有效载荷应该是一些ICMP数据包。但这是错误的! 解密方法是否错误,或者变量是否错误地进入数据包?

1 个答案:

答案 0 :(得分:2)

  • 如果当前的8字节IV(ESP-IV,请参见下文)可以成功解密消息:

                7a 2b 37 d7 16 0c 85 3c
    

    被以下12个字节的IV取代(Nonce / AES-GCM-IV,请参见下文):

    b3 0d e6 26 7a 2b 37 d7 16 0c 85 3c 
    
  • 解密后的消息是:

    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
    
  • 说明:根据AES-GCM-ESP说明(第8.1节),AES-128-GCM-ESP的密钥有20个字节。前16个字节是AES-128-GCM密钥,后4个字节是salt。随机数由salt(4个字节)和ESP-IV(8个字节)组成,因此大小为12个字节。随机数是AES-GCM-IV。有关ESP-IV和AES-GCM-IV之间的区别的说明,请参见here,第2节。在当前代码中,ESP-IV被用作AES-GCM-IV,这是错误的。如果将现时值用作AES-GCM-IV,则解密成功。

  • 盐的4个字节可能被强行强制为:

    b3 0d e6 26
    

    它们应对应于20字节AES-128-GCM-ESP密钥的最后4个字节。

  • _aes_gcm_decrypt方法包含一个小缺陷,但是在GCM模式下没有任何后果。但是,该方法应进行如下修改:

    ...
    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
    ...
    

    plaintext_len中存储了解密消息的长度。启用填充后,EVP_DecryptFinal会解密一个可能的最后一个未完全填充的块。由于GCM模式不使用填充,因此该错误无效。但是,存储在outlen中的解密消息的长度在当前代码中丢失,另请参见here