Skip to content

Instantly share code, notes, and snippets.

@uilianries
Created January 4, 2018 21:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uilianries/0459f59287bd63e49b1b8ef03b30d421 to your computer and use it in GitHub Desktop.
Save uilianries/0459f59287bd63e49b1b8ef03b30d421 to your computer and use it in GitHub Desktop.
Validate x509 certificate using pyOpenSSL
import sys
import os
from OpenSSL import crypto
def verify_certificate_chain(cert_path, trusted_certs):
# Download the certificate from the url and load the certificate
cert_file = open(cert_path, 'r')
cert_data = cert_file.read()
certificate = crypto.load_certificate(crypto.FILETYPE_PEM, cert_data)
#Create a certificate store and add your trusted certs
try:
store = crypto.X509Store()
# Assuming the certificates are in PEM format in a trusted_certs list
for _cert in trusted_certs:
cert_file = open(_cert, 'r')
cert_data = cert_file.read()
client_certificate = crypto.load_certificate(crypto.FILETYPE_PEM, cert_data)
store.add_cert(client_certificate)
# Create a certificate context using the store and the downloaded certificate
store_ctx = crypto.X509StoreContext(store, certificate)
# Verify the certificate, returns None if it can validate the certificate
store_ctx.verify_certificate()
return True
except Exception as e:
print(e)
return False
if __name__ == "__main__":
certs_dir = os.path.join(os.sep, "etc", "nginx", "certs")
cert_path = os.path.join(certs_dir, "client", "client.crt")
trusted_certs = [os.path.join(certs_dir, "ca", "ca.crt")]
if not verify_certificate_chain(cert_path, trusted_certs):
print("Invalid certificate!")
sys.exit(1)
print("Valid certificate!")
sys.exit(0)
@kerk12
Copy link

kerk12 commented Mar 8, 2018

It should be noted that this cannot be used to verify "untrusted" certificates (for example an untrusted intermediate), say:
Root CA -> Rogue Issuing CA -> Fake End User Cert.

It would be awesome if pyOpenSSL provided a way to verify untrusted chains, as the openssl library does with the openssl verify command with the -untrusted parameter. :(

@misi1987107
Copy link

can you get the valid certificate chain?about the chain info.

@sepulm01
Copy link

Hi

It should be noted that this cannot be used to verify "untrusted" certificates (for example an untrusted intermediate), say:
Root CA -> Rogue Issuing CA -> Fake End User Cert.

It would be awesome if pyOpenSSL provided a way to verify untrusted chains, as the openssl library does with the openssl verify command with the -untrusted parameter. :(

Hi @kerk12, I think you are interested in this article http://www.yothenberg.com/validate-x509-certificate-in-python/
regards.

@cyberpion-yotam
Copy link

@QianYC
Copy link

QianYC commented Mar 9, 2021

so if we want to verify untrusted chain, we just loop over every certificates?

@alfonsrv
Copy link

alfonsrv commented Mar 13, 2021

Any idea on how to get the CA for a given certificate "dynamically" out of the system's certificate store? In case someone wanted to verify a certificate given a URL instead of static files.

This can load the certificate, but couldn't figure out on how to get the corresponding CA:

sock = socket()

sock.connect((hostname, port))
peername = sock.getpeername()
ctx = SSL.Context(SSL.SSLv23_METHOD) # most compatible
ctx.check_hostname = False
ctx.verify_mode = SSL.VERIFY_NONE

sock_ssl = SSL.Connection(ctx, sock)
sock_ssl.set_connect_state()
sock_ssl.set_tlsext_host_name(hostname_idna)
sock_ssl.do_handshake()
cert = sock_ssl.get_peer_certificate()
chain = sock_ssl.get_peer_cert_chain()
crypto_cert = cert.to_cryptography()
sock_ssl.close()
sock.close()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment