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