Python中的AES-128 CBC解密

Posted

技术标签:

【中文标题】Python中的AES-128 CBC解密【英文标题】:AES-128 CBC decryption in Python 【发布时间】:2018-04-04 21:16:58 【问题描述】:

我正在尝试在 python 中实现此代码(我是 python 新手),它给了我以下错误:

AttributeError: 'str' 对象没有属性 'decode'

如果我们删除.decode ('hex')只是为了避免这样的错误:

from itertools import product
from Crypto.Cipher import AES
import Crypto.Cipher.AES

key = ('2b7e151628aed2a6abf7158809cf4f3c').decode('hex')
IV = ('000102030405060708090a0b0c0d0e0f').decode('hex')
plaintext1 = ('6bc1bee22e409f96e93d7e117393172a').decode('hex')
plaintext2 = ('ae2d8a571e03ac9c9eb76fac45af8e51').decode('hex')
plaintext3 = ('30c81c46a35ce411e5fbc1191a0a52ef').decode('hex')
cipher = AES.new(key, AES.MODE_CBC, IV)
ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
(ciphertext).encode('hex')
decipher = AES.new(key, AES.MODE_CBC, IV)
plaintext = decipher.decrypt(ciphertext)
(plaintext).encode('hex')

但它给了我以下错误:

ValueError: IV 必须是 16 字节长

因为算法需要我必须删除的.decode ('hex')

from itertools import product
from Crypto.Cipher import AES
import Crypto.Cipher.AES

key = ('2b7e151628aed2a6abf7158809cf4f3c')
IV = ('000102030405060708090a0b0c0d0e0f')
plaintext1 = ('6bc1bee22e409f96e93d7e117393172a')
plaintext2 = ('ae2d8a571e03ac9c9eb76fac45af8e51')
plaintext3 = ('30c81c46a35ce411e5fbc1191a0a52ef')
cipher = AES.new(key,AES.MODE_CBC,IV)
ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
(ciphertext).encode('hex')
decipher = AES.new(key,AES.MODE_CBC,IV)
plaintext = decipher.decrypt(ciphertext)
(plaintext).encode('hex')

有谁知道我可以怎样做才能使这段代码正常工作?

【问题讨论】:

这会起作用(对于 python2),因为您的数据是 3 个 16 字节的块,否则您必须填充。 【参考方案1】:

您使用的是 Python 3,而不是 Python 2。您不能在 Python 3 中对字符串使用 decode(),它们已经是文本,因此不能应用诸如 'hex' 之类的字节到字节编解码器方式。

改用binascii 模块:

from binascii import hexlify, unhexlify

key = unhexlify('2b7e151628aed2a6abf7158809cf4f3c')
IV = unhexlify('000102030405060708090a0b0c0d0e0f')
plaintext1 = unhexlify('6bc1bee22e409f96e93d7e117393172a')
plaintext2 = unhexlify('ae2d8a571e03ac9c9eb76fac45af8e51')
plaintext3 = unhexlify('30c81c46a35ce411e5fbc1191a0a52ef')

ciphertext_hex = hexlify(ciphertext)
# ...
plaintext_hex = hexlify(plaintext)

所以要将十六进制字符串解码为字节,请使用binascii.unhexlify(),而要编码回十六进制,请使用binascii.hexlify()。请注意,您不能就地转换数据,您必须将结果存储回变量中(或打印出值等)。

演示:

>>> from Crypto.Cipher import AES
>>> import Crypto.Cipher.AES
>>> from binascii import hexlify, unhexlify
>>> key = unhexlify('2b7e151628aed2a6abf7158809cf4f3c')
>>> IV = unhexlify('000102030405060708090a0b0c0d0e0f')
>>> plaintext1 = unhexlify('6bc1bee22e409f96e93d7e117393172a')
>>> plaintext2 = unhexlify('ae2d8a571e03ac9c9eb76fac45af8e51')
>>> plaintext3 = unhexlify('30c81c46a35ce411e5fbc1191a0a52ef')
>>> cipher = AES.new(key,AES.MODE_CBC,IV)
>>> ciphertext = cipher.encrypt(plaintext1 + plaintext2 + plaintext3)
>>> hexlify(ciphertext)
b'7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e22229516'
>>> decipher = AES.new(key,AES.MODE_CBC,IV)
>>> plaintext = decipher.decrypt(ciphertext)
>>> plaintext == plaintext1 + plaintext2 + plaintext3  # test if decryption was successful
True
>>> hexlify(plaintext)
b'6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52ef'

【讨论】:

我很想听听我的回答没有帮助或错误的地方,值得一票否决。这样我可以改进我的答案! 请求 cmets 投反对票只会让您获得更多反对票...再有一个...等等...不...废弃... @rene 我会定期清理这些 cmets;有时,只是有时,当我在 dv 之后提出要求时,我确实会得到有用的反馈。毕竟,众所周知,我有时会犯错! 很公平,我可以每天开一个玩笑,对吧? (我承认这是我可怜的荷兰幽默) @rene:在我个人看来,荷兰式幽默被低估了。

以上是关于Python中的AES-128 CBC解密的主要内容,如果未能解决你的问题,请参考以下文章

无法使用来自 AES-256-CBC 的 pgcrypto 解密,但 AES-128-CBC 可以

Java 中的 AES 128 加密 PHP 中的解密

AES在线加密解密-附AES128,192,256,CBC,CFB,ECB,OFB,PCBC各种加密解密源码

如何使用Javascript中的AES CBC零填充进行加密并使用Java进行解密

nodejs中aes-128-cbc加密和解密

微信AES-128-CBC加密解密