Flow 23 --- RSA-2048 → ML-KEM-768 Immediate Rotation
This scenario shows an instant successor upgrade from a classical RSA-2048 key to a post-quantum ML-KEM-768 key with capability reduction acknowledgment and then proves that the old KID can still be used transparently:
-
Generate an RSA-2048 key capable of
encrypt/decrypt(also supportssign/verify). -
Create an ML-KEM-768 successor in one API call (
createRotation) with explicit acknowledgment that signing capabilities will be lost. -
Encrypt a plaintext with the original RSA KID and watch the platform silently redirect the request to the ML-KEM successor.
Key points
Capability Reduction Handling: RSA-2048 supports 4 operations (encrypt/decrypt/sign/verify), while ML-KEM-768 only supports 2 (encrypt/decrypt). The rotation requires explicit acknowledgment via
setAcknowledgeCapabilityReduction(true).Zero downtime: the old KID stays valid while cryptography is instantly upgraded.
The SDK's response reveals both the key you asked for and the successor actually used.
Works for any successor pair with or without capability reduction (P-384 → ML-KEM-768, RSA-3072 → FALCON-1024, ...).
Perfect fit for brown-field services that must migrate to PQC without touching client code.
When to use it
-
Regulatory cut-overs---move to quantum-safe algorithms overnight yet keep legacy identifiers alive.
-
Gradual roll-outs---encrypt new data with the successor while historical tokens continue to decrypt with the old key.
-
Secrets-rotation policies---rotate keys on schedule (or on compromise) without ever re-encrypting data client-side.
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/ExampleScenario23.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.AuthenticatedSdk;
import co.ankatech.ankasecure.sdk.exception.AnkaSecureSdkException;
import co.ankatech.ankasecure.sdk.model.EncryptResult;
import co.ankatech.ankasecure.sdk.model.GenerateKeySpec;
import co.ankatech.ankasecure.sdk.model.KeyGenerationSummarySpec;
import java.nio.file.Files;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import static co.ankatech.ankasecure.sdk.examples.ExampleUtil.*;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Scenario 23 — Key Rotation with Capability Reduction (RSA-2048 → ML-KEM-768).
*
* <p>This scenario demonstrates handling capability reduction when rotating from
* RSA (which supports encrypt/decrypt/sign/verify) to ML-KEM (which only
* supports encrypt/decrypt). The rotation requires explicit acknowledgment
* of the loss of signing capabilities.</p>
*
* @author ANKATech Solutions Inc.
* @since 3.0.0
* @see ExampleUtil
* @see AuthenticatedSdk
*/
public final class ExampleScenario23 {
private static final String RSA_KID =
"scenario23_rsa_" + System.currentTimeMillis();
/** No instantiation — this class only exposes {@link #main(String[])}. */
private ExampleScenario23() { }
/**
* Runs the key rotation with capability reduction scenario.
*
* <p>Loads CLI properties, authenticates against ANKASecure©,
* and delegates to the scenario logic. On any unrecoverable error
* the JVM terminates via
* {@link ExampleUtil#fatal(String, Throwable)}.</p>
*
* @param args command-line arguments (ignored)
*/
public static void main(String[] args) {
System.out.println("===== SCENARIO 23 START =====");
System.out.println("""
Purpose :
* Provision an RSA-2048 key and rotate it to ML-KEM-768.
* Demonstrate capability reduction handling (losing sign/verify).
* Encrypt with original KID and observe successor selection.
Steps :
1) Generate RSA-2048 key (supports: encrypt, decrypt, sign, verify)
2) Rotate to ML-KEM-768 successor (supports: encrypt, decrypt only)
3) Encrypt plaintext using rotated key
--------------------------------------------------------------""");
try {
Files.createDirectories(TEMP_DIR);
Properties props = loadProperties();
AuthenticatedSdk sdk = authenticate(props);
runScenario(sdk);
} catch (Exception ex) {
fatal("Scenario 23 failed", ex);
}
System.out.println("===== SCENARIO 23 END =====");
}
/* ====================================================================== */
private static void runScenario(AuthenticatedSdk sdk)
throws AnkaSecureSdkException {
/* 1 – RSA-2048 key ------------------------------------------------ */
sdk.generateKey(new GenerateKeySpec()
.setKid(RSA_KID)
.setKty("RSA")
.setAlg("RSA-2048")
.setKeyOps(List.of("encrypt", "decrypt")));
System.out.println("[1] RSA-2048 key generated -> kid = " + RSA_KID);
/* 2 – rotate to ML-KEM-768 ------------------------------------- */
String kemKid = "scenario23_mlkem_" + System.currentTimeMillis();
KeyGenerationSummarySpec successor = sdk.rotateKey(
RSA_KID,
new GenerateKeySpec()
.setKid(kemKid)
.setKty("ML-KEM")
.setAlg("ML-KEM-768")
.setAcknowledgeCapabilityReduction(true));
// RSA supports sign/verify, ML-KEM does not - acknowledging reduction
Objects.requireNonNull(successor, "Rotation must return successor metadata");
System.out.println("[2] Successor created -> kid = " + successor.getKid());
System.out.println(" Capability reduction acknowledged: sign/verify → (removed)");
/* 3 – encrypt with original KID -------------------------------- */
byte[] plaintext = "Post-rotation encryption demo".getBytes(UTF_8);
EncryptResult enc = sdk.encrypt(RSA_KID, plaintext);
System.out.println("[3] Encryption metadata");
System.out.println(" Key requested : " + nullSafe(enc.getKeyRequested()));
System.out.println(" Key used : " + nullSafe(enc.getActualKeyUsed()));
System.out.println(" Algorithm used : " + nullSafe(enc.getAlgorithmUsed()));
}
}
How to run
Console milestones
-
RSA-2048 key generated (supports: encrypt, decrypt, sign, verify)
-
ML-KEM-768 successor created with capability reduction acknowledgment (
createRotation) -
Capability reduction acknowledged: sign/verify operations removed
-
Encryption call shows Key requested = RSA KID but Key used = ML-KEM successor
-
Algorithm usedreportsML-KEM-768+...confirming PQC redirect
Where next?
© 2025 ANKATech Solutions INC. All rights reserved.