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'

 


 

 

posted @ 2021-03-07 14:48  春江水暖  阅读(11045)  评论(1编辑  收藏  举报