Zig
Zig
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 Zig Downloads
const std = @import("std");
const chilkat = @import("chilkat");
pub fn main(init: std.process.Init) !void {
const alloc = init.arena.allocator();
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// 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.)
const sb_xml = try chilkat.StringBuilder.init();
defer sb_xml.deinit();
try sb_xml.loadFile("xmlToSign.xml", "utf-8");
const gen = try chilkat.XmlDSigGen.init();
defer gen.deinit();
gen.setSigLocation("TransakcniLogSystemu");
gen.setSigLocationMod(0);
gen.setSigId("SignatureID-Signature1");
gen.setSigNamespacePrefix("ds");
gen.setSigNamespaceUri("http://www.w3.org/2000/09/xmldsig#");
gen.setSignedInfoCanonAlg("C14N");
gen.setSignedInfoDigestMethod("sha256");
// Set the KeyInfoId before adding references..
gen.setKeyInfoId("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.
const object1 = try chilkat.Xml.init();
defer object1.deinit();
object1.setTag("xades:QualifyingProperties");
object1.addAttribute("xmlns:xades", "http://uri.etsi.org/01903/v1.3.2#") catch {};
object1.addAttribute("Target", "#Signature1") catch {};
object1.updateAttrAt("xades:SignedProperties", true, "Id", "SignedProperties-Signature-Signature1") catch {};
object1.updateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningTime", "TO BE GENERATED BY CHILKAT");
object1.updateAttrAt("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestMethod", true, "Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256") catch {};
object1.updateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestValue", "TO BE GENERATED BY CHILKAT");
object1.updateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:IssuerSerialV2", "TO BE GENERATED BY CHILKAT");
// The EncapsulatedTimestamp will be included in the unsigned properties.
object1.updateAttrAt("xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp", true, "Id", "signature-timestamp-5561-8212-3316-5191") catch {};
object1.updateAttrAt("xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp|ds:CanonicalizationMethod", true, "Algorithm", "http://www.w3.org/2001/10/xml-exc-c14n#") catch {};
object1.updateAttrAt("xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp|xades:EncapsulatedTimeStamp", true, "Encoding", "http://uri.etsi.org/01903/v1.2.2#DER") catch {};
object1.updateChildContent("xades:UnsignedProperties|xades:UnsignedSignatureProperties|xades:SignatureTimeStamp|xades:EncapsulatedTimeStamp", "TO BE GENERATED BY CHILKAT");
gen.addObject("XadesObjectId-Signature1", try object1.getXml(alloc), "", "") catch {};
// -------- Reference 1 --------
gen.addObjectRef("SignedProperties-Signature-Signature1", "sha256", "EXCL_C14N", "", "http://uri.etsi.org/01903#SignedProperties") catch {};
// -------- Reference 2 --------
gen.addSameDocRef("KeyInfoId-Signature-Signature1", "sha256", "EXCL_C14N", "", "") catch {};
gen.setRefIdAttr("KeyInfoId-Signature-Signature1", "ReferenceKeyInfo") catch {};
// -------- Reference 3 --------
gen.addSameDocRef("", "sha256", "EXCL_C14N", "", "") catch {};
gen.setRefIdAttr("", "Reference-Signature1") catch {};
// Provide a certificate + private key. (PFX password is test123)
const cert = try chilkat.Cert.init();
defer cert.deinit();
cert.loadPfxFile("qa_data/pfx/cert_test123.pfx", "test123") catch {
std.debug.print("{s}\n", .{try cert.getLastErrorText(alloc)});
return;
};
gen.setX509Cert(cert, true) catch {};
gen.setKeyInfoType("X509Data");
gen.setX509Type("Certificate");
gen.setBehaviors("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:
// -------------------------------------------------------------------------------------------
const json_tsa = try chilkat.JsonObject.init();
defer json_tsa.deinit();
json_tsa.updateString("timestampToken.tsaUrl", "https://www3.postsignum.cz/TSS/TSS_crt/") catch {};
json_tsa.updateBool("timestampToken.requestTsaCert", true) catch {};
gen.setTsa(json_tsa) catch {};
// -------------------------------------------------------------------------------------------
// 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.
// -------------------------------------------------------------------------------------------
const http = try chilkat.Http.init();
defer http.deinit();
http.setSslClientCertPfx("/home/bob/pfxFiles/myClientSideCertWithPrivateKey.pfx", "pfxPassword") catch {
std.debug.print("{s}\n", .{try http.getLastErrorText(alloc)});
return;
};
// Tell the XmlDSigGen object to use the above HTTP object for TSA communications.
gen.setHttpObj(http);
// Sign the XML...
gen.createXmlDSigSb(sb_xml) catch {
std.debug.print("{s}\n", .{try gen.getLastErrorText(alloc)});
return;
};
// -----------------------------------------------
// Save the signed XML to a file.
try sb_xml.writeFile("c:/temp/qa_output/signedXml.xml", "utf-8", false);
std.debug.print("{s}\n", .{try sb_xml.getAsString(alloc)});
}