OpenSSL语句使用PBKDF2生成32字节密钥和16字节IV。为此,隐式生成一个随机的8字节盐,并应用指定的密码、迭代次数和摘要(默认值:SHA-256)。使用密钥/IV对,在CBC模式和PKCS7填充的情况下使用AES-256加密纯文本,详情请见
这里。结果以OpenSSL格式返回,该格式由8个ASCII编码的字节“Salted__”开始,后跟8个盐字节和实际的密文,所有内容均使用Base64编码。盐在解密过程中是必需的,以便可以重建密钥和IV。
请注意,OpenSSL语句中的密码实际上是没有引号的,即在发布的OpenSSL语句中,引号是密码的一部分。
在Python中进行解密时,必须先从加密数据中确定盐和实际的密文。使用盐可以重建密钥/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
encryptedDataB64 = 'U2FsdGVkX18A+AhjLZpfOq2HilY+8MyrXcz3lHMdUII2cud0DnnIcAtomToclwWOtUUnoyTY2qCQQXQfwDYotw=='
encryptedData = base64.b64decode(encryptedDataB64)
salt = encryptedData[8:16]
ciphertext = encryptedData[16:]
pbkdf2Hash = PBKDF2(b'"mypassword"', salt, 32 + 16, count=100000, hmac_hash_module=SHA256)
key = pbkdf2Hash[0:32]
iv = pbkdf2Hash[32:32 + 16]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(ciphertext), 16)
print(decrypted)
编辑 - 关于您的评论:16 MB是可能的,但对于更大的数据,密文通常会从文件中读取,解密后的数据会写入文件,与上面发布的示例相比。
是否可以一步解密数据最终取决于可用内存。如果内存不足,则必须以块为单位处理数据。
使用块时,不Base64编码加密数据而直接以二进制格式存储它们会更有意义。这可以通过在OpenSSL语句中省略 -a 选项来实现。否则,必须确保始终加载相对于未解码的密文的块大小的整数倍,其中未解码的密文的3个字节对应于Base64编码的密文的4个字节。
在二进制存储的密文的情况下:在解密过程中,应该(二进制)只在第一步中读取第一个块(16个字节)。从中可以确定盐(第8到16个字节),然后确定密钥和IV(类似于上面发布的代码)。
其余的密文可以按合适的大小分块(=块大小的倍数,例如1024字节)进行(二进制)读取。每个块都要单独加密/解密,请参见多重加/解密调用。有关使用Python以块读取/写入文件的详细信息,请参见此处。更多详细信息最好在单独问题的范围内回答。