【问题标题】:pycryprodome AES CBC mismatch after decryption in Pythonpycryptodome AES CBC在Python中解密后不匹配
【发布时间】:2018-09-20 22:04:05
【问题描述】:

我的目标是有一个非常简单的 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)

【问题讨论】:

  • 您必须使用静脉输液。当不将 IV 传递给 AES.new 时,它会创建一个随机 IV。

标签: python encryption aes pycrypto pycryptodome


【解决方案1】:

正如t.m.adam 所述,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 on GitHub 所指出的 EAX 和 GCM。其中许多不需要填充。

【讨论】:

    【解决方案2】:

    如果您使用 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))
    
    猜你喜欢
    • 1970-01-01
    • 2018-04-04
    • 2013-08-11
    • 2023-02-23
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多