Zig Requires Chilkat v11.0.0+
Zig
Aadhaar Paperless Offline e-kyc
See more XML Digital Signatures Examples
Opens an encrypted .zip containing Aadhaar Paperless Offline e-KYC XML. Gets the XML and validates the digital signature. Then computes the hash for the mobile number and Email ID.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.
// Open the .zip containing the Aadhaar Paperless Offline e-KYC XML.
// The .zip is encrypted using the "Share Phrase".
const zip = try chilkat.Zip.init();
defer zip.deinit();
zip.openZip("qa_data/xml_dsig/offline_paperless_kyc.zip") catch {
std.debug.print("{s}\n", .{try zip.getLastErrorText(alloc)});
return;
};
// The .zip should contain 1 XML file.
const entry = try chilkat.ZipEntry.init();
defer entry.deinit();
zip.entryAt(0, entry) catch {
std.debug.print("{s}\n", .{try zip.getLastErrorText(alloc)});
return;
};
// To get the contents, we need to specify the Share Phrase.
const share_phrase = "Lock@487";
zip.setDecryptPassword(share_phrase);
const bd_xml = try chilkat.BinData.init();
defer bd_xml.deinit();
// The XML file will be unzipped into the bdXml object.
entry.unzipToBd(bd_xml) catch {
std.debug.print("{s}\n", .{try entry.getLastErrorText(alloc)});
return;
};
// First verify the XML digital signature.
const dsig = try chilkat.XmlDSig.init();
defer dsig.deinit();
dsig.loadSignatureBd(bd_xml) catch {
std.debug.print("{s}\n", .{try dsig.getLastErrorText(alloc)});
return;
};
// The UIDAI XML signature does not contain the KeyInfo, so we must load the uidai certificate
// and indicate that its public key is to be used for verifying the signature.
const cert = try chilkat.Cert.init();
defer cert.deinit();
cert.loadFromFile("qa_data/xml_dsig/uidai_auth_sign_prod_2023.cer") catch {
std.debug.print("{s}\n", .{try cert.getLastErrorText(alloc)});
return;
};
// Get the certificate's public key.
const pub_key = try chilkat.PublicKey.init();
defer pub_key.deinit();
cert.getPublicKey(pub_key) catch {};
dsig.setPublicKey(pub_key) catch {};
// The XML in this example contains only 1 signature.
const b_verify_reference_digests = true;
dsig.verifySignature(b_verify_reference_digests) catch {
std.debug.print("{s}\n", .{try dsig.getLastErrorText(alloc)});
std.debug.print("The signature was not valid.\n", .{});
return;
};
std.debug.print("The XML digital signature is valid.\n", .{});
// Let's compute the hash for the Mobile Number.
// Hashing logic for Mobile Number :
// Sha256(Sha256(Mobile+SharePhrase))*number of times last digit of Aadhaar number
// (Ref ID field contains last 4 digits).
//
// Example :
// Mobile: 1234567890
// Aadhaar Number:XXXX XXXX 3632
// Passcode : Lock@487
// Hash: Sha256(Sha256(1234567890Lock@487))*2
// In case of Aadhaar number ends with Zero we will hashed one time.
const crypt = try chilkat.Crypt2.init();
defer crypt.deinit();
crypt.setHashAlgorithm("sha256");
crypt.setEncodingMode("hexlower");
var str_to_hash: [:0]const u8 = "1234567890Lock@487";
const bd_hash = try chilkat.BinData.init();
defer bd_hash.deinit();
try bd_hash.appendString(str_to_hash, "utf-8");
// Hash a number of times equal to the last digit of your Aadhaar number.
// If the Aadhaar number ends with 0, then hash one time.
// For this example, we'll just set the number of times to hash
// for the case where an Aadhaar number ends in "9"
const num_times_to_hash = 9;
var i: i32 = 0;
i = 1;
while (i <= num_times_to_hash) : (i += 1) {
const tmp_str = try crypt.hashBdENC(alloc, bd_hash);
bd_hash.clear() catch {};
bd_hash.appendString(tmp_str, "utf-8") catch {};
}
std.debug.print("Computed Mobile hash = {s}\n", .{try bd_hash.getString(alloc, "utf-8")});
// Let's get the mobile hash stored in the XML and compare it with our computed hash.
const xml = try chilkat.Xml.init();
defer xml.deinit();
try xml.loadBd(bd_xml, true);
const m_hash = try xml.chilkatPath(alloc, "UidData|Poi|(m)");
std.debug.print("Stored Mobile hash = {s}\n", .{m_hash});
// Now do the same thing for the email hash:
str_to_hash = "abc@gm.comLock@487";
bd_hash.clear() catch {};
try bd_hash.appendString(str_to_hash, "utf-8");
i = 1;
while (i <= num_times_to_hash) : (i += 1) {
const tmp_str = try crypt.hashBdENC(alloc, bd_hash);
bd_hash.clear() catch {};
bd_hash.appendString(tmp_str, "utf-8") catch {};
}
std.debug.print("Computed Email hash = {s}\n", .{try bd_hash.getString(alloc, "utf-8")});
const e_hash = try xml.chilkatPath(alloc, "UidData|Poi|(e)");
std.debug.print("Stored Email hash = {s}\n", .{e_hash});
}