【问题标题】:Using pycrypto, how to import a RSA public key and use it to encrypt a string?使用 pycrypto,如何导入 RSA 公钥并使用它来加密字符串?
【发布时间】:2014-02-15 03:23:32
【问题描述】:

RSA 公钥:

PUBKEY = 'MIGfMA0GCSqGSIb3DQEBA3UAA4GNADCBiQKBgQC35eMaYoJXEoJt5HxarHkzDBEMU3qIWE0HSQ77CwP / 8UbX07W2XKwngUyY4k6Hl2M / n9TOZMZsiBzer / fqV + QNPN1m9M94eUm2gQgwkoRj5battRCaNJK / 23GGpCsTQatJN8PZBhJBb2Vlsvw5lFrSdMT1R7vaz + 2EeNR / FitFXwIDAQAB' P>

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

我尝试了以下代码,但 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


    【解决方案1】:

    这对我有用。 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)
    decrypted = decrypt_data(encrypted)
    print(message)
    print(encrypted)
    print(decrypted)
    

    【讨论】:

    • 您能否通过添加一些 cmets 来解释它的作用来改进您的答案?
    【解决方案2】:

    如果您想使用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-----
      

      在Linux(我不了解Windows)中,您可以通过以下命令进行检查:

       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:我用"\"表示该语句在下一行继续。

    【讨论】:

    • 请避免在 Stoack 溢出答案中使用“短信语言”(u, ur idk)。要求最低质量水平。我已经编辑过了。
    【解决方案3】:

    根据这里的一些答案,我最终使用的方法:

    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)
    

    【讨论】:

      【解决方案4】:

      感谢@user9527 为你投票

      解决了我的问题

      我的环境: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")
      

      输出:

      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
      

      【讨论】:

        【解决方案5】:
        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,而且对未来的访问者来说。请添加一些描述以使其他人理解。 :)
        • 我进入keyPub = RSA.importKey(keyDER) -> RSA.py:588 -> ValueError: RSA key format is not supported
        • 我用双引号替换了单引号,它工作正常:) 变量 pubkey
        • @DimaLituiev 你知道如何解决这个问题吗?
        • 如果您得到“不支持 RSA 密钥格式”,您可能需要跳过它执行 b64decode 的部分。
        【解决方案6】:

        我也遇到过这个问题。我让它像这样工作:

        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)
        

        【讨论】:

        • 这会报错:/usr/local/lib/python3.6/site-packages/Crypto/PublicKey/RSA.py in encrypt(self, plaintext, K) --&gt; 372 NotImplementedError: Use module Crypto.Cipher.PKCS1_OAEP instead
        • 您可能必须像这样msg.encode("utf-8") 编码味精
        • pubKeyObj.encrypt - 这在 python 3.8 中不可见
        【解决方案7】:

        通过使用:

        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----- 后对我有用,并且应该从文件中读取keystr 不起作用
        【解决方案8】:

        来自documentation

        importKey(externKey, passphrase=None)
        Import an RSA key (public or private half), encoded in standard form.
        

        【讨论】:

        • 这是我尝试的第一种方法,它会引发“ValueError: RSA key format is not supported”。然后我在我的问题中尝试了该方法(来自stackoverflow.com/questions/10569189/…),它也不起作用。
        猜你喜欢
        • 2018-05-02
        • 2014-10-29
        • 2013-06-08
        • 1970-01-01
        • 1970-01-01
        • 2020-12-07
        • 2013-12-08
        • 2017-01-18
        • 1970-01-01
        相关资源
        最近更新 更多