Encryption

是什麼導致第一個 AES 解密塊出現亂碼,即使使用正確的 IV?

  • April 29, 2012

我正在嘗試為 TLS HTTP 會話複製wireshark 的數據包擷取解密,我在其中控制伺服器的私鑰。

密碼套件號為 0x00002f,TLS_RSA_AES_128_CBC_SHA

我編寫了一個實用程序,它使用 libpcap 分解數據包擷取,到目前為止,它可以匹配來自 wireshark 的日誌在 MAC 密鑰、寫入密鑰和 IV 方面所說的內容;將二進制數據列印為十六進製字元。

從視覺上看,我可以確認密鑰塊和密文與wireshark 的日誌顯示的內容相同。

但是,在我執行以下解密步驟後:

... decrypt pre_master_secret, generate keyblock
... initialize cipher context

EVP_CIPHER_CTX_init(&myevp);
if (!EVP_CipherInit_ex(&myevp, cipher, NULL, wKey, IV, 0))
   LogError("evp_cipherinit_ex:", ERR_error_string(ERR_get_error(), NUL));

dec = EVP_DecryptUpdate(&myevp, outb, outlen, data, datalen);
totalcount += outlen;

if (!dec) 
   LogError("evp_decryptupdate:", ERR_error_string(ERR_get_error(), NUL));

if (dec && blocklen != 1) {
   dec = EVP_DecryptFinal_ex(&myevp, outb + totalcount, outlen);
   totalcount += outlen;    
}

...get padding from last bit of outb, and remove padding from outb (plaintext)
...remove the MAC from the plaintext

我得到的結果明文與wireshark在他們的日誌中吐出的內容相同,只是第一個解密數據塊的執行。

我知道,一般來說,這通常是由於開始解密時沒有正確的初始化向量造成的。但是,我計算的所有 keyblock 值似乎都是正確的(也就是說,它們與 wireshark 吐出的東西不一樣)。

這是wireshark顯示的前幾塊……

Plaintext[432]:
47 45 54 20 2f 68 65 6c 6c 6f 2e 68 74 6d 6c 20
48 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20
31 37 32 2e 31 36 2e 32 34 34 2e 31 39 36 0d 0a
...

和我的

plaintext_update[432]
e1 a2 f4 b3 2a 93 d1 c4 1b f4 60 d8 c9 92 03 25
48 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20
31 37 32 2e 31 36 2e 32 34 34 2e 31 39 36 0d 0a
...

這只是第一塊。我可以在解密步驟之前驗證 evp 上下文具有正確的原始 IV 值並且目前存在。

LogData("evp oiv", &myevp->evp.oiv, &myevp->evp.cipher->iv_len);
LogData("evp iv", &myevp->evp.iv, &myevp->evp.cipher->iv_len);

這是來自wireshark的

Client Write IV[16]:
8b 55 c0 c5 3c 77 dc 91 09 22 18 8b 0c 53 16 66

這是我的

evp iv[16]
8b 55 c0 c5 3c 77 dc 91 09 22 18 8b 0c 53 16 66

同樣,鍵是相同的。我認為我不需要說明這些值,因為剩餘的塊確實可以正確解密。

我還檢查以確保第一個塊沒有被壓縮,或者其他什麼。我檢查了 wireshark 程式碼,他們正在做我正在做的同樣的事情,儘管在 libgpgcrypt 中。

有人見過這樣的嗎?

對於 TLS,第一個數據包的 IV 是從共享密鑰生成的;引用RFC 2246

要生成密鑰材料,請計算

  key_block = PRF(SecurityParameters.master_secret,
                     "key expansion",
                     SecurityParameters.server_random +
                     SecurityParameters.client_random);

直到產生足夠的輸出。那麼key_block的分區如下:

  client_write_MAC_secret[SecurityParameters.hash_size]
  server_write_MAC_secret[SecurityParameters.hash_size]
  client_write_key[SecurityParameters.key_material_length]
  server_write_key[SecurityParameters.key_material_length]
  client_write_IV[SecurityParameters.IV_size]
  server_write_IV[SecurityParameters.IV_size]

我想你已經生成了這些,並檢查了它們?(密碼套件中需要 6·16 個字節,最後 32 個是 IV,每個方向一個。)

此外,下一個 TLS 記錄的 IV 是同一方向上前一個記錄的最後一個密文塊。因此,您還需要跟踪這些。所以第一個 IV 永遠不會發送,當我們收到新數據包或發送新數據包時,您需要不斷更新 IV。

引用自:https://crypto.stackexchange.com/questions/695