如何用RSA加密和解密AES密钥并存储到文本文件中
Python, Pycrypto, RSA, AES
我正在尝试写一个脚本,用来加密一个文件。这个脚本会先生成一个随机的AES密钥,然后用一个RSA公钥来加密这个AES密钥。加密后的AES密钥会分享给那些拥有私钥的授权人员,他们可以用私钥来解密它。代码如下:
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto import Random
RSAkey = '-----BEGIN PUBLIC KEY-----\nSome RSA Key here\n-----END PUBLIC KEY-----'
RSAkey = RSA.importKey(RSAkey)
key = Random.new().read(32)
enc_key = RSAkey.encrypt(key, '')
enc_key = str(enc_key)
custom_writefile_function('enc_key.txt', enc_key)
我把加密后的密钥(enc_key)转换成字符串,这样我才能把它写入一个文本文件。否则,enc_key.txt里会是一些无意义的东西。不过,问题是,在另一个脚本中,我想解密这个enc_key,以获取用来加密文件的原始AES密钥,但尝试解密这个已经转换成字符串的enc_key时出现了错误:
RSAkey.decrypt(str(RSAkey.encrypt(key, ''))) 错误追踪(最近的调用最后): 文件 "", 第 1 行, 在 文件 "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", 第 174 行, 在 decrypt return pubkey.pubkey.decrypt(self, ciphertext) 文件 "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/pubkey.py", 第 93 行, 在 decrypt plaintext=self._decrypt(ciphertext) 文件 "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", 第 237 行, 在 _decrypt cp = self.key._blind(ciphertext, r) ValueError: 消息太大
代码如下:
RSAkey = custom_readfile_function('private_key.txt', 'r')
RSAkey = RSA.importKey(RSAkey)
enc_key = custom_readfile_function('enc_key.txt', 'r')
aes_key = RSAkey.decrypt(enc_key)
custom_writefile_function('key.txt', str(aes_key), 'w')
我认为问题出在数据类型不匹配上。RSAkey.encrypt(key, '') 返回的是一个元组(tuple),所以我猜RSA.decrypt()也期望这个类型,但我不能把这个类型写入文本文件。因此,当我把它转换成字符串以便写入文件时,在解密时又需要把它转换回元组类型。我该怎么做呢?或者也许还有其他更好的方法可以实现我想要的结果,我还没有考虑到?
谢谢
2 个回答
虽然你提问已经过去一年多了,但我还是想给你的问题提供一个实际的解决方案,因为我自己也曾为这个小而让人不舒服的错误而苦恼过,希望能帮助到遇到这种情况的人,快速解决问题。
首先,正如其他回答所建议的,为了让人更容易理解,我会使用base64编码:
enc_key = RSAkey.encrypt(key, '')
enc_key = base64.b64encode(enc_key[0])
这里的 [0]
代表的是通过 encrypt
方法生成的元组中的第一个值(也就是加密后的内容)。
然后,当你想要解密的时候,可以调用:
aes_key = RSAkey.decrypt(base64.b64decode(enc_key))
这样应该能返回你原来的明文,而不会出现 ValueError: Message too large
的错误。
使用 base 64,而不是直接转换成字符串。
要注意你正在使用的 encrypt 方法的文档:
返回值: 一个包含两个项目的元组。第一个项目是和明文(原始数据)同类型的密文(字符串或长整型)。第二个项目总是 None。 覆盖:pubkey.pubkey.encrypt
此外,你 应该 注意以下建议:
注意:这个函数执行的是简单的、基础的 RSA 加密(教科书上的内容)。在实际应用中,你总是需要使用合适的加密填充,不能直接用这个方法加密数据。如果不这样做,可能会导致安全漏洞。建议使用模块 Crypto.Cipher.PKCS1_OAEP 或 Crypto.Cipher.PKCS1_v1_5。