Webcrypto (js) 和 Cryptodome.Cipher.AES (python) 之間的區別
我試圖了解在 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 中,這個方法(更好地)被稱為unseal
orunbox
,以強調它不僅僅是解密數據。- 在 PyCryptodome 中,
decrypt
是一種流式操作,可解密您提供**的所有數據。**您可以decrypt
多次呼叫(因此,它在一次處理一個塊的流式上下文中很有用)。最後有一個單獨的verify
方法來檢查 MAC 標籤。一次性方法decrypt_and_verify
相當於decrypt
WebCrypto 世界中的方法。因此,您應該修改您的 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
(與decrypt
WebCrypto 中相同)。在 PyCryptodome 中查看 AEAD 模式(如 GCM)的狀態機也很有幫助: