OpenSSL 语句使用 PBKDF2 创建一个 32 字节的密钥和一个 16 字节的 IV。为此,会隐式生成一个随机的 8 字节盐,并应用指定的密码、迭代计数和摘要(默认值:SHA-256)。密钥/IV 对用于在 CBC 模式下使用 AES-256 和 PKCS7 填充加密明文,s。 here。结果以 OpenSSL 格式返回,该格式以 Salted__ 的 8 字节 ASCII 编码开头,然后是 8 字节盐和实际密文,均采用 Base64 编码。解密需要盐,以便重建密钥和IV。
注意,OpenSSL 语句中的密码实际上是不带引号传递的,即在张贴的 OpenSSL 语句中,引号是密码的一部分。
对于 Python 中的解密,必须首先从加密数据中确定 salt 和实际密文。使用盐可以重建密钥/IV 对。最后,密钥/IV 对可用于解密。
示例:使用张贴的 OpenSSL 语句,明文
The quick brown fox jumps over the lazy dog
被加密成密文
U2FsdGVkX18A+AhjLZpfOq2HilY+8MyrXcz3lHMdUII2cud0DnnIcAtomToclwWOtUUnoyTY2qCQQXQfwDYotw==
使用 Python 进行解密的方法如下(使用 PyCryptodome):
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Hash import SHA256
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES
import base64
# Determine salt and ciphertext
encryptedDataB64 = 'U2FsdGVkX18A+AhjLZpfOq2HilY+8MyrXcz3lHMdUII2cud0DnnIcAtomToclwWOtUUnoyTY2qCQQXQfwDYotw=='
encryptedData = base64.b64decode(encryptedDataB64)
salt = encryptedData[8:16]
ciphertext = encryptedData[16:]
# Reconstruct Key/IV-pair
pbkdf2Hash = PBKDF2(b'"mypassword"', salt, 32 + 16, count=100000, hmac_hash_module=SHA256)
key = pbkdf2Hash[0:32]
iv = pbkdf2Hash[32:32 + 16]
# Decrypt with AES-256 / CBC / PKCS7 Padding
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(ciphertext), 16)
print(decrypted)
编辑 - 关于您的评论:16 MB 应该是可能的,但对于较大的数据,密文通常会从文件中读取,解密后的数据会写入文件,与上面发布的示例。
数据能否一步解密最终取决于可用内存。如果内存不够,数据必须分块处理。
使用块时,不对加密数据进行 Base64 编码而是直接以二进制格式存储它们会更有意义。这可以通过在 OpenSSL 语句中省略 -a 选项来实现。否则,必须确保始终加载块大小的整数倍(相对于未解码的密文),其中 3 个字节的未解码密文对应于 4 个字节的 Base64 编码密文。
在二进制存储密文的情况下:在解密过程中,第一步应该(二进制)读取第一个块(16 个字节)。由此,可以确定盐(字节 8 到 16),然后是密钥和 IV(类似于上面发布的代码)。
密文的其余部分可以(二进制)以合适大小的块(=块大小的倍数,例如 1024 字节)读取。每个块都单独加密/解密,请参阅multiple encrypt/decrypt-calls。对于使用 Python 读取/写入块中的文件,请参见例如here。
更多细节最好在单独问题的范围内回答。