Используя pycrypto, как импортировать открытый ключ RSA и использовать его для шифрования строки?

Открытый ключ RSA:

Публичный = 'MIGfMA0GCSqGSIb3DQEBA3UAA4GNADCBiQKBgQC35eMaYoJXEoJt5HxarHkzDBEMU3qIWE0HSQ77CwP / 8UbX07W2XKwngUyY4k6Hl2M / n9TOZMZsiBzer / fqV + QNPN1m9M94eUm2gQgwkoRj5battRCaNJK / 23GGpCsTQatJN8PZBhJBb2Vlsvw5lFrSdMT1R7vaz + 2EeNR / FitFXwIDAQAB'

как его импортировать и использовать для шифрования строки?

Я попробовал следующий код, но RSA.construct() вызывает исключение (TypeError: должен быть длинным, а не str).

from Crypto.PublicKey import RSA
from Crypto.Util import asn1
from base64 import b64decode

keyDER = b64decode(pubkey)
seq = asn1.DerSequence()
seq.decode(keyDER)
keyPub = RSA.construct((seq[0], seq[1]))
print keyPub.encrypt('mysecret', 32)

Спасибо.


person user21916    schedule 24.01.2014    source источник


Ответы (7)


У меня тоже была с этим беда. У меня это работает так:

key = RSA.generate(2048)

binPrivKey = key.exportKey('DER')
binPubKey =  key.publickey().exportKey('DER')

privKeyObj = RSA.importKey(binPrivKey)
pubKeyObj =  RSA.importKey(binPubKey)

msg = "attack at dawn"
emsg = pubKeyObj.encrypt(msg, 'x')[0]
dmsg = privKeyObj.decrypt(emsg)

assert(msg == dmsg)

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

def bin2hex(binStr):
    return binascii.hexlify(binStr)

def hex2bin(hexStr):
    return binascii.unhexlify(hexStr)
person Chet    schedule 18.11.2014
comment
Выдает ошибку: /usr/local/lib/python3.6/site-packages/Crypto/PublicKey/RSA.py in encrypt(self, plaintext, K) --> 372 NotImplementedError: Use module Crypto.Cipher.PKCS1_OAEP instead - person Dima Lituiev; 15.12.2017
comment
Возможно, вам придется закодировать сообщение следующим образом msg.encode("utf-8") - person jmercouris; 01.06.2018
comment
pubKeyObj.encrypt — это не видно в python 3.8 - person Abhishek; 01.07.2020

Используя:

RSA.importKey(externKey)

с параметром externKey выглядят следующим образом:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAybVqRvfYvWbLsB98BqkD
lWd0/5y6SyhHt6/r6M0l7JXBweqMvxVt7XmI2yqPL56YxzcgQ8ycDkoqHJ+XozgP
iRnLNpYRlCzsiaOElbmQcnrI8iOb9Ahm6j0cbBB1S8VNvD+u9RQJt53zPxPj8/Dq
f1oNGFXOM8udNYWZaRCukLs/TumsAn0a+BF4639WtFiUvTWdVhlyvCQTs49ytRkH
rXH30RkB528RIvTGeW8xBTV4NaiTIzAEKCVSPagLr4Hzbb9b5+bODic/zkLGQazy
/NKOFgiB7kD2+WEMcuhTr5noeXau0PDAhgmrBhzzWOjUwwaO+ACvJLkPXZfjhy7P
+wIDAQAB
-----END PUBLIC KEY-----

Вы не должны b64decode externKey и строка должна начинаться с "-----BEGIN PUBLIC KEY-----" и "-----END PUBLIC KEY-----".

person EwyynTomato    schedule 29.04.2014
comment
У меня работает после добавления -----BEGIN PUBLIC KEY----- и -----END PUBLIC KEY----- и должен читать key из файла, str не работает - person Simin Jie; 08.01.2017

Метод, который я использовал, основанный на нескольких ответах здесь:

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5

def encrypt_data(data):
    with open("/path/to/public.pem", "rb") as k:
        key = RSA.importKey(k.read())

    cipher = Cipher_PKCS1_v1_5.new(key)
    return cipher.encrypt(data.encode())


def decrypt_data(data):
    with open("path/to/private.pem", "rb") as k:
        key = RSA.importKey(k.read())

    decipher = Cipher_PKCS1_v1_5.new(key)
    return decipher.decrypt(data, None).decode()


message = "hello world!"
encrypted = encrypt_data(message)
decrypted = decrypt_data(message)
person Ari    schedule 08.11.2019

Из документации

importKey(externKey, passphrase=None)
Import an RSA key (public or private half), encoded in standard form.
person Ber    schedule 24.01.2014
comment
Это был первый метод, который я пробовал, он вызывал ошибку ValueError: формат ключа RSA не поддерживается. Затем я попробовал этот метод (из stackoverflow.com/questions/10569189/) в моем вопросе это тоже не работает. - person user21916; 26.01.2014

спасибо @user9527 голосую за вас

это решило мою проблему

моя среда: win10x64 python3.6.4 pycrypto2.6.1

вот мой код, зашифровать и расшифровать, ключ был из чьего-то блога. (если U произошло с «ValueError: формат ключа RSA не поддерживается», проверьте формат ключа, он должен быть искажен чем-то вроде «----- НАЧАЛО XXXX КЛЮЧ-----")

pubkey = """-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----"""

prvkey = """-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----"""

from Crypto.PublicKey import RSA

from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5

msg = "test"
print("raw msg->", msg)
keyPub = RSA.importKey(pubkey) # import the public key
cipher = Cipher_PKCS1_v1_5.new(keyPub)
#print(cipher.encrypt.__doc__)
cipher_text = cipher.encrypt(msg.encode()) # now we have the cipher
print("cipher text->", cipher_text)


keyPriv = RSA.importKey(prvkey) # import the private key
cipher = Cipher_PKCS1_v1_5.new(keyPriv)
#print(cipher.decrypt.__doc__)
decrypt_text = cipher.decrypt(cipher_text, None).decode()
print("decrypted msg->", decrypt_text)
assert msg == decrypt_text # check that
print("test passed")

выход:

raw msg-> test
cipher text-> b'\xb0]\x1f@B\x8b\xb5\xbf\x891:\t4D\x80$\xc0y\xaa\xb4\x86t/|\xeaM%\xf06\x14,\x9e?\x86R\x83\xd72\xe5\xfdsr:\x99\xe7v\xd9]&\xbc\x85\xd3\x16\x80\x19q\xe7\xb1\x89\xff/\x12\xe5\xb3\x9cu\x1f\x04x\xa5\xdfl\xcd\xae_\xba\x1b\x97\x9fa\xcf9O\xbfB\xf6\xd1N\xf5|<\xbf^\x84R\xecSo\x9a*\xf7\x8d\x8e\xbe0Q\xcd\x14\x13\xf98x\xe7\xd8x\x19\xaf\x98\xefu\xa8\xb1\xd3\xfa\xf2N\xca\xb5'
decrypted msg-> test
test passed
person 返还击    schedule 13.09.2018

Если вы хотите импортировать внешний ключ с помощью RSA.importkey( ), у вас есть два варианта:

  1. Прочитать ключ из файла:

     file = open('external.pem','r')
     external_key = file.read()
     key = RSA.import_key(external_key)
    

    и ваш формат внешнего ключа должен быть примерно таким:

     -----BEGIN PUBLIC KEY-----
     MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsDcmhF1kqsMw9HAUc231
     IEr3OwVwocSM4JPUGVSTBDcM9tGoflx8UoN4M9EJrdCcVicZEt709L13jhUxo/hX
     jUDqyQ6U+zyOYhoSwQpHKju2bwn6HMC8iq/ZwNqRFiqa23O2L8WSjZq4J/U1wWZ9
     Zh7f0E5w8GZDkngceQI8nBWFPSAeQNAh0b4Vy1SYKapPrvUJdS9LsT3V9B2k2Nm1
     4lUOtfufpWP5xjoC3MwOxgBsPJsuqpe7sZddG4YzQi3IuMAcc+C/ms9mA7OX5yxt
     xgU3tAIzzBHgvwn9vANNJPzJMaOcm9kKMVJYXLHfg37IfIk1oV+/3BxMQ26ErNcC
     9wIDAQAB
     -----END PUBLIC KEY-----
    

    В линуксе (не знаю как в винде) это можно проверить такой командой:

     less exteralkey.pem
    
  2. Если вы хотите жестко закодировать свой ключ в свой код, ваш ключ должен быть таким:

     pubkey = "-----BEGIN PUBLIC KEY-----\n\
     MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsDcmhF1kqsMw9HAUc231\n\
     IEr3OwVwocSM4JPUGVSTBDcM9tGoflx8UoN4M9EJrdCcVicZEt709L13jhUxo/hX\n\
     jUDqyQ6U+zyOYhoSwQpHKju2bwn6HMC8iq/ZwNqRFiqa23O2L8WSjZq4J/U1wWZ9\n\
     Zh7f0E5w8GZDkngceQI8nBWFPSAeQNAh0b4Vy1SYKapPrvUJdS9LsT3V9B2k2Nm1\n\
     4lUOtfufpWP5xjoC3MwOxgBsPJsuqpe7sZddG4YzQi3IuMAcc+C/ms9mA7OX5yxt\n\
     xgU3tAIzzBHgvwn9vANNJPzJMaOcm9kKMVJYXLHfg37IfIk1oV+/3BxMQ26ErNcC\n\
     9wIDAQAB\n\
     -----END PUBLIC KEY-----"
    

    то вы можете импортировать его:

     key = RSA.importkey(pubkey)
    

Примечание: если вы не добавите "\n" в конец каждой строки вашего ключа RSA, RSA.importkey( ) вызовет ошибку:

Формат ключа RSA не поддерживается

Примечание 2. Я использовал "\", чтобы указать, что выражение продолжается на следующей строке.

person fomehellandhell    schedule 31.07.2020
comment
Пожалуйста, избегайте использования языка SMS (u, ur idk) в ответах Stoack Overflow. Требуется минимальный уровень качества. Я отредактировал его. - person Roberto Caboni; 31.07.2020

person    schedule
comment
В хорошем ответе всегда будет объяснение того, что было сделано и почему это было сделано таким образом, не только для ОП, но и для будущих посетителей SO. Пожалуйста, добавьте описание, чтобы другие поняли. :) - person Rucha Bhatt Joshi; 22.09.2017
comment
Я вхожу в keyPub = RSA.importKey(keyDER) -> RSA.py:588 -> ValueError: RSA key format is not supported - person Dima Lituiev; 15.12.2017
comment
Я заменил одинарную кавычку на двойную, все заработало :) для переменной pubkey - person Nayef; 01.09.2018