尝试使用 openssl 解密 AES-CBC 加密文件时解密错误

bad decrypt when trying to decrypt a AES-CBC encrypted file using openssl

我正在尝试使用 python 加密文件,如下所示:

import os
from binascii import hexlify
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

key = hexlify(os.urandom(16))
print(key.decode())
iv = hexlify(os.urandom(16))
print(iv[:16].decode())
cipher = Cipher(algorithms.AES(key), modes.CBC(iv[:16]))
encryptor = cipher.encryptor()
msg = b"a secret message"
ct = encryptor.update(msg) + encryptor.finalize()
open("ciphertext.bin", "wb").write(ct)

然后我尝试使用 openSSL 解密它(我必须使用 openSSL,因为我的教授要求它)来检查是否成功,如下所示:

openssl enc -aes-128-cbc -d -K <key_the_program_prints> -iv <iv_the_program_prints> -in ciphertext.bin -out res.txt

但我得到:

hex string is too short, padding with zero bytes to length
bad decrypt
139711335437696:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:crypto/evp/evp_enc.c:583:

我做错了什么?我相信我的所有组件的尺寸都是正确的,所以我不明白这个错误

这与 python 以字节为单位处理密钥和 iv 以及我将它们以字符串格式用于 openSSL 有什么关系吗?

谢谢

在 Python 代码中,密钥(AES-128 为 16 字节)和 IV(AES 为 16 字节)必须以二进制形式传递。在 OpenSSL 语句中,它们必须指定为十六进制编码,即在 Python 代码中使用:

key = os.urandom(16)
print(hexlify(key)) # for OpenSSL
iv = os.urandom(16)
print(hexlify(iv)) # for OpenSSL

这也意味着在 Cipher 实例化期间可以直接使用 iv 而不是 iv[:16]

Cryptography 库不会自动填充。但是,OpenSSL 默认应用 PKCS7 填充。因此,必须在 OpenSSL 语句 here.

中使用 -nopad 选项禁用此功能

请注意,如果不进行填充,则只能加密长度为 AES 块大小(16 字节)整数倍的明文。否则必须应用填充。 Cryptography 库支持多种填充变体,包括 PKCS7、here。有了padding,当然要去掉OpenSSL语句中的-nopad选项