2013-10-23 74 views
6

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

当我尝试使用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 

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

是否有可能使用PyCrypto公钥解密?

+1

你把它颠倒过来。公钥用于加密,私钥用于解密。 – jchysk

+1

公开解密与加密相同。你的问题可以这样解决:'decrypted = rsakey.encrypt(raw_cipher_data,0)' – Helio

+0

如果源真的用私钥加密,那么他们已经有效地签署了数据。一些工具,如Java,可以让你做到这一点。要解密签名,您可以使用公钥(或私钥的公共部分)。请参阅:https://stackoverflow.com/questions/48280670/pycrypto-how-to-view-raw-rsa-signature-data –

回答

5

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

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

要验证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" 

我会强烈建议,使其产生这样的签名更改PHP代码。

+0

感谢您的建议,我毫无疑问会考虑它。您能否详细说明使用公钥解密非秘密数据以证明真实性的不安全性?你是否说它可以被欺骗,因为我没有填充? – sergiopereira

+0

没有密钥的人仍然可以伪造一些看起来像来自真正所有者的有效消息。这是由于RSA是一种相当可塑的算法,如果不与经过验证的填充相结合。您所描述的实际上是一种具有所谓的完整邮件恢复的签名:其中一个例子是ISO 9796-1标准,该标准已完全破解。 – SquareRootOfTwentyThree

+0

不应该“导入”是“importKey”? –

0

你的功能是正确的。你只需要给你的私钥的路径,以解密而不是你的公钥。公钥用于加密,私钥用于解密。

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

然后我无法保证谁加密了邮件。我最终在接受的答案中遵循了这个建议,并且我们转而使用签名。此外,我的问题与OAuth令牌有关,最终我们转移到使用签名的JWT。 – sergiopereira

+0

正确的是,除非发送人使用他们的私钥签署了邮件,并且您已将他们的公钥分别验证为他们的公钥,否则您将无法确定真实性。使用JWT,您仍然可以使用RSA与RS512等算法进行签名。如果您专注于确保发件人的真实性,则应该关注发行人属性。 – jchysk