【问题标题】:Decrypt MCRYPT_RIJNDAEL_256 with 32-byte initialization vectors with PyCrypto使用 PyCrypto 使用 32 字节初始化向量解密 MCRYPT_RIJNDAEL_256
【发布时间】:2015-02-04 16:44:42
【问题描述】:

我的数据在 PHP 中加密如下:

mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SECRET, $data, MCRYPT_MODE_CBC, $iv)

我需要在 Python 3 应用程序中解密这些数据。我正在尝试使用 PyCrypto,但我对其他库持开放态度。我希望以下工作:

decryptor = AES.new(key, mode, IV=IV)
plain = decryptor.decrypt(ciphertext)

我的初始化向量是32字节,抛出如下异常:

ValueError: IV must be 16 bytes long

如何将 PyCrypto 设置为使用 32 字节的初始化向量和 32 字节的块大小? 或者,我可以使用其他库来解密数据吗?

【问题讨论】:

  • 您不能将 AES 设置为 32 字节块大小,因为 AES 仅针对 16 字节块大小定义。你必须为 python 找到一个 Rijndael 256/256(假设你的密钥也是 32 字节长)实现。
  • Python equivalent of PHP's MCRYPT_RIJNDAEL_256 CBC 的可能副本。在 Google 搜索中看到自己的答案总是很有趣。
  • 谢谢。这似乎实现了分组密码,但没有实现 CBC 加密模式。是否有可以与我的 32 字节初始化向量一起使用的 CBC 实现?
  • 实现 CBC 并不难,因为它主要是 XORing,因此模式上的侧通道攻击风险很小。 PHP 填充模式是添加 0..15 个零,直到达到块大小。

标签: python-3.x aes pycrypto rijndael cbc-mode


【解决方案1】:

感谢 cmets,我实施了合适的解决方案。我在链接的重复问题中修改了rijndael.py 以接受字节而不是字符串。然后我使用它来解密具有 32 字节初始化向量的 32 字节块。

from rijndael import rijndael

iv = b'myInitializationVectorfoobarfoob'
key = b'myKeyfoobarfoobarfoobarfoobarfoo'
text = b'myCipherTextFoobarfoobarfoobarfo'

r = rijndael(key, block_size=32)
plaintext = r.decrypt(text)
l = ''.join([chr(a ^ b) for a, b in zip(plaintext.encode('latin-1'), iv)])
print(l)

请注意,使用 this 而不是 PyCrypto 是唯一必要的,因为 libmcrypt 错误地将数据块大小以及初始化向量大小设置为等于密钥大小。据我了解,AES-Rijndael 的数据块大小应始终为 128 位。

【讨论】:

  • 是的,AES 是 Rijndael,块大小为 128 位,密钥大小为 128、192 或 256 位(具有正常的轮数和常数)。
  • 我不确定解密例程是否正确,它似乎只适用于单个块。我会尝试纠正它并在另一个答案中发布解决方案。
  • 完成,看看,别忘了给其他答案点赞!
  • 没错,这个答案只适用于单个块。感谢您提供完整的解决方案。
  • @gavinmh 很想知道你制作的模组“接受字节而不是字符串”。
猜你喜欢
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 2020-01-05
  • 2018-01-24
  • 2014-10-15
  • 1970-01-01
相关资源
最近更新 更多