Verifying an SSL certificate with python

This one took me a considerable amount of time and had to figure some parts from scratch.

Unfortunately there doesn’t seem to exist an easy (out-of-the-box) way for checking whether a certificate is signed by another certificate in python.

After days of searching and despair, here is a solution without using M2Crypto:

import OpenSSL
from Crypto.Util import asn1

c=OpenSSL.crypto

# This is the certificate to validate
# an OpenSSL.crypto.X509 object
cert=...

# This is the CA certificate to use for validation
# again an OpenSSL.crypto.X509 object
cacert=...

# Get the signing algorithm
algo=cert.get_signature_algorithm()

# Get the ASN1 format of the certificate
cert_asn1=c.dump_certificate(c.FILETYPE_ASN1, cert)

# Decode the certificate
der=asn1.DerSequence()
der.decode(cert_asn1)

# The certificate has three parts:
# - certificate
# - signature algorithm
# - signature
# http://usefulfor.com/nothing/2009/06/10/x509-certificate-basics/
der_cert=der[0]
der_algo=der[1]
der_sig=der[2]

# The signature is a BIT STRING (Type 3)
# Decode that as well
der_sig_in=asn1.DerObject()
der_sig_in.decode(der_sig)

# Get the payload
sig0=der_sig_in.payload

# Do the following to see a validation error for tests
# der_cert=der_cert[:20]+'1'+der_cert[21:]

# First byte is the number of unused bits. This should be 0
# http://msdn.microsoft.com/en-us/library/windows/desktop/bb540792(v=vs.85).aspx
if sig0[0]!='\x00':
    raise Exception('Number of unused bits is strange')

# Now get the signature itself
sig=sig0[1:]

# And verify the certificate
try:
    c.verify(cacert, sig, der_cert, algo)
    print "Certificate looks good"
except OpenSSL.crypto.Error, e:
    print "Sorry. Nope."

Note: You can use the above under the MIT license. If it doesn’t fit your needs let me know. My intention is to make this usable by anyone for any kind of use with no obligation.

5 Comments

  1. Hi! I’ve been searching for sth like this for a long time. I tried to run your code using cert from “google.com” and loaded CA-certs from /etc/ssl/certs/ca-certificates.crt. Using your code I get following error:

    Error: [(‘rsa routines’, ‘RSA_padding_check_PKCS1_type_1?, ‘block type is not 01?), (‘rsa routines’, ‘RSA_EAY_PUBLIC_DECRYPT’, ‘padding check failed’)]

    Are you somehow familiar with this type of error code? Thanks in advance.

    Cheers,
    Victor

  2. Hi
    I’m Trying to use your cerificate validation in an MSc project. What format for the certificates does you routine expect to use? I get a failure at this part
    # Get the signing algorithm
    algo=cert.get_signature_algorithm()

    algo=cert.get_signature_algorithm(0)
    AttributeError: ‘str’ object has no attribute ‘get_signature_algorithm’
    I think it’s because the cert and cacert are in the wrong format

    Thanks
    Bill Laing

      • OK I got it working. I had to “load” my certificates into cert and cacert.

        Now I can retrieve a certificate (cert) from my web server and validate it with a self-signed certificate (cacert) from another source (a blockchain simulation.)
        The project is about alternaive methods of certificate validataion.

        You script is exactly what I needed so I thank you for taking the time to develop it.

  3. Hello again

    I’m presenting my certificates in pem format like this
    —–BEGIN CERTIFICATE—–MIIDqDCCApACCQCU071Gj4NFbjANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMCVUsxFjAUBgNVBAgMD …..

    I’m now thinking it’s a problem with the OpenSSL crypto module.

    algo=cert.get_signature_algorithm()
    AttributeError: ‘str’ object has no attribute ‘get_signature_algorithm’

    If I comment out algo=cert.get_signature_algorithm() the next error is similar

    cert_asn1=c.dump_certificate(c.FILETYPE_ASN1, cert)
    File “/usr/local/lib/python2.7/dist-packages/OpenSSL/crypto.py”, line 1711, in dump_certificate
    result_code = _lib.i2d_X509_bio(bio, cert._x509)
    AttributeError: ‘unicode’ object has no attribute ‘_x509’

    I’m using
    Name: pyOpenSSL
    Version: 17.0.0

    Name: cryptography
    Version: 1.8.1

    Any ideas?

    Thanks
    Bill

Leave a Reply

Your email address will not be published. Required fields are marked *