Sto lavorando all'implementazione di un'applicazione Web che utilizza un'API. Durante una risposta, il server API invia un collegamento a un certificato X509 (in formato PEM, composto da un certificato di firma e uno o più certificati intermedi in un certificato CA radice) che devo scaricare e utilizzare per effettuare ulteriori verifiche.Come convalidare/verificare una catena di attendibilità del certificato X509 in Python?
Prima di utilizzare il certificato, è necessario garantire che tutti i certificati della catena si combinino per creare una catena di trust con un certificato CA radice affidabile (per rilevare ed evitare richieste malevoli). Sto facendo fatica a farlo in Python e la mia ricerca sull'argomento non sta portando a nulla di utile.
Il certificato è facilmente afferrato e caricato utilizzando richieste e M2Crypto
import requests
from M2Crypto import RSA, X509
mypem = requests.get('https://server.com/my_certificate.pem')
cert = X509.load_cert_string(str(mypem.text), X509.FORMAT_PEM)
Tuttavia, convalidare la catena di certificati è un problema. Non è possibile per me scrivere il certificato su disco per utilizzare un'utilità della riga di comando come openssl
tramite qualcosa come un sottoprocesso, quindi deve essere eseguito tramite python. Inoltre, non ho nessuna connessione aperta e quindi l'utilizzo di una soluzione di convalida basata sulla connessione (come menzionato in questa risposta/thread: https://stackoverflow.com/a/1088224/4984533) non funzionerà neanche.
su un altro thread su questo problema (a https://stackoverflow.com/a/4427081) Abate spiega che M2Crypto è incapace di fare questa convalida e dice che lui ha scritto una proroga per consentire la validazione (utilizzando il modulo m2ext
), ma sua patch non sembra mai di lavoro, ritornando sempre falso, anche se so che è valida:
from m2ext import SSL
ctx = SSL.Context()
ctx.load_verify_locations(capath='/etc/ssl/certs/') # I have run c_rehash in this directory to generate a list of cert files with signature based names
if not ctx.validate_certificate(cert): # always happens
print('Invalid certificate!')
C'è anche questa risposta su un thread simile qui https://stackoverflow.com/a/9007764/4984533 in cui John Matthews sostiene di avere una patch scritta, che lo farà, ma purtroppo il link cerotto ora è morto - e comunque c'è un commento su quel thread che afferma che la patch non ha funzionato con openssl 0.9.8e.
Tutte le risposte relative alla convalida di una catena di certificati di trust in python sembrano essere collegate alla patch morta o tornare a m2ext
.
Esiste un modo semplice e diretto per convalidare la catena di attendibilità dei certificati in Python?
Btw pyOpenSSL avvolge OpenSSL quindi non si avrebbe bisogno di usarla dalla riga di comando. Vale anche la pena leggerlo se non hai già https://www.python.org/dev/peps/pep-0476/ –
Grazie per il link Avi, non l'avevo mai visto prima. Non mi aiuta nella mia attuale situazione (sembra riguardare soprattutto i client http). Non ho problemi a usare un programma a riga di comando per effettuare la verifica se necessario, ma non se sono obbligato a scrivere il file pem su disco su ogni richiesta. Se il comando openssl verify potesse prendere una stringa raw, potrei usare quello che suppongo (anche se sembra una soluzione hacky per qualcosa che pensavo di sicuro sarebbe stato banale in Python). – speznot