从 OpenSSL AES 解密 python 中的 AES CBC
Decrypting AES CBC in python from OpenSSL AES
我需要用 python 解密在 OpenSSL 上加密的文件,但我不理解 pycrypto 的选项。
这是我在 OpenSSL 中所做的
openssl enc -aes-256-cbc -a -salt -pbkdf2 -iter 100000 -in "clear.txt" -out "crypt.txt" -pass pass:"我的密码
openssl enc -d -aes-256-cbc -a -pbkdf2 -iter 100000 -in "crypt.txt" -out "out.txt" -pass pass:"我的密码
我试过了(显然不行)
obj2 = AES.new("mypassword", AES.MODE_CBC)
output = obj2.decrypt(text)
我只想做python中的第二步,但是看样例的时候:
https://pypi.org/project/pycrypto/
obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
obj2.decrypt(ciphertext)
我不需要 IV,如何指定盐? pbkdf2 哈希?我也在看这个帖子
How to decrypt OpenSSL AES-encrypted files in Python?
但没有帮助。
谁能告诉我如何使用 python 来做到这一点?
谢谢。
OpenSSL 语句使用 PBKDF2 创建一个 32 字节的密钥和一个 16 字节的 IV。为此,隐式生成一个随机的 8 字节盐,并应用指定的密码、迭代计数和摘要(默认值:SHA-256)。 key/IV 对用于使用 CBC 模式的 AES-256 和 PKCS7 填充 s 对明文进行加密。 here。结果以OpenSSL格式返回,以Salted__[=39=的8字节ASCII编码开头,后面是8字节salt和实际密文,全部Base64编码。解密需要加盐,这样才能重构key和IV。
请注意,OpenSSL语句中的密码实际上是不带引号传递的,即在发布的OpenSSL语句中,引号是密码的一部分。
对于 Python 中的解密,必须首先从加密数据中确定 salt 和实际密文。使用盐可以重建 key/IV 对。最后,key/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 个字节对应于 Base64 编码密文的 4 个字节。
在二进制存储密文的情况下:在解密过程中,第一步只应(二进制)读取第一个块(16 字节)。由此,可以确定盐(字节 8 到 16),然后是密钥和 IV(类似于上面发布的代码)。
密文的其余部分可以(二进制)以合适大小的块(=块大小的倍数,例如 1024 字节)读取。每个块都是 encrypted/decrypted 单独的,请参阅 multiple encrypt/decrypt-calls. For reading/writing files in chunks with Python see e.g. here。
最好在单独的问题范围内回答更多详细信息。
我需要用 python 解密在 OpenSSL 上加密的文件,但我不理解 pycrypto 的选项。
这是我在 OpenSSL 中所做的
openssl enc -aes-256-cbc -a -salt -pbkdf2 -iter 100000 -in "clear.txt" -out "crypt.txt" -pass pass:"我的密码
openssl enc -d -aes-256-cbc -a -pbkdf2 -iter 100000 -in "crypt.txt" -out "out.txt" -pass pass:"我的密码
我试过了(显然不行)
obj2 = AES.new("mypassword", AES.MODE_CBC)
output = obj2.decrypt(text)
我只想做python中的第二步,但是看样例的时候:
https://pypi.org/project/pycrypto/
obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
obj2.decrypt(ciphertext)
我不需要 IV,如何指定盐? pbkdf2 哈希?我也在看这个帖子
How to decrypt OpenSSL AES-encrypted files in Python?
但没有帮助。
谁能告诉我如何使用 python 来做到这一点?
谢谢。
OpenSSL 语句使用 PBKDF2 创建一个 32 字节的密钥和一个 16 字节的 IV。为此,隐式生成一个随机的 8 字节盐,并应用指定的密码、迭代计数和摘要(默认值:SHA-256)。 key/IV 对用于使用 CBC 模式的 AES-256 和 PKCS7 填充 s 对明文进行加密。 here。结果以OpenSSL格式返回,以Salted__[=39=的8字节ASCII编码开头,后面是8字节salt和实际密文,全部Base64编码。解密需要加盐,这样才能重构key和IV。
请注意,OpenSSL语句中的密码实际上是不带引号传递的,即在发布的OpenSSL语句中,引号是密码的一部分。
对于 Python 中的解密,必须首先从加密数据中确定 salt 和实际密文。使用盐可以重建 key/IV 对。最后,key/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 个字节对应于 Base64 编码密文的 4 个字节。
在二进制存储密文的情况下:在解密过程中,第一步只应(二进制)读取第一个块(16 字节)。由此,可以确定盐(字节 8 到 16),然后是密钥和 IV(类似于上面发布的代码)。
密文的其余部分可以(二进制)以合适大小的块(=块大小的倍数,例如 1024 字节)读取。每个块都是 encrypted/decrypted 单独的,请参阅 multiple encrypt/decrypt-calls. For reading/writing files in chunks with Python see e.g. here。
最好在单独的问题范围内回答更多详细信息。