Zig
Zig
Example: Crypt2.RandomizeIV method
Demonstrates using a random initialization vector for AES GCM encryption.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 assumes the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
const crypt = try chilkat.Crypt2.init();
defer crypt.deinit();
crypt.setCryptAlgorithm("aes");
crypt.setCipherMode("gcm");
crypt.setKeyLength(256);
const k = "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F";
const aad = "feedfacedeadbeeffeedfacedeadbeefabaddad2";
const pt = "This is the text to be AES-GCM encrypted.";
// Generate a random IV.
crypt.randomizeIV();
const iv = try crypt.getEncodedIV(alloc, "hex");
crypt.setEncodedKey(k, "hex");
try crypt.setEncodedAad(aad, "hex");
// Return the encrypted bytes as base64
crypt.setEncodingMode("base64");
crypt.setCharset("utf-8");
const cipher_text = crypt.encryptStringENC(alloc, pt) catch {
std.debug.print("{s}\n", .{try crypt.getLastErrorText(alloc)});
return;
};
// Get the GCM authenticated tag computed when encrypting.
const auth_tag = try crypt.getEncodedAuthTag(alloc, "base64");
std.debug.print("Cipher Text: {s}\n", .{cipher_text});
std.debug.print("Auth Tag: {s}\n", .{auth_tag});
// Let's send the IV, CipherText, and AuthTag to the decrypting party.
// We'll send them concatenated like this: [IV || Ciphertext || AuthTag]
// In base64 format.
const bd_encrypted = try chilkat.BinData.init();
defer bd_encrypted.deinit();
bd_encrypted.appendEncoded(iv, "hex") catch {};
bd_encrypted.appendEncoded(cipher_text, "base64") catch {};
bd_encrypted.appendEncoded(auth_tag, "base64") catch {};
const concatenated_gcm_output = try bd_encrypted.getEncoded(alloc, "base64");
std.debug.print("Concatenated GCM Output: {s}\n", .{concatenated_gcm_output});
// Sample output so far:
// -------------------------------------------------------------------------------------
// Now let's GCM decrypt...
// -------------------------------------------------------------------------------------
const decrypt = try chilkat.Crypt2.init();
defer decrypt.deinit();
// The values shared and agreed upon by both sides beforehand are: algorithm, cipher mode, secret key, and AAD.
// Sometimes the IV can be a value already known and agreed upon, but in this case the encryptor sends the IV to the decryptor.
decrypt.setCryptAlgorithm("aes");
decrypt.setCipherMode("gcm");
decrypt.setKeyLength(256);
decrypt.setEncodedKey(k, "hex");
decrypt.setEncodedAad(aad, "hex") catch {};
const bd_from_encryptor = try chilkat.BinData.init();
defer bd_from_encryptor.deinit();
bd_from_encryptor.appendEncoded(concatenated_gcm_output, "base64") catch {};
const sz = bd_from_encryptor.getNumBytes();
// Extract the parts.
const extracted_iv = try bd_from_encryptor.getEncodedChunk(alloc, 0, 16, "hex");
const extracted_cipher_text = try bd_from_encryptor.getEncodedChunk(alloc, 16, sz - 32, "base64");
const expected_auth_tag = try bd_from_encryptor.getEncodedChunk(alloc, sz - 16, 16, "base64");
// Before GCM decrypting, we must set the authenticated tag to the value that is expected.
// The decryption will fail if the resulting authenticated tag is not equal to the expected result.
try decrypt.setEncodedAuthTag(expected_auth_tag, "base64");
// Also set the IV.
decrypt.setEncodedIV(extracted_iv, "hex");
// Decrypt..
decrypt.setEncodingMode("base64");
decrypt.setCharset("utf-8");
const decrypted_text = decrypt.decryptStringENC(alloc, extracted_cipher_text) catch {
// Failed. The resultant authenticated tag did not equal the expected authentication tag.
std.debug.print("{s}\n", .{try decrypt.getLastErrorText(alloc)});
return;
};
std.debug.print("Decrypted: {s}\n", .{decrypted_text});
}