Sample code for 30+ languages & platforms
PureBasic

Validate Certificate using OCSP Protocol

See more Certificates Examples

Demonstrates how to validate a certificate (check the revoked status) using the OCSP protocol.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkJsonObject.pb"
IncludeFile "CkHttp.pb"
IncludeFile "CkPrng.pb"
IncludeFile "CkHttpResponse.pb"
IncludeFile "CkCert.pb"
IncludeFile "CkBinData.pb"

Procedure ChilkatExample()

    success.i = 0

    ; This requires the Chilkat API to have been previously unlocked.
    ; See Global Unlock Sample for sample code.

    ; This example will check the revoked status of a certificate loaded from a file.
    cert.i = CkCert::ckCreate()
    If cert.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkCert::ckLoadFromFile(cert,"qa_data/certs/google.crt")
    If success = 0
        Debug CkCert::ckLastErrorText(cert)
        CkCert::ckDispose(cert)
        ProcedureReturn
    EndIf

    ; Get the cert's OCSP URL.
    ocspUrl.s = CkCert::ckOcspUrl(cert)

    ; Build the JSON that will be the OCSP request.

    ; Possible hash algorithms are sha1, sha256, sha384, sha512.  
    hashAlg.s = "sha256"
    prng.i = CkPrng::ckCreate()
    If prng.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    json.i = CkJsonObject::ckCreate()
    If json.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkJsonObject::setCkEmitCompact(json, 0)
    ; Read more about OCSP nonce lengths
    CkJsonObject::ckUpdateString(json,"extensions.ocspNonce",CkPrng::ckGenRandom(prng,16,"base64"))
    CkJsonObject::setCkI(json, 0)
    CkJsonObject::ckUpdateString(json,"request[i].cert.hashAlg",hashAlg)
    CkJsonObject::ckUpdateString(json,"request[i].cert.issuerNameHash",CkCert::ckHashOf(cert,"IssuerDN",hashAlg,"base64"))
    CkJsonObject::ckUpdateString(json,"request[i].cert.issuerKeyHash",CkCert::ckHashOf(cert,"IssuerPublicKey",hashAlg,"base64"))
    CkJsonObject::ckUpdateString(json,"request[i].cert.serialNumber",CkCert::ckSerialNumber(cert))

    Debug CkJsonObject::ckEmit(json)

    ; Our OCSP request looks something like this:
    ; {
    ;   "extensions": {
    ;     "ocspNonce": "qZDfbpO+nUxRzz6c/SPjE5QCAsPfpkQlRDxTnGl0gnxt7iXO"
    ;   },
    ;   "request": [
    ;     {
    ;       "cert": {
    ;         "hashAlg": "sha1",
    ;         "issuerNameHash": "9u2wY2IygZo19o11oJ0CShGqbK0=",
    ;         "issuerKeyHash": "d8K4UJpndnaxLcKG0IOgfqZ+uks=",
    ;         "serialNumber": "6175535D87BF94B6"
    ;       }
    ;     }
    ;   ]
    ; }

    ocspRequest.i = CkBinData::ckCreate()
    If ocspRequest.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    http.i = CkHttp::ckCreate()
    If http.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; Convert our JSON to a binary (ASN.1) OCSP request
    success = CkHttp::ckCreateOcspRequest(http,json,ocspRequest)
    If success = 0
        Debug CkHttp::ckLastErrorText(http)
        CkCert::ckDispose(cert)
        CkPrng::ckDispose(prng)
        CkJsonObject::ckDispose(json)
        CkBinData::ckDispose(ocspRequest)
        CkHttp::ckDispose(http)
        ProcedureReturn
    EndIf

    ; Send the OCSP request to the OCSP server
    resp.i = CkHttpResponse::ckCreate()
    If resp.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkHttp::ckHttpBd(http,"POST",ocspUrl,ocspRequest,"application/ocsp-request",resp)
    If success = 0
        Debug CkHttp::ckLastErrorText(http)
        CkCert::ckDispose(cert)
        CkPrng::ckDispose(prng)
        CkJsonObject::ckDispose(json)
        CkBinData::ckDispose(ocspRequest)
        CkHttp::ckDispose(http)
        CkHttpResponse::ckDispose(resp)
        ProcedureReturn
    EndIf

    ; Get the binary (ASN.1) OCSP reply
    ocspReply.i = CkBinData::ckCreate()
    If ocspReply.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkHttpResponse::ckGetBodyBd(resp,ocspReply)

    ; Convert the binary reply to JSON.
    ; Also returns the overall OCSP response status.
    jsonReply.i = CkJsonObject::ckCreate()
    If jsonReply.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ocspStatus.i = CkHttp::ckParseOcspReply(http,ocspReply,jsonReply)

    ; The ocspStatus can have one of these values:
    ; -1:  The ARG1 does not contain a valid OCSP reply.
    ; 0:  Successful - Response has valid confirmations..
    ; 1: Malformed request - Illegal confirmation request.
    ; 2: Internal error - Internal error in issuer.
    ; 3: Try later -  Try again later.
    ; 4: Not used - This value is never returned.
    ; 5: Sig required - Must sign the request.
    ; 6: Unauthorized - Request unauthorized.

    If ocspStatus < 0
        Debug "Invalid OCSP reply."
        CkCert::ckDispose(cert)
        CkPrng::ckDispose(prng)
        CkJsonObject::ckDispose(json)
        CkBinData::ckDispose(ocspRequest)
        CkHttp::ckDispose(http)
        CkHttpResponse::ckDispose(resp)
        CkBinData::ckDispose(ocspReply)
        CkJsonObject::ckDispose(jsonReply)
        ProcedureReturn
    EndIf

    Debug "Overall OCSP Response Status: " + Str(ocspStatus)

    ; Let's examine the OCSP response (in JSON).
    CkJsonObject::setCkEmitCompact(jsonReply, 0)
    Debug CkJsonObject::ckEmit(jsonReply)

    ; The JSON reply looks like this:
    ; (Use the online tool at https://tools.chilkat.io/jsonParse.cshtml
    ; to generate JSON parsing code.)

    ; {
    ;   "responseStatus": 0,
    ;   "responseTypeOid": "1.3.6.1.5.5.7.48.1.1",
    ;   "responseTypeName": "ocspBasic",
    ;   "response": {
    ;     "responderIdChoice": "KeyHash",
    ;     "responderKeyHash": "d8K4UJpndnaxLcKG0IOgfqZ+uks=",
    ;     "dateTime": "20180803193937Z",
    ;     "cert": [
    ;       {
    ;         "hashOid": "1.3.14.3.2.26",
    ;         "hashAlg": "SHA-1",
    ;         "issuerNameHash": "9u2wY2IygZo19o11oJ0CShGqbK0=",
    ;         "issuerKeyHash": "d8K4UJpndnaxLcKG0IOgfqZ+uks=",
    ;         "serialNumber": "6175535D87BF94B6",
    ;         "status": 0,
    ;         "thisUpdate": "20180803193937Z",
    ;         "nextUpdate": "20180810193937Z"
    ;       }
    ;     ]
    ;   }
    ; }
    ; 

    ; The certificate status:
    certStatus.i = -1
    If CkJsonObject::ckHasMember(jsonReply,"response.cert[0].status") = 1
        certStatus = CkJsonObject::ckIntOf(jsonReply,"response.cert[0].status")
    EndIf

    ; Possible certStatus values are:
    ; -1: No status returned.
    ; 0: Good
    ; 1: Revoked
    ; 2: Unknown.
    Debug "Certificate Status: " + Str(certStatus)


    CkCert::ckDispose(cert)
    CkPrng::ckDispose(prng)
    CkJsonObject::ckDispose(json)
    CkBinData::ckDispose(ocspRequest)
    CkHttp::ckDispose(http)
    CkHttpResponse::ckDispose(resp)
    CkBinData::ckDispose(ocspReply)
    CkJsonObject::ckDispose(jsonReply)


    ProcedureReturn
EndProcedure