Python Crypto AES加密模式踩坑記


前言

  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加密

  # Size of a data block (in bytes)
  block_size = 16
  # Size of a key (in bytes)
  key_size = (16, 24, 32)
  解決方法就是將需要加密的數據Padding到16Byte的整數倍; 
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'

 


 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM