如何检查Python的AES解密错误?

How to check Python's AES decrypt error?

我正在使用 python 来加密和解密文件。文件加密后,尝试这样解密:

from Crypto.Cipher import AES
from Crypto import Random
def decrypt(in_file, out_file, pwd, key_len=32):
    bs = AES.block_size
    salt = in_file.read(bs)[len('Salted__'):]
    key, iv = derive_keyiv(pwd, salt, key_len, bs)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    next_chunk = ''
    finished = False
    try:
        while not finished:
            chunk, next_chunk = next_chunk, cipher.decrypt(in_file.read(1024*bs))
            if len(next_chunk) == 0:
                padding_len = ord(chunk[-1])
                chunk = chunk[:-padding_len]
                finished = True
            out_file.write(chunk)
        return True, None
    except Exception as e:
        return False, e

但是如果密码输入错误,decrypt仍然解密in_file并写入out_file并且没有异常抛出。

解密时如何检查密码错误?

AES 本身无法检查密钥是否为 "correct"。它只是一个将一些字节转换为其他字节的纯函数。

要实现你想要的,你需要自己去实现。一种方法是在加密前向明文添加一个固定的 header(如 16 个字节的零)。解密后,检查并丢弃所述 header 如果它匹配或如果 header 不匹配则引发错误。

旁注:您在没有任何身份验证的情况下进行加密,这可能是不安全的。

编辑

首先,您应该添加身份验证。未经身份验证的加密很容易导致许多安全漏洞,其中许多对于未经培训的人来说并不明显。特别是因为您在 CBC 模式下使用 AES,您可能会在没有身份验证的情况下向 padding oracle 攻击开放自己。

当您以正确的方式进行身份验证加密时 (encrypt-then-mac),如果用户输入错误的密码,您将收到身份验证错误。如果你想进一步区分错误的密码和被篡改的数据,你必须设计自己的方法,比如在前面加上一个幻数的密文。