How can I decode a SSL certificate using python? How can I decode a SSL certificate using python? python python

How can I decode a SSL certificate using python?


Python's standard library, even in the latest version, does not include anything that can decode X.509 certificates. However, the add-on cryptography package does support this. Quoting an example from the documentation:

>>> from cryptography import x509>>> from cryptography.hazmat.backends import default_backend>>> cert = x509.load_pem_x509_certificate(pem_data, default_backend())>>> cert.serial_number2

Another add-on package that might be an option is pyopenssl. This is a thin wrapper around the OpenSSL C API, which means it will be possible to do what you want, but expect to spend a couple days tearing your hair out at the documentation.

If you can't install Python add-on packages, but you do have the openssl command-line utility,

import subprocesscert_txt = subprocess.check_output(["openssl", "x509", "-text", "-noout",                                     "-in", certificate])

should produce roughly the same stuff you got from your web utility in cert_txt.

Incidentally, the reason doing a straight-up base64 decode gives you binary gobbledygook is that there are two layers of encoding here. X.509 certificates are ASN.1 data structures, serialized to X.690 DER format and then, since DER is a binary format, base64-armored for ease of file transfer. (A lot of the standards in this area were written way back in the nineties when you couldn’t reliably ship anything but seven-bit ASCII around.)


You can use pyasn1 and pyasn1-modules packages to parse this kind of data. For instance:

from pyasn1_modules import pem, rfc2459from pyasn1.codec.der import decodersubstrate = pem.readPemFromFile(open('cert.pem'))cert = decoder.decode(substrate, asn1Spec=rfc2459.Certificate())[0]print(cert.prettyPrint())

Read the docs for pyasn1 for the rest.


Notes:

Regarding the certificate (PEM) from the question:

  • Saved it in a file called q016899247.crt (in the script (code00.py) dir)
  • The end tag: ("-----END CERTIFICATE----") was missing a hyphen (-) at the end; corrected in Question @VERSION #4.)

code00.py:

#!/usr/bin/env python3import sysimport osimport sslimport pprintdef main(*argv):    cert_file_base_name = "q016899247.crt"    cert_file_name = os.path.join(os.path.dirname(__file__), cert_file_base_name)    try:        cert_dict = ssl._ssl._test_decode_cert(cert_file_name)    except Exception as e:        print("Error decoding certificate: {0:}".format(e))    else:        print("Certificate ({0:s}) data:\n".format(cert_file_base_name))        pprint.pprint(cert_dict)if __name__ == "__main__":    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))    rc = main(sys.argv[1:])    print("\nDone.")    sys.exit(rc)

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q016899247]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.pyPython 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32Certificate (q016899247.crt) data:{'OCSP': ('http://ocsp.digicert.com',), 'caIssuers': ('http://www.digicert.com/CACerts/DigiCertHighAssuranceEVCA-1.crt',), 'crlDistributionPoints': ('http://crl3.digicert.com/ev2009a.crl',                           'http://crl4.digicert.com/ev2009a.crl'), 'issuer': ((('countryName', 'US'),),            (('organizationName', 'DigiCert Inc'),),            (('organizationalUnitName', 'www.digicert.com'),),            (('commonName', 'DigiCert High Assurance EV CA-1'),)), 'notAfter': 'Jul 29 12:00:00 2013 GMT', 'notBefore': 'May 27 00:00:00 2011 GMT', 'serialNumber': '0E77768A5D07F0E57959CA2A9D5082B5', 'subject': ((('businessCategory', 'Private Organization'),),             (('jurisdictionCountryName', 'US'),),             (('jurisdictionStateOrProvinceName', 'California'),),             (('serialNumber', 'C3268102'),),             (('countryName', 'US'),),             (('stateOrProvinceName', 'California'),),             (('localityName', 'San Francisco'),),             (('organizationName', 'GitHub, Inc.'),),             (('commonName', 'github.com'),)), 'subjectAltName': (('DNS', 'github.com'), ('DNS', 'www.github.com')), 'version': 3}Done.