Delphi DLL
Delphi DLL
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 Delphi DLL Downloads
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DtObj, HttpResponse, JsonObject, Http, BinData, Cert, Crypt2;
...
procedure TForm1.Button1Click(Sender: TObject);
var
success: Boolean;
crypt: HCkCrypt2;
base64Hash: PWideChar;
http: HCkHttp;
requestToken: HCkBinData;
optionalPolicyOid: PWideChar;
addNonce: Boolean;
requestTsaCert: Boolean;
tsaUrl: PWideChar;
resp: HCkHttpResponse;
timestampReply: HCkBinData;
tsaCert: HCkCert;
pkiStatus: Integer;
json: HCkJsonObject;
signingTime: HCkDtObj;
authAttrSigningTimeUtctime: HCkDtObj;
strVal: PWideChar;
certSerialNumber: PWideChar;
certIssuerCN: PWideChar;
certDigestAlgOid: PWideChar;
certDigestAlgName: PWideChar;
contentType: PWideChar;
messageDigest: PWideChar;
signingAlgOid: PWideChar;
signingAlgName: PWideChar;
authAttrContentTypeName: PWideChar;
authAttrContentTypeOid: PWideChar;
authAttrSigningTimeName: PWideChar;
authAttrSigningCertificateName: PWideChar;
authAttrSigningCertificateDer: PWideChar;
authAttrMessageDigestName: PWideChar;
authAttrMessageDigestDigest: PWideChar;
timestampReplyPkiStatusValue: Integer;
timestampReplyPkiStatusMeaning: PWideChar;
i: Integer;
count_i: Integer;
begin
success := False;
// 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"
crypt := CkCrypt2_Create();
CkCrypt2_putHashAlgorithm(crypt,'sha256');
CkCrypt2_putEncodingMode(crypt,'base64');
base64Hash := CkCrypt2__hashStringENC(crypt,'Hello World');
http := CkHttp_Create();
requestToken := CkBinData_Create();
optionalPolicyOid := '';
addNonce := False;
requestTsaCert := True;
// Create a time-stamp request token
success := CkHttp_CreateTimestampRequest(http,'sha256',base64Hash,optionalPolicyOid,addNonce,requestTsaCert,requestToken);
if (success = False) then
begin
Memo1.Lines.Add(CkHttp__lastErrorText(http));
Exit;
end;
// 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
tsaUrl := 'https://freetsa.org/tsr';
// Another timestamp server you could try is: http://timestamp.digicert.com
tsaUrl := 'http://timestamp.digicert.com';
resp := CkHttpResponse_Create();
success := CkHttp_HttpBd(http,'POST',tsaUrl,requestToken,'application/timestamp-query',resp);
if (success = False) then
begin
Memo1.Lines.Add(CkHttp__lastErrorText(http));
Exit;
end;
// Get the timestamp reply from the HTTP response object.
timestampReply := CkBinData_Create();
CkHttpResponse_GetBodyBd(resp,timestampReply);
// Show the base64 encoded timestamp reply.
Memo1.Lines.Add(CkBinData__getEncoded(timestampReply,'base64'));
// Let's verify the timestamp reply against the TSA's cert, which we've previously downloaded.
// See https://freetsa.org/index_en.php
tsaCert := CkCert_Create();
success := CkCert_LoadFromFile(tsaCert,'qa_data/certs/freetsa.org.cer');
if (success = False) then
begin
Memo1.Lines.Add(CkCert__lastErrorText(tsaCert));
Exit;
end;
// 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
pkiStatus := CkHttp_VerifyTimestampReply(http,timestampReply,tsaCert);
if (pkiStatus < 0) then
begin
Memo1.Lines.Add(CkHttp__lastErrorText(http));
Exit;
end;
Memo1.Lines.Add('pkiStatus = ' + IntToStr(pkiStatus));
json := CkJsonObject_Create();
CkHttp_GetLastJsonData(http,json);
CkJsonObject_putEmitCompact(json,False);
Memo1.Lines.Add(CkJsonObject__emit(json));
// 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="
// }
// }
// }
// ]
// }
// }
// }
signingTime := CkDtObj_Create();
authAttrSigningTimeUtctime := CkDtObj_Create();
timestampReplyPkiStatusValue := CkJsonObject_IntOf(json,'timestampReply.pkiStatus.value');
timestampReplyPkiStatusMeaning := CkJsonObject__stringOf(json,'timestampReply.pkiStatus.meaning');
i := 0;
count_i := CkJsonObject_SizeOfArray(json,'pkcs7.verify.digestAlgorithms');
while i < count_i do
begin
CkJsonObject_putI(json,i);
strVal := CkJsonObject__stringOf(json,'pkcs7.verify.digestAlgorithms[i]');
i := i + 1;
end;
i := 0;
count_i := CkJsonObject_SizeOfArray(json,'pkcs7.verify.signerInfo');
while i < count_i do
begin
CkJsonObject_putI(json,i);
certSerialNumber := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].cert.serialNumber');
certIssuerCN := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].cert.issuerCN');
certDigestAlgOid := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].cert.digestAlgOid');
certDigestAlgName := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].cert.digestAlgName');
contentType := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].contentType');
CkJsonObject_DtOf(json,'pkcs7.verify.signerInfo[i].signingTime',False,signingTime);
messageDigest := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].messageDigest');
signingAlgOid := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].signingAlgOid');
signingAlgName := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].signingAlgName');
authAttrContentTypeName := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.3".name');
authAttrContentTypeOid := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.3".oid');
authAttrSigningTimeName := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.5".name');
CkJsonObject_DtOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.5".utctime',False,authAttrSigningTimeUtctime);
authAttrSigningCertificateName := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.16.2.12".name');
authAttrSigningCertificateDer := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.16.2.12".der');
authAttrMessageDigestName := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.4".name');
authAttrMessageDigestDigest := CkJsonObject__stringOf(json,'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.4".digest');
i := i + 1;
end;
CkCrypt2_Dispose(crypt);
CkHttp_Dispose(http);
CkBinData_Dispose(requestToken);
CkHttpResponse_Dispose(resp);
CkBinData_Dispose(timestampReply);
CkCert_Dispose(tsaCert);
CkJsonObject_Dispose(json);
CkDtObj_Dispose(signingTime);
CkDtObj_Dispose(authAttrSigningTimeUtctime);
end;