Шифрование и дешифрование RSA в Python

Мне нужна помощь в использовании шифрования и дешифрования RSA в Python.

Я создаю пару закрытого / открытого ключей, шифрую сообщение ключами и записываю сообщение в файл. Затем я читаю зашифрованный текст из файла и расшифровываю текст с помощью ключа.

У меня проблемы с расшифровкой. Как вы можете видеть в моем коде ниже, когда я добавляю 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()

person Community    schedule 05.05.2015    source источник
comment
У меня проблемы с расшифровкой - не очень хорошее описание вашей проблемы. Прочтите Как задать вопрос. Вам следует отредактировать свой вопрос, включив в него свои входы, выходы и ожидаемые результаты.   -  person Artjom B.    schedule 05.05.2015
comment
Редактирование помогло, но оно все равно поможет, если вы включите вывод своей программы, и ожидаемый результат.   -  person daphshez    schedule 05.05.2015
comment
В вашем коде несколько опечаток. Так что вы на самом деле пробовали?   -  person kay    schedule 05.05.2015
comment
Имейте в виду, что это RSA для учебников, который слабый , особенно для коротких сообщений. Заполнение (через PKCS # 1) устраняет эти проблемы, которые может решить PyCrypto (и PyCryptodome, поддерживаемая вилка).   -  person Nick T    schedule 25.01.2017
comment
связанные: Как зашифровать строку с помощью ключа   -  person jfs    schedule 15.07.2018


Ответы (7)


Чтобы он работал, вам нужно преобразовать ключ из 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()
person Esdes    schedule 05.05.2015
comment
Это сработало! большое спасибо! я бы никогда не подумал добавить это. Я ценю вашу помощь! - person ; 05.05.2015
comment
В документации @Alysson PyCrypto говорится о publickey.encrypt(): не следует напрямую шифруйте данные с помощью этого метода, и он рекомендует PKCS # 1 OAEP вместо этого (для примера кода перейдите по ссылке) - person jfs; 13.11.2016
comment
Не могли бы вы сделать версию для Python 3.3+? - person cascading-style; 28.05.2017
comment
encrypted = publickey.encrypt ('encrypt this message', 32) - неподдерживаемые типы операндов для pow (): 'str', 'int', 'int' - person GML-VS; 01.04.2021

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))
person Rajan saha Raju    schedule 21.03.2019
comment
Возможен ли вам такой подход для шифрования всего файла? - person Ritvik; 19.06.2020
comment
У объекта _RSAobj нет атрибута export_key - person GML-VS; 01.04.2021

# 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)
person Nick Korolkov    schedule 23.01.2017

Вот моя реализация для 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)
person Anagnostou John    schedule 19.10.2018
comment
Не могли бы вы объяснить, как Base 64 кодировать зашифрованный результат? - person LCJ; 02.10.2019
comment
Какой модуль Crypto вы использовали (например, pycrypto)? - person Kevin Wallis; 22.01.2020
comment
pycryptodome pycryptodome.readthedocs.io/en/latest - это полная документация - person Anagnostou John; 22.01.2020
comment
Чтобы base64 закодировать результат, вы можете import base64, а затем base64.b64encode(encrypted). - person hacKaTun3s; 26.06.2021

Вы можете использовать простой способ создания RSA. Использовать библиотеку rsa

pip install rsa 
person AliReza Azizi    schedule 27.12.2019

Остерегайтесь использования криптовалюты !!! Это замечательная библиотека, но у нее есть проблема с python3.8, потому что из библиотеки time был удален атрибут clock (). Чтобы исправить это, просто измените источник в /usr/lib/python3.8/site-packages/Crypto/Random/_UserFriendlyRNG.pyline 77, изменив t = time.clock() int t = time.perf_counter()

person Alessandro    schedule 10.04.2020
comment
Добро пожаловать в stackoverflow! Ваш пост недостаточно описательный, чтобы ответить на вопрос ОП. См. как писать хорошие ответы. - person hacKaTun3s; 26.06.2021

person    schedule
comment
Ответы только на код обычно бесполезны. - person 10 Rep; 30.06.2021