Flow 23 --- RSA-2048 → ML-KEM-768 Immediate Rotation
This scenario shows an in-place algorithm migration from a classical RSA-2048 key to a post-quantum ML-KEM-768 key with capability reduction acknowledgment. The key identifier (kid) is FIXED across rotation — rotation advances the key material to a new version under the same kid — and the same KID keeps working transparently:
-
Generate an RSA-2048 key capable of
encrypt/decrypt(also supportssign/verify). -
Rotate the key material to ML-KEM-768 in one API call (
rotateKey) with explicit acknowledgment that signing capabilities will be lost. The kid does not change. -
Encrypt a plaintext with the same KID and observe that the platform resolves it to the new
PRIMARYmaterial (ML-KEM-768).
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
acknowledgeCapabilityReduction = true.Zero downtime: the kid stays valid (and unchanged) while the cryptography is instantly upgraded.
The SDK's response reports the same kid and the algorithm now in effect (ML-KEM-768).
Works for any algorithm migration 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 the same identifiers alive.
-
Gradual roll-outs---encrypt new data with the new PRIMARY material while historical tokens continue to decrypt with the RETIRED material version.
-
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.secure.client.model.KeyRequest;
import co.ankatech.secure.client.model.RotationMaterialSpec;
import co.ankatech.ankasecure.sdk.model.KeyMetadata;
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 its material to ML-KEM-768.
* Demonstrate capability reduction handling (losing sign/verify).
* Encrypt with the same KID and observe the new PRIMARY material.
Steps :
1) Generate RSA-2048 key (supports: encrypt, decrypt, sign, verify)
2) Rotate material to ML-KEM-768 (supports: encrypt, decrypt only), kid unchanged
3) Encrypt plaintext using the same KID
--------------------------------------------------------------""");
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 KeyRequest()
.kid(RSA_KID)
.kty("RSA")
.alg("RSA-2048")
.keyOps(List.of("encrypt", "decrypt")));
System.out.println("[1] RSA-2048 key generated -> kid = " + RSA_KID);
/* 2 – rotate material to ML-KEM-768 (kid unchanged) ------------ */
KeyMetadata rotated = sdk.rotateKey(
RSA_KID,
new RotationMaterialSpec()
.kty("ML-KEM")
.alg("ML-KEM-768"),
true); // acknowledgeCapabilityReduction: RSA has sign/verify, ML-KEM does not
Objects.requireNonNull(rotated, "Rotation must return key metadata");
System.out.println("[2] Material rotated -> kid = " + rotated.getKid() + " (unchanged)");
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(" Material version : " + versionSafe(enc.getMaterialVersion()));
System.out.println(" Algorithm used : " + nullSafe(enc.getAlgorithmUsed()));
}
}
How to run
Console milestones
-
RSA-2048 key generated (supports: encrypt, decrypt, sign, verify)
-
Material rotated to ML-KEM-768 with capability reduction acknowledgment (
rotateKey); the kid is unchanged -
Capability reduction acknowledged: sign/verify operations removed
-
Encryption call uses the same KID — the platform resolves it to the new
PRIMARYmaterial -
Algorithm usedreportsML-KEM-768+...confirming the in-place PQC migration
Where next?
© 2025 ANKATech Solutions INC. All rights reserved.