Xbase++ Requires Chilkat v11.0.0+
Xbase++
RFC3161 Timestamp Client - Fetch from Timestamp Authority (TSA) and Verify
See more HTTP Examples
Sends an RFC 3161 timestamp request to a TSA (Timestamp Authority) server and validates the timestamp token response.Chilkat Xbase++ Downloads
LOCAL nSuccess
LOCAL oCrypt
LOCAL cBase64Hash
LOCAL oHttp
LOCAL oRequestToken
LOCAL cOptionalPolicyOid
LOCAL nAddNonce
LOCAL nRequestTsaCert
LOCAL cTsaUrl
LOCAL oResp
LOCAL oTimestampReply
LOCAL oTsaCert
LOCAL nPkiStatus
LOCAL oJson
LOCAL oSigningTime
LOCAL oAuthAttrSigningTimeUtctime
LOCAL cStrVal
LOCAL cCertSerialNumber
LOCAL cCertIssuerCN
LOCAL cCertDigestAlgOid
LOCAL cCertDigestAlgName
LOCAL cContentType
LOCAL cMessageDigest
LOCAL cSigningAlgOid
LOCAL cSigningAlgName
LOCAL cAuthAttrContentTypeName
LOCAL cAuthAttrContentTypeOid
LOCAL cAuthAttrSigningTimeName
LOCAL cAuthAttrSigningCertificateName
LOCAL cAuthAttrSigningCertificateDer
LOCAL cAuthAttrMessageDigestName
LOCAL cAuthAttrMessageDigestDigest
LOCAL nTimestampReplyPkiStatusValue
LOCAL cTimestampReplyPkiStatusMeaning
LOCAL i
LOCAL nCount_i
nSuccess := 0
// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// First sha-256 hash the data that is to be timestamped.
// In this example, the data is the string "Hello World"
oCrypt := CreateObject("Chilkat.Crypt2")
oCrypt:HashAlgorithm := "sha256"
oCrypt:EncodingMode := "base64"
cBase64Hash := oCrypt:HashStringENC("Hello World")
oHttp := CreateObject("Chilkat.Http")
oRequestToken := CreateObject("Chilkat.BinData")
cOptionalPolicyOid := ""
nAddNonce := 0
nRequestTsaCert := 1
// Create a time-stamp request token
nSuccess := oHttp:CreateTimestampRequest("sha256", cBase64Hash, cOptionalPolicyOid, nAddNonce, nRequestTsaCert, oRequestToken)
IF (nSuccess == 0)
? oHttp:LastErrorText
oCrypt:destroy()
oHttp:destroy()
oRequestToken:destroy()
RETURN
ENDIF
// Send the time-stamp request token to the TSA.
// This is the equivalent of the following CURL command:
// curl -H "Content-Type: application/timestamp-query" --data-binary '@file.tsq' https://freetsa.org/tsr > file.tsr
cTsaUrl := "https://freetsa.org/tsr"
// Another timestamp server you could try is: http://timestamp.digicert.com
cTsaUrl := "http://timestamp.digicert.com"
oResp := CreateObject("Chilkat.HttpResponse")
nSuccess := oHttp:HttpBd("POST", cTsaUrl, oRequestToken, "application/timestamp-query", oResp)
IF (nSuccess == 0)
? oHttp:LastErrorText
oCrypt:destroy()
oHttp:destroy()
oRequestToken:destroy()
oResp:destroy()
RETURN
ENDIF
// Get the timestamp reply from the HTTP response object.
oTimestampReply := CreateObject("Chilkat.BinData")
oResp:GetBodyBd(oTimestampReply)
// Show the base64 encoded timestamp reply.
? oTimestampReply:GetEncoded("base64")
// Let's verify the timestamp reply against the TSA's cert, which we've previously downloaded.
// See https://freetsa.org/index_en.php
oTsaCert := CreateObject("Chilkat.Cert")
nSuccess := oTsaCert:LoadFromFile("qa_data/certs/freetsa.org.cer")
IF (nSuccess == 0)
? oTsaCert:LastErrorText
oCrypt:destroy()
oHttp:destroy()
oRequestToken:destroy()
oResp:destroy()
oTimestampReply:destroy()
oTsaCert:destroy()
RETURN
ENDIF
// The VerifyTimestampReply method will return one of the following values:
// -1: The timestampReply does not contain a valid timestamp reply.
// -2: The timestampReply is a valid timestamp reply, but failed verification using the public key of the tsaCert.
// 0: Granted and verified.
// 1: Granted and verified, with mods (see RFC 3161)
// 2: Rejected.
// 3: Waiting.
// 4: Revocation Warning
// 5: Revocation Notification
nPkiStatus := oHttp:VerifyTimestampReply(oTimestampReply, oTsaCert)
IF (nPkiStatus < 0)
? oHttp:LastErrorText
oCrypt:destroy()
oHttp:destroy()
oRequestToken:destroy()
oResp:destroy()
oTimestampReply:destroy()
oTsaCert:destroy()
RETURN
ENDIF
? "pkiStatus = " + Str(nPkiStatus)
oJson := CreateObject("Chilkat.JsonObject")
oHttp:GetLastJsonData(oJson)
oJson:EmitCompact := 0
? oJson:Emit()
// The JSON looks like the following.
// Use this online tool to generate parsing code from sample JSON:
// Generate Parsing Code from JSON
// {
// "timestampReply": {
// "pkiStatus": {
// "value": 0,
// "meaning": "granted"
// }
// },
// "pkcs7": {
// "verify": {
// "digestAlgorithms": [
// "sha256"
// ],
// "signerInfo": [
// {
// "cert": {
// "serialNumber": "04CD3F8568AE76C61BB0FE7160CCA76D",
// "issuerCN": "DigiCert SHA2 Assured ID Timestamping CA",
// "digestAlgOid": "2.16.840.1.101.3.4.2.1",
// "digestAlgName": "SHA256"
// },
// "contentType": "1.2.840.113549.1.9.16.1.4",
// "signingTime": "200405023019Z",
// "messageDigest": "f14zOsdnN9vyyV3HjjBiLzNDi1PF28hAFMODxNkNRZs=",
// "signingAlgOid": "1.2.840.113549.1.1.1",
// "signingAlgName": "RSA-PKCSV-1_5",
// "authAttr": {
// "1.2.840.113549.1.9.3": {
// "name": "contentType",
// "oid": "1.2.840.113549.1.9.16.1.4"
// },
// "1.2.840.113549.1.9.5": {
// "name": "signingTime",
// "utctime": "200405023019Z"
// },
// "1.2.840.113549.1.9.16.2.12": {
// "name": "signingCertificate",
// "der": "MBowGDAWBBQDJb1QXtqWMC3CL0+gHkwovig0xQ=="
// },
// "1.2.840.113549.1.9.4": {
// "name": "messageDigest",
// "digest": "f14zOsdnN9vyyV3HjjBiLzNDi1PF28hAFMODxNkNRZs="
// }
// }
// }
// ]
// }
// }
// }
oSigningTime := CreateObject("Chilkat.DtObj")
oAuthAttrSigningTimeUtctime := CreateObject("Chilkat.DtObj")
nTimestampReplyPkiStatusValue := oJson:IntOf("timestampReply.pkiStatus.value")
cTimestampReplyPkiStatusMeaning := oJson:StringOf("timestampReply.pkiStatus.meaning")
i := 0
nCount_i := oJson:SizeOfArray("pkcs7.verify.digestAlgorithms")
DO WHILE i < nCount_i
oJson:I := i
cStrVal := oJson:StringOf("pkcs7.verify.digestAlgorithms[i]")
i := i + 1
ENDDO
i := 0
nCount_i := oJson:SizeOfArray("pkcs7.verify.signerInfo")
DO WHILE i < nCount_i
oJson:I := i
cCertSerialNumber := oJson:StringOf("pkcs7.verify.signerInfo[i].cert.serialNumber")
cCertIssuerCN := oJson:StringOf("pkcs7.verify.signerInfo[i].cert.issuerCN")
cCertDigestAlgOid := oJson:StringOf("pkcs7.verify.signerInfo[i].cert.digestAlgOid")
cCertDigestAlgName := oJson:StringOf("pkcs7.verify.signerInfo[i].cert.digestAlgName")
cContentType := oJson:StringOf("pkcs7.verify.signerInfo[i].contentType")
oJson:DtOf("pkcs7.verify.signerInfo[i].signingTime", 0, oSigningTime)
cMessageDigest := oJson:StringOf("pkcs7.verify.signerInfo[i].messageDigest")
cSigningAlgOid := oJson:StringOf("pkcs7.verify.signerInfo[i].signingAlgOid")
cSigningAlgName := oJson:StringOf("pkcs7.verify.signerInfo[i].signingAlgName")
cAuthAttrContentTypeName := oJson:StringOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.3".name')
cAuthAttrContentTypeOid := oJson:StringOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.3".oid')
cAuthAttrSigningTimeName := oJson:StringOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.5".name')
oJson:DtOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.5".utctime', 0, oAuthAttrSigningTimeUtctime)
cAuthAttrSigningCertificateName := oJson:StringOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.16.2.12".name')
cAuthAttrSigningCertificateDer := oJson:StringOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.16.2.12".der')
cAuthAttrMessageDigestName := oJson:StringOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.4".name')
cAuthAttrMessageDigestDigest := oJson:StringOf('pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.4".digest')
i := i + 1
ENDDO
oCrypt:destroy()
oHttp:destroy()
oRequestToken:destroy()
oResp:destroy()
oTimestampReply:destroy()
oTsaCert:destroy()
oJson:destroy()
oSigningTime:destroy()
oAuthAttrSigningTimeUtctime:destroy()