Flow 20 --- In-Memory JWE / JWS Quick-start
This scenario runs a 100 % file-less round-trip using two post-quantum algorithms:
-
Generate an
HQC-128
key for encryption/decryption. -
Generate an
SLH-DSA-SHA2-128S
key for signing/verification. -
Encrypt a UTF-8 message → Compact JWE (all in RAM).
-
Decrypt the token back to bytes.
-
Sign the same bytes → Compact JWS.
-
Verify the signature, print rich metadata, and confirm the plaintext still matches.
Key points
Zero I/O: Every artefact (keys, tokens, plaintext) lives only in memory.
Uses modern post-quantum algorithms (HQC-128 & SLH-DSA-128S).
Shows the lightweight
encrypt()
/decrypt()
andsign()
/verifySignature()
helpers that return tokens directly.Ideal as a boiler-plate for micro-services, lambdas, or event pipelines.
When to use it
-
High-throughput services that must avoid disk latency or sandboxed file-system access.
-
Stateless functions (FaaS) or message brokers where tokens flow through headers or payloads.
-
Security demos / smoke tests proving that PQC algorithms work end-to-end without touching the HDD/SSD.
Shared helper – this code imports the utility class from
example_util.md (configuration, authentication, JSON).
Complete Java implementation
src/main/java/co/ankatech/ankasecure/sdk/examples/ExampleScenario20.java
/* *****************************************************************************
* FILE: ExampleScenario20.java
* Copyright © 2025 Anka Technologies.
* SPDX-License-Identifier: MIT
* ---------------------------------------------------------------------------
* Scenario 20 – 100 % In-Memory PQC Quick-Start
* ---------------------------------------------------------------------------
* Demonstrates how to:
* * Generate two post-quantum keys (HQC-128 for encryption, SLH-DSA-SHA2-128S
* for signing) entirely in RAM.
* * Encrypt UTF-8 data → Compact JWE and decrypt it back to bytes.
* * Sign the same bytes → Compact JWS and verify the signature.
* * Inspect end-to-end metadata and validate round-trip integrity.
*
* No temporary files are created; every artefact lives only in memory,
* making this flow ideal for service-to-service integrations and
* event-driven architectures where disk I/O is undesirable.
* ****************************************************************************/
package co.ankatech.ankasecure.sdk.examples;
import co.ankatech.ankasecure.sdk.AnkaSecureSdk;
import co.ankatech.ankasecure.sdk.exception.AnkaSecureSdkException;
import co.ankatech.ankasecure.sdk.model.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
/**
* <h2>Scenario 20 – In-Memory Post-Quantum Crypto (Compact JWE/JWS)</h2>
*
* <p>This scenario performs an <em>entirely file-less</em> encryption ➜ decryption
* and signing ➜ verification cycle with post-quantum algorithms:</p>
* <ol>
* <li>Generate an HQC-128 key for encryption and decryption.</li>
* <li>Generate an SLH-DSA-SHA2-128S key for signing and verification.</li>
* <li>Encrypt a UTF-8 message into a Compact JWE token and decrypt it
* back to bytes.</li>
* <li>Sign the same bytes, producing a Compact JWS token, and verify
* that signature.</li>
* </ol>
*
* <p>All artefacts remain in memory; nothing touches the disk.</p>
*
* @author ANKATech – Security Engineering
*/
public final class ExampleScenario20 {
/* Dynamically generated key IDs (avoid clashes between runs) */
private static final String ENC_KID = "sc20_HQC128_" + System.currentTimeMillis();
private static final String SIGN_KID = "sc20_SLHDSA128S_" + System.currentTimeMillis();
/* ====================================================================== */
/** Entry-point. */
public static void main(final String[] args) {
System.out.println("===== SCENARIO 20 START =====");
System.out.println("""
Purpose :
* 100 % in-memory encrypt ➜ decrypt and sign ➜ verify.
Steps :
1) Generate HQC-128 key (encrypt/decrypt).
2) Generate SLH-DSA-SHA2-128S key (sign/verify).
3) Encrypt plaintext -> Compact JWE.
4) Decrypt Compact JWE.
5) Sign plaintext -> Compact JWS.
6) Verify Compact JWS signature.
--------------------------------------------------------------""");
try {
Properties props = ExampleUtil.loadProperties();
AnkaSecureSdk sdk = ExampleUtil.authenticate(props);
runScenario(sdk);
} catch (Exception ex) {
fatal("Scenario 20 failed", ex);
}
System.out.println("===== SCENARIO 20 END =====");
}
/* ====================================================================== */
/** Executes the complete in-memory flow. */
private static void runScenario(final AnkaSecureSdk sdk) throws AnkaSecureSdkException {
/* 0 ── plaintext -------------------------------------------------- */
byte[] plaintext = "Hello PQC world – Scenario 20".getBytes(StandardCharsets.UTF_8);
System.out.println("[0] Plaintext prepared (" + plaintext.length + " bytes)");
/* 1 ── HQC-128 key (encrypt/decrypt) ----------------------------- */
sdk.generateKey(new GenerateKeySpec()
.setKid(ENC_KID)
.setKty("HQC")
.setAlg("HQC-128")
.setKeyOps(List.of("encrypt", "decrypt")));
System.out.println("[1] HQC-128 key generated -> kid = " + ENC_KID);
/* 2 ── SLH-DSA-SHA2-128S key (sign/verify) ---------------------- */
sdk.generateKey(new GenerateKeySpec()
.setKid(SIGN_KID)
.setKty("SLH-DSA")
.setAlg("SLH-DSA-SHA2-128S")
.setKeyOps(List.of("sign", "verify")));
System.out.println("[2] SLH-DSA-128S key generated -> kid = " + SIGN_KID);
/* 3 ── Encrypt (Compact JWE) ------------------------------------ */
EncryptResult encRes = sdk.encrypt(ENC_KID, plaintext);
String jwe = encRes.getJweToken();
System.out.println("[3] JWE created (length = " + jwe.length() + ")");
printEncryptMeta(encRes);
/* 4 ── Decrypt --------------------------------------------------- */
DecryptResult decRes = sdk.decrypt(jwe);
byte[] recovered = decRes.getDecryptedData();
System.out.println("[4] Decrypted text : " +
new String(recovered, StandardCharsets.UTF_8));
printDecryptMeta(decRes);
/* 5 ── Sign (Compact JWS) --------------------------------------- */
SignResult sigRes = sdk.sign(SIGN_KID, plaintext);
String jws = sigRes.getJwsToken();
System.out.println("[5] JWS created (length = " + jws.length() + ")");
printSignMeta(sigRes);
/* 6 ── Verify ---------------------------------------------------- */
VerifySignatureResult verRes = sdk.verifySignature(jws);
System.out.println("[6] Signature valid? -> " + verRes.isValid());
printVerifyMeta(verRes);
/* 7 ── Integrity check ----------------------------------------- */
boolean match = Objects.equals(
new String(plaintext, StandardCharsets.UTF_8),
new String(recovered, StandardCharsets.UTF_8));
System.out.println(match
? "[✔] SUCCESS – round-trip data matches."
: "[✘] FAILURE – data mismatch!");
}
/* ====================================================================== */
/* ------------------------- Helper utilities --------------------------- */
private static void printSignMeta(final SignResult r) {
System.out.println("----- SIGN METADATA -----");
System.out.println("Key requested : " + nullSafe(r.getKeyRequested()));
System.out.println("Key used : " + nullSafe(r.getActualKeyUsed()));
System.out.println("Algorithm : " + nullSafe(r.getAlgorithmUsed()));
printWarnings(r.getWarnings());
}
private static void printVerifyMeta(final VerifySignatureResult r) {
System.out.println("----- VERIFY METADATA -----");
System.out.println("Valid : " + r.isValid());
System.out.println("Key requested : " + nullSafe(r.getKeyRequested()));
System.out.println("Key used : " + nullSafe(r.getActualKeyUsed()));
System.out.println("Algorithm : " + nullSafe(r.getAlgorithmUsed()));
printWarnings(r.getWarnings());
}
private static void printEncryptMeta(final EncryptResult r) {
System.out.println("----- ENCRYPT METADATA -----");
System.out.println("Key requested : " + nullSafe(r.getKeyRequested()));
System.out.println("Key used : " + nullSafe(r.getActualKeyUsed()));
System.out.println("Algorithm : " + nullSafe(r.getAlgorithmUsed()));
printWarnings(r.getWarnings());
}
private static void printDecryptMeta(final DecryptResult r) {
System.out.println("----- DECRYPT METADATA -----");
System.out.println("Key requested : " + nullSafe(r.getMeta().getKeyRequested()));
System.out.println("Key used : " + nullSafe(r.getMeta().getActualKeyUsed()));
System.out.println("Algorithm : " + nullSafe(r.getMeta().getAlgorithmUsed()));
printWarnings(r.getMeta().getWarnings());
}
private static void printWarnings(final List<String> warnings) {
if (warnings != null && !warnings.isEmpty()) {
System.out.println("Warnings :");
warnings.forEach(w -> System.out.println(" * " + w));
}
}
private static String nullSafe(final String s) {
return (s == null || s.isBlank()) ? "(none)" : s;
}
/** Logs a fatal error and terminates the JVM. */
private static void fatal(final String msg, final Throwable t) {
System.err.println(msg);
if (t != null) {
t.printStackTrace(System.err);
}
System.exit(1);
}
/** Utility class – no instantiation. */
private ExampleScenario20() { /* no-instantiation */ }
}
How to run
Console milestones
-
HQC-128 & SLH-DSA-128S keys generated in RAM
-
Compact-JWE produced (string length printed)
-
Decryption returns original UTF-8 text
-
Compact-JWS produced and verified (valid = true)
-
SUCCESS -- decrypted plaintext matches original
Where next?
© 2025 Anka Technologies. All rights reserved.