I’ve recently been given a task to determine the set of browsers and operating systems that a particular commonly trusted root certificate is embedded into. The methods to find this set vary depending on the browser vendor; I’ve found myself downloading various browsers to inspect their trust stores, digging into OS keystores, and when I’m lucky parsing a list that is publicly available. With Opera, I was happy to see that they publish their root certificate lists. Unfortunately, the format of the online repository leaves a little to be desired. The certificates are stored as a set of XML files that are named using a scheme which is most likely a hash or fingerprint of the certificate record (I’ve confirmed they are not named with the actual certificate thumbprint or serial number, even though that would seem to be a logical choice for the naming convention).
The schema of the XML files is simple enough; each file contains 3 fields of note: an issuer field a shortname field, and a certificate-data field. For my purposes, the field that I needed to analyze was the ‘Issuer’ field. Since there are 255 certificates listed in the latest directory with the Opera site, I decided to automate my search using a combination of python, wget, and openssl commands. As this is my first foray into python, I ran into a few speedbumps along the way (especially since my previous scripting language of choice was Perl). In the end, I used the following script to automate my search. Hopefully this will save someone else time in the future.
#!/usr/bin/python import os import sys import subprocess import re url = sys.argv[1] cmd = 'wget --quiet -O - %s' % (url) print "Fetching the list of certs from ", url # get the list of filenames page = subprocess.Popen(cmd,shell=True, \ stdout=subprocess.PIPE).communicate()[0] p = re.compile(r".*\"\>(.*xml)<") matches = p.findall(page) for m in matches: certsrc = url + '/' + m cmd = 'wget --quiet -O - %s' % (certsrc) cert = subprocess.Popen(cmd,shell=True,\ stdout = subprocess.PIPE).communicate()[0] p = re.compile(r"<issuer>\n(.*)\n</issuer>",re.MULTILINE) issuer = p.search(cert) print "%s issuer: %s" % (m,issuer.group(1))