首页 > 解决方案 > Pycrypto:在 ECB 模式下使用 AES 进行“双重加密”不会产生明文

问题描述

这是cryptopals挑战的一部分(cryptopals.org)

以下代码对上一轮得到的密文进行“加密”操作:

from Crypto.Cipher import AES


def ecb(plaintext, key):
    assert len(plaintext) == 16

    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = cipher.encrypt(plaintext)

    return ciphertext


if __name__ == '__main__':
    testbytes = b'a' * 16
    key = b'0' * 16

    ciphertext = ecb(testbytes, key)
    plaintext = ecb(ciphertext, key)

    assert testbytes == plaintext


理论上ECB就是这么简单,加解密模式的唯一区别就是明文和密文交换的地方:加密时明文输入密文输出,解密时密文输入明文输出,其余为相同的。由此推断,再次“加密”密文应该产生明文,但这段代码不能那样工作。如果我必须猜测encrypt并且decrypt不仅仅是应用块操作。无论如何,为什么双重加密不能按预期工作?

标签: pythonencryptionaes

解决方案


不应该在您的代码assert testbytes == plaintext中测试您的假设吗?

反正。加密由两部分组成,算法(此处为 AES)和操作模式(此处为 ECB)。算法本身只能加密单个块。操作模式将此扩展到任何长度的明文。为了使您的假设正确,解密和加密的各个处理步骤及其顺序对于这两个部分、算法和操作模式都必须相同。

关于 ECB 模式,您的假设是正确的,因为每个块都是独立处理的(这也使得这种模式不安全)。但是,对于 AES,您的假设不正确,因为解密本质上是reverse按照加密顺序完成的,有关详细信息,请参见此处

检查后者的最简单方法是仅加密一个块而不进行填充。由于 ECB 模式不使用 IV,因此加密简化为 AES 原语本身。不必禁用填充,因为 PyCryptodome 不会隐式填充(与许多其他库相比)。这种情况只对应于您的代码(尽管您必须检查 和 之间的相等性testbytesplaintext。结果验证了使用 AES 的双重加密不会产生原始明文。


推荐阅读