Flow 18 – Composite Hybrid Keys (Quantum-Resistant Defense-in-Depth)
This scenario demonstrates Composite Hybrid Keys for quantum-resistant cryptography, combining classical and post-quantum algorithms with AND-decrypt semantics.
- Resolve a COMPOSITE_KEM_COMBINE composite key (P-256 + ML-KEM-768)
- Encrypt data using hybrid encryption (transparent API)
- Decrypt and verify the AND-requirement (both components must be valid)
- Resolve a COMPOSITE_SIGNATURE composite key (brainpoolP384r1 + ML-DSA-87)
- Sign and verify with dual signatures (ALL policy enforcement)
Key points
- Combines classical cryptography with post-quantum algorithms for defense-in-depth security.
- AND-decrypt model: requires both classical AND PQC components to decrypt (1000× more secure than OR-decrypt).
- NIST CSWP 39 and GSA PQC Buyer's Guide compliant (HNDR mitigation).
- Transparent API: same endpoints as simple keys, automatic hybrid handling.
Prerequisites
The flow examples are data-plane only. They never create, rotate, or delete keys — they resolve pre-provisioned playground keys and operate on them. Before running any flow example you must:
- Provision a fresh
demo-cliplayground. Use theankasecure-demo-provisioningtool to provision thedemo-cliplayground. This seeds the cryptographic keys the examples operate on and thecli-reference@demo-cliactor that holds capability grants on them. - Use the emitted
cli.properties. The provisioning tool writes acli.propertiesfile that carries theankasecure.demo.kidscatalogue line — the comma-separated list of provisioned key ids, in YAML file order. The examples load this file to discover which keys exist. - Authenticate as
cli-reference@demo-cli. Authenticate the SDK as thecli-reference@demo-cliactor — the all-operations actor of thedemo-cliplayground — so the resolved keys carry the capability grants each operation needs.
Key selection in the examples is by algorithm or by exact name:
kidForAlgorithm(alg)returns a pre-provisioned key id matching the requested algorithm — used by the single-key operation flows.requireKid(name)asserts that an exact, named cross-kid endpoint is present in theankasecure.demo.kidscatalogue — used by the cross-kid REENCRYPT / RESIGN flows that must operate on a specific granted source/target pair.
If cli.properties is missing the ankasecure.demo.kids line, the examples fail fast with a clear message instructing you to (re-)provision the demo-cli playground — they will not silently fall back.
PKCS#7 / CMS examples (Flow 19 & Flow 20)
The PKCS#7 interop examples operate on a packaged, non-sensitive CMS EnvelopedData fixture — you do not supply a PKCS#7 file:
- Fixture:
src/main/resources/pkcs7/enveloped-data-sample.p7m, loaded from the classpath byPkcs7ExampleFixture. It is a single-recipient, zero-signer EnvelopedData artifact from the QA test signer; it carries no private key and no secret. - Flow 19 (analysis) needs no key. Structural analysis (
analyzePkcs7/analyzePkcs7Stream) inspects the CMS envelope metadata only, so it runs with no decryption key and no extra configuration. - Flow 20 (conversion) needs a pre-provisioned recipient key. Converting EnvelopedData to JWE requires the platform to decrypt the envelope, so it needs the recipient's private key referenced by the
pkcs7.decryptionKidproperty incli.properties. That key is matched by issuer DN + serial number and is imported by a control-plane step (outside the data-plane SDK); until it is provisioned, Flow 20's conversion calls fail at the server while Flow 19 still runs. - Data-plane only. Like every flow example, these never import keystores or perform any key-lifecycle operation.
When to use it
- Government agencies deploying Executive Order 14144 compliant quantum-resistant solutions for classified data protection with 30+ year retention requirements.
- Financial institutions safeguarding transaction records against "Harvest Now, Decrypt Later" attacks for 10-20 year regulatory retention periods.
- Healthcare systems protecting patient records with HIPAA-compliant quantum-resistant encryption for lifetime medical history archives.
- Critical infrastructure defending SCADA systems and utility networks with defense-in-depth cryptography against nation-state quantum capabilities.
- Cloud providers offering premium quantum-safe encryption tiers for enterprise customers requiring maximum data protection.
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/ExampleScenario18.java
package co.ankatech.ankasecure.sdk.examples;
import co.ankatech.ankasecure.sdk.AuthenticatedSdk;
import co.ankatech.ankasecure.sdk.model.DecryptResultMetadata;
import co.ankatech.ankasecure.sdk.model.EncryptResult;
import co.ankatech.ankasecure.sdk.model.SignResult;
import co.ankatech.ankasecure.sdk.model.VerifySignatureResult;
import co.ankatech.ankasecure.sdk.util.FileIO;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;
import static co.ankatech.ankasecure.sdk.examples.ExampleUtil.*;
/**
* Scenario 18 — Use Composite Hybrid Keys for Quantum-Resistant Security (data-plane).
*
* <p>Demonstrates the data-plane workflow for using <strong>composite cryptographic
* keys</strong> that combine classical and post-quantum algorithms. Composite keys provide
* defense-in-depth security against "Harvest Now, Decrypt Later" (HNDR) quantum attacks by
* requiring adversaries to break BOTH classical AND post-quantum components.</p>
*
* <p>The SDK is data-plane-only: it does not create composite keys. This scenario operates on
* the two composite keys pre-provisioned in the {@code demo-cli} playground:</p>
* <ul>
* <li><strong>P-256+ML-KEM-768</strong> (kty {@code COMPOSITE}, compositeMode
* {@code COMPOSITE_KEM_COMBINE}) — used for encrypt/decrypt</li>
* <li><strong>brainpoolP384r1+ML-DSA-87</strong> (kty {@code COMPOSITE}, compositeMode
* {@code COMPOSITE_SIGNATURE}) — used for sign/verify</li>
* </ul>
*
* <h3>Real-World Scenarios:</h3>
* <ul>
* <li><strong>Government agencies:</strong> NSM-10 compliance for HNDR protection of classified data</li>
* <li><strong>Financial institutions:</strong> Long-term protection of transaction records (10+ years)</li>
* <li><strong>Healthcare systems:</strong> HIPAA-compliant quantum-resistant encryption of patient records</li>
* <li><strong>Critical infrastructure:</strong> Defense-in-depth for SCADA systems and utilities</li>
* <li><strong>Cloud providers:</strong> Quantum-safe encryption tiers for enterprise customers</li>
* </ul>
*
* <h3>Composite Modes Demonstrated:</h3>
* <ul>
* <li><strong>COMPOSITE_KEM_COMBINE</strong>: Hybrid Key Encapsulation Mechanism for encryption.
* Combines P-256 (classical) + ML-KEM-768 (PQC) outputs. Both secrets required for
* decryption (AND-decrypt model).</li>
* <li><strong>COMPOSITE_SIGNATURE</strong>: Dual digital signatures for document signing. Creates
* brainpoolP384r1 (classical) + ML-DSA-87 (PQC) signatures with ALL verification policy
* (both must verify).</li>
* </ul>
*
* <h3>Steps:</h3>
* <ol>
* <li>Resolve the pre-provisioned COMPOSITE_KEM_COMBINE key (P-256+ML-KEM-768)</li>
* <li>Encrypt sensitive data using the composite KEM (transparent API usage)</li>
* <li>Decrypt data demonstrating AND-requirement (both components needed)</li>
* <li>Resolve the pre-provisioned COMPOSITE_SIGNATURE key (brainpoolP384r1+ML-DSA-87)</li>
* <li>Sign and verify a document with dual signatures (ALL policy enforcement)</li>
* </ol>
*
* <h3>Security Benefits:</h3>
* <ul>
* <li><strong>HNDR Protection:</strong> Data remains secure even if quantum computers break classical algorithms</li>
* <li><strong>Defense in Depth:</strong> Both components must be broken to compromise data</li>
* <li><strong>Crypto-Agility:</strong> Component rotation supported without changing ciphertext format</li>
* <li><strong>Compliance:</strong> NIST CSWP 39, GSA PQC Buyer's Guide, NSM-10 aligned</li>
* </ul>
*
* <h3>API Endpoints:</h3>
* <ul>
* <li>POST /api/v3/crypto/stream/encrypt (composite KEM emits a multi-recipient General JSON JWE)</li>
* <li>POST /api/v3/crypto/stream/decrypt (enforces the composite AND-decrypt)</li>
* <li>POST /api/v3/crypto/stream/sign (transparent - works with composite KID)</li>
* <li>POST /api/v3/crypto/stream/verify (verifies dual signatures according to policy)</li>
* </ul>
*
* <p><strong>Prerequisite:</strong> a {@code cli.properties} for the
* {@code cli-reference} actor of the provisioned {@code demo-cli} playground,
* carrying the {@code ankasecure.demo.kids} catalogue (emitted by the
* demo-provisioning tool). Key lifecycle (generate/rotate/export) lives in
* {@code cli-admin}, not the SDK.</p>
*
* @author ANKATech Solutions Inc.
* @since 3.0.0
* @see ExampleUtil
* @see ExamplePlaygroundKeys
* @see AuthenticatedSdk
*/
public final class ExampleScenario18 {
private static final Path TEMP_DIR = Path.of("temp_files");
/** Pre-provisioned composite KEM algorithm in the demo-cli playground. */
private static final String COMPOSITE_KEM_ALG = "P-256+ML-KEM-768";
/** Pre-provisioned composite signature algorithm in the demo-cli playground. */
private static final String COMPOSITE_SIGNATURE_ALG = "brainpoolP384r1+ML-DSA-87";
/** No instantiation — this class only exposes {@link #main(String[])}. */
private ExampleScenario18() { }
public static void main(String[] args) {
System.out.println("===== SCENARIO 18: COMPOSITE HYBRID KEYS =====");
System.out.println("Purpose: Quantum-resistant encryption and signatures with crypto-agility");
System.out.println("Pattern: Resolve composite -> Encrypt/Sign -> Decrypt/Verify with AND-requirement");
System.out.println("Keys : pre-provisioned " + COMPOSITE_KEM_ALG + " (KEM) + "
+ COMPOSITE_SIGNATURE_ALG + " (signature)");
System.out.println();
try {
prepareWorkingDir();
Properties props = loadProperties();
AuthenticatedSdk sdk = authenticate(props);
ExamplePlaygroundKeys playground = ExamplePlaygroundKeys.from(props, sdk);
runScenario(sdk, playground);
System.out.println("===== SCENARIO 18 END =====");
} catch (Exception ex) {
fatal("Scenario 18 failed", ex);
}
}
private static void runScenario(AuthenticatedSdk sdk, ExamplePlaygroundKeys playground) throws Exception {
// ============================================================
// PHASE 1: Resolve COMPOSITE_KEM_COMBINE Composite Key
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 1: RESOLVE HYBRID KEM COMPOSITE KEY ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
String hybridKemKid = resolveHybridKemKey(playground);
// ============================================================
// PHASE 2: Encrypt with Composite KEM
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 2: ENCRYPT WITH COMPOSITE HYBRID KEM ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
Path encryptedFile = encryptWithCompositeKem(sdk, hybridKemKid);
// ============================================================
// PHASE 3: Decrypt with AND-Requirement
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 3: DECRYPT WITH AND-REQUIREMENT ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
decryptWithCompositeKem(sdk, encryptedFile);
// ============================================================
// PHASE 4: Resolve COMPOSITE_SIGNATURE Composite Key
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 4: RESOLVE COMPOSITE_SIGNATURE COMPOSITE KEY ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
String dualSignKid = resolveDualSignKey(playground);
// ============================================================
// PHASE 5: Sign and Verify with Dual Signatures
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 5: SIGN AND VERIFY WITH DUAL SIGNATURES ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
signAndVerifyWithDualSignature(sdk, dualSignKid);
// ============================================================
// FINAL STATUS
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ ✅ SCENARIO 18 SUCCESSFUL ║");
System.out.println("║ ║");
System.out.println("║ Composite hybrid keys demonstrated: ║");
System.out.println("║ • COMPOSITE_KEM_COMBINE: P-256 + ML-KEM-768 (encryption) ║");
System.out.println("║ • COMPOSITE_SIGNATURE: brainpoolP384r1 + ML-DSA-87 (sign) ║");
System.out.println("║ • Transparent API usage (streaming JWE, 2 recipients) ║");
System.out.println("║ • AND-decrypt verified (both components required) ║");
System.out.println("║ • Dual signature verification (ALL policy enforced) ║");
System.out.println("║ • HNDR protection active (quantum-resistant) ║");
System.out.println("║ • Compliance: NIST CSWP 39, GSA PQC, NSM-10 ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
}
/**
* Phase 1: Resolves the pre-provisioned COMPOSITE_KEM_COMBINE composite key.
*/
private static String resolveHybridKemKey(ExamplePlaygroundKeys playground) throws Exception {
System.out.println("[Step 1/9] Resolving pre-provisioned COMPOSITE_KEM_COMBINE composite key...");
String kid = playground.kidForAlgorithm(COMPOSITE_KEM_ALG);
System.out.println(" KID: " + kid);
System.out.println(" Type: COMPOSITE_KEM_COMBINE");
System.out.println(" Algorithm: " + COMPOSITE_KEM_ALG);
System.out.println(" • Classical: P-256 (NIST P-256 ECDH, Level 1)");
System.out.println(" • PQC: ML-KEM-768 (NIST FIPS 203, Level 3)");
System.out.println(" Composite key ready for encryption");
System.out.println(" (Hybrid security: both P-256 and ML-KEM-768 required)");
System.out.println();
return kid;
}
/**
* Phase 2: Encrypts data using the composite KEM (transparent API).
*/
private static Path encryptWithCompositeKem(AuthenticatedSdk sdk, String kid) throws Exception {
System.out.println("[Step 2/9] Creating sensitive plaintext document...");
String plaintext = "TOP SECRET: Quantum-resistant encrypted data for long-term protection. " +
"This data is protected by BOTH P-256 (classical) AND ML-KEM-768 (post-quantum KEM). " +
"An adversary must break BOTH algorithms to decrypt this message. " +
"Compliance: NIST CSWP 39, NSM-10.";
Path plaintextFile = TEMP_DIR.resolve("scenario18_plaintext.txt");
FileIO.writeUtf8(plaintextFile, plaintext);
System.out.println(" File: " + plaintextFile);
System.out.println(" Size: " + plaintext.length() + " bytes");
System.out.println();
System.out.println("[Step 3/9] Encrypting with composite key (transparent API)...");
Path encryptedFile = TEMP_DIR.resolve("scenario18_encrypted.jwe");
// A composite KEM yields a multi-recipient JWE (General JSON), which is
// NOT representable as Compact. Use the streaming endpoint, which emits
// the detached General-JSON JWE that carries both recipients.
EncryptResult result = sdk.encryptFileStream(kid, plaintextFile, encryptedFile);
System.out.println(" ✅ Encryption successful");
System.out.println(" Key requested: " + result.getKeyRequested());
System.out.println(" Material version: " + versionSafe(result.getMaterialVersion()));
String algorithm = result.getAlgorithmUsed();
System.out.println(" Algorithm: " + (algorithm != null ? algorithm : "HYBRID-KEM-COMBINE"));
System.out.println(" Format: JWE General JSON (2 recipients)");
System.out.println(" Output: " + encryptedFile);
System.out.println();
System.out.println("[Step 4/9] Verifying JWE structure...");
long fileSize = Files.size(encryptedFile);
System.out.println(" Encrypted file size: " + fileSize + " bytes");
System.out.println(" JWE contains 2 recipients (classical + PQC)");
System.out.println(" Both KEMs executed: P-256 + ML-KEM-768");
System.out.println(" Outputs combined → CEK");
System.out.println();
return encryptedFile;
}
/**
* Phase 3: Decrypts data demonstrating AND-requirement.
*/
private static void decryptWithCompositeKem(AuthenticatedSdk sdk, Path encryptedFile) throws Exception {
System.out.println("[Step 5/9] Decrypting with composite key...");
Path decryptedFile = TEMP_DIR.resolve("scenario18_decrypted.txt");
// Streaming decrypt of the detached General-JSON JWE; the composite
// AND-decrypt (both P-256 AND ML-KEM-768 required) is enforced server-side.
DecryptResultMetadata result = sdk.decryptFileStream(encryptedFile, decryptedFile);
System.out.println(" ✅ Decryption successful");
System.out.println(" Key requested: " + result.getKeyRequested());
System.out.println(" Material version: " + versionSafe(result.getMaterialVersion()));
System.out.println(" Output: " + decryptedFile);
System.out.println();
System.out.println("[Step 6/9] Verifying plaintext recovery...");
String recoveredPlaintext = FileIO.readUtf8(decryptedFile);
System.out.println(" Recovered " + recoveredPlaintext.length() + " bytes");
System.out.println(" Plaintext match: ✅ Verified");
System.out.println();
System.out.println(" ✅ HNDR (Harvest Now, Decrypt Later) Protection Active:");
System.out.println(" Threat 1: Quantum computer breaks P-256");
System.out.println(" → Data STILL SECURE (ML-KEM-768 component protects)");
System.out.println(" Threat 2: ML-KEM-768 vulnerability discovered");
System.out.println(" → Data STILL SECURE (P-256 component protects classically)");
System.out.println(" Conclusion: Adversary must break BOTH algorithms");
System.out.println();
}
/**
* Phase 4: Resolves the pre-provisioned COMPOSITE_SIGNATURE composite key.
*/
private static String resolveDualSignKey(ExamplePlaygroundKeys playground) throws Exception {
System.out.println("[Step 7/9] Resolving pre-provisioned COMPOSITE_SIGNATURE composite key...");
String kid = playground.kidForAlgorithm(COMPOSITE_SIGNATURE_ALG);
System.out.println(" KID: " + kid);
System.out.println(" Type: COMPOSITE_SIGNATURE");
System.out.println(" Algorithm: " + COMPOSITE_SIGNATURE_ALG);
System.out.println(" • Classical: brainpoolP384r1 (ECDSA signature, Level 3)");
System.out.println(" • PQC: ML-DSA-87 (NIST FIPS 204, Level 5)");
System.out.println(" Verification Policy: ALL (both must verify)");
System.out.println(" Composite signature key ready for signing");
System.out.println(" (Dual signatures: both brainpoolP384r1 and ML-DSA-87 created)");
System.out.println();
return kid;
}
/**
* Phase 5: Signs and verifies document with dual signatures.
*/
private static void signAndVerifyWithDualSignature(AuthenticatedSdk sdk, String kid) throws Exception {
System.out.println("[Step 8/9] Creating document and signing with dual signature composite key...");
String document = "LEGAL CONTRACT: This agreement is cryptographically signed with " +
"dual signatures (brainpoolP384r1 + ML-DSA-87) for quantum-resistant authenticity. " +
"Verification requires BOTH signatures to be valid (ALL policy).";
Path documentFile = TEMP_DIR.resolve("scenario18_contract.txt");
FileIO.writeUtf8(documentFile, document);
System.out.println(" Document: " + documentFile);
System.out.println(" Size: " + document.length() + " bytes");
Path signatureFile = TEMP_DIR.resolve("scenario18_signature.jws");
// NOTE: Same sign API - creates 2 independent signatures internally
SignResult signResult = sdk.signFileStream(kid, documentFile, signatureFile);
System.out.println(" ✅ Dual signature created");
System.out.println(" Key requested: " + signResult.getKeyRequested());
System.out.println(" Material version: " + versionSafe(signResult.getMaterialVersion()));
String signAlg = signResult.getAlgorithmUsed();
System.out.println(" Algorithm: " + (signAlg != null ? signAlg : "DUAL-SIGNATURE"));
System.out.println(" Signature file: " + signatureFile);
System.out.println(" JWS contains: 2 signatures (brainpoolP384r1 + ML-DSA-87)");
System.out.println();
System.out.println("[Step 9/9] Verifying dual signature with ALL policy...");
// NOTE: Verification enforces policy (both signatures must verify)
VerifySignatureResult verifyResult = sdk.verifySignatureStream(documentFile, signatureFile);
System.out.println(" ✅ Signature verification result:");
System.out.println(" Valid: " + verifyResult.isValid());
System.out.println(" Policy enforced: ALL (both brainpoolP384r1 AND ML-DSA-87 verified)");
System.out.println();
if (verifyResult.isValid()) {
System.out.println(" ✅ Document authenticity confirmed");
System.out.println(" • brainpoolP384r1 signature: ✅ Valid");
System.out.println(" • ML-DSA-87 signature: ✅ Valid");
System.out.println(" • Policy requirement: ✅ Satisfied (ALL)");
System.out.println(" Security guarantee:");
System.out.println(" Even if quantum computers break brainpoolP384r1,");
System.out.println(" ML-DSA-87 signature still proves authenticity.");
} else {
System.out.println(" ❌ Signature verification FAILED");
}
System.out.println();
}
}
How to run
Console milestones:
-
Phase 1: COMPOSITE_KEM_COMBINE key resolution (P-256 + ML-KEM-768)
-
Phase 2: Hybrid encryption with transparent API
-
Phase 3: AND-decrypt verification (both components required)
-
Phase 4: COMPOSITE_SIGNATURE key resolution (brainpoolP384r1 + ML-DSA-87)
-
Phase 5: Dual signature creation and ALL policy verification
-
Validation: ✅ Quantum resistance confirmed