Skip to content

Flow 1 – ML-KEM-512 Stream Encrypt / Decrypt (Detached JWET)

This scenario shows a complete post-quantum encryption round-trip with the streaming endpoints:

  1. Generate a PQC key-pair (ML-KEM-512).
  2. Export its public metadata.
  3. Stream-encrypt a plaintext file → detached JWET (General-JSON header + binary part).
  4. Stream-decrypt the ciphertext.
  5. Validate that the decrypted data matches the original.

Key points

  • Leverages the streaming helpers encryptFileStream / decryptFileStream, letting you encrypt or decrypt multi-gigabyte files while holding only a few kB in memory.\
  • Emits a detached JWET (General JSON): header + tag stay in a tiny JSON structure, the raw ciphertext streams as-is — zero Base64 expansion, ideal for direct‐to-disk or direct-to-object-store writes.\
  • Illustrates a full post-quantum ML-KEM-512 life-cycle (generate key ➜ export metadata ➜ encrypt ➜ decrypt) and surfaces rich key-usage telemetry in HTTP headers so you can monitor rotations, expiry or soft-limit warnings in real time.

When to use it

  • Massive datasets that must stay encrypted at rest — think nightly database dumps, genomic archives, video libraries or research data running into tens or hundreds of GB. Streaming keeps RAM flat while detached JWET avoids Base64 bloat.
  • Write-once / read-seldom storage tiers — because the ciphertext is pure binary, you can pipe it straight to S3, GCS, Azure Blob or tape without post-processing; the slim JSON header is all you need to catalogue or audit the object later.
  • Long-term confidentiality with quantum resilience — ML-KEM-512 protects backups and legal holds that must remain secret beyond the expected RSA/ECC break horizon, giving confidence for 10- to 20-year data-retention mandates.

Dependency — this example imports co.ankatech.ankasecure.sdk.examples.ExampleUtil.
If you have not copied that class yet, see example_util.md.


Complete Java implementation

src/main/java/co/ankatech/ankasecure/sdk/examples/ExampleScenario1.java

/*
 * Copyright 2025 ANKATech Solutions Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */
package co.ankatech.ankasecure.sdk.examples;

import co.ankatech.ankasecure.sdk.AnkaSecureSdk;
import co.ankatech.ankasecure.sdk.model.DecryptResultMetadata;
import co.ankatech.ankasecure.sdk.model.EncryptResult;
import co.ankatech.ankasecure.sdk.model.ExportedKeySpec;
import co.ankatech.ankasecure.sdk.model.GenerateKeySpec;
import co.ankatech.ankasecure.sdk.util.FileIO;
import java.nio.file.Path;
import java.util.Properties;

import static co.ankatech.ankasecure.sdk.examples.ExampleUtil.*;

/**
 * <h2>Scenario&nbsp;1 – End-to-End ML-KEM-512 Life-cycle (Streaming)</h2>
 *
 * <p>This scenario walks through a complete post-quantum key life-cycle using
 * the <strong>streaming</strong> endpoints of <span
 * style="font-variant: small-caps;">ANKASecure</span>. In streaming mode the
 * service produces a <em>detached&nbsp;JWE</em> (General-JSON header + raw
 * ciphertext stream) instead of a single compact JWE string.</p>
 *
 * <ol>
 *   <li>Generate an <code>ML-KEM-512</code> key-pair.</li>
 *   <li>Export its public metadata to JSON.</li>
 *   <li>Stream-encrypt a local file (detached JWE).</li>
 *   <li>Stream-decrypt the ciphertext.</li>
 *   <li>Validate round-trip integrity.</li>
 * </ol>
 *
 * <p><strong>Prerequisite:</strong> a valid access-token must be present in the
 * CLI configuration.</p>
 *
 * <p><b>Implementation notes (Java&nbsp;21+):</b></p>
 * <ul>
 *   <li>All file handling relies on the {@link java.nio.file.Path} API.</li>
 *   <li>UTF-8 is enforced explicitly to avoid platform-dependent defaults.</li>
 *   <li>Temporary artefacts are written under <kbd>temp_files/</kbd>.</li>
 * </ul>
 *
 * <p><b>Thread-safety:</b> the class is stateless and immutable; a fresh
 * {@link AnkaSecureSdk} instance is created inside {@code main}.</p>
 *
 * @author ANKATech – Security Engineering
 * @since 2.1.0
 */
public final class ExampleScenario1 {

    /* ====================================================================== */
    /** Entry-point. */
    public static void main(String[] args) {

        System.out.println("===== SCENARIO 1 START =====");
        System.out.println("""
                Purpose :
                  * End-to-end ML-KEM-512 life-cycle in streaming mode
                  * Demonstrates detached-JWE pipeline (encrypt → decrypt)
                Steps   :
                  1) Generate ML-KEM-512 key
                  2) Export public metadata
                  3) Encrypt payload (detached JWE)
                  4) Decrypt ciphertext
                  5) Validate integrity
                --------------------------------------------------------------""");

        try {
            ensureTempDir(TEMP_DIR);

            Properties   props = loadProperties();
            AnkaSecureSdk sdk  = authenticate(props);

            runScenario(sdk);

        } catch (Exception ex) {
            fatal("Scenario 1 failed", ex);
        }

        System.out.println("===== SCENARIO 1 END =====");
    }

    /* ====================================================================== */
    /**
     * Executes Scenario&nbsp;1.
     *
     * @param sdk an authenticated {@link AnkaSecureSdk} instance
     * @throws Exception on any I/O or cryptographic failure
     */
    private static void runScenario(final AnkaSecureSdk sdk) throws Exception {

        final String kid = "sc1_kem_" + System.currentTimeMillis();

        /* ---------- file system artefacts ---------------------------------- */
        Path plainFile  = TEMP_DIR.resolve("scenario1_plain.txt");
        Path encFile    = TEMP_DIR.resolve("scenario1.enc");
        Path decFile    = TEMP_DIR.resolve("scenario1.dec");
        Path exportJson = TEMP_DIR.resolve("scenario1_keydata.json");

        /* 1 ── plaintext ----------------------------------------------------- */
        FileIO.writeUtf8(plainFile,
                "Hello Scenario-1 – streaming encryption demo!");
        System.out.println("[1] Plaintext ready          -> " + plainFile.toAbsolutePath());

        /* 2 ── key generation ---------------------------------------------- */
        sdk.generateKey(new GenerateKeySpec()
                .setKid(kid)
                .setKty("ML-KEM")
                .setAlg("ML-KEM-512"));
        System.out.println("[2] Key generated            -> kid = " + kid);

        /* 3 ── export metadata --------------------------------------------- */
        ExportedKeySpec exported = sdk.exportKey(kid);
        FileIO.writeUtf8(exportJson, toJson(exported));
        System.out.println("[3] Metadata exported        -> " + exportJson.toAbsolutePath());

        /* 4 ── streaming encrypt (detached JWE) ----------------------------- */
        EncryptResult encMeta = sdk.encryptFileStream(kid, plainFile, encFile);
        System.out.println("[4] Ciphertext written       -> " + encFile.toAbsolutePath());
        printEncryptionMeta(encMeta);

        /* 5 ── streaming decrypt ------------------------------------------- */
        DecryptResultMetadata decMeta = sdk.decryptFileStream(encFile, decFile);
        System.out.println("[5] Decrypted file           -> " + decFile.toAbsolutePath());
        printDecryptionMeta(decMeta);

        /* 6 ── validation --------------------------------------------------- */
        String original  = FileIO.readUtf8(plainFile);
        String recovered = FileIO.readUtf8(decFile);
        System.out.println(original.equals(recovered)
                ? "[6] Validation OK – plaintext matches."
                : "[6] WARNING – plaintext mismatch!");
    }

    /** Utility class – no instantiation. */
    private ExampleScenario1() {
        /* no-instantiation */
    }
}

How to run


mvn -q compile exec:java\
  -Dexec.mainClass="co.ankatech.ankasecure.sdk.examples.ExampleScenario1"

Console milestones:

  • ML-KEM-512 key creation

  • Metadata export → scenario1_keydata.json

  • Detached-JWET stream-encryption → scenario1.enc

  • Stream-decryption → scenario1.dec

  • Validation OK -- byte-perfect round-trip


Where next?