前言:
demo code使用的lib 版本為 :pycryptodome 3.10.1
寫了一小段AES加密的demo code, 運行起來錯誤不斷,花費了半天時間逐一解決。分享出來,希望能對大家有所幫助!
同時,關於AES 加密模式的說明可以參考這篇文章,講的很清晰:https://blog.csdn.net/slslslyxz/article/details/111232040
問題一:decrypt() cannot be called after encrypt()
運行時報告:Exception has occurred: TypeError, decrypt() cannot be called after encrypt()
出現這個問題的原因,在encrypt / decrypt函數中有說明,由於encrypt / decrypt是stateful,不能用加密的對象再去解蜜;
A cipher object is stateful: once you have encrypted a message , you cannot encrypt (or decrypt) another message using the same object.
解決方法就是重新new一個對象用來處理解密
from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.Padding import unpad key=b'1234567890123456'cipher=AES.new(key,AES.MODE_CBC) text=b'secret text' padtext=pad(text,16,style='pkcs7') cipherText=cipher.encrypt(padtext) print(padtext) print(cipherText) plaintext=cipher.decrypt(cipherText) #can't use same object to decrypt print(plaintext)
問題二:Data must be padded to 16 byte boundary in CBC mode
這個是AES加密算法模式導致的。 AES只能以Block的模式加密, 且Block大小為16Byte. 加密的key大小為:16,24,32,對應到128bit, 192bit, 256bit加密
from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.Padding import unpad key=b'1234567890123456'cipher=AES.new(key,AES.MODE_CBC) text=b'secret text' padtext=pad(text,16,style='pkcs7') cipherText=cipher.encrypt(padtext) print(padtext) print(cipherText) decrypter=AES.new(key,AES.MODE_CBC) plaintext=decrypter.decrypt(cipherText) print(plaintext)
問題三:每次加密得到的結果不一樣
這個問題的原因是AES CBC_MODE需要初始化向量。如果不指定初始化向量,則AES會在初始化時隨機生成一個。這樣就導致了每次加密得到的密文不一樣;
解決方法就是指定一個固定的初始化向量,同時也要注意解密時也使用同樣的向量。
from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.Padding import unpad key=b'1234567890123456' iv=b'abcdefghijklmnop' cipher=AES.new(key,AES.MODE_CBC,iv) text=b'secret text' padtext=pad(text,16,style='pkcs7') cipherText=cipher.encrypt(padtext) print(padtext) print(cipherText) decrypter=AES.new(key,AES.MODE_CBC,iv) plaintext=decrypter.decrypt(cipherText) print(plaintext)
問題四:解密無法得到原始明文數據
上面的程序運行出來發現后面還是跟着之前Paddding的數據,這是因為decrypt並不會將Padding的數據去掉。
解決辦法就是將解密的數據再進行unpad得到原始數據
from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.Padding import unpad key=b'1234567890123456' iv=b'abcdefghijklmnop' cipher=AES.new(key,AES.MODE_CBC,iv) text=b'secret text' padtext=pad(text,16,style='pkcs7') cipherText=cipher.encrypt(padtext) print(padtext) print(cipherText) decrypter=AES.new(key,AES.MODE_CBC,iv) plaintext=decrypter.decrypt(cipherText) unpadtext=unpad(plaintext,16,'pkcs7') print(plaintext) print(unpadtext)
經過上面的一系列的錯誤修正后,運行程序后可以得到正確的結果了
原始數據:secret text padding數據:b'secret text\x05\x05\x05\x05\x05' 加密數據:b'\xb0\xb0\xd4h\xbc\x85\xd3\xd1>\x13\xdf\xa7AE(8' 解密后數據:b'secret text'