Fun with Python’s ssl and M2Crypto modules
I had to implement a couple of things related to the validation of client SSL/TLS certificates – as returned by the ssl.SSLSocket.getpeercert(True) method – and I thought I’d share the code with others, I guess there’s never too much of sample code in that area. Turned out that everything went smoothly with ssl and M2Crypto and it’s all below. Note that the code downloads the certificate off the Internet but it will work properly with a client certificate as well – well, maybe except for the fact that getpeercert(True) returns a DER while get_server_certificate gives you a PEM – but otherwise it will work just fine. Cheers!
# -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function, unicode_literals # stdlib import ssl # M2Crypto from M2Crypto import X509 # Grab a certificate from the nearest server .. cert_pem = ssl.get_server_certificate(('duckduckgo.com', 443)) # .. let's start with converting PEM to DER .. cert_der = ssl.PEM_cert_to_DER_cert(cert_pem) # .. how does the DER look like (not too pretty).. print('\nDER:') print(cert_der) # .. M2Crypto has a bunch of useful functions .. x509 = X509.load_cert_string(cert_pem, X509.FORMAT_PEM) # .. does the certificate belong to a CA .. print('\nIs it a CA:') print(x509.check_ca()) # .. the fingerprint .. fp = x509.get_fingerprint('sha1') fp = ':'.join(fp[pos:pos+2] for pos in xrange(0, len(fp), 2)) print('\nSHA1 fingerprint:') print(fp) # .. serial number .. print('\nSerial number:') print(x509.get_serial_number()) # .. who has it been issued by .. print('\nIssuer:') print(x509.get_issuer()) # .. how about the subject's commonName and organization only .. subject = x509.get_subject() print('\nSubject\'s commonName and organization:') print(subject.CN) print(subject.O) # .. public key's exponent .. # inspired by http://mail.python.org/pipermail/python-crypto/2004-August/000683.html e_data = x509.get_pubkey().get_rsa().e # First 4 bytes are the length of what then follows length, e_raw = e_data[:4], e_data[4:] e = 0 for c in e_raw: e = (e*256) + ord(c) print('\nPublic key\'s exponent:') print(e)
