Aes

Webcrypto (js) 和 Cryptodome.Cipher.AES (python) 之間的區別

  • October 29, 2018

我試圖了解在 python 中使用 Webcrypto 和 Cryptodome.Cipher.AES 的 AES 解密(GCM 模式)輸出的差異。

from Cryptodome.Cipher import AES
from binascii import hexlify, unhexlify
key = 'E52BC6CEDC2E096584B1F57D3AE6A60724C7B301EECB975813819673E6D23126'
iv = 'B5DDEDB80480A649D1763BE7'
encrypted_data = '37631B44E6B7DB7C404F2947F40FC629BB537BF303B728A674280C23528C3B09815BA2CD39B3844A38C4527464353A66'
cipher_item_key = AES.new(unhexlify(key), AES.MODE_GCM, nonce=unhexlify(iv))
res = cipher_item_key.decrypt(unhexlify(encrypted_data))
print hexlify(res).upper()

印刷EEE72939E910F74104846B5BADBDDAD007A46E3392ADE713F6EE33900299C250C83D25005D7D7E27211B2BBFF48E62AC

對比

https://gist.github.com/syst3mw0rm/9b22a1eadd6cbf38474573d54cd54f0c

印刷EEE72939E910F74104846B5BADBDDAD007A46E3392ADE713F6EE33900299C250

我注意到前 64 個字元完全相同,這讓我認為問題可能在於 python 中的輸出未填充,但我不確定這樣做的正確方法是什麼,或者這是根本原因第一名。


同樣,我注意到加密數據時輸出的差異。

from Cryptodome.Cipher import AES
from binascii import hexlify, unhexlify
key = 'EEE72939E910F74104846B5BADBDDAD007A46E3392ADE713F6EE33900299C250'
iv = '523AEBE425EA83DCE42F9512'
data = '{"username":"test","password":"test"}'
cipher_data = AES.new(unhexlify(key), AES.MODE_GCM, nonce=unhexlify(iv))
cipher_data.update('')
encrypted_data, mac = cipher_data.encrypt_and_digest(bytearray(data))
print (hexlify(encrypted_data) + hexlify(mac)).upper()

印刷C7D1A799120CBDD6539378509AFC4D0C3F78BA8D42C9F3546E15DFBD94CBE789350DD3554AF092A39AF0345623E117D28F493CD7DE

對比

https://gist.github.com/syst3mw0rm/22bb4a8c7c51516b358b482b3336d927

印刷C7F3F0EA027EA0B75BF6286AD688497F265AF3AF10A8BA273B7AD9D9D3F1B6FD247E85771BAE4447F81447389A84A3145155E7DE387D6B3E181516707731EC2DC3CEF847FCA949EE484B3FC0A6C66853D42C956BA0735642D29E

我不確定為什麼以上兩個的輸出會有所不同。我使用完全相同的密鑰,iv,additionalData(根據微妙的加密規範預設為’’),數據。有人可以告訴我我是否遺漏了一些明顯的東西嗎?

該方法decrypt有兩個稍微不同的含義:

  • 在 WebCrypto 中,decrypt是一次性操作,執行 MAC 標籤的解密驗證。假定標籤是輸入的最後 16 個字節。您只能呼叫decrypt一次。在某些 API 中,這個方法(更好地)被稱為unsealor unbox,以強調它不僅僅是解密數據。
  • 在 PyCryptodome 中,decrypt是一種流式操作,可解密您提供**的所有數據。**您可以decrypt多次呼叫(因此,它在一次處理一個塊的流式上下文中很有用)。最後有一個單獨的verify方法來檢查 MAC 標籤。一次性方法decrypt_and_verify相當於decryptWebCrypto 世界中的方法。

因此,您應該修改您的 Python 程式碼:

res = cipher_item_key.decrypt(unhexlify(encrypted_data))

成為:

raw = unhexlify(encrypted_data)
res = cipher_item_key.decrypt_and_verify(raw[:-16], raw[-16:])

類似的加密:

  • 在 WebCrypto 中,encrypt執行兩個操作:實際加密以及 MAC 標籤的創建。輸出由密文和 16 字節標記連接而成。您只能呼叫encrypt一次。
  • 在 PyCryptodome 中,encrypt僅執行加密,並且您必須digest在最後呼叫(可能在多次encrypt呼叫之後)以獲取 16 字節 MAC 標記。執行加密和創建 MAC 標籤的方法實際上是encrypt_and_digest(與decryptWebCrypto 中相同)。

在 PyCryptodome 中查看 AEAD 模式(如 GCM)的狀態機也很有幫助:

在此處輸入圖像描述

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