This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new e235025a85a9 CAMEL-23846: Camel-PQC - make the NIST parameter set
configurable on the endpoint (#24654)
e235025a85a9 is described below
commit e235025a85a9013df9affcc5410407eadaf9bcae
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Jul 13 12:24:28 2026 +0200
CAMEL-23846: Camel-PQC - make the NIST parameter set configurable on the
endpoint (#24654)
CAMEL-23846: Camel-PQC make the NIST parameter set configurable on the
endpoint
The default key material classes hardcode one parameter set per algorithm
(PQCDefaultMLDSAMaterial uses ML-DSA-65, ML-KEM defaults to ML-KEM-512,
...), and
the lifecycle generateKeyPair path only used the 2-arg overload. Selecting
another
NIST security level therefore required registering custom KeyPair/Signature/
KeyGenerator beans.
Add a parameterSpec endpoint option that selects the BouncyCastle parameter
set:
- new PQCParameterSpecResolver maps an algorithm plus a parameter-set name
to the
BouncyCastle AlgorithmParameterSpec (16 algorithms; names are
case-insensitive
and the underscore form ml_dsa_87 is accepted as an alias of ML-DSA-87);
- PQCComponent generates the key material with the configured parameter set,
caching it per algorithm and parameter set so that endpoints sharing the
same
configuration (a sign and a verify endpoint) use the same key, mirroring
the
shared default material;
- the generateKeyPair lifecycle operation now uses the parameterSpec-aware
KeyLifecycleManager overload.
Not supported for the stateful signature algorithms (XMSS, XMSSMT, LMS,
HSS), for
MAYO/SNOVA, nor for the hybrid operations; those are rejected with a clear
error.
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
---
.../org/apache/camel/catalog/components/pqc.json | 34 ++---
.../component/pqc/PQCComponentConfigurer.java | 6 +
.../camel/component/pqc/PQCEndpointConfigurer.java | 6 +
.../camel/component/pqc/PQCEndpointUriFactory.java | 3 +-
.../org/apache/camel/component/pqc/pqc.json | 34 ++---
.../camel-pqc/src/main/docs/pqc-component.adoc | 49 +++++++
.../apache/camel/component/pqc/PQCComponent.java | 105 ++++++++++++++
.../camel/component/pqc/PQCConfiguration.java | 19 +++
.../component/pqc/PQCParameterSpecResolver.java | 153 +++++++++++++++++++++
.../apache/camel/component/pqc/PQCProducer.java | 9 +-
.../pqc/PQCParameterSpecResolverTest.java | 104 ++++++++++++++
.../camel/component/pqc/PQCParameterSpecTest.java | 118 ++++++++++++++++
.../component/dsl/PqcComponentBuilderFactory.java | 25 ++++
.../endpoint/dsl/PQCEndpointBuilderFactory.java | 23 ++++
14 files changed, 654 insertions(+), 34 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
index a57b6015bc51..a9295759a94e 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json
@@ -45,15 +45,16 @@
"keyRotationSchedulerEnabled": { "index": 18, "kind": "property",
"displayName": "Key Rotation Scheduler Enabled", "group": "advanced", "label":
"advanced", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue":
false, "description": "Whether to start an automated background key rotation
scheduler for this component. Requires keyLifecycleManager to be set. The
scheduler periodically rotates keys that exce [...]
"keyStore": { "index": 19, "kind": "property", "displayName": "Key Store",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.KeyStore", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "A KeyStore where we could get Cryptographic
material" },
"keyStorePassword": { "index": 20, "kind": "property", "displayName": "Key
Store Password", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true, "security":
"secret", "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The KeyStore password to use in combination
with KeySto [...]
- "signatureAlgorithm": { "index": 21, "kind": "property", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
- "signer": { "index": 22, "kind": "property", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
- "statefulKeyWarningThreshold": { "index": 23, "kind": "property",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key exh
[...]
- "storeExtractedSecretKeyAsHeader": { "index": 24, "kind": "property",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSec [...]
- "strictKeyLifecycle": { "index": 25, "kind": "property", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
- "symmetricKeyAlgorithm": { "index": 26, "kind": "property", "displayName":
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced",
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539",
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256",
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "co [...]
- "symmetricKeyLength": { "index": 27, "kind": "property", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" },
- "healthCheckConsumerEnabled": { "index": 28, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
- "healthCheckProducerEnabled": { "index": 29, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
+ "parameterSpec": { "index": 21, "kind": "property", "displayName":
"Parameter Spec", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The NIST parameter set
(security level) to use for the configured signature or key [...]
+ "signatureAlgorithm": { "index": 22, "kind": "property", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
+ "signer": { "index": 23, "kind": "property", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
+ "statefulKeyWarningThreshold": { "index": 24, "kind": "property",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key exh
[...]
+ "storeExtractedSecretKeyAsHeader": { "index": 25, "kind": "property",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSec [...]
+ "strictKeyLifecycle": { "index": 26, "kind": "property", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
+ "symmetricKeyAlgorithm": { "index": 27, "kind": "property", "displayName":
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced",
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539",
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256",
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "co [...]
+ "symmetricKeyLength": { "index": 28, "kind": "property", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" },
+ "healthCheckConsumerEnabled": { "index": 29, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
+ "healthCheckProducerEnabled": { "index": 30, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
},
"headers": {
"CamelPQCOperation": { "index": 0, "kind": "header", "displayName": "",
"group": "producer", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The operation we want to perform", "constantName":
"org.apache.camel.component.pqc.PQCConstants#OPERATION" },
@@ -97,12 +98,13 @@
"keyPairAlias": { "index": 13, "kind": "parameter", "displayName": "Key
Pair Alias", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "A KeyPair alias to use
in combination with KeyStore parameter" },
"keyStore": { "index": 14, "kind": "parameter", "displayName": "Key
Store", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "java.security.KeyStore", "deprecated": false,
"deprecationNote": "", "autowired": true, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "A KeyStore where we
could get Cryptographic material" },
"keyStorePassword": { "index": 15, "kind": "parameter", "displayName":
"Key Store Password", "group": "advanced", "label": "advanced", "required":
false, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true, "security":
"secret", "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The KeyStore password to use in combination
with KeySt [...]
- "signatureAlgorithm": { "index": 16, "kind": "parameter", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", " [...]
- "signer": { "index": 17, "kind": "parameter", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
- "statefulKeyWarningThreshold": { "index": 18, "kind": "parameter",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key ex [...]
- "storeExtractedSecretKeyAsHeader": { "index": 19, "kind": "parameter",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSe [...]
- "strictKeyLifecycle": { "index": 20, "kind": "parameter", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
- "symmetricKeyAlgorithm": { "index": 21, "kind": "parameter",
"displayName": "Symmetric Key Algorithm", "group": "advanced", "label":
"advanced", "required": false, "type": "enum", "javaType": "java.lang.String",
"enum": [ "AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6",
"CHACHA7539", "DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128",
"HC256", "SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "c [...]
- "symmetricKeyLength": { "index": 22, "kind": "parameter", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" }
+ "parameterSpec": { "index": 16, "kind": "parameter", "displayName":
"Parameter Spec", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The NIST parameter set
(security level) to use for the configured signature or key [...]
+ "signatureAlgorithm": { "index": 17, "kind": "parameter", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", " [...]
+ "signer": { "index": 18, "kind": "parameter", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
+ "statefulKeyWarningThreshold": { "index": 19, "kind": "parameter",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key ex [...]
+ "storeExtractedSecretKeyAsHeader": { "index": 20, "kind": "parameter",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSe [...]
+ "strictKeyLifecycle": { "index": 21, "kind": "parameter", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
+ "symmetricKeyAlgorithm": { "index": 22, "kind": "parameter",
"displayName": "Symmetric Key Algorithm", "group": "advanced", "label":
"advanced", "required": false, "type": "enum", "javaType": "java.lang.String",
"enum": [ "AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6",
"CHACHA7539", "DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128",
"HC256", "SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "c [...]
+ "symmetricKeyLength": { "index": 23, "kind": "parameter", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" }
}
}
diff --git
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
index 4799514a49fa..6a0af67553dc 100644
---
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
+++
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCComponentConfigurer.java
@@ -74,6 +74,8 @@ public class PQCComponentConfigurer extends
PropertyConfigurerSupport implements
case "lazystartproducer":
case "lazyStartProducer":
target.setLazyStartProducer(property(camelContext, boolean.class, value));
return true;
case "operation":
getOrCreateConfiguration(target).setOperation(property(camelContext,
org.apache.camel.component.pqc.PQCOperations.class, value)); return true;
+ case "parameterspec":
+ case "parameterSpec":
getOrCreateConfiguration(target).setParameterSpec(property(camelContext,
java.lang.String.class, value)); return true;
case "signaturealgorithm":
case "signatureAlgorithm":
getOrCreateConfiguration(target).setSignatureAlgorithm(property(camelContext,
java.lang.String.class, value)); return true;
case "signer":
getOrCreateConfiguration(target).setSigner(property(camelContext,
java.security.Signature.class, value)); return true;
@@ -143,6 +145,8 @@ public class PQCComponentConfigurer extends
PropertyConfigurerSupport implements
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "operation": return
org.apache.camel.component.pqc.PQCOperations.class;
+ case "parameterspec":
+ case "parameterSpec": return java.lang.String.class;
case "signaturealgorithm":
case "signatureAlgorithm": return java.lang.String.class;
case "signer": return java.security.Signature.class;
@@ -208,6 +212,8 @@ public class PQCComponentConfigurer extends
PropertyConfigurerSupport implements
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "operation": return
getOrCreateConfiguration(target).getOperation();
+ case "parameterspec":
+ case "parameterSpec": return
getOrCreateConfiguration(target).getParameterSpec();
case "signaturealgorithm":
case "signatureAlgorithm": return
getOrCreateConfiguration(target).getSignatureAlgorithm();
case "signer": return getOrCreateConfiguration(target).getSigner();
diff --git
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointConfigurer.java
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointConfigurer.java
index 97181137be25..43199c58e09e 100644
---
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointConfigurer.java
+++
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointConfigurer.java
@@ -52,6 +52,8 @@ public class PQCEndpointConfigurer extends
PropertyConfigurerSupport implements
case "lazystartproducer":
case "lazyStartProducer":
target.setLazyStartProducer(property(camelContext, boolean.class, value));
return true;
case "operation":
target.getConfiguration().setOperation(property(camelContext,
org.apache.camel.component.pqc.PQCOperations.class, value)); return true;
+ case "parameterspec":
+ case "parameterSpec":
target.getConfiguration().setParameterSpec(property(camelContext,
java.lang.String.class, value)); return true;
case "signaturealgorithm":
case "signatureAlgorithm":
target.getConfiguration().setSignatureAlgorithm(property(camelContext,
java.lang.String.class, value)); return true;
case "signer":
target.getConfiguration().setSigner(property(camelContext,
java.security.Signature.class, value)); return true;
@@ -106,6 +108,8 @@ public class PQCEndpointConfigurer extends
PropertyConfigurerSupport implements
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "operation": return
org.apache.camel.component.pqc.PQCOperations.class;
+ case "parameterspec":
+ case "parameterSpec": return java.lang.String.class;
case "signaturealgorithm":
case "signatureAlgorithm": return java.lang.String.class;
case "signer": return java.security.Signature.class;
@@ -156,6 +160,8 @@ public class PQCEndpointConfigurer extends
PropertyConfigurerSupport implements
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "operation": return target.getConfiguration().getOperation();
+ case "parameterspec":
+ case "parameterSpec": return
target.getConfiguration().getParameterSpec();
case "signaturealgorithm":
case "signatureAlgorithm": return
target.getConfiguration().getSignatureAlgorithm();
case "signer": return target.getConfiguration().getSigner();
diff --git
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointUriFactory.java
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointUriFactory.java
index df93bc5d8304..cb21061b179e 100644
---
a/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointUriFactory.java
+++
b/components/camel-pqc/src/generated/java/org/apache/camel/component/pqc/PQCEndpointUriFactory.java
@@ -24,7 +24,7 @@ public class PQCEndpointUriFactory extends
org.apache.camel.support.component.En
private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
private static final Map<String, String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(23);
+ Set<String> props = new HashSet<>(24);
props.add("classicalKEMAlgorithm");
props.add("classicalKeyAgreement");
props.add("classicalKeyPair");
@@ -41,6 +41,7 @@ public class PQCEndpointUriFactory extends
org.apache.camel.support.component.En
props.add("label");
props.add("lazyStartProducer");
props.add("operation");
+ props.add("parameterSpec");
props.add("signatureAlgorithm");
props.add("signer");
props.add("statefulKeyWarningThreshold");
diff --git
a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
index a57b6015bc51..a9295759a94e 100644
---
a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
+++
b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json
@@ -45,15 +45,16 @@
"keyRotationSchedulerEnabled": { "index": 18, "kind": "property",
"displayName": "Key Rotation Scheduler Enabled", "group": "advanced", "label":
"advanced", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue":
false, "description": "Whether to start an automated background key rotation
scheduler for this component. Requires keyLifecycleManager to be set. The
scheduler periodically rotates keys that exce [...]
"keyStore": { "index": 19, "kind": "property", "displayName": "Key Store",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.KeyStore", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "A KeyStore where we could get Cryptographic
material" },
"keyStorePassword": { "index": 20, "kind": "property", "displayName": "Key
Store Password", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true, "security":
"secret", "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The KeyStore password to use in combination
with KeySto [...]
- "signatureAlgorithm": { "index": 21, "kind": "property", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
- "signer": { "index": 22, "kind": "property", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
- "statefulKeyWarningThreshold": { "index": 23, "kind": "property",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key exh
[...]
- "storeExtractedSecretKeyAsHeader": { "index": 24, "kind": "property",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSec [...]
- "strictKeyLifecycle": { "index": 25, "kind": "property", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
- "symmetricKeyAlgorithm": { "index": 26, "kind": "property", "displayName":
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced",
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539",
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256",
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "co [...]
- "symmetricKeyLength": { "index": 27, "kind": "property", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" },
- "healthCheckConsumerEnabled": { "index": 28, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
- "healthCheckProducerEnabled": { "index": 29, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
+ "parameterSpec": { "index": 21, "kind": "property", "displayName":
"Parameter Spec", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The NIST parameter set
(security level) to use for the configured signature or key [...]
+ "signatureAlgorithm": { "index": 22, "kind": "property", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "c [...]
+ "signer": { "index": 23, "kind": "property", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
+ "statefulKeyWarningThreshold": { "index": 24, "kind": "property",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key exh
[...]
+ "storeExtractedSecretKeyAsHeader": { "index": 25, "kind": "property",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSec [...]
+ "strictKeyLifecycle": { "index": 26, "kind": "property", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
+ "symmetricKeyAlgorithm": { "index": 27, "kind": "property", "displayName":
"Symmetric Key Algorithm", "group": "advanced", "label": "advanced",
"required": false, "type": "enum", "javaType": "java.lang.String", "enum": [
"AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6", "CHACHA7539",
"DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128", "HC256",
"SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false, "deprecationNote":
"", "autowired": false, "secret": false, "co [...]
+ "symmetricKeyLength": { "index": 28, "kind": "property", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" },
+ "healthCheckConsumerEnabled": { "index": 29, "kind": "property",
"displayName": "Health Check Consumer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all consumer based health checks
from this component" },
+ "healthCheckProducerEnabled": { "index": 30, "kind": "property",
"displayName": "Health Check Producer Enabled", "group": "health", "label":
"health", "required": false, "type": "boolean", "javaType": "boolean",
"deprecated": false, "autowired": false, "secret": false, "defaultValue": true,
"description": "Used for enabling or disabling all producer based health checks
from this component. Notice: Camel has by default disabled all producer based
health-checks. You can turn on produce [...]
},
"headers": {
"CamelPQCOperation": { "index": 0, "kind": "header", "displayName": "",
"group": "producer", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The operation we want to perform", "constantName":
"org.apache.camel.component.pqc.PQCConstants#OPERATION" },
@@ -97,12 +98,13 @@
"keyPairAlias": { "index": 13, "kind": "parameter", "displayName": "Key
Pair Alias", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "A KeyPair alias to use
in combination with KeyStore parameter" },
"keyStore": { "index": 14, "kind": "parameter", "displayName": "Key
Store", "group": "advanced", "label": "advanced", "required": false, "type":
"object", "javaType": "java.security.KeyStore", "deprecated": false,
"deprecationNote": "", "autowired": true, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "A KeyStore where we
could get Cryptographic material" },
"keyStorePassword": { "index": 15, "kind": "parameter", "displayName":
"Key Store Password", "group": "advanced", "label": "advanced", "required":
false, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": true, "security":
"secret", "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The KeyStore password to use in combination
with KeySt [...]
- "signatureAlgorithm": { "index": 16, "kind": "parameter", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", " [...]
- "signer": { "index": 17, "kind": "parameter", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
- "statefulKeyWarningThreshold": { "index": 18, "kind": "parameter",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key ex [...]
- "storeExtractedSecretKeyAsHeader": { "index": 19, "kind": "parameter",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSe [...]
- "strictKeyLifecycle": { "index": 20, "kind": "parameter", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
- "symmetricKeyAlgorithm": { "index": 21, "kind": "parameter",
"displayName": "Symmetric Key Algorithm", "group": "advanced", "label":
"advanced", "required": false, "type": "enum", "javaType": "java.lang.String",
"enum": [ "AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6",
"CHACHA7539", "DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128",
"HC256", "SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "c [...]
- "symmetricKeyLength": { "index": 22, "kind": "parameter", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" }
+ "parameterSpec": { "index": 16, "kind": "parameter", "displayName":
"Parameter Spec", "group": "advanced", "label": "advanced", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false,
"configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The NIST parameter set
(security level) to use for the configured signature or key [...]
+ "signatureAlgorithm": { "index": 17, "kind": "parameter", "displayName":
"Signature Algorithm", "group": "advanced", "label": "advanced", "required":
false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLDSA",
"SLHDSA", "LMS", "HSS", "XMSS", "XMSSMT", "DILITHIUM", "FALCON", "PICNIC",
"SNOVA", "MAYO", "SPHINCSPLUS" ], "deprecated": false, "deprecationNote": "",
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", " [...]
+ "signer": { "index": 18, "kind": "parameter", "displayName": "Signer",
"group": "advanced", "label": "advanced", "required": false, "type": "object",
"javaType": "java.security.Signature", "deprecated": false, "deprecationNote":
"", "autowired": true, "secret": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The Signer to be used" },
+ "statefulKeyWarningThreshold": { "index": 19, "kind": "parameter",
"displayName": "Stateful Key Warning Threshold", "group": "advanced", "label":
"advanced", "required": false, "type": "number", "javaType": "double",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "defaultValue": 0.1, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "The warning threshold for stateful key ex [...]
+ "storeExtractedSecretKeyAsHeader": { "index": 20, "kind": "parameter",
"displayName": "Store Extracted Secret Key As Header", "group": "advanced",
"label": "advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "deprecationNote": "", "autowired": false,
"secret": false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.pqc.PQCConfiguration", "configurationField":
"configuration", "description": "In the context of extractSe [...]
+ "strictKeyLifecycle": { "index": 21, "kind": "parameter", "displayName":
"Strict Key Lifecycle", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
true, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "Whether to enforce key
status checks before cryptographic [...]
+ "symmetricKeyAlgorithm": { "index": 22, "kind": "parameter",
"displayName": "Symmetric Key Algorithm", "group": "advanced", "label":
"advanced", "required": false, "type": "enum", "javaType": "java.lang.String",
"enum": [ "AES", "ARIA", "RC2", "RC5", "CAMELLIA", "CAST5", "CAST6",
"CHACHA7539", "DSTU7624", "GOST28147", "GOST3412_2015", "GRAIN128", "HC128",
"HC256", "SALSA20", "SEED", "SM4", "DESEDE" ], "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "c [...]
+ "symmetricKeyLength": { "index": 23, "kind": "parameter", "displayName":
"Symmetric Key Length", "group": "advanced", "label": "advanced", "required":
false, "type": "integer", "javaType": "int", "deprecated": false,
"deprecationNote": "", "autowired": false, "secret": false, "defaultValue":
128, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration",
"configurationField": "configuration", "description": "The required length of
the symmetric key used" }
}
}
diff --git a/components/camel-pqc/src/main/docs/pqc-component.adoc
b/components/camel-pqc/src/main/docs/pqc-component.adoc
index 838534e7111c..cd3c119d70f4 100644
--- a/components/camel-pqc/src/main/docs/pqc-component.adoc
+++ b/components/camel-pqc/src/main/docs/pqc-component.adoc
@@ -63,6 +63,55 @@ Experimental and non-standardized
- MAYO
- SPHINCS+
+== Parameter Sets (NIST Security Levels)
+
+By default each algorithm uses a fixed parameter set - for example ML-DSA-65
for `MLDSA` and ML-KEM-512 for `MLKEM`.
+Use the `parameterSpec` option to select a different NIST parameter set
(security level); the key material is then
+generated with that parameter set instead of the algorithm default.
+
+._Java DSL: selecting ML-DSA-87 (NIST level 5)_
+[source,java]
+----
+from("direct:sign")
+
.to("pqc:sign?operation=sign&signatureAlgorithm=MLDSA¶meterSpec=ML-DSA-87")
+
.to("pqc:verify?operation=verify&signatureAlgorithm=MLDSA¶meterSpec=ML-DSA-87");
+----
+
+Endpoints configured with the same algorithm and `parameterSpec` share the
same generated key, so a sign/verify endpoint
+pair works out of the box - exactly as with the default key material.
+
+Values are the BouncyCastle parameter-set names, resolved case-insensitively.
The underscore form used by the
+BouncyCastle constants (`ml_dsa_87`) is accepted as an alias of the canonical
name (`ML-DSA-87`).
+
+[cols="1,3",options="header"]
+|===
+| Algorithm | Parameter sets
+
+| `MLDSA` | `ML-DSA-44`, `ML-DSA-65` (default), `ML-DSA-87`
+| `MLKEM` | `ML-KEM-512` (default), `ML-KEM-768`, `ML-KEM-1024`
+| `SLHDSA` | `SLH-DSA-SHA2-128S`, `SLH-DSA-SHAKE-256F`, ... (see
`SLHDSAParameterSpec`)
+| `FALCON` | `FALCON-512`, `FALCON-1024`
+| `DILITHIUM` | `DILITHIUM2`, `DILITHIUM3`, `DILITHIUM5`
+| `SPHINCSPLUS` | `sha2-128s`, ... (see `SPHINCSPlusParameterSpec`)
+| `PICNIC` | `picnicl1fs`, ... (see `PicnicParameterSpec`)
+| `KYBER` | `kyber512`, `kyber768`, `kyber1024`
+| `NTRU` | `ntruhps2048509`, ... (see `NTRUParameterSpec`)
+| `NTRULPRime` | `ntrulpr653`, ... (see `NTRULPRimeParameterSpec`)
+| `SNTRUPrime` | `sntrup761`, ... (see `SNTRUPrimeParameterSpec`)
+| `BIKE` | `bike128`, `bike192`, `bike256`
+| `HQC` | `hqc128`, `hqc192`, `hqc256`
+| `CMCE` | `mceliece348864`, ... (see `CMCEParameterSpec`)
+| `FRODO` | `frodokem640aes`, ... (see `FrodoParameterSpec`)
+| `SABER` | `lightsaberkem128r3`, ... (see `SABERParameterSpec`)
+|===
+
+The `parameterSpec` option is also honoured by the `generateKeyPair` lifecycle
operation, which then generates the key
+at the configured security level.
+
+NOTE: `parameterSpec` is not supported for the stateful hash-based signature
algorithms (XMSS, XMSSMT, LMS, HSS), for
+MAYO and SNOVA, nor for the hybrid operations: those either have no
name-addressable BouncyCastle parameter set, or pair
+a fixed classical key set with a matching PQC key set. For those, register a
`KeyPair` bean in the registry instead.
+
== Supported Operations
The component supports the following operations:
diff --git
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
index a8e9942bd882..65643de19781 100644
---
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
+++
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCComponent.java
@@ -16,8 +16,16 @@
*/
package org.apache.camel.component.pqc;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Security;
+import java.security.Signature;
+import java.security.spec.AlgorithmParameterSpec;
import java.time.Duration;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.crypto.KeyGenerator;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
@@ -30,6 +38,9 @@ import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.annotations.Component;
import org.apache.camel.support.HealthCheckComponent;
import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.SecureRandomHelper;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
/**
* For working with Post Quantum Cryptography Algorithms
@@ -58,6 +69,10 @@ public class PQCComponent extends HealthCheckComponent {
private KeyRotationScheduler keyRotationScheduler;
+ // Key pairs generated for a specific parameterSpec, cached per algorithm
and parameter set so that endpoints
+ // sharing the same configuration (for example a sign and a verify
endpoint) use the same key
+ private final Map<String, KeyPair> parameterSpecKeyPairs = new
ConcurrentHashMap<>();
+
public PQCComponent() {
this(null);
}
@@ -73,6 +88,12 @@ public class PQCComponent extends HealthCheckComponent {
PQCEndpoint endpoint = new PQCEndpoint(uri, this, configuration);
setProperties(endpoint, parameters);
+ // When a parameterSpec (NIST security level) is configured, generate
the key material with that parameter set
+ // instead of using the algorithm's hardcoded default material
+ if (ObjectHelper.isNotEmpty(configuration.getParameterSpec())) {
+ configureParameterSpecMaterial(configuration);
+ }
+
if (ObjectHelper.isEmpty(configuration.getSigner()) &&
ObjectHelper.isEmpty(configuration.getKeyPair())
&& ObjectHelper.isEmpty(configuration.getKeyStore()) &&
ObjectHelper.isEmpty(configuration.getKeyPairAlias())) {
if
(ObjectHelper.isNotEmpty(configuration.getSignatureAlgorithm())) {
@@ -178,6 +199,90 @@ public class PQCComponent extends HealthCheckComponent {
return endpoint;
}
+ /**
+ * Generates the key material for the configured parameterSpec (the NIST
parameter set / security level) instead of
+ * using the algorithm's hardcoded default material. Key material supplied
explicitly by the route author always
+ * wins and is never regenerated.
+ */
+ private void configureParameterSpecMaterial(PQCConfiguration
configuration) throws Exception {
+ PQCOperations operation = configuration.getOperation();
+ if (operation != null && isHybridOperation(operation)) {
+ // The hybrid operations pair a specific classical key set with a
matching PQC key set, so a custom
+ // parameter set cannot be applied without breaking that pairing
+ throw new IllegalArgumentException(
+ "The parameterSpec option is not supported for hybrid
operations. Configure the hybrid key material"
+ + " explicitly (keyPair and
classicalKeyPair) instead.");
+ }
+
+ if (ObjectHelper.isNotEmpty(configuration.getKeyPair()) ||
ObjectHelper.isNotEmpty(configuration.getKeyStore())
+ || ObjectHelper.isNotEmpty(configuration.getKeyPairAlias())) {
+ // The route author supplied the key material explicitly
+ return;
+ }
+
+ if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+ if (Security.getProvider(BouncyCastlePQCProvider.PROVIDER_NAME) ==
null) {
+ Security.addProvider(new BouncyCastlePQCProvider());
+ }
+
+ String spec = configuration.getParameterSpec();
+ String signatureAlgorithm = configuration.getSignatureAlgorithm();
+ String kemAlgorithm = configuration.getKeyEncapsulationAlgorithm();
+
+ if (ObjectHelper.isNotEmpty(signatureAlgorithm)) {
+ PQCSignatureAlgorithms algorithm =
PQCSignatureAlgorithms.valueOf(signatureAlgorithm);
+ configuration.setKeyPair(
+ resolveKeyPair(signatureAlgorithm, spec,
algorithm.getAlgorithm(), algorithm.getBcProvider()));
+ if (ObjectHelper.isEmpty(configuration.getSigner())) {
+
configuration.setSigner(Signature.getInstance(algorithm.getAlgorithm(),
algorithm.getBcProvider()));
+ }
+ } else if (ObjectHelper.isNotEmpty(kemAlgorithm)) {
+ PQCKeyEncapsulationAlgorithms algorithm =
PQCKeyEncapsulationAlgorithms.valueOf(kemAlgorithm);
+ configuration.setKeyPair(
+ resolveKeyPair(kemAlgorithm, spec,
algorithm.getAlgorithm(), algorithm.getBcProvider()));
+ if (ObjectHelper.isEmpty(configuration.getKeyGenerator())) {
+ configuration.setKeyGenerator(
+ KeyGenerator.getInstance(algorithm.getAlgorithm(),
algorithm.getBcProvider()));
+ }
+ } else {
+ throw new IllegalArgumentException(
+ "The parameterSpec option requires either
signatureAlgorithm or keyEncapsulationAlgorithm to be"
+ + " set");
+ }
+ }
+
+ /**
+ * Returns the key pair for the given algorithm and parameter set,
generating it on first use. The key pair is
+ * cached per algorithm and parameter set so that endpoints sharing the
same configuration - for example a sign and
+ * a verify endpoint - use the same key, mirroring the behaviour of the
shared default key material.
+ */
+ private KeyPair resolveKeyPair(String algorithm, String parameterSpec,
String jceAlgorithm, String provider)
+ throws Exception {
+ String cacheKey = algorithm + ':' + parameterSpec;
+ KeyPair keyPair = parameterSpecKeyPairs.get(cacheKey);
+ if (keyPair == null) {
+ AlgorithmParameterSpec spec =
PQCParameterSpecResolver.resolve(algorithm, parameterSpec);
+ KeyPairGenerator generator =
KeyPairGenerator.getInstance(jceAlgorithm, provider);
+ generator.initialize(spec, SecureRandomHelper.getSecureRandom());
+ keyPair = generator.generateKeyPair();
+ KeyPair existing = parameterSpecKeyPairs.putIfAbsent(cacheKey,
keyPair);
+ if (existing != null) {
+ keyPair = existing;
+ }
+ }
+ return keyPair;
+ }
+
+ private static boolean isHybridOperation(PQCOperations operation) {
+ return operation == PQCOperations.hybridSign
+ || operation == PQCOperations.hybridVerify
+ || operation ==
PQCOperations.hybridGenerateSecretKeyEncapsulation
+ || operation ==
PQCOperations.hybridExtractSecretKeyEncapsulation
+ || operation ==
PQCOperations.hybridExtractSecretKeyFromEncapsulation;
+ }
+
/**
* Auto-configures hybrid signature materials based on classical and PQC
algorithm settings.
*/
diff --git
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCConfiguration.java
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCConfiguration.java
index c28515872c29..c84d1a490598 100644
---
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCConfiguration.java
+++
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCConfiguration.java
@@ -54,6 +54,9 @@ public class PQCConfiguration implements Cloneable {
@UriParam(enums =
"MLKEM,BIKE,HQC,CMCE,SABER,FRODO,NTRU,NTRULPRime,SNTRUPrime,KYBER")
@Metadata(label = "advanced")
private String keyEncapsulationAlgorithm;
+ @UriParam
+ @Metadata(label = "advanced")
+ private String parameterSpec;
@UriParam(enums =
"AES,ARIA,RC2,RC5,CAMELLIA,CAST5,CAST6,CHACHA7539,DSTU7624,GOST28147,GOST3412_2015,GRAIN128,HC128,HC256,SALSA20,SEED,SM4,DESEDE")
@Metadata(label = "advanced")
private String symmetricKeyAlgorithm;
@@ -188,6 +191,22 @@ public class PQCConfiguration implements Cloneable {
this.keyEncapsulationAlgorithm = keyEncapsulationAlgorithm;
}
+ public String getParameterSpec() {
+ return parameterSpec;
+ }
+
+ /**
+ * The NIST parameter set (security level) to use for the configured
signature or key encapsulation algorithm, using
+ * the BouncyCastle parameter-set names: for example ML-DSA-44, ML-DSA-65
or ML-DSA-87 for MLDSA, and ML-KEM-512,
+ * ML-KEM-768 or ML-KEM-1024 for MLKEM. Names are case-insensitive and the
underscore form (ml_dsa_87) is accepted
+ * as an alias. When set, the key material is generated with this
parameter set instead of the algorithm default.
+ * Not supported for the stateful signature algorithms (XMSS, XMSSMT, LMS,
HSS), for MAYO and SNOVA, nor for the
+ * hybrid operations: for those, register a KeyPair bean in the registry
instead.
+ */
+ public void setParameterSpec(String parameterSpec) {
+ this.parameterSpec = parameterSpec;
+ }
+
public String getSymmetricKeyAlgorithm() {
return symmetricKeyAlgorithm;
}
diff --git
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCParameterSpecResolver.java
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCParameterSpecResolver.java
new file mode 100644
index 000000000000..c0fcff9a4c44
--- /dev/null
+++
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCParameterSpecResolver.java
@@ -0,0 +1,153 @@
+/*
+ * 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.spec.AlgorithmParameterSpec;
+import java.util.Set;
+
+import org.apache.camel.util.ObjectHelper;
+import org.bouncycastle.jcajce.spec.MLDSAParameterSpec;
+import org.bouncycastle.jcajce.spec.MLKEMParameterSpec;
+import org.bouncycastle.jcajce.spec.SLHDSAParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.BIKEParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.CMCEParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.DilithiumParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.FalconParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.FrodoParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.HQCParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.KyberParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.NTRULPRimeParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.NTRUParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.PicnicParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.SABERParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.SNTRUPrimeParameterSpec;
+import org.bouncycastle.pqc.jcajce.spec.SPHINCSPlusParameterSpec;
+
+/**
+ * Resolves the BouncyCastle {@link AlgorithmParameterSpec} for a PQC
algorithm from the parameter-set name configured
+ * on the endpoint, for example {@code ML-DSA-87} for {@code MLDSA} or {@code
ML-KEM-1024} for {@code MLKEM}.
+ * <p/>
+ * Names are resolved case-insensitively, and the underscore form used by the
BouncyCastle constants ({@code ml_dsa_87})
+ * is accepted as an alias of the canonical dashed name ({@code ML-DSA-87}).
+ * <p/>
+ * The parameter set determines the NIST security level of the generated key
material. The stateful hash-based signature
+ * algorithms (XMSS, XMSSMT, LMS, HSS) and MAYO/SNOVA have no name-addressable
BouncyCastle parameter spec and are
+ * therefore not supported here - for those, register a
KeyPair/Signature/KeyGenerator bean in the registry instead.
+ */
+public final class PQCParameterSpecResolver {
+
+ /**
+ * The algorithms for which a parameter set can be selected by name.
+ */
+ private static final Set<String> SUPPORTED_ALGORITHMS = Set.of(
+ // Signature algorithms
+ "MLDSA", "SLHDSA", "FALCON", "DILITHIUM", "SPHINCSPLUS", "PICNIC",
+ // Key encapsulation algorithms
+ "MLKEM", "KYBER", "NTRU", "NTRULPRime", "SNTRUPrime", "BIKE",
"HQC", "CMCE", "FRODO", "SABER");
+
+ private PQCParameterSpecResolver() {
+ }
+
+ /**
+ * Whether a parameter set can be selected by name for the given algorithm.
+ */
+ public static boolean isSupported(String algorithm) {
+ return algorithm != null && SUPPORTED_ALGORITHMS.contains(algorithm);
+ }
+
+ /**
+ * Resolves the parameter spec for the given algorithm.
+ *
+ * @param algorithm the PQC signature or key encapsulation
algorithm
+ * @param parameterSpec the parameter-set name as defined by
BouncyCastle, for example {@code ml_dsa_65}
+ * @return the resolved parameter spec
+ * @throws IllegalArgumentException if the algorithm has no
name-addressable parameter set, or the name is unknown
+ */
+ public static AlgorithmParameterSpec resolve(String algorithm, String
parameterSpec) {
+ ObjectHelper.notNull(algorithm, "algorithm");
+ ObjectHelper.notNull(parameterSpec, "parameterSpec");
+
+ if (!isSupported(algorithm)) {
+ throw new IllegalArgumentException(
+ "The parameterSpec option is not supported for algorithm "
+ algorithm
+ + ". Supported algorithms are:
" + SUPPORTED_ALGORITHMS
+ + ". For the stateful signature
algorithms (XMSS, XMSSMT, LMS, HSS) and"
+ + " for MAYO/SNOVA, register a
KeyPair bean in the registry instead.");
+ }
+
+ // BouncyCastle resolves parameter-set names case-insensitively but
never uses underscores in them, so accept
+ // the underscore form (ml_dsa_87), which matches the BouncyCastle
constant names, as an alias.
+ String name = parameterSpec.replace('_', '-');
+
+ AlgorithmParameterSpec resolved;
+ try {
+ resolved = doResolve(algorithm, name);
+ } catch (IllegalArgumentException e) {
+ // The ML-DSA/ML-KEM/SLH-DSA specs throw for an unknown name
+ throw new IllegalArgumentException(
+ "Unknown parameterSpec '" + parameterSpec + "' for
algorithm " + algorithm, e);
+ }
+ if (resolved == null) {
+ // The older BouncyCastle specs return null instead of throwing
for an unknown name
+ throw new IllegalArgumentException(
+ "Unknown parameterSpec '" + parameterSpec + "' for
algorithm " + algorithm);
+ }
+ return resolved;
+ }
+
+ private static AlgorithmParameterSpec doResolve(String algorithm, String
parameterSpec) {
+ switch (algorithm) {
+ // Signature algorithms
+ case "MLDSA":
+ return MLDSAParameterSpec.fromName(parameterSpec);
+ case "SLHDSA":
+ return SLHDSAParameterSpec.fromName(parameterSpec);
+ case "FALCON":
+ return FalconParameterSpec.fromName(parameterSpec);
+ case "DILITHIUM":
+ return DilithiumParameterSpec.fromName(parameterSpec);
+ case "SPHINCSPLUS":
+ return SPHINCSPlusParameterSpec.fromName(parameterSpec);
+ case "PICNIC":
+ return PicnicParameterSpec.fromName(parameterSpec);
+ // Key encapsulation algorithms
+ case "MLKEM":
+ return MLKEMParameterSpec.fromName(parameterSpec);
+ case "KYBER":
+ return KyberParameterSpec.fromName(parameterSpec);
+ case "NTRU":
+ return NTRUParameterSpec.fromName(parameterSpec);
+ case "NTRULPRime":
+ return NTRULPRimeParameterSpec.fromName(parameterSpec);
+ case "SNTRUPrime":
+ return SNTRUPrimeParameterSpec.fromName(parameterSpec);
+ case "BIKE":
+ return BIKEParameterSpec.fromName(parameterSpec);
+ case "HQC":
+ return HQCParameterSpec.fromName(parameterSpec);
+ case "CMCE":
+ return CMCEParameterSpec.fromName(parameterSpec);
+ case "FRODO":
+ return FrodoParameterSpec.fromName(parameterSpec);
+ case "SABER":
+ return SABERParameterSpec.fromName(parameterSpec);
+ default:
+ // Guarded by isSupported above
+ throw new IllegalStateException("Unsupported algorithm: " +
algorithm);
+ }
+ }
+}
diff --git
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCProducer.java
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCProducer.java
index 8906a5a2cfa7..920911b999e0 100644
---
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCProducer.java
+++
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCProducer.java
@@ -805,7 +805,14 @@ public class PQCProducer extends DefaultProducer {
throw new IllegalArgumentException("Key ID header (" +
PQCConstants.KEY_ID + ") is required for generateKeyPair");
}
- KeyPair generated = klm.generateKeyPair(algorithm, keyId);
+ String parameterSpec = getConfiguration().getParameterSpec();
+ KeyPair generated;
+ if (ObjectHelper.isNotEmpty(parameterSpec)) {
+ // Use the parameterSpec-aware overload so the key is generated at
the configured NIST security level
+ generated = klm.generateKeyPair(algorithm, keyId,
PQCParameterSpecResolver.resolve(algorithm, parameterSpec));
+ } else {
+ generated = klm.generateKeyPair(algorithm, keyId);
+ }
exchange.getMessage().setHeader(PQCConstants.KEY_PAIR, generated);
}
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCParameterSpecResolverTest.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCParameterSpecResolverTest.java
new file mode 100644
index 000000000000..6164c533dcdc
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCParameterSpecResolverTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.Security;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class PQCParameterSpecResolverTest {
+
+ @BeforeAll
+ 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());
+ }
+ }
+
+ @Test
+ void testResolveSignatureParameterSets() {
+ // canonical BouncyCastle names
+ assertNotNull(PQCParameterSpecResolver.resolve("MLDSA", "ML-DSA-44"));
+ assertNotNull(PQCParameterSpecResolver.resolve("MLDSA", "ML-DSA-87"));
+ assertNotNull(PQCParameterSpecResolver.resolve("SLHDSA",
"SLH-DSA-SHA2-128S"));
+ assertNotNull(PQCParameterSpecResolver.resolve("FALCON",
"FALCON-1024"));
+ }
+
+ @Test
+ void testNamesAreCaseInsensitiveAndAcceptUnderscoreAlias() {
+ assertNotNull(PQCParameterSpecResolver.resolve("MLDSA", "ml-dsa-65"));
+ // the underscore form matching the BouncyCastle constant names is
accepted as an alias
+ assertNotNull(PQCParameterSpecResolver.resolve("MLDSA", "ml_dsa_87"));
+ assertNotNull(PQCParameterSpecResolver.resolve("MLKEM",
"ml_kem_1024"));
+ }
+
+ @Test
+ void testResolveKeyEncapsulationParameterSets() {
+ assertNotNull(PQCParameterSpecResolver.resolve("MLKEM", "ml_kem_512"));
+ assertNotNull(PQCParameterSpecResolver.resolve("MLKEM",
"ml_kem_1024"));
+ assertNotNull(PQCParameterSpecResolver.resolve("KYBER", "kyber768"));
+ assertNotNull(PQCParameterSpecResolver.resolve("BIKE", "bike128"));
+ }
+
+ @Test
+ void testIsSupported() {
+ assertTrue(PQCParameterSpecResolver.isSupported("MLDSA"));
+ assertTrue(PQCParameterSpecResolver.isSupported("MLKEM"));
+ // Stateful hash-based signatures and MAYO/SNOVA have no
name-addressable parameter spec
+ assertFalse(PQCParameterSpecResolver.isSupported("XMSS"));
+ assertFalse(PQCParameterSpecResolver.isSupported("XMSSMT"));
+ assertFalse(PQCParameterSpecResolver.isSupported("LMS"));
+ assertFalse(PQCParameterSpecResolver.isSupported("HSS"));
+ assertFalse(PQCParameterSpecResolver.isSupported("MAYO"));
+ assertFalse(PQCParameterSpecResolver.isSupported("SNOVA"));
+ assertFalse(PQCParameterSpecResolver.isSupported(null));
+ }
+
+ @Test
+ void testUnsupportedAlgorithmRejected() {
+ IllegalArgumentException e =
assertThrows(IllegalArgumentException.class,
+ () -> PQCParameterSpecResolver.resolve("XMSS", "anything"));
+ assertTrue(e.getMessage().contains("not supported"));
+ }
+
+ @Test
+ void testUnknownParameterSpecRejected() {
+ // ML-DSA/ML-KEM/SLH-DSA throw for an unknown name
+ IllegalArgumentException e =
assertThrows(IllegalArgumentException.class,
+ () -> PQCParameterSpecResolver.resolve("MLDSA", "ml_dsa_999"));
+ assertTrue(e.getMessage().contains("Unknown parameterSpec"));
+ }
+
+ @Test
+ void testUnknownParameterSpecRejectedWhenSpecReturnsNull() {
+ // the older BouncyCastle spec classes return null rather than
throwing for an unknown name
+ IllegalArgumentException e =
assertThrows(IllegalArgumentException.class,
+ () -> PQCParameterSpecResolver.resolve("BIKE", "bogus"));
+ assertTrue(e.getMessage().contains("Unknown parameterSpec"));
+ }
+}
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCParameterSpecTest.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCParameterSpecTest.java
new file mode 100644
index 000000000000..90045fac3381
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCParameterSpecTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.Security;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PQCParameterSpecTest extends CamelTestSupport {
+
+ @EndpointInject("mock:verify")
+ protected MockEndpoint resultVerify;
+
+ @BeforeAll
+ public static void startup() {
+ if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ // sign and verify use the same algorithm + parameterSpec, so
they must share the same key
+ from("direct:sign")
+
.to("pqc:sign?operation=sign&signatureAlgorithm=MLDSA¶meterSpec=ml_dsa_87")
+
.to("pqc:verify?operation=verify&signatureAlgorithm=MLDSA¶meterSpec=ml_dsa_87")
+ .to("mock:verify");
+ }
+ };
+ }
+
+ private int publicKeyLength(String uri) {
+ PQCEndpoint endpoint = context.getEndpoint(uri, PQCEndpoint.class);
+ return
endpoint.getConfiguration().getKeyPair().getPublic().getEncoded().length;
+ }
+
+ @Test
+ void testParameterSpecDrivesSignatureKeySize() {
+ int pk44 =
publicKeyLength("pqc:a?operation=sign&signatureAlgorithm=MLDSA¶meterSpec=ml_dsa_44");
+ int pk65 =
publicKeyLength("pqc:b?operation=sign&signatureAlgorithm=MLDSA¶meterSpec=ml_dsa_65");
+ int pk87 =
publicKeyLength("pqc:c?operation=sign&signatureAlgorithm=MLDSA¶meterSpec=ml_dsa_87");
+ assertTrue(pk44 < pk65, "ml_dsa_44 public key should be smaller than
ml_dsa_65");
+ assertTrue(pk65 < pk87, "ml_dsa_65 public key should be smaller than
ml_dsa_87");
+ }
+
+ @Test
+ void testParameterSpecDrivesKemKeySize() {
+ int pk512 =
publicKeyLength("pqc:k1?operation=generateSecretKeyEncapsulation"
+ +
"&keyEncapsulationAlgorithm=MLKEM¶meterSpec=ml_kem_512");
+ int pk1024 =
publicKeyLength("pqc:k2?operation=generateSecretKeyEncapsulation"
+ +
"&keyEncapsulationAlgorithm=MLKEM¶meterSpec=ml_kem_1024");
+ assertTrue(pk512 < pk1024, "ml_kem_512 public key should be smaller
than ml_kem_1024");
+ }
+
+ @Test
+ void testEndpointsShareTheKeyForTheSameParameterSpec() {
+ PQCEndpoint sign = context.getEndpoint(
+
"pqc:s1?operation=sign&signatureAlgorithm=MLDSA¶meterSpec=ml_dsa_44",
PQCEndpoint.class);
+ PQCEndpoint verify = context.getEndpoint(
+
"pqc:s2?operation=verify&signatureAlgorithm=MLDSA¶meterSpec=ml_dsa_44",
PQCEndpoint.class);
+
assertArrayEquals(sign.getConfiguration().getKeyPair().getPublic().getEncoded(),
+
verify.getConfiguration().getKeyPair().getPublic().getEncoded(),
+ "endpoints with the same algorithm and parameterSpec must
share the same key");
+ }
+
+ @Test
+ void testSignVerifyWithNonDefaultParameterSpec() throws Exception {
+ resultVerify.expectedMessageCount(1);
+ template.sendBody("direct:sign", "hello ml-dsa-87");
+ resultVerify.assertIsSatisfied();
+
assertTrue(resultVerify.getExchanges().get(0).getMessage().getHeader(PQCConstants.VERIFY,
Boolean.class),
+ "a signature made with a non-default parameter set should
verify");
+ }
+
+ @Test
+ void testUnsupportedAlgorithmIsRejected() {
+ // XMSS has no name-addressable parameter spec
+ assertThrows(Exception.class,
+ () ->
context.getEndpoint("pqc:x?operation=sign&signatureAlgorithm=XMSS¶meterSpec=whatever",
+ PQCEndpoint.class));
+ }
+
+ @Test
+ void testHybridOperationIsRejected() {
+ assertThrows(Exception.class,
+ () -> context.getEndpoint(
+
"pqc:h?operation=hybridSign&signatureAlgorithm=MLDSA&classicalSignatureAlgorithm=ECDSA_P256"
+ + "¶meterSpec=ml_dsa_87",
+ PQCEndpoint.class));
+ }
+}
diff --git
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
index be73ea8fdd64..869bd26fa51c 100644
---
a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
+++
b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PqcComponentBuilderFactory.java
@@ -407,6 +407,30 @@ public interface PqcComponentBuilderFactory {
return this;
}
+ /**
+ * The NIST parameter set (security level) to use for the configured
+ * signature or key encapsulation algorithm, using the BouncyCastle
+ * parameter-set names: for example ML-DSA-44, ML-DSA-65 or ML-DSA-87
+ * for MLDSA, and ML-KEM-512, ML-KEM-768 or ML-KEM-1024 for MLKEM.
Names
+ * are case-insensitive and the underscore form (ml_dsa_87) is accepted
+ * as an alias. When set, the key material is generated with this
+ * parameter set instead of the algorithm default. Not supported for
the
+ * stateful signature algorithms (XMSS, XMSSMT, LMS, HSS), for MAYO and
+ * SNOVA, nor for the hybrid operations: for those, register a KeyPair
+ * bean in the registry instead.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: advanced
+ *
+ * @param parameterSpec the value to set
+ * @return the dsl builder
+ */
+ default PqcComponentBuilder parameterSpec(java.lang.String
parameterSpec) {
+ doSetProperty("parameterSpec", parameterSpec);
+ return this;
+ }
+
/**
* In case there is no signer, we specify an algorithm to build the
* KeyPair or the Signer.
@@ -613,6 +637,7 @@ public interface PqcComponentBuilderFactory {
case "keyRotationSchedulerEnabled": ((PQCComponent)
component).setKeyRotationSchedulerEnabled((boolean) value); return true;
case "keyStore": getOrCreateConfiguration((PQCComponent)
component).setKeyStore((java.security.KeyStore) value); return true;
case "keyStorePassword": getOrCreateConfiguration((PQCComponent)
component).setKeyStorePassword((java.lang.String) value); return true;
+ case "parameterSpec": getOrCreateConfiguration((PQCComponent)
component).setParameterSpec((java.lang.String) value); return true;
case "signatureAlgorithm": getOrCreateConfiguration((PQCComponent)
component).setSignatureAlgorithm((java.lang.String) value); return true;
case "signer": getOrCreateConfiguration((PQCComponent)
component).setSigner((java.security.Signature) value); return true;
case "statefulKeyWarningThreshold":
getOrCreateConfiguration((PQCComponent)
component).setStatefulKeyWarningThreshold((double) value); return true;
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PQCEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PQCEndpointBuilderFactory.java
index 7c079a7ec760..547230ed89fc 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PQCEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PQCEndpointBuilderFactory.java
@@ -432,6 +432,29 @@ public interface PQCEndpointBuilderFactory {
doSetProperty("keyStorePassword", keyStorePassword);
return this;
}
+ /**
+ * The NIST parameter set (security level) to use for the configured
+ * signature or key encapsulation algorithm, using the BouncyCastle
+ * parameter-set names: for example ML-DSA-44, ML-DSA-65 or ML-DSA-87
+ * for MLDSA, and ML-KEM-512, ML-KEM-768 or ML-KEM-1024 for MLKEM.
Names
+ * are case-insensitive and the underscore form (ml_dsa_87) is accepted
+ * as an alias. When set, the key material is generated with this
+ * parameter set instead of the algorithm default. Not supported for
the
+ * stateful signature algorithms (XMSS, XMSSMT, LMS, HSS), for MAYO and
+ * SNOVA, nor for the hybrid operations: for those, register a KeyPair
+ * bean in the registry instead.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: advanced
+ *
+ * @param parameterSpec the value to set
+ * @return the dsl builder
+ */
+ default AdvancedPQCEndpointBuilder parameterSpec(String parameterSpec)
{
+ doSetProperty("parameterSpec", parameterSpec);
+ return this;
+ }
/**
* In case there is no signer, we specify an algorithm to build the
* KeyPair or the Signer.