This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch CAMEL-22522
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 587a554e9d80e6761027bf6b71407020c661e20a
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Oct 9 18:18:00 2025 +0200

    CAMEL-22522 - Camel-PQC: Add Hashicorp-vault lifecycle manager
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 components/camel-pqc/pom.xml                       |  15 +
 .../camel-pqc/src/main/docs/pqc-component.adoc     | 331 ++++++++++-
 .../HashicorpVaultKeyLifecycleManager.java         | 642 +++++++++++++++++++++
 .../pqc/HashicorpVaultKeyLifecycleIT.java          | 268 +++++++++
 4 files changed, 1255 insertions(+), 1 deletion(-)

diff --git a/components/camel-pqc/pom.xml b/components/camel-pqc/pom.xml
index 6dd24cfad661..e4d0cd581e15 100644
--- a/components/camel-pqc/pom.xml
+++ b/components/camel-pqc/pom.xml
@@ -46,6 +46,14 @@
             <version>${bouncycastle-version}</version>
         </dependency>
 
+        <!-- Spring Vault for HashicorpVaultKeyLifecycleManager (optional) -->
+        <dependency>
+            <groupId>org.springframework.vault</groupId>
+            <artifactId>spring-vault-core</artifactId>
+            <version>${spring-vault-core-version}</version>
+            <optional>true</optional>
+        </dependency>
+
         <!-- for testing -->
         <dependency>
             <groupId>org.apache.camel</groupId>
@@ -63,5 +71,12 @@
             <version>${bouncycastle-version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-hashicorp-vault</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/components/camel-pqc/src/main/docs/pqc-component.adoc 
b/components/camel-pqc/src/main/docs/pqc-component.adoc
index 8cb124ecb9d8..ae64dcce316d 100644
--- a/components/camel-pqc/src/main/docs/pqc-component.adoc
+++ b/components/camel-pqc/src/main/docs/pqc-component.adoc
@@ -408,7 +408,7 @@ The `KeyLifecycleManager` interface provides the following 
operations:
 
 === Available Implementations
 
-The component provides two implementations of `KeyLifecycleManager`:
+The component provides three implementations of `KeyLifecycleManager`:
 
 ==== FileBasedKeyLifecycleManager
 
@@ -476,6 +476,335 @@ KeyPair keyPair = keyManager.generateKeyPair("FALCON", 
"test-key");
 keyManager.clear();
 
--------------------------------------------------------------------------------
 
+==== HashicorpVaultKeyLifecycleManager
+
+An enterprise-grade implementation that integrates with HashiCorp Vault for 
centralized secret management.
+
+**Features:**
+
+* Centralized secret management via HashiCorp Vault
+* Automatic audit logging of all key operations
+* Fine-grained access control with Vault policies
+* Encryption at rest
+* High availability support (Vault HA clusters)
+* In-memory caching for performance
+* Uses Spring Vault (spring-vault-core) consistent with camel-hashicorp-vault
+
+**Use Cases:**
+
+* Production environments with existing Vault infrastructure
+* Multi-node/distributed deployments
+* Enterprise security and compliance requirements
+* Centralized key management across multiple applications
+* Audit and compliance mandates
+
+**Dependencies:**
+
+To use HashicorpVaultKeyLifecycleManager, add the following optional 
dependency:
+
+[source,xml]
+--------------------------------------------------------------------------------
+<dependency>
+    <groupId>org.springframework.vault</groupId>
+    <artifactId>spring-vault-core</artifactId>
+    <version>${spring-vault-core-version}</version>
+</dependency>
+--------------------------------------------------------------------------------
+
+**Example with VaultTemplate:**
+
+[source,java]
+--------------------------------------------------------------------------------
+// Option 1: Using existing VaultTemplate (recommended when using 
camel-hashicorp-vault)
+@BindToRegistry("vaultTemplate")
+public VaultTemplate createVaultTemplate() {
+    VaultEndpoint vaultEndpoint = new VaultEndpoint();
+    vaultEndpoint.setHost("localhost");
+    vaultEndpoint.setPort(8200);
+    vaultEndpoint.setScheme("https");
+
+    return new VaultTemplate(vaultEndpoint, new 
TokenAuthentication("s.token"));
+}
+
+@BindToRegistry("keyLifecycleManager")
+public HashicorpVaultKeyLifecycleManager createKeyManager() {
+    return new HashicorpVaultKeyLifecycleManager(
+        vaultTemplate,      // Reuse existing VaultTemplate
+        "secret",           // Secrets engine name
+        "pqc/keys"         // Key prefix in Vault
+    );
+}
+
+// Generate a Dilithium key stored in Vault
+KeyPair keyPair = keyManager.generateKeyPair("DILITHIUM", "app-signing-key",
+    DilithiumParameterSpec.dilithium2);
+
+// Key is stored in Vault at: secret/data/pqc/keys/app-signing-key
+--------------------------------------------------------------------------------
+
+**Example with Direct Configuration:**
+
+[source,java]
+--------------------------------------------------------------------------------
+// Option 2: Direct configuration with connection parameters
+HashicorpVaultKeyLifecycleManager keyManager =
+    new HashicorpVaultKeyLifecycleManager(
+        "vault.example.com",  // host
+        8200,                 // port
+        "https",              // scheme
+        "s.your-token",       // Vault token
+        "secret",             // secrets engine (optional, defaults to 
"secret")
+        "pqc/keys"           // key prefix (optional, defaults to "pqc/keys")
+    );
+
+// Generate and store key in Vault
+KeyPair keyPair = keyManager.generateKeyPair("DILITHIUM", "vault-key",
+    DilithiumParameterSpec.dilithium2);
+--------------------------------------------------------------------------------
+
+**Example with HashiCorp Cloud Platform (HCP) Vault:**
+
+[source,java]
+--------------------------------------------------------------------------------
+// Option 3: Configuration for HCP Vault with namespace
+HashicorpVaultKeyLifecycleManager keyManager =
+    new HashicorpVaultKeyLifecycleManager(
+        "your-cluster.vault.hashicorp.cloud",  // HCP Vault host
+        8200,                                    // port
+        "https",                                 // scheme
+        "s.your-hcp-token",                     // HCP Vault token
+        "secret",                                // secrets engine
+        "pqc/keys",                             // key prefix
+        true,                                    // cloud=true for HCP Vault
+        "admin"                                  // namespace (required for 
HCP)
+    );
+
+// Generate and store key in HCP Vault
+KeyPair keyPair = keyManager.generateKeyPair("DILITHIUM", "hcp-key",
+    DilithiumParameterSpec.dilithium2);
+
+// Key is stored in HCP Vault at: admin/secret/data/pqc/keys/hcp-key
+--------------------------------------------------------------------------------
+
+**YAML Configuration:**
+
+[source,yaml]
+--------------------------------------------------------------------------------
+camel:
+  beans:
+    # Create VaultTemplate
+    vaultEndpoint:
+      type: org.springframework.vault.client.VaultEndpoint
+      properties:
+        host: "vault.example.com"
+        port: 8200
+        scheme: "https"
+
+    tokenAuthentication:
+      type: org.springframework.vault.authentication.TokenAuthentication
+      constructorArgs:
+        - "${VAULT_TOKEN}"
+
+    vaultTemplate:
+      type: org.springframework.vault.core.VaultTemplate
+      constructorArgs:
+        - "#bean:vaultEndpoint"
+        - "#bean:tokenAuthentication"
+
+    # Create HashicorpVaultKeyLifecycleManager
+    keyLifecycleManager:
+      type: 
org.apache.camel.component.pqc.lifecycle.HashicorpVaultKeyLifecycleManager
+      constructorArgs:
+        - "#bean:vaultTemplate"
+        - "secret"
+        - "pqc/keys"
+        - false              # cloud
+        - null               # namespace
+--------------------------------------------------------------------------------
+
+**YAML Configuration for HCP Vault:**
+
+[source,yaml]
+--------------------------------------------------------------------------------
+camel:
+  beans:
+    # Create VaultTemplate for HCP
+    vaultEndpoint:
+      type: org.springframework.vault.client.VaultEndpoint
+      properties:
+        host: "your-cluster.vault.hashicorp.cloud"
+        port: 8200
+        scheme: "https"
+
+    tokenAuthentication:
+      type: org.springframework.vault.authentication.TokenAuthentication
+      constructorArgs:
+        - "${HCP_VAULT_TOKEN}"
+
+    vaultTemplate:
+      type: org.springframework.vault.core.VaultTemplate
+      constructorArgs:
+        - "#bean:vaultEndpoint"
+        - "#bean:tokenAuthentication"
+
+    # Create HashicorpVaultKeyLifecycleManager for HCP Vault
+    keyLifecycleManager:
+      type: 
org.apache.camel.component.pqc.lifecycle.HashicorpVaultKeyLifecycleManager
+      constructorArgs:
+        - "#bean:vaultTemplate"
+        - "secret"
+        - "pqc/keys"
+        - true               # cloud=true for HCP Vault
+        - "admin"            # namespace (required for HCP)
+--------------------------------------------------------------------------------
+
+**Vault Storage Structure:**
+
+Keys are stored in Vault's KV v2 secrets engine with the following structure:
+
+*On-Premise Vault:*
+
+[source,text]
+--------------------------------------------------------------------------------
+secret/                           # Secrets engine
+├── data/
+│   └── pqc/
+│       └── keys/
+│           ├── app-signing-key
+│           │   ├── keyPair           # Serialized KeyPair (Base64)
+│           │   ├── metadata          # Serialized KeyMetadata (Base64)
+│           │   ├── keyId             # Key identifier
+│           │   └── algorithm         # Algorithm name
+│           └── app-signing-key-v2
+└── metadata/
+    └── pqc/
+        └── keys/
+            ├── app-signing-key/      # Metadata entry
+            └── app-signing-key-v2/
+--------------------------------------------------------------------------------
+
+*HCP Vault (with namespace):*
+
+[source,text]
+--------------------------------------------------------------------------------
+admin/                            # Namespace
+└── secret/                       # Secrets engine
+    ├── data/
+    │   └── pqc/
+    │       └── keys/
+    │           ├── app-signing-key
+    │           └── app-signing-key-v2
+    └── metadata/
+        └── pqc/
+            └── keys/
+                ├── app-signing-key/
+                └── app-signing-key-v2/
+--------------------------------------------------------------------------------
+
+**Integration with camel-hashicorp-vault:**
+
+HashicorpVaultKeyLifecycleManager can share the same VaultTemplate with the 
camel-hashicorp-vault component:
+
+[source,java]
+--------------------------------------------------------------------------------
+// Reuse VaultTemplate from camel-hashicorp-vault
+@BindToRegistry("keyLifecycleManager")
+public HashicorpVaultKeyLifecycleManager createKeyManager() {
+    VaultTemplate vaultTemplate = context.getRegistry()
+        .lookupByNameAndType("vaultTemplate", VaultTemplate.class);
+
+    return new HashicorpVaultKeyLifecycleManager(
+        vaultTemplate,
+        "secret",
+        "pqc/keys"
+    );
+}
+--------------------------------------------------------------------------------
+
+**Vault Setup:**
+
+To use HashicorpVaultKeyLifecycleManager, configure Vault with appropriate 
policies:
+
+[source,bash]
+--------------------------------------------------------------------------------
+# Enable KV v2 secrets engine (usually enabled by default)
+vault secrets enable -path=secret kv-v2
+
+# Create policy for PQC key management
+cat > pqc-policy.hcl <<EOF
+path "secret/data/pqc/keys/*" {
+  capabilities = ["create", "read", "update", "delete", "list"]
+}
+
+path "secret/metadata/pqc/keys/*" {
+  capabilities = ["list", "read", "delete"]
+}
+EOF
+
+# Apply policy
+vault policy write pqc-keys pqc-policy.hcl
+
+# Create token with policy
+vault token create -policy=pqc-keys
+--------------------------------------------------------------------------------
+
+**Comparison of Implementations:**
+
+[options="header"]
+|===
+|Feature |FileBasedKeyLifecycleManager |InMemoryKeyLifecycleManager 
|HashicorpVaultKeyLifecycleManager
+
+|Persistence
+|✅ File system
+|❌ Memory only
+|✅ Vault backend
+
+|Distributed
+|❌ Single node
+|❌ Single node
+|✅ Multi-node
+
+|Audit Logging
+|❌ Manual
+|❌ None
+|✅ Automatic
+
+|Access Control
+|❌ File permissions
+|❌ None
+|✅ Vault policies
+
+|Encryption at Rest
+|❌ OS-dependent
+|❌ N/A
+|✅ Always
+
+|High Availability
+|❌ No
+|❌ No
+|✅ Yes (Vault HA)
+
+|External Dependencies
+|❌ None
+|❌ None
+|✅ Vault + spring-vault
+
+|Caching
+|✅ Yes
+|✅ Yes
+|✅ Yes
+
+|Spring Integration
+|❌ No
+|❌ No
+|✅ Yes
+
+|Use Case
+|Single server
+|Testing/Dev
+|Production/Enterprise
+|===
+
 === Key Generation
 
 The key lifecycle manager supports all PQC algorithms with sensible default 
parameter specifications.
diff --git 
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/HashicorpVaultKeyLifecycleManager.java
 
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/HashicorpVaultKeyLifecycleManager.java
new file mode 100644
index 000000000000..b607becbfad3
--- /dev/null
+++ 
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/lifecycle/HashicorpVaultKeyLifecycleManager.java
@@ -0,0 +1,642 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.component.pqc.lifecycle;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.camel.component.pqc.PQCKeyEncapsulationAlgorithms;
+import org.apache.camel.component.pqc.PQCSignatureAlgorithms;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.vault.authentication.TokenAuthentication;
+import org.springframework.vault.client.VaultEndpoint;
+import org.springframework.vault.core.VaultKeyValueOperations;
+import org.springframework.vault.core.VaultKeyValueOperationsSupport;
+import org.springframework.vault.core.VaultTemplate;
+import org.springframework.vault.support.VaultResponse;
+
+/**
+ * HashiCorp Vault-based implementation of KeyLifecycleManager using Spring 
Vault. Stores keys and metadata in Vault's
+ * KV secrets engine with centralized secret management, audit logging, and 
fine-grained access control.
+ *
+ * Features: - Centralized secret management via HashiCorp Vault - Automatic 
audit logging - Fine-grained access control
+ * with Vault policies - Encryption at rest - High availability support - 
In-memory caching for performance
+ *
+ * Configuration: - host: Vault server host (e.g., localhost) - port: Vault 
server port (default: 8200) - scheme:
+ * http/https (default: https) - token: Vault authentication token - 
secretsEngine: KV secrets engine name (default:
+ * secret) - keyPrefix: Prefix for all key paths in Vault (default: pqc/keys)
+ *
+ * This implementation uses Spring Vault (spring-vault-core) consistent with 
the camel-hashicorp-vault component.
+ */
+public class HashicorpVaultKeyLifecycleManager implements KeyLifecycleManager {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(HashicorpVaultKeyLifecycleManager.class);
+
+    private final VaultTemplate vaultTemplate;
+    private final String secretsEngine;
+    private final String keyPrefix;
+    private final boolean cloud;
+    private final String namespace;
+    private final ConcurrentHashMap<String, KeyPair> keyCache = new 
ConcurrentHashMap<>();
+    private final ConcurrentHashMap<String, KeyMetadata> metadataCache = new 
ConcurrentHashMap<>();
+
+    /**
+     * Create a HashicorpVaultKeyLifecycleManager with an existing 
VaultTemplate
+     *
+     * @param vaultTemplate Configured VaultTemplate instance
+     * @param secretsEngine KV secrets engine name
+     * @param keyPrefix     Prefix for key paths in Vault
+     */
+    public HashicorpVaultKeyLifecycleManager(VaultTemplate vaultTemplate, 
String secretsEngine, String keyPrefix) {
+        this(vaultTemplate, secretsEngine, keyPrefix, false, null);
+    }
+
+    /**
+     * Create a HashicorpVaultKeyLifecycleManager with an existing 
VaultTemplate including HCP Vault support
+     *
+     * @param vaultTemplate Configured VaultTemplate instance
+     * @param secretsEngine KV secrets engine name
+     * @param keyPrefix     Prefix for key paths in Vault
+     * @param cloud         Whether Vault is deployed on HashiCorp Cloud 
Platform
+     * @param namespace     Namespace for HCP Vault (required if cloud is true)
+     */
+    public HashicorpVaultKeyLifecycleManager(VaultTemplate vaultTemplate, 
String secretsEngine, String keyPrefix,
+                                             boolean cloud, String namespace) {
+        this.vaultTemplate = vaultTemplate;
+        this.secretsEngine = secretsEngine != null ? secretsEngine : "secret";
+        this.keyPrefix = keyPrefix != null ? keyPrefix : "pqc/keys";
+        this.cloud = cloud;
+        this.namespace = namespace;
+
+        LOG.info(
+                "Initialized HashicorpVaultKeyLifecycleManager with 
secretsEngine: {}, keyPrefix: {}, cloud: {}, namespace: {}",
+                this.secretsEngine, this.keyPrefix, this.cloud, 
this.namespace);
+
+        try {
+            loadExistingKeys();
+        } catch (Exception e) {
+            LOG.warn("Failed to load existing keys from Vault", e);
+        }
+    }
+
+    /**
+     * Create a HashicorpVaultKeyLifecycleManager with default settings
+     *
+     * @param host   Vault server host
+     * @param port   Vault server port
+     * @param scheme Vault scheme (http/https)
+     * @param token  Vault token for authentication
+     */
+    public HashicorpVaultKeyLifecycleManager(String host, int port, String 
scheme, String token) {
+        this(host, port, scheme, token, "secret", "pqc/keys", false, null);
+    }
+
+    /**
+     * Create a HashicorpVaultKeyLifecycleManager with custom settings
+     *
+     * @param host          Vault server host
+     * @param port          Vault server port
+     * @param scheme        Vault scheme (http/https)
+     * @param token         Vault token for authentication
+     * @param secretsEngine KV secrets engine name
+     * @param keyPrefix     Prefix for key paths in Vault
+     */
+    public HashicorpVaultKeyLifecycleManager(String host, int port, String 
scheme, String token, String secretsEngine,
+                                             String keyPrefix) {
+        this(host, port, scheme, token, secretsEngine, keyPrefix, false, null);
+    }
+
+    /**
+     * Create a HashicorpVaultKeyLifecycleManager with full settings including 
HCP Vault support
+     *
+     * @param host          Vault server host
+     * @param port          Vault server port
+     * @param scheme        Vault scheme (http/https)
+     * @param token         Vault token for authentication
+     * @param secretsEngine KV secrets engine name
+     * @param keyPrefix     Prefix for key paths in Vault
+     * @param cloud         Whether Vault is deployed on HashiCorp Cloud 
Platform
+     * @param namespace     Namespace for HCP Vault (required if cloud is true)
+     */
+    public HashicorpVaultKeyLifecycleManager(String host, int port, String 
scheme, String token, String secretsEngine,
+                                             String keyPrefix, boolean cloud, 
String namespace) {
+        this.secretsEngine = secretsEngine != null ? secretsEngine : "secret";
+        this.keyPrefix = keyPrefix != null ? keyPrefix : "pqc/keys";
+        this.cloud = cloud;
+        this.namespace = namespace;
+
+        // Create VaultEndpoint
+        VaultEndpoint vaultEndpoint = new VaultEndpoint();
+        vaultEndpoint.setHost(host);
+        vaultEndpoint.setPort(port);
+        vaultEndpoint.setScheme(scheme != null ? scheme : "https");
+
+        // Create VaultTemplate with TokenAuthentication
+        this.vaultTemplate = new VaultTemplate(vaultEndpoint, new 
TokenAuthentication(token));
+
+        LOG.info(
+                "Initialized HashicorpVaultKeyLifecycleManager with Vault at: 
{}://{}:{}, secretsEngine: {}, keyPrefix: {}, cloud: {}, namespace: {}",
+                scheme, host, port, this.secretsEngine, this.keyPrefix, 
this.cloud, this.namespace);
+
+        try {
+            loadExistingKeys();
+        } catch (Exception e) {
+            LOG.warn("Failed to load existing keys from Vault", e);
+        }
+    }
+
+    @Override
+    public KeyPair generateKeyPair(String algorithm, String keyId) throws 
Exception {
+        return generateKeyPair(algorithm, keyId, null);
+    }
+
+    @Override
+    public KeyPair generateKeyPair(String algorithm, String keyId, Object 
parameterSpec) throws Exception {
+        LOG.info("Generating key pair for algorithm: {}, keyId: {}", 
algorithm, keyId);
+
+        KeyPairGenerator generator;
+        String provider = determineProvider(algorithm);
+
+        if (provider != null) {
+            generator = 
KeyPairGenerator.getInstance(getAlgorithmName(algorithm), provider);
+        } else {
+            generator = 
KeyPairGenerator.getInstance(getAlgorithmName(algorithm));
+        }
+
+        // Initialize with parameter spec if provided
+        if (parameterSpec != null) {
+            if (parameterSpec instanceof AlgorithmParameterSpec) {
+                generator.initialize((AlgorithmParameterSpec) parameterSpec, 
new SecureRandom());
+            } else if (parameterSpec instanceof Integer) {
+                generator.initialize((Integer) parameterSpec, new 
SecureRandom());
+            }
+        } else {
+            // Use default parameter spec for the algorithm
+            AlgorithmParameterSpec defaultSpec = 
getDefaultParameterSpec(algorithm);
+            if (defaultSpec != null) {
+                generator.initialize(defaultSpec, new SecureRandom());
+            } else {
+                generator.initialize(getDefaultKeySize(algorithm), new 
SecureRandom());
+            }
+        }
+
+        KeyPair keyPair = generator.generateKeyPair();
+
+        // Create metadata
+        KeyMetadata metadata = new KeyMetadata(keyId, algorithm);
+        metadata.setDescription("Generated on " + new Date());
+
+        // Store the key
+        storeKey(keyId, keyPair, metadata);
+
+        LOG.info("Generated key pair in Vault: {}", metadata);
+        return keyPair;
+    }
+
+    @Override
+    public byte[] exportKey(KeyPair keyPair, KeyFormat format, boolean 
includePrivate) throws Exception {
+        return KeyFormatConverter.exportKeyPair(keyPair, format, 
includePrivate);
+    }
+
+    @Override
+    public byte[] exportPublicKey(KeyPair keyPair, KeyFormat format) throws 
Exception {
+        return KeyFormatConverter.exportPublicKey(keyPair.getPublic(), format);
+    }
+
+    @Override
+    public KeyPair importKey(byte[] keyData, KeyFormat format, String 
algorithm) throws Exception {
+        // Try to import as private key first (which includes public key)
+        try {
+            PrivateKey privateKey = 
KeyFormatConverter.importPrivateKey(keyData, format, 
getAlgorithmName(algorithm));
+            LOG.warn("Importing private key only - public key derivation may 
be needed");
+            return new KeyPair(null, privateKey);
+        } catch (Exception e) {
+            // Try as public key only
+            PublicKey publicKey = KeyFormatConverter.importPublicKey(keyData, 
format, getAlgorithmName(algorithm));
+            return new KeyPair(publicKey, null);
+        }
+    }
+
+    @Override
+    public KeyPair rotateKey(String oldKeyId, String newKeyId, String 
algorithm) throws Exception {
+        LOG.info("Rotating key from {} to {}", oldKeyId, newKeyId);
+
+        // Get old key metadata
+        KeyMetadata oldMetadata = getKeyMetadata(oldKeyId);
+        if (oldMetadata == null) {
+            throw new IllegalArgumentException("Old key not found: " + 
oldKeyId);
+        }
+
+        // Mark old key as deprecated
+        oldMetadata.setStatus(KeyMetadata.KeyStatus.DEPRECATED);
+        updateKeyMetadata(oldKeyId, oldMetadata);
+
+        // Generate new key
+        KeyPair newKeyPair = generateKeyPair(algorithm, newKeyId);
+
+        LOG.info("Key rotation completed in Vault: {} -> {}", oldKeyId, 
newKeyId);
+        return newKeyPair;
+    }
+
+    @Override
+    public void storeKey(String keyId, KeyPair keyPair, KeyMetadata metadata) 
throws Exception {
+        // Use PKCS#8 format for private key and X.509 for public key 
(industry standard)
+        // This is more secure than Java serialization
+        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded(); // PKCS#8 
format
+        byte[] publicKeyBytes = keyPair.getPublic().getEncoded(); // 
X.509/SubjectPublicKeyInfo format
+        String privateKeyBase64 = 
Base64.getEncoder().encodeToString(privateKeyBytes);
+        String publicKeyBase64 = 
Base64.getEncoder().encodeToString(publicKeyBytes);
+        String metadataBase64 = serializeMetadata(metadata);
+
+        VaultKeyValueOperations keyValue = 
vaultTemplate.opsForKeyValue(secretsEngine,
+                VaultKeyValueOperationsSupport.KeyValueBackend.versioned());
+
+        // Store private key separately (strict ACL recommended in production)
+        Map<String, Object> privateKeyData = new HashMap<>();
+        privateKeyData.put("key", privateKeyBase64);
+        privateKeyData.put("format", "PKCS8");
+        privateKeyData.put("algorithm", metadata.getAlgorithm());
+        keyValue.put(getKeyPath(keyId) + "/private", privateKeyData);
+
+        // Store public key separately (can have read-only ACL)
+        Map<String, Object> publicKeyData = new HashMap<>();
+        publicKeyData.put("key", publicKeyBase64);
+        publicKeyData.put("format", "X509");
+        publicKeyData.put("algorithm", metadata.getAlgorithm());
+        keyValue.put(getKeyPath(keyId) + "/public", publicKeyData);
+
+        // Store metadata separately
+        Map<String, Object> metadataData = new HashMap<>();
+        metadataData.put("metadata", metadataBase64);
+        metadataData.put("keyId", keyId);
+        metadataData.put("algorithm", metadata.getAlgorithm());
+        keyValue.put(getKeyPath(keyId) + "/metadata", metadataData);
+
+        // Update caches
+        keyCache.put(keyId, keyPair);
+        metadataCache.put(keyId, metadata);
+
+        LOG.debug("Stored private key, public key, and metadata separately in 
Vault for: {}", keyId);
+    }
+
+    @Override
+    public KeyPair getKey(String keyId) throws Exception {
+        // Check cache first
+        if (keyCache.containsKey(keyId)) {
+            return keyCache.get(keyId);
+        }
+
+        // Read private key from Vault
+        String privateKeyPath = buildDataPath(getKeyPath(keyId) + "/private");
+        VaultResponse privateResponse = vaultTemplate.read(privateKeyPath);
+
+        if (privateResponse == null || privateResponse.getData() == null) {
+            throw new IllegalArgumentException("Private key not found in 
Vault: " + keyId);
+        }
+
+        // Read public key from Vault
+        String publicKeyPath = buildDataPath(getKeyPath(keyId) + "/public");
+        VaultResponse publicResponse = vaultTemplate.read(publicKeyPath);
+
+        if (publicResponse == null || publicResponse.getData() == null) {
+            throw new IllegalArgumentException("Public key not found in Vault: 
" + keyId);
+        }
+
+        // Reconstruct KeyPair from PKCS#8 private key and X.509 public key
+        Map<String, Object> privateData = privateResponse.getData();
+        Map<String, Object> publicData = publicResponse.getData();
+
+        String privateKeyBase64 = (String) privateData.get("key");
+        String publicKeyBase64 = (String) publicData.get("key");
+        String algorithm = (String) privateData.get("algorithm");
+
+        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);
+        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64);
+
+        // Use KeyFormatConverter to reconstruct keys from standard formats
+        PrivateKey privateKey = 
KeyFormatConverter.importPrivateKey(privateKeyBytes,
+                KeyLifecycleManager.KeyFormat.DER, 
getAlgorithmName(algorithm));
+        PublicKey publicKey = 
KeyFormatConverter.importPublicKey(publicKeyBytes,
+                KeyLifecycleManager.KeyFormat.DER, 
getAlgorithmName(algorithm));
+
+        KeyPair keyPair = new KeyPair(publicKey, privateKey);
+
+        // Cache it
+        keyCache.put(keyId, keyPair);
+        return keyPair;
+    }
+
+    @Override
+    public KeyMetadata getKeyMetadata(String keyId) throws Exception {
+        // Check cache first
+        if (metadataCache.containsKey(keyId)) {
+            return metadataCache.get(keyId);
+        }
+
+        // Read metadata from Vault
+        String metadataPath = buildDataPath(getKeyPath(keyId) + "/metadata");
+        VaultResponse response = vaultTemplate.read(metadataPath);
+
+        if (response == null || response.getData() == null) {
+            return null;
+        }
+
+        Map<String, Object> data = response.getData();
+        String metadataBase64 = (String) data.get("metadata");
+        KeyMetadata metadata = deserializeMetadata(metadataBase64);
+
+        // Cache it
+        metadataCache.put(keyId, metadata);
+        return metadata;
+    }
+
+    @Override
+    public void updateKeyMetadata(String keyId, KeyMetadata metadata) throws 
Exception {
+        // Read existing key pair
+        KeyPair keyPair = getKey(keyId);
+
+        // Store updated metadata with existing key pair
+        storeKey(keyId, keyPair, metadata);
+    }
+
+    @Override
+    public void deleteKey(String keyId) throws Exception {
+        VaultKeyValueOperations keyValue = 
vaultTemplate.opsForKeyValue(secretsEngine,
+                VaultKeyValueOperationsSupport.KeyValueBackend.versioned());
+
+        // Delete private key, public key, and metadata separately
+        keyValue.delete(getKeyPath(keyId) + "/private");
+        keyValue.delete(getKeyPath(keyId) + "/public");
+        keyValue.delete(getKeyPath(keyId) + "/metadata");
+
+        keyCache.remove(keyId);
+        metadataCache.remove(keyId);
+
+        LOG.info("Deleted private key, public key, and metadata from Vault: 
{}", keyId);
+    }
+
+    @Override
+    public List<KeyMetadata> listKeys() throws Exception {
+        // List all keys under the key prefix
+        String metadataPath = buildMetadataPath(keyPrefix);
+        List<String> keyIds = vaultTemplate.list(metadataPath);
+
+        List<KeyMetadata> metadataList = new ArrayList<>();
+        if (keyIds != null) {
+            for (String keyId : keyIds) {
+                try {
+                    // Remove trailing slash if present
+                    String cleanKeyId = keyId.endsWith("/") ? 
keyId.substring(0, keyId.length() - 1) : keyId;
+                    KeyMetadata metadata = getKeyMetadata(cleanKeyId);
+                    if (metadata != null) {
+                        metadataList.add(metadata);
+                    }
+                } catch (Exception e) {
+                    LOG.warn("Failed to load metadata for key: {}", keyId, e);
+                }
+            }
+        }
+
+        return metadataList;
+    }
+
+    @Override
+    public boolean needsRotation(String keyId, Duration maxAge, long maxUsage) 
throws Exception {
+        KeyMetadata metadata = getKeyMetadata(keyId);
+        if (metadata == null) {
+            return false;
+        }
+
+        if (metadata.needsRotation()) {
+            return true;
+        }
+
+        if (maxAge != null && metadata.getAgeInDays() > maxAge.toDays()) {
+            return true;
+        }
+
+        if (maxUsage > 0 && metadata.getUsageCount() >= maxUsage) {
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void expireKey(String keyId) throws Exception {
+        KeyMetadata metadata = getKeyMetadata(keyId);
+        if (metadata != null) {
+            metadata.setStatus(KeyMetadata.KeyStatus.EXPIRED);
+            updateKeyMetadata(keyId, metadata);
+            LOG.info("Expired key in Vault: {}", keyId);
+        }
+    }
+
+    @Override
+    public void revokeKey(String keyId, String reason) throws Exception {
+        KeyMetadata metadata = getKeyMetadata(keyId);
+        if (metadata != null) {
+            metadata.setStatus(KeyMetadata.KeyStatus.REVOKED);
+            metadata.setDescription((metadata.getDescription() != null ? 
metadata.getDescription() + "; " : "")
+                                    + "Revoked: " + reason);
+            updateKeyMetadata(keyId, metadata);
+            LOG.info("Revoked key in Vault: {} - {}", keyId, reason);
+        }
+    }
+
+    private void loadExistingKeys() throws Exception {
+        String metadataPath = buildMetadataPath(keyPrefix);
+        List<String> keyIds = vaultTemplate.list(metadataPath);
+
+        if (keyIds != null) {
+            LOG.info("Found {} existing keys in Vault", keyIds.size());
+
+            for (String keyId : keyIds) {
+                try {
+                    // Remove trailing slash if present
+                    String cleanKeyId = keyId.endsWith("/") ? 
keyId.substring(0, keyId.length() - 1) : keyId;
+                    KeyMetadata metadata = getKeyMetadata(cleanKeyId);
+                    if (metadata != null) {
+                        LOG.debug("Loaded existing key from Vault: {}", 
metadata);
+                    }
+                } catch (Exception e) {
+                    LOG.warn("Failed to load key from Vault: {}", keyId, e);
+                }
+            }
+        }
+    }
+
+    private String getKeyPath(String keyId) {
+        return keyPrefix + "/" + keyId;
+    }
+
+    /**
+     * Build the data path for reading/writing secrets, following HCP Vault 
pattern from camel-hashicorp-vault
+     */
+    private String buildDataPath(String secretPath) {
+        if (!cloud) {
+            return secretsEngine + "/data/" + secretPath;
+        } else {
+            if (namespace != null && !namespace.isEmpty()) {
+                return namespace + "/" + secretsEngine + "/data/" + secretPath;
+            } else {
+                return secretsEngine + "/data/" + secretPath;
+            }
+        }
+    }
+
+    /**
+     * Build the metadata path for listing secrets, following HCP Vault 
pattern from camel-hashicorp-vault
+     */
+    private String buildMetadataPath(String secretPath) {
+        if (!cloud) {
+            return secretsEngine + "/metadata/" + secretPath;
+        } else {
+            if (namespace != null && !namespace.isEmpty()) {
+                return namespace + "/" + secretsEngine + "/metadata/" + 
secretPath;
+            } else {
+                return secretsEngine + "/metadata/" + secretPath;
+            }
+        }
+    }
+
+    private String serializeMetadata(KeyMetadata metadata) throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(metadata);
+        }
+        return Base64.getEncoder().encodeToString(baos.toByteArray());
+    }
+
+    private KeyMetadata deserializeMetadata(String base64) throws Exception {
+        byte[] data = Base64.getDecoder().decode(base64);
+        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+        try (ObjectInputStream ois = new ObjectInputStream(bais)) {
+            return (KeyMetadata) ois.readObject();
+        }
+    }
+
+    private String determineProvider(String algorithm) {
+        try {
+            PQCSignatureAlgorithms sigAlg = 
PQCSignatureAlgorithms.valueOf(algorithm);
+            return sigAlg.getBcProvider();
+        } catch (IllegalArgumentException e1) {
+            try {
+                PQCKeyEncapsulationAlgorithms kemAlg = 
PQCKeyEncapsulationAlgorithms.valueOf(algorithm);
+                return kemAlg.getBcProvider();
+            } catch (IllegalArgumentException e2) {
+                return null;
+            }
+        }
+    }
+
+    private String getAlgorithmName(String algorithm) {
+        try {
+            return PQCSignatureAlgorithms.valueOf(algorithm).getAlgorithm();
+        } catch (IllegalArgumentException e1) {
+            try {
+                return 
PQCKeyEncapsulationAlgorithms.valueOf(algorithm).getAlgorithm();
+            } catch (IllegalArgumentException e2) {
+                return algorithm;
+            }
+        }
+    }
+
+    private AlgorithmParameterSpec getDefaultParameterSpec(String algorithm) {
+        // Provide default parameter specs for PQC algorithms
+        try {
+            switch (algorithm) {
+                case "DILITHIUM":
+                    return 
org.bouncycastle.pqc.jcajce.spec.DilithiumParameterSpec.dilithium2;
+                case "MLDSA":
+                case "SLHDSA":
+                    // These use default initialization
+                    return null;
+                case "FALCON":
+                    return 
org.bouncycastle.pqc.jcajce.spec.FalconParameterSpec.falcon_512;
+                case "SPHINCSPLUS":
+                    return 
org.bouncycastle.pqc.jcajce.spec.SPHINCSPlusParameterSpec.sha2_128s;
+                case "XMSS":
+                    return new 
org.bouncycastle.pqc.jcajce.spec.XMSSParameterSpec(
+                            10,
+                            
org.bouncycastle.pqc.jcajce.spec.XMSSParameterSpec.SHA256);
+                case "XMSSMT":
+                    return 
org.bouncycastle.pqc.jcajce.spec.XMSSMTParameterSpec.XMSSMT_SHA2_20d2_256;
+                case "LMS":
+                case "HSS":
+                    return new 
org.bouncycastle.pqc.jcajce.spec.LMSKeyGenParameterSpec(
+                            
org.bouncycastle.pqc.crypto.lms.LMSigParameters.lms_sha256_n32_h10,
+                            
org.bouncycastle.pqc.crypto.lms.LMOtsParameters.sha256_n32_w4);
+                case "MLKEM":
+                case "KYBER":
+                    // These use default initialization
+                    return null;
+                case "NTRU":
+                    return 
org.bouncycastle.pqc.jcajce.spec.NTRUParameterSpec.ntruhps2048509;
+                case "NTRULPRime":
+                    return 
org.bouncycastle.pqc.jcajce.spec.NTRULPRimeParameterSpec.ntrulpr653;
+                case "SNTRUPrime":
+                    return 
org.bouncycastle.pqc.jcajce.spec.SNTRUPrimeParameterSpec.sntrup761;
+                case "SABER":
+                    return 
org.bouncycastle.pqc.jcajce.spec.SABERParameterSpec.lightsaberkem128r3;
+                case "FRODO":
+                    return 
org.bouncycastle.pqc.jcajce.spec.FrodoParameterSpec.frodokem640aes;
+                case "BIKE":
+                    return 
org.bouncycastle.pqc.jcajce.spec.BIKEParameterSpec.bike128;
+                case "HQC":
+                    return 
org.bouncycastle.pqc.jcajce.spec.HQCParameterSpec.hqc128;
+                case "CMCE":
+                    return 
org.bouncycastle.pqc.jcajce.spec.CMCEParameterSpec.mceliece348864;
+                default:
+                    return null;
+            }
+        } catch (Exception e) {
+            LOG.warn("Failed to create default parameter spec for algorithm: 
{}", algorithm, e);
+            return null;
+        }
+    }
+
+    private int getDefaultKeySize(String algorithm) {
+        // Default key sizes for different algorithms
+        // For PQC algorithms, key size is usually determined by parameter 
specs
+        return 256;
+    }
+
+    /**
+     * Get the underlying VaultTemplate for advanced operations
+     */
+    public VaultTemplate getVaultTemplate() {
+        return vaultTemplate;
+    }
+}
diff --git 
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/HashicorpVaultKeyLifecycleIT.java
 
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/HashicorpVaultKeyLifecycleIT.java
new file mode 100644
index 000000000000..58592fceee56
--- /dev/null
+++ 
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/HashicorpVaultKeyLifecycleIT.java
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.component.pqc;
+
+import java.security.KeyPair;
+import java.security.Security;
+import java.time.Duration;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import 
org.apache.camel.component.pqc.lifecycle.HashicorpVaultKeyLifecycleManager;
+import org.apache.camel.component.pqc.lifecycle.KeyLifecycleManager;
+import org.apache.camel.component.pqc.lifecycle.KeyMetadata;
+import 
org.apache.camel.test.infra.hashicorp.vault.services.HashicorpServiceFactory;
+import 
org.apache.camel.test.infra.hashicorp.vault.services.HashicorpVaultService;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
+import org.bouncycastle.pqc.jcajce.spec.DilithiumParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.FalconParameterSpec;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * End-to-end integration test for HashicorpVaultKeyLifecycleManager. Tests 
key generation, storage, retrieval,
+ * rotation, and usage in Camel routes with a real Vault instance via 
testcontainers.
+ */
+public class HashicorpVaultKeyLifecycleIT extends CamelTestSupport {
+
+    @RegisterExtension
+    public static HashicorpVaultService service = 
HashicorpServiceFactory.createService();
+
+    private HashicorpVaultKeyLifecycleManager keyManager;
+
+    @EndpointInject("mock:signed")
+    private MockEndpoint mockSigned;
+
+    @EndpointInject("mock:verified")
+    private MockEndpoint mockVerified;
+
+    @BeforeAll
+    public static void startup() {
+        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+        if (Security.getProvider(BouncyCastlePQCProvider.PROVIDER_NAME) == 
null) {
+            Security.addProvider(new BouncyCastlePQCProvider());
+        }
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+
+        // Create HashicorpVaultKeyLifecycleManager using Vault test 
infrastructure
+        keyManager = new HashicorpVaultKeyLifecycleManager(
+                service.host(),
+                service.port(),
+                "http", // Test container uses http
+                service.token(),
+                "secret",
+                "pqc/test-keys");
+
+        // Register the manager in the registry
+        context.getRegistry().bind("keyLifecycleManager", keyManager);
+
+        return context;
+    }
+
+    @Test
+    public void testGenerateAndStoreKeyInVault() throws Exception {
+        // Generate a Dilithium key
+        KeyPair keyPair = keyManager.generateKeyPair("DILITHIUM", 
"test-dilithium-key", DilithiumParameterSpec.dilithium2);
+
+        assertNotNull(keyPair);
+        assertNotNull(keyPair.getPublic());
+        assertNotNull(keyPair.getPrivate());
+
+        // Verify metadata was created
+        KeyMetadata metadata = keyManager.getKeyMetadata("test-dilithium-key");
+        assertNotNull(metadata);
+        assertEquals("test-dilithium-key", metadata.getKeyId());
+        assertEquals("DILITHIUM", metadata.getAlgorithm());
+        assertEquals(KeyMetadata.KeyStatus.ACTIVE, metadata.getStatus());
+    }
+
+    @Test
+    public void testRetrieveKeyFromVault() throws Exception {
+        // Generate and store key
+        keyManager.generateKeyPair("FALCON", "test-falcon-key", 
FalconParameterSpec.falcon_512);
+
+        // Clear cache to force Vault read
+        // (In production this would simulate a different process/server 
accessing the key)
+
+        // Retrieve key from Vault
+        KeyPair retrieved = keyManager.getKey("test-falcon-key");
+        assertNotNull(retrieved);
+        assertNotNull(retrieved.getPublic());
+        assertNotNull(retrieved.getPrivate());
+
+        // Verify metadata
+        KeyMetadata metadata = keyManager.getKeyMetadata("test-falcon-key");
+        assertEquals("FALCON", metadata.getAlgorithm());
+    }
+
+    @Test
+    public void testKeyRotation() throws Exception {
+        // Generate initial key
+        keyManager.generateKeyPair("DILITHIUM", "rotation-key-old", 
DilithiumParameterSpec.dilithium2);
+
+        KeyMetadata oldMetadata = 
keyManager.getKeyMetadata("rotation-key-old");
+        assertEquals(KeyMetadata.KeyStatus.ACTIVE, oldMetadata.getStatus());
+
+        // Rotate the key
+        KeyPair newKeyPair = keyManager.rotateKey("rotation-key-old", 
"rotation-key-new", "DILITHIUM");
+        assertNotNull(newKeyPair);
+
+        // Verify old key is deprecated
+        oldMetadata = keyManager.getKeyMetadata("rotation-key-old");
+        assertEquals(KeyMetadata.KeyStatus.DEPRECATED, 
oldMetadata.getStatus());
+
+        // Verify new key is active
+        KeyMetadata newMetadata = 
keyManager.getKeyMetadata("rotation-key-new");
+        assertEquals(KeyMetadata.KeyStatus.ACTIVE, newMetadata.getStatus());
+    }
+
+    @Test
+    public void testNeedsRotation() throws Exception {
+        keyManager.generateKeyPair("DILITHIUM", "rotation-check-key", 
DilithiumParameterSpec.dilithium2);
+
+        // New key should not need rotation
+        assertFalse(keyManager.needsRotation("rotation-check-key", 
Duration.ofDays(90), 10000));
+
+        // Simulate old key by setting next rotation time in the past
+        KeyMetadata metadata = keyManager.getKeyMetadata("rotation-check-key");
+        metadata.setNextRotationAt(java.time.Instant.now().minusSeconds(1));
+        keyManager.updateKeyMetadata("rotation-check-key", metadata);
+
+        // Now it should need rotation
+        assertTrue(keyManager.needsRotation("rotation-check-key", 
Duration.ofDays(90), 10000));
+    }
+
+    @Test
+    public void testListKeys() throws Exception {
+        // Generate multiple keys
+        keyManager.generateKeyPair("DILITHIUM", "list-key-1", 
DilithiumParameterSpec.dilithium2);
+        keyManager.generateKeyPair("FALCON", "list-key-2", 
FalconParameterSpec.falcon_512);
+        keyManager.generateKeyPair("DILITHIUM", "list-key-3", 
DilithiumParameterSpec.dilithium3);
+
+        // List all keys
+        List<KeyMetadata> keys = keyManager.listKeys();
+        assertTrue(keys.size() >= 3, "Should have at least 3 keys");
+
+        // Verify all our keys are present
+        assertTrue(keys.stream().anyMatch(k -> 
k.getKeyId().equals("list-key-1")));
+        assertTrue(keys.stream().anyMatch(k -> 
k.getKeyId().equals("list-key-2")));
+        assertTrue(keys.stream().anyMatch(k -> 
k.getKeyId().equals("list-key-3")));
+    }
+
+    @Test
+    public void testExpireAndRevokeKey() throws Exception {
+        // Test expiration
+        keyManager.generateKeyPair("DILITHIUM", "expire-key", 
DilithiumParameterSpec.dilithium2);
+        keyManager.expireKey("expire-key");
+
+        KeyMetadata expiredMetadata = keyManager.getKeyMetadata("expire-key");
+        assertEquals(KeyMetadata.KeyStatus.EXPIRED, 
expiredMetadata.getStatus());
+
+        // Test revocation
+        keyManager.generateKeyPair("DILITHIUM", "revoke-key", 
DilithiumParameterSpec.dilithium2);
+        keyManager.revokeKey("revoke-key", "Key compromised in test");
+
+        KeyMetadata revokedMetadata = keyManager.getKeyMetadata("revoke-key");
+        assertEquals(KeyMetadata.KeyStatus.REVOKED, 
revokedMetadata.getStatus());
+        assertTrue(revokedMetadata.getDescription().contains("Revoked: Key 
compromised in test"));
+    }
+
+    @Test
+    public void testDeleteKey() throws Exception {
+        keyManager.generateKeyPair("DILITHIUM", "delete-key", 
DilithiumParameterSpec.dilithium2);
+        assertNotNull(keyManager.getKey("delete-key"));
+
+        keyManager.deleteKey("delete-key");
+
+        // Should throw exception when trying to get deleted key
+        assertThrows(IllegalArgumentException.class, () -> 
keyManager.getKey("delete-key"));
+    }
+
+    @Test
+    public void testExportAndImportKey() throws Exception {
+        KeyPair keyPair = keyManager.generateKeyPair("DILITHIUM", 
"export-key", DilithiumParameterSpec.dilithium2);
+
+        // Export public key as PEM
+        byte[] exported = keyManager.exportPublicKey(keyPair, 
KeyLifecycleManager.KeyFormat.PEM);
+        assertNotNull(exported);
+        assertTrue(exported.length > 0);
+
+        String pemString = new String(exported);
+        assertTrue(pemString.contains("-----BEGIN PUBLIC KEY-----"));
+        assertTrue(pemString.contains("-----END PUBLIC KEY-----"));
+
+        // Import the key
+        KeyPair imported = keyManager.importKey(exported, 
KeyLifecycleManager.KeyFormat.PEM, "DILITHIUM");
+        assertNotNull(imported);
+        assertNotNull(imported.getPublic());
+    }
+
+    @Test
+    public void testMetadataTracking() throws Exception {
+        // Generate key
+        keyManager.generateKeyPair("DILITHIUM", "tracking-key", 
DilithiumParameterSpec.dilithium2);
+
+        // Get initial metadata
+        KeyMetadata metadata = keyManager.getKeyMetadata("tracking-key");
+        assertEquals(0, metadata.getUsageCount());
+        assertEquals(KeyMetadata.KeyStatus.ACTIVE, metadata.getStatus());
+
+        // Simulate usage by updating metadata
+        for (int i = 0; i < 5; i++) {
+            metadata.updateLastUsed();
+        }
+        keyManager.updateKeyMetadata("tracking-key", metadata);
+
+        // Verify usage was tracked
+        metadata = keyManager.getKeyMetadata("tracking-key");
+        assertEquals(5, metadata.getUsageCount());
+        assertNotNull(metadata.getLastUsedAt());
+
+        // Verify age calculation
+        long ageInDays = metadata.getAgeInDays();
+        assertEquals(0, ageInDays); // Should be 0 for a newly created key
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // Signing route using PQC component with Vault-stored key
+                from("direct:sign")
+                        
.to("pqc:sign?operation=sign&signatureAlgorithm=DILITHIUM")
+                        .to("mock:signed")
+                        
.to("pqc:verify?operation=verify&signatureAlgorithm=DILITHIUM")
+                        .to("mock:verified");
+            }
+        };
+    }
+}

Reply via email to