使用 pycrypto,如何导入一个 RSA 公钥并使用它来加密一个字符串?

15 人关注

RSA公钥。

pubkey ='MIGfMA0GCSqGSIb3DQEBA3UAA4GNADCBiQKBgQC35eMaYoJXEoJt5HxarHkzDBEMU3qIWE0HSQ77CwP/8UbX07W2XKwngUyY4k6Hl2M/n9TOZMZsiBzer/fqV+QNPN1m9M94eUm2gQgwkoRj5battRCaNJK/23GGpCsTQatJN8PZBhJBb2Vlsvw5lFrSdMT1R7vaz+2EeNR/FitFXwIDAQAB'

如何导入它并使用它来加密一个字符串?

我尝试了以下代码,但RSA.construct()引发了异常(TypeError: must be long, not 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)
    
python
rsa
pycrypto
Romstar
Romstar
发布于 2014-01-24
8 个回答
user9527
user9527
发布于 2021-10-26
已采纳
0 人赞同
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
from base64 import b64decode,b64encode
pubkey = 'MIGfMA0GCSqGSIb3DQEBA3UAA4GNADCBiQKBgQC35eMaYoJXEoJt5HxarHkzDBEMU3qIWE0HSQ77CwP/8UbX07W2XKwngUyY4k6Hl2M/n9TOZMZsiBzer/fqV+QNPN1m9M94eUm2gQgwkoRj5battRCaNJK/23GGpCsTQatJN8PZBhJBb2Vlsvw5lFrSdMT1R7vaz+2EeNR/FitFXwIDAQAB'
msg = "test"
keyDER = b64decode(pubkey)
keyPub = RSA.importKey(keyDER)
cipher = Cipher_PKCS1_v1_5.new(keyPub)
cipher_text = cipher.encrypt(msg.encode())
emsg = b64encode(cipher_text)
print emsg
    
一个好的答案总是会有一个解释,说明做了什么,为什么会以这样的方式做,这不仅是为了OP,也是为了SO的未来访客。请添加一些描述,以使其他人理解。)
I am getting in keyPub = RSA.importKey(keyDER) -> RSA.py:588 -> ValueError: RSA key format is not supported
我把单引号换成了双引号,效果很好:) 对于变量来说 pubkey
Lara
@DimaLituiev 你想出如何解决这个问题了吗?
如果你得到的是 "不支持RSA密钥格式",你可能不得不跳过它进行b64解码的部分。
Chet
Chet
发布于 2021-10-26
0 人赞同

我在这方面也遇到了麻烦。我让它像这样工作。

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)
    
这发出了一个错误。【替换代码0
你可能需要对味精进行这样的编码 msg.encode("utf-8")
pubKeyObj.encrypt - this is not visible in python 3.8
EwyynTomato
EwyynTomato
发布于 2021-10-26
0 人赞同

By using:

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-----

你不应该对externKey进行b64解码,字符串应该以"-----BEGIN PUBLIC KEY-----"和"-----END PUBLIC KEY-----"开始。

在添加了 -----BEGIN PUBLIC KEY----- -----END PUBLIC KEY----- 并应从文件中读取 key 后,对我来说是有效的, str 不工作。
Ari
Ari
发布于 2021-10-26
0 人赞同

我最后使用的方法是基于这里的一些答案。

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)
    
Ber
Ber
发布于 2021-10-26
0 人赞同

From the 文件

importKey(externKey, passphrase=None)
Import an RSA key (public or private half), encoded in standard form.
    
这是我尝试的第一个方法,它将引发 "ValueError。RSA密钥格式不被支持"。 然后我又试了一下这个方法(来自 stackoverflow.com/questions/10569189/... ) in my question, it doesn't work either.
返还击
返还击
发布于 2021-10-26
0 人赞同

谢谢 @用户9527 为你投上一票

这解决了我的问题

my env: win10x64 python3.6.4 pycrypto2.6.1

这是我的代码,加密结束解密,密钥来自某人的博客。(如果U出现 "ValueError:RSA密钥格式不被支持",请检查密钥格式,它应该被翘起,如"-----BEGIN XXXX KEY-----")

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")

the output:

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
    
forgotten
forgotten
发布于 2021-10-26
0 人赞同

如果你想用 RSA.importkey( ) 导入一个外部密钥,你有两个选择。

  • 从文件中读取密钥。

     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-----
    

    在Linux中(我不知道Windows的情况),你可以通过这个命令来检查它。

     less exteralkey.pem
    
  • 如果你想把你的密钥硬编码到你的代码中,你的密钥必须是这样的。

     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)
    

    Note如果你没有在你的RSA密钥的每一行末尾添加"\n",那么RSA.importkey( )将引发一个错误。

    不支持RSA密钥格式

    Note 2:我用"\"来表示该语句在下一行继续。

  • 请避免在Stoack Overflow答案中使用 "SMS语言"(u,ur idk)。该要求有最低的质量水平。我已经编辑了。
    Juan Echagüe Guardiola
    Juan Echagüe Guardiola
    发布于 2021-10-26
    0 人赞同

    This worked for me. Python 3.8

    ubuntu@ubuntu:~$ sudo pip3 list|grep crypto

    密码学 2.8

    密码学-向量 2.8

    pycrypto 2.6.1

    from Crypto.PublicKey import RSA
    from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5
    def encrypt_data(data):
        with open("/home/echague/.ssh/id_rsa.pub", "rb") as k:
            key_pub = RSA.importKey(k.read())
        cipher = Cipher_PKCS1_v1_5.new(key_pub)
        return cipher.encrypt(data.encode())
    def decrypt_data(data):
        with open("/home/echague/.ssh/id_rsa", "rb") as k:
            key_priv = RSA.importKey(k.read())
        decipher = Cipher_PKCS1_v1_5.new(key_priv)
        return decipher.decrypt(data, None).decode()
    message = "hello world!"
    encrypted = encrypt_data(message)