Flow 11 --- ML-DSA-87 Compact-JWS Sign / Verify (Non-Streaming)
This scenario walks through a post-quantum, non-streaming signature round-trip with an ML-DSA-87 key:
-
Generate an
ML-DSA-87
key-pair (kty="ML-DSA"
). -
Sign a document → compact JWS written as UTF-8 text.
-
Export the key's public metadata to a JSON file.
-
Verify the compact JWS.
-
Validate that the fresh signature is accepted by the server.
Key points
Uses
signFile( )
/verifySignature( )
helpers (entire token in memory).Demonstrates the Compact JWS format, easy to paste into logs or manifests.
Prints rich server metadata: key actually used, algorithm, policy warnings.
When to use it
-
Portable attestations --- compact-JWS strings are perfect for embedding in SBOMs, PDF manifests or CI artefacts without binary handling.
-
Post-quantum assurance --- ML-DSA-87 delivers NIST-selected signature security that survives future RSA/ECC compromises.
-
Quick auditing --- public-key JSON export lets auditors validate signatures offline or store public keys in catalogues.
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/ExampleScenario11.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
*/
/* *****************************************************************************
* FILE: ExampleScenario11.java
* ****************************************************************************/
package co.ankatech.ankasecure.sdk.examples;
import co.ankatech.ankasecure.sdk.AnkaSecureSdk;
import co.ankatech.ankasecure.sdk.model.GenerateKeySpec;
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.Path;
import java.text.MessageFormat;
import java.util.Properties;
import static co.ankatech.ankasecure.sdk.examples.ExampleUtil.*;
/**
* <h2>Scenario 11 – ML-DSA-87 Bulk Helpers (Compact JWS)</h2>
*
* <p>This scenario shows the <strong>non-streaming</strong> helper methods for
* RFC 7515 <em>Compact JWS</em> using an ML-DSA-87 key:</p>
* <ol>
* <li>Generate an <code>ML-DSA-87</code> key.</li>
* <li>Sign a plaintext document.</li>
* <li>Export the key’s public metadata.</li>
* <li>Verify the resulting JWS.</li>
* </ol>
*
* <p><b>Implementation notes (Java 21+):</b></p>
* <ul>
* <li>Filesystem operations use {@link java.nio.file.Path}.</li>
* <li>UTF-8 encoding is enforced for deterministic behaviour.</li>
* <li>Temporary artefacts reside under <kbd>temp_files/</kbd>.</li>
* </ul>
*
* <p><b>Thread-safety:</b> this class is stateless and immutable.</p>
*
* @author ANKATech – Security Engineering
* @since 2.1.0
*/
public final class ExampleScenario11 {
/* ====================================================================== */
/** Entry-point. */
public static void main(final String[] args) {
System.out.println("===== SCENARIO 11 START =====");
System.out.println("""
Purpose :
* Demonstrate Compact-JWS helpers with an ML-DSA-87 key
Steps :
1) Generate ML-DSA-87 key
2) Sign payload (compact JWS)
3) Export public metadata
4) Verify JWS and validate integrity
--------------------------------------------------------------""");
try {
ensureTempDir(TEMP_DIR);
Properties props = loadProperties();
AnkaSecureSdk sdk = authenticate(props);
runScenario(sdk);
} catch (Exception ex) {
fatal("Scenario 11 failed", ex);
}
System.out.println("===== SCENARIO 11 END =====");
}
/* ====================================================================== */
/**
* Executes Scenario 11.
*
* @param sdk an authenticated {@link AnkaSecureSdk} instance
* @throws Exception if any step fails
*/
private static void runScenario(final AnkaSecureSdk sdk) throws Exception {
Path docFile = TEMP_DIR.resolve("scenario11_doc.txt");
Path jwsFile = TEMP_DIR.resolve("scenario11.jws");
Path metaJson = TEMP_DIR.resolve("scenario11_keydata.json");
/* 1 ── create document --------------------------------------------- */
FileIO.writeUtf8(docFile,
"Scenario-11 – ML-DSA-87 non-streaming sign / verify demo.");
System.out.println("[1] Document ready -> " + docFile.toAbsolutePath());
/* 2 ── generate ML-DSA-87 key -------------------------------------- */
String kid = "sc11_dsa87_" + System.currentTimeMillis();
sdk.generateKey(new GenerateKeySpec()
.setKid(kid)
.setKty("ML-DSA")
.setAlg("ML-DSA-87"));
System.out.println("[2] Key generated -> kid = " + kid);
/* 3 ── sign document (compact JWS) --------------------------------- */
SignResult signMeta = sdk.signFile(kid, docFile, jwsFile);
System.out.println("[3] JWS written -> " + jwsFile.toAbsolutePath());
printSignMeta(signMeta);
/* 4 ── export key metadata ---------------------------------------- */
FileIO.writeUtf8(metaJson, toJson(sdk.exportKey(kid)));
System.out.println("[4] Metadata exported -> " + metaJson.toAbsolutePath());
/* 5 ── verify signature ------------------------------------------- */
VerifySignatureResult verMeta = sdk.verifySignature(jwsFile);
System.out.println(MessageFormat.format(
"[5] Signature valid? -> {0}", verMeta.isValid()));
printVerifyMeta(verMeta);
System.out.println(verMeta.isValid()
? "[6] SUCCESS – JWS verified."
: "[6] FAILURE – verification failed.");
}
/** Utility class – no instantiation. */
private ExampleScenario11() {
/* no-instantiation */
}
}
How to run
Console milestones
-
ML-DSA-87 key generation
-
Compact-JWS signing →
scenario11.jws
-
Key-metadata export →
scenario11_keydata.json
-
Signature verification → SUCCESS confirmation