2015-01-20 11 views
6
import OpenSSL 

key = ... 
signature = ... 
data = ... 

x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, key) 
OpenSSL.crypto.verify(x509, signature, data, 'sha1') 

Finora, sono in grado di fare tutto questo senza problemi. Tuttavia, non sembra che questo sia abbastanza sicuro, dal momento che la chiave stessa mi viene data tramite un URL (che dovrei fidarmi *), e il metodo per costruire la firma è pubblicamente disponibile.Come autenticare una chiave pubblica con l'autorità di certificazione usando Python?

Quindi, supponiamo che la chiave sia verificata da "VeriSign Classe 3 Code Signing 2010 CA", qualcuno può dirmi come posso verificare che si tratti di un reclamo valido?

Suppongo di dover avere il certificato VeriSign localmente sulla mia macchina. Supponendo che io lo faccia, da dove vado?

Grazie!

* l'URL mi viene fornito come parametro in una richiesta JSON. Certo, l'URL sarà HTTPS e posso controllare il nome di dominio e tutto il resto. Ma sembra che dovrei fare controlli sul certificato stesso

risposta

2

Hai ragione a controllare il certificato stesso. E sì, è necessario che i certificati radice VeriSign (e tutti gli altri certificati intermedi abbiano la catena di fiducia completa) che hanno firmato il certificato da verificare.

I certificati correnti di Symantec (VeriSign) sono disponibili here in zipfile.

Scaricare e decomprimere il file zip e trovare tutti i certificati che si desidera considerare affidabili e riunirli (in formato pem) in un unico file di certificati.

Ora è necessario effettuare la verifica effettiva.Sfortunatamente, la chiamata OpenSSL di cui hai bisogno è X509_verify_certificate. Ho esaminato la fonte sia per pyopenssl che per M2Crypto e non espongo la chiamata, quindi non esiste un codice Python diretto che puoi chiamare per verificare il certificato con uno di questi pacchetti.

Tuttavia, dal momento che si utilizza pyopenssl ovviamente è disponibile la libreria openssl. Quindi probabilmente hai già o puoi facilmente installare il set di strumenti da riga di comando openssl. Se è così, è possibile chiamare il comando openssl verify attraverso un tubo facendo qualcosa di simile a questo:

cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, key) 
# the command like likes pem format 
cert_pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) 

# the bundle that you created from the zip extraction 
certificate_bundle = 'verisign-root-bundle.pem' 

# Pipe the cert to the openssl verify command and check the return code 
# a return code of 0 is successful verify 
import subprocess 
p = subprocess.Popen(['openssl', 'verify', '-CAfile', certificate_bundle], 
        stdin=subprocess.PIPE) 
p.communicate(input=cert_pem) 
p.wait() 
if (p.returncode == 0): 
    print('Certificate Verified.') 
else: 
    print('Problem with certificate') 

Il tubo sopra esegue il comando

openssl verify -CAfile ca.bundle certificate.pem 

Infine, se non hai familiarità con openssl, il comando per mostrare i certificati è

openssl x509 -inform PEM -text -in certificate.pem 

Spero che questo aiuti!

2

Forse mi rivolgo solo in parte alla tua domanda. Sembra che la tua più grande preoccupazione sia la sicurezza del canale tramite il quale ottieni la chiave. Non viene mostrato alcun codice su come si ottiene tale chiave, ma si è detto che lo si recupera tramite HTTPS e ora si desidera verificare l'autenticità di questa connessione mediante la verifica del certificato.

È possibile farlo comodamente utilizzando la consolidata struttura client Web di terze parti requests.

Citazione di the docs:

Le richieste possono verificare i certificati SSL per le richieste HTTPS, proprio come un browser web . Per controllare il certificato SSL di un host, è possibile utilizzare la verifica argomento:

requests.get(url, verify=True) 

anche:

È possibile passare verificare il percorso di un file CA_BUNDLE con certificati di CA di fiducia.

Quest'ultima potrebbe sembrare

requests.get(url, verify='/path/to/cert.pem') 

Nel caso in cui davvero si vuole prendere il controllo (e ridurre la complessità), quindi caricare il file direttamente dal http://www.symantec.com/page.jsp?id=roots e prendere l'approccio verify='/path/to/cert.pem'. Immagino tu abbia bisogno di http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority-G2.pem

+1

Non convalida il carico utile, se questo è ciò che intendi. Non so esattamente quale sia la "chiave" che ottieni tramite questa connessione HTTPS. Ma posso assicurarti che questa chiave è trattata come qualsiasi altro dato di payload trasmesso via HTTPS. –

Problemi correlati