0

我的目标是拥有一个非常简单的 AES 128 CBC 方案,它加密明文,然后根据 Python 中的给定密钥对其进行解密。我正在使用 pycryptodome 框架,但找不到任何带有 AES CBC 方案示例的文档。

以下是我的代码。解密后的数据与加密前的数据不同。如果有人可以帮助我确定这里出了什么问题,那就太好了。

key = b'Sixteen byte key'
data = 'Jeevan B Manoj'.encode("UTF-8")
data = pad(data,16)
cipher = AES.new(key, AES.MODE_CBC)
print("data before encryption")
print(data)
ciphertext = cipher.encrypt(data)
cipher = AES.new(key, AES.MODE_CBC)
plaintext = cipher.decrypt(ciphertext)
print(plaintext)
4

2 回答 2

3

正如tmadam 所指出的,CBC 操作模式需要一个初始化向量 (IV) 才能工作。因为 IV 通常被遗忘(而且它必须是唯一的和不可预测的,例如随机的),Pycryptodome 在初始化密码对象时创建一个随机的。

IV 对于每个加密必须是唯一的,并且是解密所必需的。通常的做法(来源?)是将IV放在密文的开头(IV不需要保密)。

为了使您的示例工作:

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

# Do not use raw passwords as keys,
# use a derivation functions to generate keys from them
key = b'Sixteen byte key'  
data = 'Jeevan B Manoj'.encode("UTF-8")
data = pad(data, AES.block_size)
encryptor = AES.new(key, AES.MODE_CBC)
iv = encryptor.IV
decryptor = AES.new(key, AES.MODE_CBC, IV=iv)

ciphertext = encryptor.encrypt(data)
plaintext = decryptor.decrypt(ciphertext)

assert plaintext == data

重要提示:密文和 IV 必须经过身份验证以确保安全(因此数据不能被篡改)。为此,Pycryptodome 提供了 AEAD 模式,如Hans-Peter Jansen 在 GitHub 上指出的 EAX 和 GCM 。对于他们中的许多人来说,填充不是必需的。

于 2018-04-15T15:14:35.757 回答
0

如果您使用 MODE_ECB 而不是 MODE_CBC 它可以工作。我也不知道您使用的是什么填充例程,所以我使用了这个。我这里还有其他几个例子: https ://github.com/SolarDon/pycryptodome/tree/master/Examples

from Crypto.Cipher import AES
 # Padding for the input string --not related to encryption itself.
BLOCK_SIZE = 16  # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

key = b'Sixteen byte key'
data = 'Jeevan B Manoj'.encode("UTF-8")
data = pad(data)
cipher = AES.new(key, AES.MODE_ECB) # AES.MODE_CBC
print("data before encryption")
print(data)
ciphertext = cipher.encrypt(data)
cipher = AES.new(key, AES.MODE_ECB) # MODE_CBC
plaintext = cipher.decrypt(ciphertext)
print(unpad(plaintext))
于 2018-04-12T04:16:16.227 回答