Python中的RSA加密和解密
Posted
技术标签:
【中文标题】Python中的RSA加密和解密【英文标题】:RSA encryption and decryption in Python 【发布时间】:2015-07-15 09:51:34 【问题描述】:我需要在 Python 中使用 RSA 加密和解密的帮助。
我正在创建一个私钥/公钥对,使用密钥加密消息并将消息写入文件。然后我从文件中读取密文并使用密钥解密文本。
我在解密部分遇到问题。正如您在下面的代码中看到的那样,当我输入decrypted = key.decrypt(message)
时,程序可以工作,但解密的消息再次被加密。似乎它没有从文件中读取密文。
谁能帮我写这段代码,以便解密从文件中读取密文,然后使用密钥解密密文?
import Crypto
from Crypto.PublicKey import RSA
from Crypto import Random
random_generator = Random.new().read
key = RSA.generate(1024, random_generator) #generate public and private keys
publickey = key.publickey # pub key export for exchange
encrypted = publickey.encrypt('encrypt this message', 32)
#message to encrypt is in the above line 'encrypt this message'
print 'encrypted message:', encrypted #ciphertext
f = open ('encryption.txt', 'w'w)
f.write(str(encrypted)) #write ciphertext to file
f.close()
#decrypted code below
f = open ('encryption.txt', 'r')
message = f.read()
decrypted = key.decrypt(message)
print 'decrypted', decrypted
f = open ('encryption.txt', 'w')
f.write(str(message))
f.write(str(decrypted))
f.close()
【问题讨论】:
我在解密部分遇到问题 不能很好地描述您的问题。请阅读How to ask。你应该edit你的问题包括你的输入、输出和你的预期输出。 编辑有所帮助,但如果您包含程序的输出以及您期望的输出,它仍然会有所帮助 您的代码中有多个拼写错误。那么你实际尝试了什么? 请记住,这是"Textbook RSA",这是弱,尤其是对于短消息。填充(通过 PKCS#1)解决了 PyCrypto(和 PyCryptodome,维护的分支)可以解决的这些问题。 相关:How to encrypt a string using the key 【参考方案1】:为了使其工作,您需要在解密之前将密钥从 str 转换为元组(ast.literal_eval 函数)。这是固定代码:
import Crypto
from Crypto.PublicKey import RSA
from Crypto import Random
import ast
random_generator = Random.new().read
key = RSA.generate(1024, random_generator) #generate pub and priv key
publickey = key.publickey() # pub key export for exchange
encrypted = publickey.encrypt('encrypt this message', 32)
#message to encrypt is in the above line 'encrypt this message'
print('encrypted message:', encrypted) #ciphertext
f = open ('encryption.txt', 'w')
f.write(str(encrypted)) #write ciphertext to file
f.close()
#decrypted code below
f = open('encryption.txt', 'r')
message = f.read()
decrypted = key.decrypt(ast.literal_eval(str(encrypted)))
print('decrypted', decrypted)
f = open ('encryption.txt', 'w')
f.write(str(message))
f.write(str(decrypted))
f.close()
【讨论】:
成功了!太感谢了!我从来没有想过要添加它。感谢您的帮助! @Alysson PyCrypto 文档中提到了publickey.encrypt()
: "you should not directly encrypt data with this method",它建议使用 PKCS#1 OAEP 代替(对于代码示例,请点击链接)
能否请您为 Python 3.3+ 制作一个版本?
encrypted = publickey.encrypt('encrypt this message', 32) - pow() 不支持的操作数类型:'str', 'int', 'int'【参考方案2】:
PKCS#1 OAEP 是一种基于 RSA 和 OAEP 填充的非对称密码
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Cipher import PKCS1_OAEP
def rsa_encrypt_decrypt():
key = RSA.generate(2048)
private_key = key.export_key('PEM')
public_key = key.publickey().exportKey('PEM')
message = input('plain text for RSA encryption and decryption:')
message = str.encode(message)
rsa_public_key = RSA.importKey(public_key)
rsa_public_key = PKCS1_OAEP.new(rsa_public_key)
encrypted_text = rsa_public_key.encrypt(message)
#encrypted_text = b64encode(encrypted_text)
print('your encrypted_text is : '.format(encrypted_text))
rsa_private_key = RSA.importKey(private_key)
rsa_private_key = PKCS1_OAEP.new(rsa_private_key)
decrypted_text = rsa_private_key.decrypt(encrypted_text)
print('your decrypted_text is : '.format(decrypted_text))
【讨论】:
你不可能用这种方法来加密整个文件 _RSAobj 对象没有“export_key”属性【参考方案3】:# coding: utf-8
from __future__ import unicode_literals
import base64
import os
import six
from Crypto import Random
from Crypto.PublicKey import RSA
class PublicKeyFileExists(Exception): pass
class RSAEncryption(object):
PRIVATE_KEY_FILE_PATH = None
PUBLIC_KEY_FILE_PATH = None
def encrypt(self, message):
public_key = self._get_public_key()
public_key_object = RSA.importKey(public_key)
random_phrase = 'M'
encrypted_message = public_key_object.encrypt(self._to_format_for_encrypt(message), random_phrase)[0]
# use base64 for save encrypted_message in database without problems with encoding
return base64.b64encode(encrypted_message)
def decrypt(self, encoded_encrypted_message):
encrypted_message = base64.b64decode(encoded_encrypted_message)
private_key = self._get_private_key()
private_key_object = RSA.importKey(private_key)
decrypted_message = private_key_object.decrypt(encrypted_message)
return six.text_type(decrypted_message, encoding='utf8')
def generate_keys(self):
"""Be careful rewrite your keys"""
random_generator = Random.new().read
key = RSA.generate(1024, random_generator)
private, public = key.exportKey(), key.publickey().exportKey()
if os.path.isfile(self.PUBLIC_KEY_FILE_PATH):
raise PublicKeyFileExists('Файл с публичным ключом существует. Удалите ключ')
self.create_directories()
with open(self.PRIVATE_KEY_FILE_PATH, 'w') as private_file:
private_file.write(private)
with open(self.PUBLIC_KEY_FILE_PATH, 'w') as public_file:
public_file.write(public)
return private, public
def create_directories(self, for_private_key=True):
public_key_path = self.PUBLIC_KEY_FILE_PATH.rsplit('/', 1)
if not os.path.exists(public_key_path):
os.makedirs(public_key_path)
if for_private_key:
private_key_path = self.PRIVATE_KEY_FILE_PATH.rsplit('/', 1)
if not os.path.exists(private_key_path):
os.makedirs(private_key_path)
def _get_public_key(self):
"""run generate_keys() before get keys """
with open(self.PUBLIC_KEY_FILE_PATH, 'r') as _file:
return _file.read()
def _get_private_key(self):
"""run generate_keys() before get keys """
with open(self.PRIVATE_KEY_FILE_PATH, 'r') as _file:
return _file.read()
def _to_format_for_encrypt(value):
if isinstance(value, int):
return six.binary_type(value)
for str_type in six.string_types:
if isinstance(value, str_type):
return value.encode('utf8')
if isinstance(value, six.binary_type):
return value
并使用
KEYS_DIRECTORY = settings.SURVEY_DIR_WITH_ENCRYPTED_KEYS
class TestingEncryption(RSAEncryption):
PRIVATE_KEY_FILE_PATH = KEYS_DIRECTORY + 'private.key'
PUBLIC_KEY_FILE_PATH = KEYS_DIRECTORY + 'public.key'
# django/flask
from django.core.files import File
class ProductionEncryption(RSAEncryption):
PUBLIC_KEY_FILE_PATH = settings.SURVEY_DIR_WITH_ENCRYPTED_KEYS + 'public.key'
def _get_private_key(self):
"""run generate_keys() before get keys """
from corportal.utils import global_elements
private_key = global_elements.request.FILES.get('private_key')
if private_key:
private_key_file = File(private_key)
return private_key_file.read()
message = 'Hello мой friend'
encrypted_mes = ProductionEncryption().encrypt(message)
decrypted_mes = ProductionEncryption().decrypt(message)
【讨论】:
【参考方案4】:这是我对 python 3 和 pycrypto 的实现
from Crypto.PublicKey import RSA
key = RSA.generate(4096)
f = open('/home/john/Desktop/my_rsa_public.pem', 'wb')
f.write(key.publickey().exportKey('PEM'))
f.close()
f = open('/home/john/Desktop/my_rsa_private.pem', 'wb')
f.write(key.exportKey('PEM'))
f.close()
f = open('/home/john/Desktop/my_rsa_public.pem', 'rb')
f1 = open('/home/john/Desktop/my_rsa_private.pem', 'rb')
key = RSA.importKey(f.read())
key1 = RSA.importKey(f1.read())
x = key.encrypt(b"dddddd",32)
print(x)
z = key1.decrypt(x)
print(z)
【讨论】:
你能解释一下如何对加密结果进行Base 64编码吗? 你使用过哪个 Crypto 模块(例如 pycrypto)? pycryptodome pycryptodome.readthedocs.io/en/latest 是完整的文档 对base64encode结果,可以import base64
再base64.b64encode(encrypted)
。【参考方案5】:
您可以使用简单的方法生成 RSA 。使用 rsa 库
pip install rsa
【讨论】:
【参考方案6】:from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
secret_message = b'ATTACK AT DAWN'
### First, make a key and save it
key = RSA.generate(2048)
with open( 'mykey.pem', 'wb' ) as f:
f.write( key.exportKey( 'PEM' ))
### Then use key to encrypt and save our message
public_crypter = PKCS1_OAEP.new( key )
enc_data = public_crypter.encrypt( secret_message )
with open( 'encrypted.txt', 'wb' ) as f:
f.write( enc_data )
### And later on load and decode
with open( 'mykey.pem', 'r' ) as f:
key = RSA.importKey( f.read() )
with open( 'encrypted.txt', 'rb' ) as f:
encrypted_data = f.read()
public_crypter = PKCS1_OAEP.new( key )
decrypted_data = public_crypter.decrypt( encrypted_data )
【讨论】:
只有代码的答案通常没有用。【参考方案7】:小心使用加密货币!!!
这是一个很棒的库,但它在 python3.8 中有一个问题,因为从库中删除了属性时钟()。要修复它,只需修改 /usr/lib/python3.8/site-packages/Crypto/Random/_UserFriendlyRNG.py
line 77 中的源更改 t = time.clock()
int t = time.perf_counter()
【讨论】:
欢迎来到***!您的帖子描述性不足以回答 OP 的问题。见how to write good answers。以上是关于Python中的RSA加密和解密的主要内容,如果未能解决你的问题,请参考以下文章