Flow 27 – Key Lifecycle Management with Revocation
Demonstrates the lifecycle of a cryptographic key from creation through active use, monitoring, and revocation. This is critical for security operations, compliance scenarios, and handling compromised keys.
Key Lifecycle States:
- ACTIVE: Key can be used for cryptographic operations
- REVOKED: Key is marked as untrusted, operations fail immediately
Why Revocation?
- Security incident: Key suspected or confirmed as compromised
- Audit trail: Preserve key metadata for compliance and forensics
- Immediate blocking: All operations fail instantly after revocation
- Non-reversible: Once revoked, key cannot be reactivated
Steps:
- Generate ML-KEM-512 key with lifecycle constraints (expiry: +1h, max usage: 10)
- Export and display initial metadata (status: ACTIVE, usageCount: 0)
- Verify key is usable (test encryption)
- Perform 5 cryptographic operations (track usage)
- Export mid-lifecycle metadata (usageCount: 5)
- Perform 4 more operations (total: 9, approaching limit)
- Revoke key (mark as untrusted)
- Verify operations fail after revocation (expect HTTP 409/403)
- Export final metadata (status: REVOKED, metadata preserved for audit)
Compliance Notes:
- Audit requirements: Revoked keys maintain metadata for forensics and compliance
- Security incident response: Immediate revocation blocks all operations
- Key rotation: Revoke old key when rotating to new key
- Non-repudiation: Preserved metadata ensures accountability
API Endpoints:
- POST
/api/key-management/keys(generate key with constraints) - GET
/api/migration/keys/{kid}(export metadata) - POST
/api/crypto/encrypt(test operations) - POST
/api/key-management/keys/{kid}/actions/revoke(revoke key)
When to use:
- Security incident response: immediately block compromised keys
- Compliance requirements: audit trail of key lifecycle events
- Key rotation workflows: revoke old key when activating new key
- Testing revocation enforcement in application logic
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
Source: src/main/java/co/ankatech/ankasecure/sdk/examples/ExampleScenario27.java
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.EncryptResult;
import co.ankatech.ankasecure.sdk.model.ExportedKeySpec;
import co.ankatech.ankasecure.sdk.model.GenerateKeySpec;
import java.nio.charset.StandardCharsets;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Properties;
import static co.ankatech.ankasecure.sdk.examples.ExampleUtil.*;
/**
* <h2>Scenario 27: Key Lifecycle Management with Revocation</h2>
* <p>
* Demonstrates the lifecycle of a cryptographic key from creation through active use,
* monitoring, and revocation. This is critical for security operations, compliance
* scenarios, and handling compromised keys.
* </p>
*
* <h3>Key Lifecycle States:</h3>
* <ul>
* <li><strong>ACTIVE:</strong> Key can be used for cryptographic operations</li>
* <li><strong>REVOKED:</strong> Key is marked as untrusted, operations fail immediately</li>
* </ul>
*
* <h3>Why Revocation?</h3>
* <ul>
* <li><strong>Security incident:</strong> Key suspected or confirmed as compromised</li>
* <li><strong>Audit trail:</strong> Preserve key metadata for compliance and forensics</li>
* <li><strong>Immediate blocking:</strong> All operations fail instantly after revocation</li>
* <li><strong>Non-reversible:</strong> Once revoked, key cannot be reactivated</li>
* </ul>
*
* <h3>Steps:</h3>
* <ol>
* <li>Generate ML-KEM-512 key with lifecycle constraints (expiry: +1h, max usage: 10)</li>
* <li>Export and display initial metadata (status: ACTIVE, usageCount: 0)</li>
* <li>Verify key is usable (test encryption)</li>
* <li>Perform 5 cryptographic operations (track usage)</li>
* <li>Export mid-lifecycle metadata (usageCount: 5)</li>
* <li>Perform 4 more operations (total: 9, approaching limit)</li>
* <li>Revoke key (mark as untrusted)</li>
* <li>Verify operations fail after revocation (expect HTTP 409/403)</li>
* <li>Export final metadata (status: REVOKED, metadata preserved for audit)</li>
* </ol>
*
* <h3>Compliance Notes:</h3>
* <ul>
* <li><strong>Audit requirements:</strong> Revoked keys maintain metadata for forensics and compliance</li>
* <li><strong>Security incident response:</strong> Immediate revocation blocks all operations</li>
* <li><strong>Key rotation:</strong> Revoke old key when rotating to new key</li>
* <li><strong>Non-repudiation:</strong> Preserved metadata ensures accountability</li>
* </ul>
*
* <h3>API Endpoints:</h3>
* <ul>
* <li>POST /api/key-management/keys (generate key with constraints)</li>
* <li>GET /api/migration/keys/{kid} (export metadata)</li>
* <li>POST /api/crypto/encrypt (test operations)</li>
* <li>POST /api/key-management/keys/{kid}/actions/revoke (revoke key)</li>
* </ul>
*
* @since 3.0.0
*/
public final class ExampleScenario27 {
private ExampleScenario27() {
/* static only */
}
public static void main(String[] args) {
System.out.println("===== SCENARIO 27: KEY LIFECYCLE MANAGEMENT WITH REVOCATION =====");
System.out.println("Purpose: Demonstrate key lifecycle from creation through revocation");
System.out.println("States: ACTIVE → REVOKED");
System.out.println();
try {
Properties props = loadProperties();
AnkaSecureSdk sdk = authenticate(props);
runScenario(sdk);
System.out.println("===== SCENARIO 27 END =====");
} catch (Exception ex) {
fatal("Scenario 27 failed", ex);
}
}
private static void runScenario(AnkaSecureSdk sdk) throws Exception {
// ============================================================
// PHASE 1: Key Creation and Initial State
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 1: KEY CREATION AND INITIAL STATE ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
String kid = createKeyWithConstraints(sdk);
verifyInitialState(sdk, kid);
// ============================================================
// PHASE 2: Key Usage and Monitoring
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 2: KEY USAGE AND MONITORING ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
performOperations(sdk, kid, 5);
checkMidLifecycleState(sdk, kid);
performOperations(sdk, kid, 4); // Total: 9
// ============================================================
// PHASE 3: Key Revocation
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ PHASE 3: KEY REVOCATION ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
System.out.println();
revokeAndVerify(sdk, kid);
// ============================================================
// FINAL STATUS
// ============================================================
System.out.println("╔═══════════════════════════════════════════════════════════════╗");
System.out.println("║ ✅ SCENARIO 27 SUCCESSFUL ║");
System.out.println("║ ║");
System.out.println("║ Key lifecycle with revocation demonstrated: ║");
System.out.println("║ • Creation: Key generated with usage constraints ║");
System.out.println("║ • Active use: 9 operations performed successfully ║");
System.out.println("║ • Monitoring: Usage tracking verified at each stage ║");
System.out.println("║ • Revocation: Key marked untrusted, operations blocked ║");
System.out.println("║ • Audit trail: Metadata preserved for compliance ║");
System.out.println("║ ║");
System.out.println("║ Lifecycle: ACTIVE → REVOKED (metadata preserved) ║");
System.out.println("╚═══════════════════════════════════════════════════════════════╝");
}
/**
* Creates a key with lifecycle constraints.
*/
private static String createKeyWithConstraints(AnkaSecureSdk sdk) throws Exception {
System.out.println("[Step 1/9] Generating ML-KEM-512 key with lifecycle constraints...");
String kid = "sc27_lifecycle_kem512_" + System.currentTimeMillis();
sdk.generateKey(new GenerateKeySpec()
.setKid(kid)
.setKty("ML-KEM")
.setAlg("ML-KEM-512")
.setKeyOps(List.of("encrypt", "decrypt"))
.setExpiresAt(ZonedDateTime.now().plus(1, ChronoUnit.HOURS))
.setMaxUsageLimit(10));
System.out.println(" Key ID: " + kid);
System.out.println(" Constraints:");
System.out.println(" • Expiry: +1 hour from now");
System.out.println(" • Max usage: 10 operations");
System.out.println();
return kid;
}
/**
* Verifies initial key state.
*/
private static void verifyInitialState(AnkaSecureSdk sdk, String kid) throws Exception {
System.out.println("[Step 2/9] Exporting initial metadata...");
ExportedKeySpec initialMeta = sdk.exportKey(kid);
System.out.println(" Status: " + initialMeta.getStatus());
System.out.println(" Usage count: " + initialMeta.getUsageCount() + " / 10");
System.out.println();
System.out.println("[Step 3/9] Verifying key is usable...");
byte[] testData = "Test payload".getBytes(StandardCharsets.UTF_8);
EncryptResult encRes = sdk.encrypt(kid, testData);
sdk.decrypt(encRes.getJweToken());
System.out.println(" ✅ Key is ACTIVE and usable");
System.out.println();
}
/**
* Performs multiple cryptographic operations.
*/
private static void performOperations(AnkaSecureSdk sdk, String kid, int count) throws Exception {
System.out.println("[Step 4/6] Performing " + count + " cryptographic operations...");
for (int i = 1; i <= count; i++) {
byte[] payload = ("Operation payload " + i).getBytes(StandardCharsets.UTF_8);
sdk.encrypt(kid, payload);
System.out.println(" Operation " + i + " completed");
}
System.out.println();
}
/**
* Checks mid-lifecycle state.
*/
private static void checkMidLifecycleState(AnkaSecureSdk sdk, String kid) throws Exception {
System.out.println("[Step 5/9] Exporting mid-lifecycle metadata...");
ExportedKeySpec midMeta = sdk.exportKey(kid);
System.out.println(" Status: " + midMeta.getStatus());
System.out.println(" Usage count: " + midMeta.getUsageCount() + " / 10");
System.out.println(" Remaining operations: " + (10 - midMeta.getUsageCount()));
System.out.println();
}
/**
* Revokes key and verifies operations fail.
*/
private static void revokeAndVerify(AnkaSecureSdk sdk, String kid) throws Exception {
System.out.println("[Step 7/9] Revoking key...");
sdk.revokeKey(kid);
System.out.println(" ✅ Key revoked");
System.out.println(" Status changed: ACTIVE → REVOKED");
System.out.println();
System.out.println("[Step 8/9] Verifying operations fail after revocation...");
byte[] testData = "Test after revocation".getBytes(StandardCharsets.UTF_8);
try {
sdk.encrypt(kid, testData);
System.out.println(" ❌ ERROR: Revoked key was accepted!");
throw new RuntimeException("Revoked key should not be usable");
} catch (AnkaSecureSdkException ex) {
int httpStatus = ex.getHttpStatus();
System.out.println(" ✅ Confirmed: Operation rejected (HTTP " + httpStatus + ")");
System.out.println(" Revoked key correctly blocked from use");
}
System.out.println();
System.out.println("[Step 9/9] Exporting final metadata (audit trail)...");
ExportedKeySpec finalMeta = sdk.exportKey(kid);
System.out.println(" Status: " + finalMeta.getStatus() + " (revoked)");
System.out.println(" Usage count: " + finalMeta.getUsageCount() + " (frozen)");
System.out.println(" ✅ Metadata preserved for audit and compliance");
System.out.println(" Note: Revoked keys maintain metadata for forensics");
System.out.println();
}
}
Running This Example
# Compile
javac -cp "ankasecure-sdk-3.0.0.jar:." ExampleScenario27.java
# Run
java -cp "ankasecure-sdk-3.0.0.jar:." co.ankatech.ankasecure.sdk.examples.ExampleScenario27
Expected Output:
===== SCENARIO 27: KEY LIFECYCLE MANAGEMENT WITH REVOCATION =====
Purpose: Demonstrate key lifecycle from creation through revocation
States: ACTIVE → REVOKED
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 1: KEY CREATION AND INITIAL STATE ║
╚═══════════════════════════════════════════════════════════════╝
[Step 1/9] Generating ML-KEM-512 key with lifecycle constraints...
Key ID: sc27_lifecycle_kem512_1735152000000
Constraints:
• Expiry: +1 hour from now
• Max usage: 10 operations
[Step 2/9] Exporting initial metadata...
Status: ACTIVE
Usage count: 0 / 10
[Step 3/9] Verifying key is usable...
✅ Key is ACTIVE and usable
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 2: KEY USAGE AND MONITORING ║
╚═══════════════════════════════════════════════════════════════╝
[Step 4/6] Performing 5 cryptographic operations...
Operation 1 completed
Operation 2 completed
Operation 3 completed
Operation 4 completed
Operation 5 completed
[Step 5/9] Exporting mid-lifecycle metadata...
Status: ACTIVE
Usage count: 5 / 10
Remaining operations: 5
[Step 4/6] Performing 4 cryptographic operations...
Operation 1 completed
Operation 2 completed
Operation 3 completed
Operation 4 completed
╔═══════════════════════════════════════════════════════════════╗
║ PHASE 3: KEY REVOCATION ║
╚═══════════════════════════════════════════════════════════════╝
[Step 7/9] Revoking key...
✅ Key revoked
Status changed: ACTIVE → REVOKED
[Step 8/9] Verifying operations fail after revocation...
✅ Confirmed: Operation rejected (HTTP 422)
Revoked key correctly blocked from use
[Step 9/9] Exporting final metadata (audit trail)...
Status: REVOKED (revoked)
Usage count: 9 (frozen)
✅ Metadata preserved for audit and compliance
Note: Revoked keys maintain metadata for forensics
╔═══════════════════════════════════════════════════════════════╗
║ ✅ SCENARIO 27 SUCCESSFUL ║
║ ║
║ Key lifecycle with revocation demonstrated: ║
║ • Creation: Key generated with usage constraints ║
║ • Active use: 9 operations performed successfully ║
║ • Monitoring: Usage tracking verified at each stage ║
║ • Revocation: Key marked untrusted, operations blocked ║
║ • Audit trail: Metadata preserved for compliance ║
║ ║
║ Lifecycle: ACTIVE → REVOKED (metadata preserved) ║
╚═══════════════════════════════════════════════════════════════╝
===== SCENARIO 27 END =====
Key Concepts
Key Lifecycle Management
Keys in AnkaSecure follow a defined lifecycle:
States: - ACTIVE: Key can perform cryptographic operations - REVOKED: Key is blocked, operations return HTTP 422 (Invalid Key State)
Metadata Preservation:
Even after revocation, key metadata is preserved for: - Forensic analysis - Compliance auditing - Incident response documentation - Non-repudiation requirements
Usage Tracking:
AnkaSecure tracks:
- Total operation count (usageCount)
- Last used timestamp (lastUsedAt)
- Remaining operations before soft/hard limit
Revocation Enforcement
When a key is revoked:
- Immediate blocking: All operations fail with HTTP 422
- Non-reversible: Cannot change status back to ACTIVE
- Metadata frozen: Usage count and timestamps preserved
- Audit trail: Full lifecycle history maintained
Compliance Use Cases
- SOC 2: Demonstrate key lifecycle controls and immediate revocation capability
- GDPR: Right to erasure - revoke keys associated with deleted user data
- PCI-DSS: Key rotation requirements and compromised key response
- HIPAA: Audit trail of cryptographic key management