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一个对象用来处理解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) #can't use same object to decrypt plaintext=cipher.decrypt(cipherText) #注意这里,因为引用同一对象会导致报错!!! 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的整数倍;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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') ##注意这里,text需要加密的字符串需要是16字节的整数倍 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会在初始化时随机生成一个。这样就导致了每次加密得到的密文不一样;
解决方法就是指定一个固定的初始化向量,同时也要注意解密时也使用同样的向量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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得到原始数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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'
文章来源:https://www.cnblogs.com/linuxcat/p/14494630.html
布施恩德可便相知重
微信扫一扫打赏
支付宝扫一扫打赏