Come verificare se il certificato dal registro dei certificati è stato revocato?

4

Ho un DB con certs da CTL. (usando l'utility 'certstream').

Ecco un esempio di un set di dati del certificato:

{
"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"
}
}

Voglio verificare la validità di questo certificato utilizzando il codice.

Ho cercato e ho visto molti usi di pyopenssl , ma tutti questi Ricalcimi per avere il file .pem . Penso di poter creare il file .cert aprendo un nuovo file come questo:

 ----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-----

.. ma mancherò comunque il file .pem .

In conclusione: Voglio usare i dati JSON forniti per scoprire se questo certificato è stato revocato o meno. Per favore dimmi cosa mi manca. Grazie.

Modifica:

Che ne dici di questo:

certutil -f –urlfetch -verify [FilenameOfCertificate]

Fonte: link

Dopo, posso analizzare la risposta e vedere se c'è uno stato revocato ... Ma se provo a firmare un certificato revocato, mi avviserà di questo?

EDIT final: Grazie a @Steffen Ullrich, il codice Python funzionante:

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)}")
    
posta JohnSnowTheDeveloper 12.10.2018 - 11:21
fonte

1 risposta

2

Per eseguire un controllo OCSP per scoprire se un certificato è stato revocato, è necessario inviare una richiesta OCSP al risponditore OCSP responsabile del certificato e quindi esaminare il risultato OCSP restituito. Per creare una richiesta OCSP è necessario il certificato dell'emittente (in realtà il DN e la chiave pubblica da esso sarebbero sufficienti) e il numero di serie del certificato che si desidera controllare. Questo perché CertID come la parte centrale della richiesta OCSP è definito in questo modo :

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

Il certificato emittenti può in questo caso essere recuperato osservando il CA Issuers nelle informazioni authorityInfoAccess del certificato, vale a dire URI:http://cert.int-x3.letsencrypt.org/ in questo caso. Per recuperare questo certificato emittente, puoi fare così:

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

Il numero di serie è anche nel JSON:

"serial_number" : "381CD50768BA9CBAC7B39C817788EAE33F3",

Quindi è necessario l'URL del resolver OCSP. Anche questo fa parte dell'estensione authorityInfoAccess e l'impostazione OCSP ha un valore di URI:http://ocsp.int-x3.letsencrypt.org .

Da questo la richiesta OCSP può essere creata e inviata al risolutore OCSP, ad esempio utilizzando 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/

Utilizzato correttamente (si prega di notare il 0x per specificare che il numero di serie è esadecimale) ciò risulta 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 significa che il certificato non è stato revocato.

Si noti che è necessario almeno OpenSSL 1.1.0 per seguire le istruzioni. Con OpenSSL 1.0.2 si ottiene invece

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

Questo perché OpenSSL 1.0.2 (e probabilmente precedente) invia una richiesta di HTTP/1.0 senza un'intestazione di Host HTTP. Mentre in teoria fini con HTTP/1.0 l'intestazione Host è necessaria qui poiché il resolver OCSP è dietro il CDN Akamai dove, praticamente con tutti i CDN (molti hoster), più hostname condividono lo stesso indirizzo IP.

Riguardo a come farlo con Python: non vedo alcun supporto per OCSP affatto in pyopenssl . E mentre esiste un supporto per OCSP nella crittografia sembra che tu abbia il certificato originale.

    
risposta data 12.10.2018 - 15:37
fonte

Leggi altre domande sui tag