2013-10-23 21 views
6

Per quanto ho capito, dovrei essere in grado di utilizzare RSA per garantire l'autenticità o la privacy, come vorrei. Nel mio caso, voglio garantire l'autenticità, quindi crittografo i dati con la chiave privata e permetto a chiunque di decodificarlo con la chiave pubblica. I dati non sono davvero segreti, ma ho bisogno di garantire che sia stato creato dal proprietario della chiave pubblica (e privata).Decifrare utilizzando una chiave pubblica RSA con PyCrypto

Quando provo a decrittografare con PyCrypto ottengo Nessun errore di chiave privata da PyCrypto. Il codice è questo:

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 

sto chiamando con il percorso del file di chiave pubblica I dati crittografati non è generata da me e non è stato fatto con Python, ma PHP (in formato OpenSSH.). In PHP c'è una funzione openssl_public_decrypt che decodifica facilmente questi dati.

È possibile decifrare utilizzando la chiave pubblica con PyCrypto?

+1

Avete invertito. La chiave pubblica viene utilizzata per crittografare e la chiave privata viene utilizzata per decrittografare. – jchysk

+1

Il decrypt pubblico è lo stesso di encrypt. Il tuo problema può essere risolto in questo modo: 'decrypted = rsakey.encrypt (raw_cipher_data, 0)' – Helio

+0

Se la fonte ha veramente crittografato con la chiave privata, hanno effettivamente firmato i dati. Alcuni strumenti, come Java, ti permettono di farlo. Per decifrare la firma è possibile utilizzare una chiave pubblica (o la parte pubblica di una chiave privata). Vedi: https://stackoverflow.com/questions/48280670/pycrypto-how-to-view-raw-rsa-signature-data –

risposta

5

Questo è totalmente insicuro, perché si utilizza RAA non formattato.

L'applicazione richiede una firma, pertanto non è necessario occuparsi di crittografia e decrittografia. Ad esempio, PKCS # 1 v1.5 è un buon protocollo, anche se la firma è un pezzo di dati che deve essere aggiunto a ciò che si vuole dimostrare l'autenticità di.

per verificare un PKCS # 1 v1.5 firma in Python, che fai:

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" 

consiglio vivamente di cambiare il codice PHP in modo da creare una firma.

+0

Grazie per il tuo suggerimento, senza dubbio lo prenderò in considerazione. Potresti approfondire ciò che è insicuro nell'usare una chiave pubblica per decrittografare un dato non segreto per provare l'autenticità? Stai dicendo che può essere falsificato perché non ho il padding? – sergiopereira

+0

Una persona senza la chiave segreta è ancora in grado di falsificare qualcosa che sembra un messaggio valido proveniente dal proprietario reale. Ciò è dovuto al fatto che RSA è un algoritmo piuttosto malleabile se non combinato con una comprovata imbottitura. Quello che descrivi è davvero una firma con il cosiddetto recupero di messaggi completi: un esempio è lo standard ISO 9796-1, che è completamente rotto. – SquareRootOfTwentyThree

+0

non dovrebbe "importare" essere "importKey"? –

0

La vostra funzione è corretta. Hai solo bisogno di dargli il percorso della tua chiave privata per decodificare invece della tua chiave pubblica. La chiave pubblica è per la crittografia, la chiave privata è per decifrare.

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

Quindi non sarei in grado di garantire chi ha crittografato il messaggio. Ho finito per seguire il suggerimento nella risposta accettata e ci siamo spostati per usare invece le firme. Inoltre, il mio problema era relativo ai token OAuth e alla fine ci siamo spostati su JWT, che utilizza anche le firme. – sergiopereira

+0

Corretto, non sareste in grado di determinare l'autenticità a meno che la persona che lo ha inviato abbia firmato il messaggio con la sua chiave privata e voi aveste la loro chiave pubblica che avete verificato separatamente come loro. Con JWT puoi comunque utilizzare RSA per la firma con un algoritmo come RS512.Se ti concentri sull'autenticità del mittente, dovresti concentrarti sull'attributo dell'emittente. – jchysk