公钥密码通常只用于少量数据。它很慢,很难正确使用。通常的做法是使用其他方法将非对称问题减少到由共享密钥提供安全性的问题,然后使用公钥加密来保护该共享密钥。例如:要加密文件,随机生成块或流密码(例如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是CBCmode of operation的一个
分组密码的API在PEP 272中描述。不幸的是,它只支持一次加密。对于大型文件,最好逐块加密;一次只加密一个块(AES为16字节),但需要一个更好的加密库。
请注意,一般情况下,不应使用RSA直接加密数据。最明显的问题是攻击者知道公钥,因此可以尝试猜测明文(如果攻击者认为明文可能是swordfish,则攻击者可以使用RSA公钥加密swordfish,并将结果与RSA加密的输出进行比较)。如果您想将文件发送给多个收件人,另一个需要考虑的问题是,如果RSA加密步骤是确定的,那么攻击者可以知道明文是相同的,因为密文是相同的。针对这些问题的通常防御方法是使用
在这里,上述问题似乎不适用于这种情况。但是,使用无保护的RSA可能会产生其他弱点。特别是,如果公共指数非常小(这里不是PyCrypto使用65537的情况),或者您为许多不同的收件人加密相同的材料(同样,这里可能不是这样,因为每个消息都有自己的密钥),那么simple mathematical calculation would allow the attacker to recover the RSA plaintext。为了避免这种攻击,用RSA加密的值需要“足够接近”RSA模,这样加密操作实际上执行模幂运算。我建议的填充确保通过生成符合0xff;this is believed to be safe的最高顺序字节,尽管在现实世界中您应该使用批准的填充模式(OAEP)。