2017-10-03 6 views
6

J'ai deux certificats, un root.crt et un client.crt qui a été signé par root.key.
Je veux vérifier que le client.crt a en effet été signé par root.key, de le faire, en utilisant OpenSSL sur la borne, je fais comme ceci:pyOpenSSL "openssl vérifier -CAfile root.crt client.crt" équivalent

$ openssl verify -CAfile root.crt client.crt 
> client.crt: OK 

Mais lorsque vous utilisez pyOpenSSL, après la documentation et this blog post, j'ai essayé quelque chose comme ceci:

client_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, file('client.crt').read()) 

root_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, file('root.crt').read()) 

store = OpenSSL.crypto.X509Store() 
store.add_cert(root_cert) 

ctx = OpenSSL.crypto.X509StoreContext(store, client_cert) 
ctx.verify_certificate() 

Mais je reçois cette erreur:

X509StoreContextError: [2, 1, 'unable to get issuer certificate']

Alors qu'est-ce qui me manque?

Répondre

2

Le problème est que mon root.crt est pas vraiment racine, mais une chaîne de certificats:

-----BEGIN CERTIFICATE----- 
... 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
... 
-----END CERTIFICATE----- 

Et OpenSSL.crypto.load_certificate charges juste le premier.

La solution est d'extraire tous les certificats dans le fichier de la chaîne et les ajouter à la X509Store.

Donc, la solution de code ressemble à ceci:

_PEM_RE = re.compile(b'-----BEGIN CERTIFICATE-----\r?.+?\r?-----END CERTIFICATE-----\r?\n?', re.DOTALL) 


def parse_chain(chain): 
    return [c.group() for c in _PEM_RE.finditer(chain)] 


client_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, file('server.crt').read()) 

store = OpenSSL.crypto.X509Store() 
for rc in parse_chain(file('root.crt').read()): 
    store.add_cert(OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cr)) 

ctx = OpenSSL.crypto.X509StoreContext(store, client_cert) 
ctx.verify_certificate() 

Adapté de https://github.com/hynek/pem/blob/master/src/pem/_core.py#L115