Skip to content

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:

  1. Generate ML-KEM-512 key with lifecycle constraints (expiry: +1h, max usage: 10)
  2. Export and display initial metadata (status: ACTIVE, usageCount: 0)
  3. Verify key is usable (test encryption)
  4. Perform 5 cryptographic operations (track usage)
  5. Export mid-lifecycle metadata (usageCount: 5)
  6. Perform 4 more operations (total: 9, approaching limit)
  7. Revoke key (mark as untrusted)
  8. Verify operations fail after revocation (expect HTTP 409/403)
  9. 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:

  1. Immediate blocking: All operations fail with HTTP 422
  2. Non-reversible: Cannot change status back to ACTIVE
  3. Metadata frozen: Usage count and timestamps preserved
  4. 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

  • Flow 14 - Key Lifecycle Walkthrough (comprehensive demo)
  • Flow 17 - Immediate Key Rotation (rotation workflow)
  • Flow 18 - Dynamic Limit/Lifetime Patch (update constraints)
  • Flow 23 - RSA→ML-KEM Immediate Rotation (rotation with revocation)