4

I have a DB with certs from CTL. (using 'certstream' utility).

Here's an example of one set of certificate data:

{
"all_domains" : [ 
    "benesseresalus.com", 
    "benesseresalus.it", 
    "dimagriresalus.com", 
    "dimagriresalus.it"
],
"as_der" : "MIIFtzCCBJ+gAwIBAgISA4HNUHaLqcuseznIF3iOrjPzMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODA4MjQwNzIyMTlaFw0xODExMjIwNzIyMTlaMB0xGzAZBgNVBAMTEmJlbmVzc2VyZXNhbHVzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANmPDiKIdOGpRQDzHiQZPVHBFVYHn+E0vv2BOC5Cp+GmuuPC+nxyRn0Mn7d7FL10xZQIjbjmY49iAfnpOQcyE/qgaZeJ80hI4ueoJD0tN1XPXIPIIJApin2i5HgB2s3UL+AEmCMCy81OmKzStC7+tVx2cugyUkBDuABz1ty6HPz9igshJJ2MhCX87Pc4lkLmX9phMAu9E1wpbT+XFdZsnqUp1fUixiHWGq8oVSL+CC4fz51WmzyDvTMV/FEreUBecjErXJ7uldlpNfv/tcPwUhEkGfTfRn8lHg9U1mhqmws8+qxdjR6bgpKjwnW2GkhMqvj9gkoT8mGtei6DyCbi17UCAwEAAaOCAsIwggK+MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUoYmVOj6I7epePo5xj33E1LBi94owHwYDVR0jBBgwFoAUqEpqYwR93brm0Tm3pkVl7/Oo7KEwbwYIKwYBBQUHAQEEYzBhMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcC5pbnQteDMubGV0c2VuY3J5cHQub3JnMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0c2VuY3J5cHQub3JnLzCBtwYDVR0RBIGvMIGsghJiZW5lc3NlcmVzYWx1cy5jb22CEWJlbmVzc2VyZXNhbHVzLml0ghJkaW1hZ3JpcmVzYWx1cy5jb22CEWRpbWFncmlyZXNhbHVzLml0ghZ3d3cuYmVuZXNzZXJlc2FsdXMuY29tghV3d3cuYmVuZXNzZXJlc2FsdXMuaXSCFnd3dy5kaW1hZ3JpcmVzYWx1cy5jb22CFXd3dy5kaW1hZ3JpcmVzYWx1cy5pdDCB/gYDVR0gBIH2MIHzMAgGBmeBDAECATCB5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5kIGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkvMBMGCisGAQQB1nkCBAMBAf8EAgUAMA0GCSqGSIb3DQEBCwUAA4IBAQCY8fgDv16BEr2jGHrC/zy21Mq5BN6PGHpCL3Vi99wxWK06NjapOjPkLLpPfrJqfL98ZNyavQLueAbYqJSb9gvQwK+CktB/ZGyyUpTgfwv9+yRXURpGNt0Vx8LZdVMtDfJIIs0JiQQ0kM0P1qpuifHiWu0z+HNkptnYMuJWFNWwqDJydh8N5scQQyh98Y9eSAnFW8647Z57zNdOPzQN94dLGVY7lzDZKbPQ2//g+F8ssh04k5tBU4RM2ZRFin6/AwY3z98L1Avaed7hPhDHbgJhkcVQF5jAV0uowD2GGDrf5fuQx71hPIDBy+LOzRcKSy2ALh8ALVijumhqdZBMFEl5",
"extensions" : {
    "authorityInfoAccess" : "CA Issuers - URI:http://cert.int-x3.letsencrypt.org/\nOCSP - URI:http://ocsp.int-x3.letsencrypt.org\n",
    "authorityKeyIdentifier" : "keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1\n",
    "basicConstraints" : "CA:FALSE",
    "certificatePolicies" : "Policy: 1.3.6.1.4.1.44947.1.1.1\n  CPS: http://cps.letsencrypt.org\n  User Notice: is Certificate may only be relied upon by Relying Parties and only in accordance with the Certificate Policy found at https://letsencrypt.org/repository/",
    "ctlPoisonByte" : true,
    "extendedKeyUsage" : "TLS Web server authentication, TLS Web client authentication",
    "keyUsage" : "Digital Signature, Key Encipherment",
    "subjectAltName" : "DNS:www.dimagriresalus.it, DNS:www.dimagriresalus.com, DNS:www.benesseresalus.it, DNS:www.benesseresalus.com, DNS:dimagriresalus.it, DNS:dimagriresalus.com, DNS:benesseresalus.it, DNS:benesseresalus.com",
    "subjectKeyIdentifier" : "A1:89:95:3A:3E:88:ED:EA:5E:3E:8E:71:8F:7D:C4:D4:B0:62:F7:8A"
},
"fingerprint" : "FC:A6:A6:3A:CB:C7:8C:6F:16:84:D3:92:0E:C6:A3:25:D5:91:72:9D",
"not_after" : 1542871339,
"not_before" : 1535095339,
"serial_number" : "381CD50768BA9CBAC7B39C817788EAE33F3",
"subject" : {
    "C" : null,
    "CN" : "benesseresalus.com",
    "L" : null,
    "O" : null,
    "OU" : null,
    "ST" : null,
    "aggregated" : "/CN=benesseresalus.com"
}
}

I want to check the validity of this certificate using code.

I've searched and seen many usages of pyopenssl, but all of these requeire me to have the .pem file. I think I can create the .cert file by opening a new file like this:

 ----BEGIN CERTIFICATE----   
MIIFtzCCBJ+gAwIBAgISA4HNUHaLqcuseznIF3iOrjPzMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODA4MjQwNzIyMTlaFw0xODExMjIwNzIyMTlaMB0xGzAZBgNVBAMTEmJlbmVzc2VyZXNhbHVzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANmPDiKIdOGpRQDzHiQZPVHBFVYHn+E0vv2BOC5Cp+GmuuPC+nxyRn0Mn7d7FL10xZQIjbjmY49iAfnpOQcyE/qgaZeJ80hI4ueoJD0tN1XPXIPIIJApin2i5HgB2s3UL+AEmCMCy81OmKzStC7+tVx2cugyUkBDuABz1ty6HPz9igshJJ2MhCX87Pc4lkLmX9phMAu9E1wpbT+XFdZsnqUp1fUixiHWGq8oVSL+CC4fz51WmzyDvTMV/FEreUBecjErXJ7uldlpNfv/tcPwUhEkGfTfRn8lHg9U1mhqmws8+qxdjR6bgpKjwnW2GkhMqvj9gkoT8mGtei6DyCbi17UCAwEAAaOCAsIwggK+MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUoYmVOj6I7epePo5xj33E1LBi94owHwYDVR0jBBgwFoAUqEpqYwR93brm0Tm3pkVl7/Oo7KEwbwYIKwYBBQUHAQEEYzBhMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcC5pbnQteDMubGV0c2VuY3J5cHQub3JnMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQteDMubGV0c2VuY3J5cHQub3JnLzCBtwYDVR0RBIGvMIGsghJiZW5lc3NlcmVzYWx1cy5jb22CEWJlbmVzc2VyZXNhbHVzLml0ghJkaW1hZ3JpcmVzYWx1cy5jb22CEWRpbWFncmlyZXNhbHVzLml0ghZ3d3cuYmVuZXNzZXJlc2FsdXMuY29tghV3d3cuYmVuZXNzZXJlc2FsdXMuaXSCFnd3dy5kaW1hZ3JpcmVzYWx1cy5jb22CFXd3dy5kaW1hZ3JpcmVzYWx1cy5pdDCB/gYDVR0gBIH2MIHzMAgGBmeBDAECATCB5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5kIGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkvMBMGCisGAQQB1nkCBAMBAf8EAgUAMA0GCSqGSIb3DQEBCwUAA4IBAQCY8fgDv16BEr2jGHrC/zy21Mq5BN6PGHpCL3Vi99wxWK06NjapOjPkLLpPfrJqfL98ZNyavQLueAbYqJSb9gvQwK+CktB/ZGyyUpTgfwv9+yRXURpGNt0Vx8LZdVMtDfJIIs0JiQQ0kM0P1qpuifHiWu0z+HNkptnYMuJWFNWwqDJydh8N5scQQyh98Y9eSAnFW8647Z57zNdOPzQN94dLGVY7lzDZKbPQ2//g+F8ssh04k5tBU4RM2ZRFin6/AwY3z98L1Avaed7hPhDHbgJhkcVQF5jAV0uowD2GGDrf5fuQx71hPIDBy+LOzRcKSy2ALh8ALVijumhqdZBMFEl5
-----END CERTIFICATE-----

..but I will still be missing the .pem file.

Bottom line: I want to use the json data provided to find out whether or not this certificate has been revoked. Please tell me what i'm missing. Thanks.

Edit:

How about this:

certutil -f –urlfetch -verify [FilenameOfCertificate]

Source: https://www.namecheap.com/support/knowledgebase/article.aspx/9968/38/how-to-check-the-certificate-revocation-status

After that, I can parse the response and see if there is a revoked status... But if I try to sign a revoked cert, will it warn me about that ?

EDIT final: Thanks to @Steffen Ullrich, the working python code:

import os
import subprocess
openssl_location = "\"C:\\Program Files\\OpenSSL-Win64\\bin\\openssl.exe\""`
for element in cursor:
        authorityInfoAccess = element['data']['leaf_cert']['extensions']['authorityInfoAccess']
        ocsp_url, crt_url = [x.strip(" ").lstrip("URI:").rstrip("\n").rstrip("\nCA Issuers") for x in authorityInfoAccess.split("-") if 'URI' in x]

        if 'ocsp' in crt_url:
            ocsp_url, crt_url = crt_url, ocsp_url

        serial_number = authorityInfoAccess = element['data']['leaf_cert']['serial_number']

        shell_convert_cmd = 'curl ' + crt_url + " > issuer.crt"
        os.system(shell_convert_cmd)

        to_pem_cmd = openssl_location + ' x509 -in issuer.crt -inform der -out issuer.pem'
        os.system(to_pem_cmd)

        request_cmd = 'ocsp -issuer issuer.pem -serial 0x' + serial_number + ' -url ' + ocsp_url
        full_cmd = openssl_location + " " + request_cmd
        out = subprocess.check_output(full_cmd, shell=True)
        print (f"program output: {str(out)}")
  • The .cert file looks like it is already in PEM format. The extension is arbitrary. – Ahmad Oct 12 '18 at 11:19
  • This looks like a programming question and not a security question. If you are looking for Python code to accomplish your task, you have asked the wrong site. – schroeder Oct 12 '18 at 11:24
  • Python is not mandatory This command allows can tell me if the cert is revoked or not? certutil -f –urlfetch -verify [FilenameOfCertificate] Source: namecheap.com/support/knowledgebase/article.aspx/9968/38/… Thanks – JohnSnowTheDeveloper Oct 12 '18 at 12:49
2

To do an OCSP check to find out if a certificate is revoked, you need to send an OCSP request to the OCSP responder responsible for the certificate and then look at the returned OCSP result. To create a OCSP request you need the issuers certificate (actually DN and public key from it would be sufficient) and the serial number of the certificate you want to check. This is because CertID as the central part of the OCSP request is defined like this:

CertID          ::=     SEQUENCE {
   hashAlgorithm       AlgorithmIdentifier,
   issuerNameHash      OCTET STRING, -- Hash of issuer's DN
   issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
   serialNumber        CertificateSerialNumber } 

The issuers certificate can in this case be retrieved by looking at the CA Issuers in the authorityInfoAccess information of the certificate, i.e. URI:http://cert.int-x3.letsencrypt.org/ in this case. To retrieve this issuer certificate you can thus do:

 $ curl http://cert.int-x3.letsencrypt.org/ > issuer.crt

The serial number is also in the JSON:

"serial_number" : "381CD50768BA9CBAC7B39C817788EAE33F3",

Then one needs the URL of the OCSP resolver. This is also part of the authorityInfoAccess extension and the OCSP setting has a value of URI:http://ocsp.int-x3.letsencrypt.org.

From this the OCSP request can be created and sent to the OCSP resolver, for example using openssl:

# convert issuer certificate from DER to PEM format, as needed by openssl ocsp
$ openssl x509 -in issuer.crt -inform der -out issuer.pem

# build the OCSP request and query the OCSP resolver
$ openssl ocsp \
  -issuer issuer.pem \
  -serial 0x381CD50768BA9CBAC7B39C817788EAE33F3 \
  -url http://ocsp.int-x3.letsencrypt.org/

Properly used (please note the 0x to specify that the serial number is hexadecimal) this results in:

WARNING: no nonce in response
Response verify OK
0x381CD50768BA9CBAC7B39C817788EAE33F3: good
        This Update: Oct 11 08:00:00 2018 GMT
        Next Update: Oct 18 08:00:00 2018 GMT

good means that the certificate is not revoked.

Note that you need at least OpenSSL 1.1.0 to follow the instructions. With OpenSSL 1.0.2 you get instead

Error querying OCSP responder
... OCSP routines:PARSE_HTTP_LINE1:server response error:ocsp_ht.c:314:Code=400,Reason=Bad Request

This is because OpenSSL 1.0.2 (and likely older) sends a HTTP/1.0 request without a HTTP Host header. While in theory fine with HTTP/1.0 the Host header is needed here since the OCSP resolver is behind the CDN Akamai where like with practically all CDN (any many hosters) multiple hostnames share the same IP address.

As to how to do this with Python: I don't see any support for OCSP at all in pyopenssl. And while there is some support for OCSP in cryptography it seems to require that you have the original certificate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.