Security & Encoding

Two recipes for hashing and encoding - file integrity verification with MD5 / SHA-256 and Base64 encode/decode for API tokens and embedded payloads.

Back to Kookbook


Checksum Verifier

Modules: Hash · File · String · Path · Konsol

Reads a text file, computes its MD5 and SHA-256 digests, and optionally verifies against an expected hash. The algorithm is auto-detected by digest length (32 chars = MD5, 64 chars = SHA-256), so the same command works for both.

Key patterns:

Usage

# compute and print both hashes
minks checksum_verifier.ks path/to/file.txt

# verify against a known MD5
minks checksum_verifier.ks path/to/file.txt 5d41402abc4b2a76b9719d911017c592

# verify against a known SHA-256
minks checksum_verifier.ks path/to/file.txt 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Sample output

=== Checksum Verifier ===
File : config.json
Size : 142 chars
MD5    : e4d7f1b4ed2e42d15898f4b27b019da4
SHA-256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
PASS - SHA-256 hash matches.
Done.

Script

// checksum_verifier.ks - compute and verify MD5/SHA-256 file checksums
// Modules: Hash, File, String, Path, OS, Konsol
// Usage:
//   minks checksum_verifier.ks <file>                  // compute and print both hashes
//   minks checksum_verifier.ks <file> <expected-hash>  // verify against known hash
//
// The expected hash is auto-detected by length:
//   32 chars → MD5    64 chars → SHA-256
//
// Note: file content is read as text.  Binary files or files with
// mixed line endings may produce different digests than byte-level
// tools like sha256sum.  For text files, API tokens, and config blobs
// this is reliable.

Konsol:Print("=== Checksum Verifier ===");

// ── Step 1: Read arguments ────────────────────────────────────────────────────
Var:List args;
OS:Args(args);

Var:Number argc;
List:Size(args, argc);

if (argc < 1) {
    Konsol:Print("Usage: minks checksum_verifier.ks <file> [expected-hash]");
    Konsol:Exit(1);
}

Var:String filePath;
List:Get(0, args, filePath);

Var:String expected = "";
if (argc >= 2) {
    List:Get(1, args, expected);
}

// ── Step 2: Verify the file exists ───────────────────────────────────────────
Var:Boolean exists;
Path:Exists(filePath, exists);
if (!exists) {
    Konsol:Print("File not found: ${filePath}");
    Konsol:Exit(1);
}

// ── Step 3: Read file content ─────────────────────────────────────────────────
// Read line by line and reassemble with newlines.  The resulting string
// is what gets hashed - both MD5 and SHA-256 hash a string, not raw bytes.
Var:Number fh;
File:Open(filePath, "r", fh);

Var:String content = "";
Var:String line;
Var:Boolean eof;

File:EOF(fh, eof);
while (!eof) {
    File:ReadLine(fh, line);
    content = content + line + "\n";
    File:EOF(fh, eof);
}
File:Close(fh);

Var:Number len;
String:Length(content, len);
Konsol:Print("File : ${filePath}");
Konsol:Print("Size : ${len} chars");

// ── Step 4: Compute hashes ────────────────────────────────────────────────────
// Hash:MD5   → 32-char lowercase hex
// Hash:SHA256 → 64-char lowercase hex
// Both follow the ByRef convention: result goes into the last argument.
Var:String md5;
Var:String sha256;

Hash:MD5(content, md5);
Hash:SHA256(content, sha256);

Konsol:Print("MD5    : ${md5}");
Konsol:Print("SHA-256: ${sha256}");

// ── Step 5: Verify against expected hash (optional) ───────────────────────────
if (expected != "") {
    // Detect algorithm by digest length (hash outputs are always lowercase,
    // so pass the expected value in lowercase for a clean comparison).
    Var:Number expLen;
    String:Length(expected, expLen);

    Var:Boolean matched = false;
    Var:String algorithm = "unknown";

    if (expLen == 32) {
        algorithm = "MD5";
        if (expected == md5) { matched = true; }
    } else if (expLen == 64) {
        algorithm = "SHA-256";
        if (expected == sha256) { matched = true; }
    } else {
        Konsol:Print("Unknown hash format (32 chars = MD5, 64 chars = SHA-256).");
        Konsol:Exit(1);
    }

    if (matched) {
        Konsol:Print("PASS - ${algorithm} hash matches.");
    } else {
        Konsol:Print("FAIL - ${algorithm} mismatch!");
        Konsol:Print("  Expected : ${expected}");
        Konsol:Exit(1);
    }
}

Konsol:Print("Done.");


Base64 Tool

Modules: Hash · File · Path · Konsol

Three modes in one script: encode a string, decode a Base64 string, or encode an entire text file. Shows round-trip verification for encode mode and a JSON embedding snippet for encode-file mode.

Key patterns:

Practical uses: embed API keys in JSON payloads, encode config files for safe transport, decode Base64 responses from REST APIs.

Usage

minks base64_tool.ks encode      "Hello, World!"
minks base64_tool.ks decode      "SGVsbG8sIFdvcmxkIQ=="
minks base64_tool.ks encode-file path/to/file.txt

Sample output

=== Base64 Tool ===
Input  : Hello, World!
Encoded: SGVsbG8sIFdvcmxkIQ==
Decoded: Hello, World!
Done.

Script

// base64_tool.ks - Base64 encode and decode strings or file content
// Modules: Hash, File, Path, OS, Konsol
// Usage:
//   minks base64_tool.ks encode      "Hello, World!"
//   minks base64_tool.ks decode      "SGVsbG8sIFdvcmxkIQ=="
//   minks base64_tool.ks encode-file path/to/file.txt
//
// Common uses: encode API tokens before sending in HTTP headers,
// embed small files as Base64 payloads in JSON, decode server responses.

Konsol:Print("=== Base64 Tool ===");

// ── Step 1: Read arguments ────────────────────────────────────────────────────
Var:List args;
OS:Args(args);

Var:Number argc;
List:Size(args, argc);

if (argc < 2) {
    Konsol:Print("Usage:");
    Konsol:Print("  minks base64_tool.ks encode      <text>");
    Konsol:Print("  minks base64_tool.ks decode      <base64-string>");
    Konsol:Print("  minks base64_tool.ks encode-file <path>");
    Konsol:Exit(1);
}

Var:String mode;
Var:String input;
List:Get(0, args, mode);
List:Get(1, args, input);

// ── Encode a string ───────────────────────────────────────────────────────────
if (mode == "encode") {
    // Hash:Base64Encode follows the ByRef convention: result in last arg.
    Var:String encoded;
    Hash:Base64Encode(input, encoded);

    Konsol:Print("Input  : ${input}");
    Konsol:Print("Encoded: ${encoded}");

    // Demonstrate round-trip correctness.
    Var:String roundTrip;
    Hash:Base64Decode(encoded, roundTrip);
    Konsol:Print("Decoded: ${roundTrip}");

// ── Decode a Base64 string ────────────────────────────────────────────────────
} else if (mode == "decode") {
    Var:String decoded;
    Hash:Base64Decode(input, decoded);

    Konsol:Print("Input  : ${input}");
    Konsol:Print("Decoded: ${decoded}");

// ── Encode a text file ────────────────────────────────────────────────────────
} else if (mode == "encode-file") {
    // Useful for embedding config files, certificates, or small assets in
    // JSON payloads without worrying about escaping special characters.
    Var:Boolean exists;
    Path:Exists(input, exists);
    if (!exists) {
        Konsol:Print("File not found: ${input}");
        Konsol:Exit(1);
    }

    Var:Number fh;
    File:Open(input, "r", fh);

    Var:String content = "";
    Var:String line;
    Var:Boolean eof;

    File:EOF(fh, eof);
    while (!eof) {
        File:ReadLine(fh, line);
        content = content + line + "\n";
        File:EOF(fh, eof);
    }
    File:Close(fh);

    Var:Number len;
    String:Length(content, len);
    Konsol:Print("File   : ${input}  (${len} chars)");

    Var:String encoded;
    Hash:Base64Encode(content, encoded);
    Konsol:Print("Encoded:");
    Konsol:Print(encoded);

    // Show how the result would be embedded in a JSON payload.
    Konsol:Print("");
    Konsol:Print("JSON usage example:");
    Konsol:Print("""{"file":"${input}","content":"${encoded}"}""");

} else {
    Konsol:Print("Unknown mode '${mode}' - use encode, decode, or encode-file.");
    Konsol:Exit(1);
}

Konsol:Print("Done.");


Back to Kookbook