Delphi DLL
Delphi DLL
XAdES using TSA Requiring Client Certificate
See more XML Digital Signatures Examples
Demonstrates how to create an XMLDSig (XAdES) signed document which includes an EncapsulatedTimestamp using a TSA (TimeStamp Authority) server requiring client certificate authentication. One such TSA is https://www3.postsignum.cz/TSS/TSS_crt/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, XmlDSigGen, StringBuilder, JsonObject, Cert, Http, Xml;
...
procedure TForm1.Button1Click(Sender: TObject);
var
success: Boolean;
sbXml: HCkStringBuilder;
gen: HCkXmlDSigGen;
object1: HCkXml;
cert: HCkCert;
jsonTsa: HCkJsonObject;
http: HCkHttp;
begin
success := False;
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
success := True;
// Load the XML to be signed. For example, the XML to be signed might contain something like this:
// <?xml version="1.0" encoding="utf-8"?>
// <TransakcniLogSystemu xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://nsess.public.cz/erms_trans/v_01_01" Id="Signature1">
// <TransLogInfo>
// <Identifikator>XYZ ABC</Identifikator>
// <DatumVzniku>2022-12-20T14:39:02.3625922+01:00</DatumVzniku>
// <DatumCasOd>2022-12-20T14:26:26.88</DatumCasOd>
// <DatumCasDo>2022-12-20T14:39:02.287</DatumCasDo>
// <Software>XYZ</Software>
// <VerzeSoftware>2.0.19.32</VerzeSoftware>
// </TransLogInfo>
// <Udalosti>
// <Udalost>
// <Poradi>1</Poradi>
// ...
// Load the XML to be signed from a file.
// (XML can be loaded from other source, such as a string variable.)
sbXml := CkStringBuilder_Create();
success := CkStringBuilder_LoadFile(sbXml,'xmlToSign.xml','utf-8');
gen := CkXmlDSigGen_Create();
CkXmlDSigGen_putSigLocation(gen,'TransakcniLogSystemu');
CkXmlDSigGen_putSigLocationMod(gen,0);
CkXmlDSigGen_putSigId(gen,'SignatureID-Signature1');
CkXmlDSigGen_putSigNamespacePrefix(gen,'ds');
CkXmlDSigGen_putSigNamespaceUri(gen,'http://www.w3.org/2000/09/xmldsig#');
CkXmlDSigGen_putSignedInfoCanonAlg(gen,'C14N');
CkXmlDSigGen_putSignedInfoDigestMethod(gen,'sha256');
// Set the KeyInfoId before adding references..
CkXmlDSigGen_putKeyInfoId(gen,'KeyInfoId-Signature-Signature1');
// Create an Object to be added to the Signature.
// Note: Chilkat will automatically fill in the values marked as "TO BE GENERATED BY CHILKAT" at the time of signing.
// The EncapsulatedTimestamp will be automatically generated.
object1 := CkXml_Create();
CkXml_putTag(object1,'xades:QualifyingProperties');
CkXml_AddAttribute(object1,'xmlns:xades','http://uri.etsi.org/01903/v1.3.2#');
CkXml_AddAttribute(object1,'Target','#Signature1');
CkXml_UpdateAttrAt(object1,'xades:SignedProperties',True,'Id','SignedProperties-Signature-Signature1');
CkXml_UpdateChildContent(object1,'xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningTime','TO BE GENERATED BY CHILKAT');
CkXml_UpdateAttrAt(object1,'xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestMethod',True,'Algorithm','http://www.w3.org/2001/04/xmlenc#sha256');
CkXml_UpdateChildContent(object1,'xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestValue','TO BE GENERATED BY CHILKAT');
CkXml_UpdateChildContent(object1,'xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:IssuerSerialV2','TO BE GENERATED BY CHILKAT');
// The EncapsulatedTimestamp will be included in the unsigned properties.
CkXml_UpdateAttrAt(object1,'xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp',True,'Id','signature-timestamp-5561-8212-3316-5191');
CkXml_UpdateAttrAt(object1,'xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp|ds:CanonicalizationMethod',True,'Algorithm','http://www.w3.org/2001/10/xml-exc-c14n#');
CkXml_UpdateAttrAt(object1,'xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp|xades:EncapsulatedTimeStamp',True,'Encoding','http://uri.etsi.org/01903/v1.2.2#DER');
CkXml_UpdateChildContent(object1,'xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp|xades:EncapsulatedTimeStamp','TO BE GENERATED BY CHILKAT');
CkXmlDSigGen_AddObject(gen,'XadesObjectId-Signature1',CkXml__getXml(object1),'','');
// -------- Reference 1 --------
CkXmlDSigGen_AddObjectRef(gen,'SignedProperties-Signature-Signature1','sha256','EXCL_C14N','','http://uri.etsi.org/01903#SignedProperties');
// -------- Reference 2 --------
CkXmlDSigGen_AddSameDocRef(gen,'KeyInfoId-Signature-Signature1','sha256','EXCL_C14N','','');
CkXmlDSigGen_SetRefIdAttr(gen,'KeyInfoId-Signature-Signature1','ReferenceKeyInfo');
// -------- Reference 3 --------
CkXmlDSigGen_AddSameDocRef(gen,'','sha256','EXCL_C14N','','');
CkXmlDSigGen_SetRefIdAttr(gen,'','Reference-Signature1');
// Provide a certificate + private key. (PFX password is test123)
cert := CkCert_Create();
success := CkCert_LoadPfxFile(cert,'qa_data/pfx/cert_test123.pfx','test123');
if (success <> True) then
begin
Memo1.Lines.Add(CkCert__lastErrorText(cert));
Exit;
end;
CkXmlDSigGen_SetX509Cert(gen,cert,True);
CkXmlDSigGen_putKeyInfoType(gen,'X509Data');
CkXmlDSigGen_putX509Type(gen,'Certificate');
CkXmlDSigGen_putBehaviors(gen,'IndentedSignature');
// -------------------------------------------------------------------------------------------
// To have the EncapsulatedTimeStamp automatically added...
// 1) Add the <xades:EncapsulatedTimeStamp Encoding="http://uri.etsi.org/01903/v1.2.2#DER">TO BE GENERATED BY CHILKAT</xades:EncapsulatedTimeStamp>
// to the unsigned properties. (This was accomplished in the above code.)
// 2) Specify the TSA URL (Timestamping Authority URL).
// Here we specify the TSA URL:
// -------------------------------------------------------------------------------------------
jsonTsa := CkJsonObject_Create();
CkJsonObject_UpdateString(jsonTsa,'timestampToken.tsaUrl','https://www3.postsignum.cz/TSS/TSS_crt/');
CkJsonObject_UpdateBool(jsonTsa,'timestampToken.requestTsaCert',True);
CkXmlDSigGen_SetTsa(gen,jsonTsa);
// -------------------------------------------------------------------------------------------
// In this case, the TSA requires client certificate authentication.
// To provide your client certificate, the application will instantiate a Chilkat HTTP object,
// then set it up with a SSL/TLS client certificate, and then tell the XmlDSigGen object
// to use the HTTP object for connections to the TSA server.
// -------------------------------------------------------------------------------------------
http := CkHttp_Create();
success := CkHttp_SetSslClientCertPfx(http,'/home/bob/pfxFiles/myClientSideCertWithPrivateKey.pfx','pfxPassword');
if (success <> True) then
begin
Memo1.Lines.Add(CkHttp__lastErrorText(http));
Exit;
end;
// Tell the XmlDSigGen object to use the above HTTP object for TSA communications.
CkXmlDSigGen_SetHttpObj(gen,http);
// Sign the XML...
success := CkXmlDSigGen_CreateXmlDSigSb(gen,sbXml);
if (success <> True) then
begin
Memo1.Lines.Add(CkXmlDSigGen__lastErrorText(gen));
Exit;
end;
// -----------------------------------------------
// Save the signed XML to a file.
success := CkStringBuilder_WriteFile(sbXml,'c:/temp/qa_output/signedXml.xml','utf-8',False);
Memo1.Lines.Add(CkStringBuilder__getAsString(sbXml));
CkStringBuilder_Dispose(sbXml);
CkXmlDSigGen_Dispose(gen);
CkXml_Dispose(object1);
CkCert_Dispose(cert);
CkJsonObject_Dispose(jsonTsa);
CkHttp_Dispose(http);
end;