2013-10-23 73 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