当前位置: 首页 > 面试题库 >

在Python中使用RSA加密文件

夏元明
2023-03-14
问题内容

我正在使用PyCrypto通过RSA实现文件加密。

我知道这有点不对,首先是因为RSA速度很慢,其次是因为PyCrypto RSA只能加密128个字符,因此您必须以128个字符的块来爆炸文件。

到目前为止的代码是:

from Crypto.PublicKey import RSA

file_to_encrypt = open('my_file.ext', 'rb').read()
pub_key = open('my_pub_key.pem', 'rb').read()
o = RSA.importKey(pub_key)

to_join = []
step = 0

while 1:
    # Read 128 characters at a time.
    s = file_to_encrypt[step*128:(step+1)*128]
    if not s: break
    # Encrypt with RSA and append the result to list.
    # RSA encryption returns a tuple containing 1 string, so i fetch the string.
    to_join.append(o.encrypt(s, 0)[0])
    step += 1

# Join the results.
# I hope the \r\r\r sequence won't appear in the encrypted result,
# when i explode the string back for decryption.
encrypted = '\r\r\r'.join(to_join)
# Write the encrypted file.
open('encrypted_file.ext', 'wb').write(encrypted)

所以我的问题是:是否有更好的方法在文件上使用私钥/公钥加密?

我听说过Mcrypt和OpenSSL,但是我不知道它们是否可以加密文件。


问题答案:

公钥加密通常仅用于少量数据。它很慢,并且很难正确使用。通常的做法是使用其他方法将不对称问题简化为共享密钥提供安全性的方法,然后使用公共密钥加密技术来保护该共享密钥。例如:

  • 要加密文件,请为块或流密码(例如AES)随机生成一个密钥。存储使用此密码加密的数据,并存储使用公共密钥加密的秘密密钥和加密的有效负载。
  • 要对文件签名,请计算一个加密摘要(例如SHA-256)。用私钥签名文件的摘要,并将其存储在文件旁边。

因此,这是加密的样子(警告,未经测试的代码,直接在浏览器中键入)的草图:

import os
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
import Crypto.Util.number
def encrypt_file(rsa, input, output):
    # Generate secret key
    secret_key = os.urandom(16)
    # Padding (see explanations below)
    plaintext_length = (Crypto.Util.number.size(rsa.n) - 2) / 8
    padding = '\xff' + os.urandom(16)
    padding += '\0' * (plaintext_length - len(padding) - len(secret_key))
    # Encrypt the secret key with RSA
    encrypted_secret_key = rsa.encrypt(padding + secret_key, None)
    # Write out the encrypted secret key, preceded by a length indication
    output.write(str(len(encrypted_secret_key)) + '\n')
    output.write(encrypted_secret_key)
    # Encrypt the file (see below regarding iv)
    iv = '\x00' * 16
    aes_engine = AES.new(secret_key, AES.MODE_CBC, iv)
    output.write(aes_engine.encrypt(input.read()))

iv是一个 初始化矢量
用于CBC
操作模式。每个消息的每个键都必须唯一。通常,它与数据一起以明文形式发送。在这里,由于密钥仅使用过一次,因此您可以使用已知的IV。

分组密码的API在PEP
272中进行了
描述。不幸的是,它仅支持一次加密。对于大文件,最好逐块加密。您一次最多可以加密一个块(AES为16个字节),但是您需要一个更好的加密库。

请注意,通常,您不应直接使用RSA加密数据。最明显的问题是,攻击者知道公钥,因此可以尝试猜测明文(如果攻击者认为明文可能是swordfish,则攻击者可以swordfish使用RSA公钥进行加密,并将结果与​​密码的输出进行比较。
RSA加密)。如果您想将文件发送给多个收件人,则会引起的另一个问题是,如果RSA加密步骤是确定性的,则攻击者可以说出明文是相同的,因为密文是相同的。解决这些问题的正常方法是使用
填充方案
,其中包括向明文添加一些随机机密数据;此数据称为填充。然后,攻击者无法猜测随机数据,并且每次加密都会看到不同的结果,因为同一明文永远不会被加密两次;就合法接收者而言,填充只是可以丢弃的数据。

在这里,上述问题似乎不适用于这种情况。但是,使用不受保护的RSA可能还会导致其他缺点。特别是,如果公共指数很小(此处不是PyCrypto使用65537的情况),或者您为许多不同的收件人加密相同的材料(同样,此处可能不是这种情况,因为每个消息都有其自己的密钥),则简单的数学计算将使攻击者能够恢复RSA明文。为了避免这种攻击,使用RSA加密的值必须与RSA模数“足够接近”,以便加密操作实际上执行模幂。我建议的填充可确保通过使高位字节适合0xff来确保填充。这被认为是安全的,尽管在现实世界中,您应该使用批准的填充模式(OAEP)。



 类似资料:
  • 我正在尝试实现RSA算法。我想加密一个图像。问题是当解密完成时,文件无法读取。我不知道问题到底出在哪里。这是RSA的实现: 这是主要方法: 这是加密方法: 这是解密方法: 阅读和写作的方法如下所述:http://www.java2s.com/Code/Java/File-Input-Output/Readfiletobytearrayandsavebytearraytofile.htm

  • 问题内容: PHP 5.3是否有任何类可提供RSA加密/解密而无需填充? 我有私钥和公钥,p,q和模数。 问题答案: 您可以使用phpseclib,这是一个纯PHP RSA实现:

  • 我正在检查一个用Python编写的代码,它用来生成一个RSA公钥对。 它会生成keypair,但是在代码的末尾,它会再次运行ssh-keygen。我不知道为什么这样做。因为,rsa.generate()本身将生成keypair,我们将其导出到两个单独的文件中。为什么需要再次运行ssh-keygen? 下面是代码中的几行: 文件pub将存储公钥,id_rsa将存储来自rsa.generate()函数

  • 我正在研究一个客户机-服务器安全协议,其中我需要使用Java中的RSA来加密HMAC摘要的SecretKey,因为密钥必须发送到服务器。加密分为两个阶段;首先,我需要用一个公共非对称密钥加密对称密钥,然后,该加密消息用一个私有非对称密钥加密。 为此,我将SecretKey生成为: 如何将SecretKey转换为字节数组,以便使用RSA和公钥对其进行加密? 由于公钥加密产生128字节的字节数组,如果

  • 我需要在Python中使用RSA加密和解密的帮助。 我正在创建一个私钥/公钥对,用密钥加密一条消息,并将消息写入一个文件。然后我从文件中读取密文,并使用密钥解密文本。 谁能帮我写这个代码,让解密从文件中读取密文,然后使用密钥解密密文?

  • 代码https://play.golang.org/p/CUEqjsJq5c 错误: 文件大小811字节(用于测试加密自源文件)。我想加密一些更大的文件,1。。500 mb。我可以用RSA来做吗?或者需要使用其他方法吗?