当前位置: 首页 > 知识库问答 >
问题:

如何在Python中解密OpenSSL AES加密的文件?

东方镜
2023-03-14

OpenSSL提供了一个流行的(但不安全-请参见下面!)AES加密的命令行界面:

openssl aes-256-cbc -salt -in filename -out filename.enc

Python以PyCrypto包的形式支持AES,但它只提供了工具。如何使用Python/Pycrypto解密已经使用OpenSSL加密的文件?

这个问题过去也涉及使用相同方案在Python中进行加密。我已经删除了这部分,以阻止任何人使用它。不要再用这种方式加密任何数据,因为按照今天的标准,它是不安全的。您应该只使用解密,除了向后兼容之外,没有其他原因,即当您没有其他选择时。要加密吗?如果可能的话,使用NaCl/Libs钠。

共有2个答案

詹正浩
2023-03-14

我正在重新发布您的代码,其中有几处更正(我不想使您的版本变得模糊不清)。当您的代码工作时,它不会检测到填充周围的一些错误。特别是,如果提供的解密密钥不正确,您的填充逻辑可能会做一些奇怪的事情。如果您同意我的更改,您可以更新您的解决方案。

from hashlib import md5
from Crypto.Cipher import AES
from Crypto import Random

def derive_key_and_iv(password, salt, key_length, iv_length):
    d = d_i = ''
    while len(d) < key_length + iv_length:
        d_i = md5(d_i + password + salt).digest()
        d += d_i
    return d[:key_length], d[key_length:key_length+iv_length]

# This encryption mode is no longer secure by today's standards.
# See note in original question above.
def obsolete_encrypt(in_file, out_file, password, key_length=32):
    bs = AES.block_size
    salt = Random.new().read(bs - len('Salted__'))
    key, iv = derive_key_and_iv(password, salt, key_length, bs)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    out_file.write('Salted__' + salt)
    finished = False
    while not finished:
        chunk = in_file.read(1024 * bs)
        if len(chunk) == 0 or len(chunk) % bs != 0:
            padding_length = bs - (len(chunk) % bs)
            chunk += padding_length * chr(padding_length)
            finished = True
        out_file.write(cipher.encrypt(chunk))

def decrypt(in_file, out_file, password, key_length=32):
    bs = AES.block_size
    salt = in_file.read(bs)[len('Salted__'):]
    key, iv = derive_key_and_iv(password, salt, key_length, bs)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    next_chunk = ''
    finished = False
    while not finished:
        chunk, next_chunk = next_chunk, cipher.decrypt(in_file.read(1024 * bs))
        if len(next_chunk) == 0:
            padding_length = ord(chunk[-1])
            if padding_length < 1 or padding_length > bs:
               raise ValueError("bad decrypt pad (%d)" % padding_length)
            # all the pad-bytes must be the same
            if chunk[-padding_length:] != (padding_length * chr(padding_length)):
               # this is similar to the bad decrypt:evp_enc.c from openssl program
               raise ValueError("bad decrypt")
            chunk = chunk[:-padding_length]
            finished = True
        out_file.write(chunk)
宋耀
2023-03-14

鉴于Python的流行,一开始我很失望这个问题没有完整的答案可以找到。我花了相当多的时间阅读了这块板上的不同答案,以及其他资源,才得到正确的答案。我想我可以分享这个结果,以便将来参考,也许可以回顾一下;我绝不是密码学专家!然而,下面的代码似乎可以无缝工作:

from hashlib import md5
from Crypto.Cipher import AES
from Crypto import Random

def derive_key_and_iv(password, salt, key_length, iv_length):
    d = d_i = ''
    while len(d) < key_length + iv_length:
        d_i = md5(d_i + password + salt).digest()
        d += d_i
    return d[:key_length], d[key_length:key_length+iv_length]

def decrypt(in_file, out_file, password, key_length=32):
    bs = AES.block_size
    salt = in_file.read(bs)[len('Salted__'):]
    key, iv = derive_key_and_iv(password, salt, key_length, bs)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    next_chunk = ''
    finished = False
    while not finished:
        chunk, next_chunk = next_chunk, cipher.decrypt(in_file.read(1024 * bs))
        if len(next_chunk) == 0:
            padding_length = ord(chunk[-1])
            chunk = chunk[:-padding_length]
            finished = True
        out_file.write(chunk)

用法:

with open(in_filename, 'rb') as in_file, open(out_filename, 'wb') as out_file:
    decrypt(in_file, out_file, password)

如果您看到有机会对此进行改进或将其扩展到更灵活的地方(例如,使其在不使用salt的情况下工作,或提供Python3兼容性),请随时这样做。

这个答案过去也涉及使用相同方案在Python中进行加密。我已经删除了这部分,以阻止任何人使用它。不要再用这种方式加密任何html" target="_blank">数据,因为按照今天的标准,它是不安全的。您应该只使用解密,除了向后兼容之外,没有其他原因,即当您没有其他选择时。要加密吗?如果可能的话,使用NaCl/Libs钠。

 类似资料:
  • 我使用下面的命令使用加密了一个文件 我怎么能解密文件使用python加密包。我尝试了下面,它不工作。 我需要一种使用openssl aes-256-cbc密码加密文件并在python中解密的方法

  • 我理解哈希和加密之间的区别。我正在寻找一种在Python中实现加密/解密字符串的简单方法。我在网上找到的大多数方法都是关于使用散列算法(MD5-SHA-1等)来进行单向散列。但不幸的是,哈希是不可逆的。有什么建议吗?

  • 问题内容: 很难在Google上找到直接答案。 我想从诸如的用户那里收集一段文字和一条消息 。 然后,我希望能够以某种方式对消息进行加密/解密,以便可以将其保存在数据库中,而不必担心如果我的网站被黑客入侵,数据就会被泄露, 有没有一种简单的方法可以用python实现,请有人提供/指导我看一个例子。 也许是一个示例,该示例如何使用诸如之类的种子创建公钥/私钥对? 提前谢谢了 :) 编辑:为了清楚起见

  • 问题内容: 我正在用Python编写程序,以通过安装程序分发给Windows用户。 该程序需要能够每天下载使用用户公钥加密的文件,然后再解密。 因此,我需要找到一个Python库,该库将允许我生成公共和私有PGP密钥,并解密使用该公共密钥加密的文件。 pyCrypto是否会做这件事(文档模糊)?还有其他纯Python库吗?使用任何语言的独立命令行工具如何? 到目前为止,我所看到的只是GNUPG,但

  • 问题内容: 我想用Java加密和解密文件,我已经阅读了这个URL http://www- users.york.ac.uk/~mal503/lore/pkencryption.htm ,我得到了两个文件,即公共安全证书和私有安全证书文件和private.pem文件,我将这些文件复制并粘贴到当前目录中,并按如下所示编写Java代码,当我运行此文件时,未执行任何加密或解密操作,请查看并告诉我我哪里出了

  • 问题内容: 我目前是一名学生,并且正在学习PHP,我正在尝试对PHP中的数据进行简单的加密/解密。我进行了一些在线研究,其中一些非常令人困惑(至少对我而言)。 这是我想做的事情: 我有一个包含这些字段 (用户ID,Fname,Lname,Email,Password)的表 我要拥有的是先将所有字段加密,然后再解密(如果没有任何加密算法,是否可以用于加密/解密) 我想学习的另一件事是如何创建一种与优