2017-10-03 15 views
6

Mam dwa certyfikaty, root.crt i client.crt, który został podpisany przez root.key.
Chcę sprawdzić, czy client.crt rzeczywiście podpisane przez root.key, aby to zrobić, używając OpenSSL na terminalu, robię tak:pyOpenSSL "openssl weryfikuj -CAfile root.crt client.crt" odpowiednik

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

Ale podczas korzystania pyOpenSSL, po documentation i this blog post, próbowałem coś tak:

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() 

Ale wtedy ten błąd:

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

Więc czego mi brakuje?

Odpowiedz

2

Problem jest, że mój root.crt naprawdę nie jest korzeniem, ale łańcuch certyfikatów:

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

I OpenSSL.crypto.load_certificate prostu ładuje się pierwszy.

Rozwiązaniem jest wyodrębnienie wszystkich certyfikatów z pliku łańcucha i dodanie ich do X509Store.

więc rozwiązanie kod wygląda następująco:

_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() 

Adaptacja https://github.com/hynek/pem/blob/master/src/pem/_core.py#L115