Python 使用带有 PyCrypto 的 RSA 公钥解密

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19548800/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 14:01:28  来源:igfitidea点击:

Decrypt using an RSA public key with PyCrypto

pythonrsapycrypto

提问by sergiopereira

As far as I understand, I should be able to use RSA to ensure authenticity or privacy, as I wish. In my case, I want to ensure authenticity so I encrypt the data with the private key and allow anyone to decrypt it with the public key. The data is not really secret but I need to guarantee that it was created by the owner of the public (and private) key.

据我所知,我应该能够使用 RSA 来确保真实性或隐私,如我所愿。就我而言,我想确保真实性,因此我使用私钥对数据进行加密,并允许任何人使用公钥对其进行解密。数据并不是真正的秘密,但我需要保证它是由公钥(和私钥)的所有者创建的。

When I try to decrypt using PyCrypto I get No private keyerror from PyCrypto. The code is this:

当我尝试使用 PyCrypto 进行解密时,我从 PyCrypto收到没有私钥错误。代码是这样的:

def _decrypt_rsa(decrypt_key_file, cipher_text):
    from Crypto.PublicKey import RSA
    from base64 import b64decode

    key = open(decrypt_key_file, "r").read()
    rsakey = RSA.importKey(key)
    raw_cipher_data = b64decode(cipher_text)
    decrypted = rsakey.decrypt(raw_cipher_data)
    return decrypted

I'm calling it with the path to the public key file (in OpenSSH format.) The encrypted data isn't generated by me and it was not done with Python but PHP. In PHP there's a openssl_public_decryptfunction that decrypts this data easily.

我用公钥文件的路径(OpenSSH 格式)调用它。加密的数据不是由我生成的,它不是用 Python 完成的,而是用 PHP 完成的。在 PHP 中有一个openssl_public_decrypt函数可以轻松解密这些数据。

Is it possible at all to decrypt using the public key with PyCrypto?

是否可以使用 PyCrypto 的公钥进行解密?

采纳答案by SquareRootOfTwentyThree

That is totally insecure, because you are using raw RSA without padding.

这是完全不安全的,因为您使用的是没有填充的原始 RSA。

Your application needs a signature, so you should not be dealing with encryptions and decryptions. For instance, PKCS#1 v1.5 is a good protocol, even though the signature is a piece of data that must be appended to what you want to prove the authenticity of.

您的应用程序需要签名,因此您不应该处理加密和解密。例如,PKCS#1 v1.5 是一个很好的协议,即使签名是一段数据,必须附加到您要证明其真实性的内容上。

To verify a PKCS#1 v1.5 signature in Python, you do:

要在 Python 中验证 PKCS#1 v1.5 签名,请执行以下操作:

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA

rsa_key = RSA.importKey(open(verification_key_file, "rb").read())
verifier = PKCS1_v1_5.new(rsa_key)
h = SHA.new(data_to_verify)
if verifier.verify(h, signature_received_with_the_data):
    print "OK"
else:
    print "Invalid"

I would strongly recommend to change the PHP code so that it creates such a signature.

我强烈建议更改 PHP 代码,以便创建这样的签名。

回答by jchysk

Your function is correct. You just need to be giving it the path to your private key in order to decrypt instead of your public key. The public key is for encrypting, the private key is for decrypting.

你的功能是正确的。您只需要为其提供私钥的路径即可解密而不是公钥。公钥用于加密,私钥用于解密。

def _decrypt_rsa(decrypt_key_file, cipher_text):
    '''
    Decrypt RSA encrypted package with private key
    :param decrypt_key_file: Private key
    :param cipher_text: Base64 encoded string to decrypt
    :return: String decrypted
    '''
    from Crypto.PublicKey import RSA
    from base64 import b64decode

    key = open(decrypt_key_file, "r").read()
    rsakey = RSA.importKey(key)
    #optionally could use OAEP
    #from Crypto.Cipher import PKCS1_OAEP
    #rsakey = PKCS1_OAEP.new(rsakey)
    raw_cipher_data = b64decode(cipher_text)
    decrypted = rsakey.decrypt(raw_cipher_data)
    return decrypted