Abstract illustration

x5092json: A New Open-Source Certificate Parser From DomainTools

I’m happy to announce that we’ve open-sourced our SSL certificate parser! This Python package is used in our production systems to robustly parse TLS certificates that we find on the web.  It provides a command-line utility as well as an importable module that you can use in your own code.

The tool is called x5092json and is now available for installation from PyPi using pip.

$ pip3 install x5092json

You can also install the tool directly from source by cloning this repository.

Alongside a JSON query tool like jq, the x5092json tool provides a powerful way to explore the intricate details of the TLS certificates that are used to encode and certify the public keys we all use for encrypted communication on the Internet. Let me show you what I mean.

Let’s start by grabbing the certificate from domaintools.com using the OpenSSL s_client tool, which is installed by default on most Unixen (Unices?, ok *nix, I know).

$ echo | openssl s_client -connect domaintools.com -port 443
CONNECTED(00000003)
[snip]
-----BEGIN CERTIFICATE-----
MIIJLzCCCBegAwIBAgIQWiQcgf4F/r2sOFBiOS+9+DANBgkqhkiG9w0BAQsFADCB
kjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNV
BAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVy
IENBMB4XDTE4MTIwOTAwMDAwMFoXDTIwMTIzMDIzNTk1OVowggEWMRAwDgYDVQQF
Ewc0NzEwNDMyMRMwEQYLKwYBBAGCNzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQIT
CERlbGF3YXJlMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjELMAkGA1UE
BhMCVVMxDjAMBgNVBBETBTk4MTIxMQswCQYDVQQIEwJXQTEQMA4GA1UEBxMHU2Vh
dHRsZTEiMCAGA1UECRMZMjEwMSA0dGggQXZlLiwgU3VpdGUgMTE1MDEUMBIGA1UE
ChMLRG9tYWluVG9vbHMxIzAhBgNVBAsTGkNPTU9ETyBFViBNdWx0aS1Eb21haW4g
U1NMMRgwFgYDVQQDEw9kb21haW50b29scy5jb20wggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQDX6hMj5fuPDtXXssQSulAhm21xYD4fsuguzWW/naPUS7z3
o+cMz9yPgNjWf7Na1LZJQt0VIOSSZfesjrD9GVsnr9kozqtAltK+HHRoCd4uvwfi
iaHAm29x32vJ6xZZLkSKd3GwDTtOKhSXubBhPK2NVzUYcwA0K3n80jA+eQ01lfn4
y0kEhPHe0y21/ngUtp0vn3XRmYVKiqzlJVs5zLOA0H9ke7l8cJUol1tB2S9dhU9M
qG1IMGcPpaXXVorFMS5jpScpyoyH8aidT/T9Z0iHj4zJR1NMe03PKdZyG9pszE22
IENCNq4HEtMZeLNcUV9XqH4fpwOWhJFxlu1QXgUC914aaWp3uyGAfFniu6Em2ryK
UkMlz4VS9Fisma/OgI+cbXqFPtsDpLlmzkneM6+aQl6jI0UudM7gbQLMazE9heEA
GkG8rogDKpctQOnN0gDyRNrHh/0kIhA5Z3p/u3jk5B226LiNcIA7tRStDIBmLvzR
bAn2OXk52i/0IoZds4uv1m3lGmHh0R6d/UjCcqCjLuvtdM6ACVaC39uRLc++VyL0
jSv/Ig1pOhb1G/L1ozchMFWZ8aBHaycL2CqmHWB9k1FnghODEZZV9fYGe/tyFnPp
nYGNJYzTO6Je0kvV6Zd1WTDhrEqM90HD2NvNhRZV0Wy6tR0DXHP+oxCR+8s16wID
AQABo4ID+DCCA/QwHwYDVR0jBBgwFoAUOdr/yigUiqh0Ewi55A6p0vp+nWkwHQYD
VR0OBBYEFAIqpVc8eQmpea0wfQQtoalRmwJ7MA4GA1UdDwEB/wQEAwIFoDAMBgNV
HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAE
SDBGMDsGDCsGAQQBsjEBAgEFATArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3Vy
ZS5jb21vZG8uY29tL0NQUzAHBgVngQwBATBWBgNVHR8ETzBNMEugSaBHhkVodHRw
Oi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FFeHRlbmRlZFZhbGlkYXRpb25T
ZWN1cmVTZXJ2ZXJDQS5jcmwwgYcGCCsGAQUFBwEBBHsweTBRBggrBgEFBQcwAoZF
aHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRXh0ZW5kZWRWYWxpZGF0
aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5j
b21vZG9jYS5jb20wgcAGA1UdEQSBuDCBtYIPZG9tYWludG9vbHMuY29tghdhY2Nv
dW50LmRvbWFpbnRvb2xzLmNvbYIVYWRtaW4uZG9tYWludG9vbHMuY29tghRsYWJz
LmRvbWFpbnRvb2xzLmNvbYIYcmVzZWFyY2guZG9tYWludG9vbHMuY29tghZzZWN1
cmUuZG9tYWludG9vbHMuY29tghV3aG9pcy5kb21haW50b29scy5jb22CE3d3dy5k
b21haW50b29scy5jb20wggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB2AO5Lvbd1
zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABZ5UDK8UAAAQDAEcwRQIgR3iQ
43TnvH6Ey9M93NA3BMU75Q90MJheEd9LBaQTx4ICIQCfiBiQrcD6QNi/XG4DNfob
zsOLTCRRoyPp6Yp9wtwIYQB1AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgia
N9kTAAABZ5UDK8gAAAQDAEYwRAIgadv4Lpofy6Gmh089Wpmvl8Mo7iMqWE1sclXO
xkqKuiACID6LRlMzjOiA0DC6uMp6jN5Ds1XCOJIRE/Ga4jfCfnCxAHYAu9nfvB+K
cbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e0YUAAAFnlQMrxwAABAMARzBFAiASS9Wm
WsrwAFji88rGi8RKsrSKvz37u20H7/cJJXa4XAIhAKiPfF7SYD8fqxnV6Z72CWBm
w/uB3vPrVEsFzLWFBjHCMA0GCSqGSIb3DQEBCwUAA4IBAQA5my8WS4kSWozmFupJ
4pxFY4nS8kqAG/z9sqkBwbIZoNbkHaIZEVoJyVEPcnn1M+KwosWTsr7lA0v7W9PP
qRACmb8bbgytAvasB85TUJzEMJzn6vDIOjiXLePTVPuVSPG2wEAZKktZSsrcdwM8
RinUjUjX6Gb2m1xqxwSeJAEUtNqR2oGg0zdeBu+gKsEc7dwc5uk5GTvjloiRHRbK
NYIVKZCSpUMJItSwPKNxZpJe+0hTCOg7mO9XZ+WPETI8pC9j9+gcn75tUYE/emka
in211bTM/94fbdA45VX/fxLGSJYr3wRp4LG1rgmvRL4QnuFX7VkKN1/u5U0Nhc37
KDJO
-----END CERTIFICATE-----
[snip]

I redacted the output a bit, because the output of s_client is rather verbose, and not easy to parse. But as we’ll see, creating machine readable output is where x5092json shines. Moving on with the example, now that we have a certificate, we can save it in a file, say domaintools.pem and then we can use x5092json to parse it. Currently, x5092json produces packed JSON ready for insertion into your favorite JSON-aware database, so I’ll pipe the output through jq for pretty-printing (maybe we should provide an option for pretty-printing within x5092json itself. PRs accepted!).

$ x5092json --in domaintoolscom.pem | jq
{
  "version": "3",
  "serial_number": "119818020514067989046491909962261839352",
  "signature_algorithm": "sha256WithRSAEncryption",
  "issuer_str": "CN=COMODO RSA Extended Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB",
  "issuer": [
    {
      "oid": {
        "dotted_string": "2.5.4.6",
        "name": "countryName"
      },
      "value": "GB"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.8",
        "name": "stateOrProvinceName"
      },
      "value": "Greater Manchester"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.7",
        "name": "localityName"
      },
      "value": "Salford"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.10",
        "name": "organizationName"
      },
      "value": "COMODO CA Limited"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.3",
        "name": "commonName"
      },
      "value": "COMODO RSA Extended Validation Secure Server CA"
    }
  ],
  "validity": {
    "not_before": "2018-12-09T00:00:00",
    "not_after": "2020-12-30T23:59:59"
  },
  "subject_str": "CN=domaintools.com,OU=COMODO EV Multi-Domain SSL,O=DomainTools,street=2101 4th Ave.\, Suite 1150,L=Seattle,ST=WA,postalCode=98121,C=US,businessCategory=Private Organization,jurisdictionST=Delaware,jurisdictionC=US,serialNumber=4710432",
  "subject": [
    {
      "oid": {
        "dotted_string": "2.5.4.5",
        "name": "serialNumber"
      },
      "value": "4710432"
    },
    {
      "oid": {
        "dotted_string": "1.3.6.1.4.1.311.60.2.1.3",
        "name": "jurisdictionCountryName"
      },
      "value": "US"
    },
    {
      "oid": {
        "dotted_string": "1.3.6.1.4.1.311.60.2.1.2",
        "name": "jurisdictionStateOrProvinceName"
      },
      "value": "Delaware"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.15",
        "name": "businessCategory"
      },
      "value": "Private Organization"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.6",
        "name": "countryName"
      },
      "value": "US"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.17",
        "name": "postalCode"
      },
      "value": "98121"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.8",
        "name": "stateOrProvinceName"
      },
      "value": "WA"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.7",
        "name": "localityName"
      },
      "value": "Seattle"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.9",
        "name": "streetAddress"
      },
      "value": "2101 4th Ave., Suite 1150"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.10",
        "name": "organizationName"
      },
      "value": "DomainTools"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.11",
        "name": "organizationalUnitName"
      },
      "value": "COMODO EV Multi-Domain SSL"
    },
    {
      "oid": {
        "dotted_string": "2.5.4.3",
        "name": "commonName"
      },
      "value": "domaintools.com"
    }
  ],
  "subject_public_key_info": {
    "algorithm": "rsaEncryption",
    "key_size": 4096,
    "key": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1+oTI+X7jw7V17LEErpQIZttcWA+H7LoLs1lv52j1Eu896PnDM/cj4DY1n+zWtS2SULdFSDkkmX3rI6w/RlbJ6/ZKM6rQJbSvhx0aAneLr8H4omhwJtvcd9ryesWWS5EindxsA07TioUl7mwYTytjVc1GHMANCt5/NIwPnkNNZX5+MtJBITx3tMttf54FLadL5910ZmFSoqs5SVbOcyzgNB/ZHu5fHCVKJdbQdkvXYVPTKhtSDBnD6Wl11aKxTEuY6UnKcqMh/GonU/0/WdIh4+MyUdTTHtNzynWchvabMxNtiBDQjauBxLTGXizXFFfV6h+H6cDloSRcZbtUF4FAvdeGmlqd7shgHxZ4ruhJtq8ilJDJc+FUvRYrJmvzoCPnG16hT7bA6S5Zs5J3jOvmkJeoyNFLnTO4G0CzGsxPYXhABpBvK6IAyqXLUDpzdIA8kTax4f9JCIQOWd6f7t45OQdtui4jXCAO7UUrQyAZi780WwJ9jl5Odov9CKGXbOLr9Zt5Rph4dEenf1IwnKgoy7r7XTOgAlWgt/bkS3Pvlci9I0r/yINaToW9Rvy9aM3ITBVmfGgR2snC9gqph1gfZNRZ4ITgxGWVfX2Bnv7chZz6Z2BjSWM0zuiXtJL1emXdVkw4axKjPdBw9jbzYUWVdFsurUdA1xz/qMQkfvLNesCAwEAAQ=="
  },
  "extensions": [
    {
      "oid": {
        "dotted_string": "2.5.29.35",
        "name": "authorityKeyIdentifier"
      },
      "critical": false,
      "value": {
        "key_identifier": "39daffca28148aa8741308b9e40ea9d2fa7e9d69"
      }
    },
    {
      "oid": {
        "dotted_string": "2.5.29.14",
        "name": "subjectKeyIdentifier"
      },
      "critical": false,
      "value": {
        "digest": "022aa5573c7909a979ad307d042da1a9519b027b"
      }
    },
    {
      "oid": {
        "dotted_string": "2.5.29.15",
        "name": "keyUsage"
      },
      "critical": true,
      "value": {
        "digital_signature": true,
        "key_encipherment": true
      }
    },
    {
      "oid": {
        "dotted_string": "2.5.29.19",
        "name": "basicConstraints"
      },
      "critical": true,
      "value": {
        "ca": false
      }
    },
    {
      "oid": {
        "dotted_string": "2.5.29.37",
        "name": "extendedKeyUsage"
      },
      "critical": false,
      "value": [
        {
          "dotted_string": "1.3.6.1.5.5.7.3.1",
          "name": "serverAuth"
        },
        {
          "dotted_string": "1.3.6.1.5.5.7.3.2",
          "name": "clientAuth"
        }
      ]
    },
    {
      "oid": {
        "dotted_string": "2.5.29.32",
        "name": "certificatePolicies"
      },
      "critical": false,
      "value": {
        "policies": [
          {
            "policy_identifier": {
              "dotted_string": "1.3.6.1.4.1.6449.1.2.1.5.1",
              "name": "Unknown OID"
            },
            "policy_qualifiers": [
              "https://secure.comodo.com/CPS"
            ]
          },
          {
            "policy_identifier": {
              "dotted_string": "2.23.140.1.1",
              "name": "Unknown OID"
            }
          }
        ]
      }
    },
    {
      "oid": {
        "dotted_string": "2.5.29.31",
        "name": "cRLDistributionPoints"
      },
      "critical": false,
      "value": {
        "distribution_points": [
          {
            "name": [
              {
                "type": "UniformResourceIdentifier",
                "uniformresourceidentifier_value": "http://crl.comodoca.com/COMODORSAExtendedValidationSecureServerCA.crl"
              }
            ]
          }
        ]
      }
    },
    {
      "oid": {
        "dotted_string": "1.3.6.1.5.5.7.1.1",
        "name": "authorityInfoAccess"
      },
      "critical": false,
      "value": {
        "descriptions": [
          {
            "access_method": {
              "dotted_string": "1.3.6.1.5.5.7.48.2",
              "name": "caIssuers"
            },
            "access_location": {
              "type": "UniformResourceIdentifier",
              "uniformresourceidentifier_value": "http://crt.comodoca.com/COMODORSAExtendedValidationSecureServerCA.crt"
            }
          },
          {
            "access_method": {
              "dotted_string": "1.3.6.1.5.5.7.48.1",
              "name": "OCSP"
            },
            "access_location": {
              "type": "UniformResourceIdentifier",
              "uniformresourceidentifier_value": "http://ocsp.comodoca.com"
            }
          }
        ]
      }
    },
    {
      "oid": {
        "dotted_string": "2.5.29.17",
        "name": "subjectAltName"
      },
      "critical": false,
      "value": [
        {
          "type": "DNSName",
          "dnsname_value": "domaintools.com"
        },
        {
          "type": "DNSName",
          "dnsname_value": "account.domaintools.com"
        },
        {
          "type": "DNSName",
          "dnsname_value": "admin.domaintools.com"
        },
        {
          "type": "DNSName",
          "dnsname_value": "labs.domaintools.com"
        },
        {
          "type": "DNSName",
          "dnsname_value": "research.domaintools.com"
        },
        {
          "type": "DNSName",
          "dnsname_value": "secure.domaintools.com"
        },
        {
          "type": "DNSName",
          "dnsname_value": "whois.domaintools.com"
        },
        {
          "type": "DNSName",
          "dnsname_value": "www.domaintools.com"
        }
      ]
    },
    {
      "oid": {
        "dotted_string": "1.3.6.1.4.1.11129.2.4.2",
        "name": "signedCertificateTimestampList"
      },
      "critical": false,
      "value": [
        {
          "version": "Version.v1",
          "log_id": "ee4bbdb775ce60bae142691fabe19e66a30f7e5fb072d88300c47b897aa8fdcb",
          "timestamp": "2018-12-09 22:07:52.261000",
          "entry_type": "LogEntryType.PRE_CERTIFICATE"
        },
        {
          "version": "Version.v1",
          "log_id": "6f5376ac31f03119d89900a45115ff77151c11d902c10029068db2089a37d913",
          "timestamp": "2018-12-09 22:07:52.264000",
          "entry_type": "LogEntryType.PRE_CERTIFICATE"
        },
        {
          "version": "Version.v1",
          "log_id": "bbd9dfbc1f8a71b593942397aa927b473857950aab52e81a909664368e1ed185",
          "timestamp": "2018-12-09 22:07:52.263000",
          "entry_type": "LogEntryType.PRE_CERTIFICATE"
        }
      ]
    }
  ]
}

So, x5092json helps human beings extract detailed information from the compactly encoded x509 TLS certificates which are used for encryption of communication over the Internet. Once we have that information parsed and serialized as a JSON data structure, within a Python program we can use other tools to focus in on what we care about (and if you use x5092json as a python module, you can just inspect the data as you and a pyca cryptography object). For example, maybe you only care about the Issuer of the cert.

$ x5092json --in domaintoolscom.pem | jq .issuer
[
  {
    "oid": {
      "dotted_string": "2.5.4.6",
      "name": "countryName"
    },
    "value": "GB"
  },
  {
    "oid": {
      "dotted_string": "2.5.4.8",
      "name": "stateOrProvinceName"
    },
    "value": "Greater Manchester"
  },
  {
    "oid": {
      "dotted_string": "2.5.4.7",
      "name": "localityName"
    },
    "value": "Salford"
  },
  {
    "oid": {
      "dotted_string": "2.5.4.10",
      "name": "organizationName"
    },
    "value": "COMODO CA Limited"
  },
  {
    "oid": {
      "dotted_string": "2.5.4.3",
      "name": "commonName"
    },
    "value": "COMODO RSA Extended Validation Secure Server CA"
  }
]

Or maybe you want to know exactly how many extensions that certificate contains.

$ x5092json --in domaintoolscom.pem | jq '.extensions|length' 10

I hope that one example is enough to illustrate the power of this little tool. But in order to tantalize you—and encourage you to to download the tool and try it out—in the rest of this blog post I thought I’d show off a few examples of interesting certificates from our collection of over 435 Million parsed certificates. In the rest of the blog, I just present the certificates here as PEM, you have to decode them yourselves (but now you know how I recommend that you do so).


Your hostname is my hostname

View Certificate

This particular certificate uses backticks in the subject common name: `hostname`. Was this supposed to do shell command evaluation on the machine that created the cert? Or was it supposed to do command evaluation upon validation on the machine that processes this cert? Or is it just that ` is the new ” and I’m not keeping up with the times?


Russell’s Paradox, in the form of a Certificate Authority

View Certificate

This certificate has a zero-length Subject and a zero-length Issuer. It also has a Basic Constraint of CA:TRUE in the extensions section. So here we find ∅ self-signs for ∅ and is willing to sign for others. And if someone is going to be the CA responsible for the empty set, is that entity also the empty set?


Rolling-yer-own ASN1, for fun and profit

View Certificate

Well this one doesn’t parse on a modern OpenSSL backend. I get this message:

unable to load certificate 
140193791300864:error:0D07808C:asn1 encoding routines:asn1_item_embed_d2i:mstring wrong tag:../crypto/asn1/tasn_dec.c:191:Type=ASN1_PRINTABLE 140193791300864:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:609:Field=value, Type=X509_NAME_ENTRY 140193791300864:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:578: 140193791300864:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:578: 140193791300864:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:609:Field=subject, Type=X509_CINF 140193791300864:error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:609:Field=cert_info, Type=X509

I included it here because after I looked closely at it, I realized that this certificate shows how seemingly tedious matters can make a certificate invalid. Here is the binary analysis, walking through the ASN.1 structures.

The issuer is:

b'1x0b0tx06x03Ux04x06x13x02RU1x140x12x06x03Ux04x08x13x0bPerm region1r0x0bx06x03Ux04x07x13x04Perm1x0c0nx06x03Ux04nx13x03TTV1x170x15x06x03Ux04x0bx13x0e IT Department1x180x16x06x03Ux04x03x13x0fdigipayments.ru1&0$x06t*[email protected]'

And the subject is:

b'1x0b0tx06x03Ux04x06x04x02RU1x140x12x06x03Ux04x08x04x0bPerm region1r0x0bx06x03Ux04x07x04x04Perm1x0c0nx06x03Ux04nx04x03TTV1x160x14x06x03Ux04x0bx04rIT Department1x180x16x06x03Ux04x03x04x0fdigipayments.ru1&0$x06t*[email protected]'

The first error that I can find is that both these structures are tagged as ASN1 Set types, when, according to RFC 5280, both Subject and Issuer are supposed to be RDNSequence objects. RDNSequence objects are supposed to be ASN1 Sequences, not Sets.

The other quirky stuff that I find here is that the values of the strings here are OctetStrings instead of PrintableStrings. If you’re willing to forgive those things, you’ll find this subject has very run-of-the mill looking information:

Country (2.5.4.6) = RU

stateOrProvinceName (2.5.4.8): Perm Region

localityName (2.5.4.7): Perm

organizationName (2.5.4.10): TTV

organizationalUnitName (2.5.4.11): IT Department

commonName (2.5.4.3): digipayments.ru

emailAddress (1.2.840.113549.1.9.1): [email protected]

Is this what happens when you try to make an certificate in a hex editor?


Don’t judge a string found on the basic multilingual plane by its encoding

View Certificate

This cert shows that you can’t take everything marked as UTF-8 on face value. High-bit set on that 0xc3, that’s not going to work.

Subject: C = ES, O = Ajuntament de Sant Quirze del VallC3A8s, jurisdictionL = Sant Quirze del VallC3A8s, jurisdictionST = Barcelona, jurisdictionC = Espanya, OU = Informatica, OU = Serveis PC3BAblics de CertificaciC3B3 CDS-1, OU = Vegeu https://www.catcert.cat/verCDSEV-1 (c)03, street = "Pl. Vila, 1", L = Sant Quirze del VallC3A8s, ST = Barcelona, postalCode = 08192, businessCategory = "V1.0, Clause 5.(c)", serialNumber = P0823800H, CN = seu.santquirzevalles.cat

A Demonstration of the Gas Laws of TLS Certificates

View Certificate

Here we see that data is like gas in a vacuum, expanding to fill the available space. Or, in this case, expanding to fill the certificate with spaces. Yes, if you take a look at the structure here, the subject contains OID 2.5.4.6, which has the following four byte value:

0x1382 0x05d8

Expanding this to binary so that we can see the structure:

0b00010011 0b10000010 0b00000101 0b11011000

Within the first octet, the first two bits tell us the class (00 for universal), the next bit being 0 means the encoding is ‘primitive’, and the last 5 bits give us the tag number: 10011 or ’19’, which is PrintableString. The next octets gives us the length. The high bit being 1 means this is a long-form length encoding and, the last 7 tell us the next 2 octets encode the length in base 256. So, 5*256^1 + 216*256^0 = 1496 bytes.

And as you see, that is 1496 bytes of spaces.


Zero-based indexing

View Certificate

This idiosyncratic certificate is the only version 4 cert that we have. I would chalk up the funny version number on this this self-signed cert for someone’s router to simply forgetting that real nerds start counting from zero, but there’s that serial number, eh? ¯_(ツ)_/¯


Carriage Return, or, the digital white-out for Email Addresses

View Certificate

What happens when you have a carriage return in the middle of an email address? Well, it makes for awkward printing, to say the least. I don’t if the kind folks of SomeOrganization in SomeCity, SomeState, countryName have received much mail at [email protected], but if I knew how to send a mail to that kind of hostname, I would love to check in.


The Heavyweight

View Certificate

Weighing in at 81,795 bytes, this certificate contains 3705 entries in its SubjectAltNames extension, and is one of the longest certificates we’ve found in the wild. Among the covered names: IP:127.0.0.1, DNSName: localhost. Seems like everything in the zone may have been included here. In these days of MB sized javascript assets and images, I suppose these 81K bytes don’t add up to a lot.


Conclusion

I hope you’ve enjoyed this introduction to the most recent open-source tool release from DomainTools as well as the brief tour of some of my favorite examples from our collection of hundreds of millions of certificates. I also hope that you’ll download x5092json and find it useful. If you have ideas for improving it, please mention them on the issues page and, if you have the ability, send a Pull Request which implements them.

Happy Hacking!