This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch mlkem in repository https://gitbox.apache.org/repos/asf/camel.git
commit 45729d1cf268f6048595ecd388fb5d304829c030 Author: Andrea Cosentino <anco...@gmail.com> AuthorDate: Fri Apr 18 08:33:54 2025 +0200 CAMEL-21969 - Camel-PQC: Support KEM operations Signed-off-by: Andrea Cosentino <anco...@gmail.com> --- .../org/apache/camel/catalog/components/pqc.json | 26 ++++-- .../component/pqc/PQCComponentConfigurer.java | 20 +++- .../camel/component/pqc/PQCEndpointConfigurer.java | 20 +++- .../camel/component/pqc/PQCEndpointUriFactory.java | 5 +- .../org/apache/camel/component/pqc/pqc.json | 26 ++++-- .../camel/component/pqc/PQCConfiguration.java | 44 +++++++++ ...ons.java => PQCKeyEncapsulationAlgorithms.java} | 18 +++- .../apache/camel/component/pqc/PQCOperations.java | 6 +- .../apache/camel/component/pqc/PQCProducer.java | 68 +++++++++++++- ...Operations.java => PQCSymmetricAlgorithms.java} | 16 +++- .../pqc/PQCMLKEMGenerateEncapsulationAESTest.java | 104 +++++++++++++++++++++ .../component/dsl/PqcComponentBuilderFactory.java | 51 ++++++++++ .../endpoint/dsl/PQCEndpointBuilderFactory.java | 59 ++++++++++++ 13 files changed, 427 insertions(+), 36 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 0695a846795..56a677dff2e 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 @@ -26,13 +26,16 @@ "componentProperties": { "configuration": { "index": 0, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Component configuration" }, "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] - "operation": { "index": 2, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The operation to perform" }, + "operation": { "index": 2, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify", "generateSecretKeyEncapsulation", "extractSecretKeyEncapsulation" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configura [...] "autowiredEnabled": { "index": 3, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] - "keyPair": { "index": 4, "kind": "property", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, - "signatureAlgorithm": { "index": 5, "kind": "property", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair o [...] - "signer": { "index": 6, "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" }, - "healthCheckConsumerEnabled": { "index": 7, "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": 8, "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 producer [...] + "keyEncapsulationAlgorithm": { "index": 4, "kind": "property", "displayName": "Key Encapsulation Algorithm", "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": "In case there is no keyGenerator, we specify an algorithm t [...] + "keyGenerator": { "index": 5, "kind": "property", "displayName": "Key Generator", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.crypto.KeyGenerator", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The Key Generator to be used in encapsulation and extraction" }, + "keyPair": { "index": 6, "kind": "property", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, + "signatureAlgorithm": { "index": 7, "kind": "property", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair o [...] + "signer": { "index": 8, "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" }, + "symmetricKeyAlgorithm": { "index": 9, "kind": "property", "displayName": "Symmetric Key Algorithm", "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": "In case we are using KEM operations, we need a Symmetric algorithm [...] + "healthCheckConsumerEnabled": { "index": 10, "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": 11, "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" }, @@ -41,10 +44,13 @@ }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "Logical name" }, - "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The operation to perform" }, + "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify", "generateSecretKeyEncapsulation", "extractSecretKeyEncapsulation" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configur [...] "lazyStartProducer": { "index": 2, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] - "keyPair": { "index": 3, "kind": "parameter", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, - "signatureAlgorithm": { "index": 4, "kind": "parameter", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair [...] - "signer": { "index": 5, "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" } + "keyEncapsulationAlgorithm": { "index": 3, "kind": "parameter", "displayName": "Key Encapsulation Algorithm", "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": "In case there is no keyGenerator, we specify an algorithm [...] + "keyGenerator": { "index": 4, "kind": "parameter", "displayName": "Key Generator", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.crypto.KeyGenerator", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The Key Generator to be used in encapsulation and extraction" }, + "keyPair": { "index": 5, "kind": "parameter", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, + "signatureAlgorithm": { "index": 6, "kind": "parameter", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair [...] + "signer": { "index": 7, "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" }, + "symmetricKeyAlgorithm": { "index": 8, "kind": "parameter", "displayName": "Symmetric Key Algorithm", "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": "In case we are using KEM operations, we need a Symmetric algorithm [...] } } 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 e74c90c83c0..405f409a321 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 @@ -37,6 +37,10 @@ public class PQCComponentConfigurer extends PropertyConfigurerSupport implements case "healthCheckConsumerEnabled": target.setHealthCheckConsumerEnabled(property(camelContext, boolean.class, value)); return true; case "healthcheckproducerenabled": case "healthCheckProducerEnabled": target.setHealthCheckProducerEnabled(property(camelContext, boolean.class, value)); return true; + case "keyencapsulationalgorithm": + case "keyEncapsulationAlgorithm": getOrCreateConfiguration(target).setKeyEncapsulationAlgorithm(property(camelContext, java.lang.String.class, value)); return true; + case "keygenerator": + case "keyGenerator": getOrCreateConfiguration(target).setKeyGenerator(property(camelContext, javax.crypto.KeyGenerator.class, value)); return true; case "keypair": case "keyPair": getOrCreateConfiguration(target).setKeyPair(property(camelContext, java.security.KeyPair.class, value)); return true; case "lazystartproducer": @@ -45,13 +49,15 @@ public class PQCComponentConfigurer extends PropertyConfigurerSupport implements 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; + case "symmetrickeyalgorithm": + case "symmetricKeyAlgorithm": getOrCreateConfiguration(target).setSymmetricKeyAlgorithm(property(camelContext, java.lang.String.class, value)); return true; default: return false; } } @Override public String[] getAutowiredNames() { - return new String[]{"keyPair", "signer"}; + return new String[]{"keyGenerator", "keyPair", "signer"}; } @Override @@ -64,6 +70,10 @@ public class PQCComponentConfigurer extends PropertyConfigurerSupport implements case "healthCheckConsumerEnabled": return boolean.class; case "healthcheckproducerenabled": case "healthCheckProducerEnabled": return boolean.class; + case "keyencapsulationalgorithm": + case "keyEncapsulationAlgorithm": return java.lang.String.class; + case "keygenerator": + case "keyGenerator": return javax.crypto.KeyGenerator.class; case "keypair": case "keyPair": return java.security.KeyPair.class; case "lazystartproducer": @@ -72,6 +82,8 @@ public class PQCComponentConfigurer extends PropertyConfigurerSupport implements case "signaturealgorithm": case "signatureAlgorithm": return java.lang.String.class; case "signer": return java.security.Signature.class; + case "symmetrickeyalgorithm": + case "symmetricKeyAlgorithm": return java.lang.String.class; default: return null; } } @@ -87,6 +99,10 @@ public class PQCComponentConfigurer extends PropertyConfigurerSupport implements case "healthCheckConsumerEnabled": return target.isHealthCheckConsumerEnabled(); case "healthcheckproducerenabled": case "healthCheckProducerEnabled": return target.isHealthCheckProducerEnabled(); + case "keyencapsulationalgorithm": + case "keyEncapsulationAlgorithm": return getOrCreateConfiguration(target).getKeyEncapsulationAlgorithm(); + case "keygenerator": + case "keyGenerator": return getOrCreateConfiguration(target).getKeyGenerator(); case "keypair": case "keyPair": return getOrCreateConfiguration(target).getKeyPair(); case "lazystartproducer": @@ -95,6 +111,8 @@ public class PQCComponentConfigurer extends PropertyConfigurerSupport implements case "signaturealgorithm": case "signatureAlgorithm": return getOrCreateConfiguration(target).getSignatureAlgorithm(); case "signer": return getOrCreateConfiguration(target).getSigner(); + case "symmetrickeyalgorithm": + case "symmetricKeyAlgorithm": return getOrCreateConfiguration(target).getSymmetricKeyAlgorithm(); default: return null; } } 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 10dad97b29e..3b0b352a379 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 @@ -23,6 +23,10 @@ public class PQCEndpointConfigurer extends PropertyConfigurerSupport implements public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { PQCEndpoint target = (PQCEndpoint) obj; switch (ignoreCase ? name.toLowerCase() : name) { + case "keyencapsulationalgorithm": + case "keyEncapsulationAlgorithm": target.getConfiguration().setKeyEncapsulationAlgorithm(property(camelContext, java.lang.String.class, value)); return true; + case "keygenerator": + case "keyGenerator": target.getConfiguration().setKeyGenerator(property(camelContext, javax.crypto.KeyGenerator.class, value)); return true; case "keypair": case "keyPair": target.getConfiguration().setKeyPair(property(camelContext, java.security.KeyPair.class, value)); return true; case "lazystartproducer": @@ -31,18 +35,24 @@ public class PQCEndpointConfigurer extends PropertyConfigurerSupport implements 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; + case "symmetrickeyalgorithm": + case "symmetricKeyAlgorithm": target.getConfiguration().setSymmetricKeyAlgorithm(property(camelContext, java.lang.String.class, value)); return true; default: return false; } } @Override public String[] getAutowiredNames() { - return new String[]{"keyPair", "signer"}; + return new String[]{"keyGenerator", "keyPair", "signer"}; } @Override public Class<?> getOptionType(String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { + case "keyencapsulationalgorithm": + case "keyEncapsulationAlgorithm": return java.lang.String.class; + case "keygenerator": + case "keyGenerator": return javax.crypto.KeyGenerator.class; case "keypair": case "keyPair": return java.security.KeyPair.class; case "lazystartproducer": @@ -51,6 +61,8 @@ public class PQCEndpointConfigurer extends PropertyConfigurerSupport implements case "signaturealgorithm": case "signatureAlgorithm": return java.lang.String.class; case "signer": return java.security.Signature.class; + case "symmetrickeyalgorithm": + case "symmetricKeyAlgorithm": return java.lang.String.class; default: return null; } } @@ -59,6 +71,10 @@ public class PQCEndpointConfigurer extends PropertyConfigurerSupport implements public Object getOptionValue(Object obj, String name, boolean ignoreCase) { PQCEndpoint target = (PQCEndpoint) obj; switch (ignoreCase ? name.toLowerCase() : name) { + case "keyencapsulationalgorithm": + case "keyEncapsulationAlgorithm": return target.getConfiguration().getKeyEncapsulationAlgorithm(); + case "keygenerator": + case "keyGenerator": return target.getConfiguration().getKeyGenerator(); case "keypair": case "keyPair": return target.getConfiguration().getKeyPair(); case "lazystartproducer": @@ -67,6 +83,8 @@ public class PQCEndpointConfigurer extends PropertyConfigurerSupport implements case "signaturealgorithm": case "signatureAlgorithm": return target.getConfiguration().getSignatureAlgorithm(); case "signer": return target.getConfiguration().getSigner(); + case "symmetrickeyalgorithm": + case "symmetricKeyAlgorithm": return target.getConfiguration().getSymmetricKeyAlgorithm(); default: return null; } } 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 ca4d27133e1..def55d2d54c 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 @@ -23,13 +23,16 @@ public class PQCEndpointUriFactory extends org.apache.camel.support.component.En private static final Set<String> SECRET_PROPERTY_NAMES; private static final Set<String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(6); + Set<String> props = new HashSet<>(9); + props.add("keyEncapsulationAlgorithm"); + props.add("keyGenerator"); props.add("keyPair"); props.add("label"); props.add("lazyStartProducer"); props.add("operation"); props.add("signatureAlgorithm"); props.add("signer"); + props.add("symmetricKeyAlgorithm"); PROPERTY_NAMES = Collections.unmodifiableSet(props); SECRET_PROPERTY_NAMES = Collections.emptySet(); MULTI_VALUE_PREFIXES = Collections.emptySet(); 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 0695a846795..56a677dff2e 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 @@ -26,13 +26,16 @@ "componentProperties": { "configuration": { "index": 0, "kind": "property", "displayName": "Configuration", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Component configuration" }, "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...] - "operation": { "index": 2, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The operation to perform" }, + "operation": { "index": 2, "kind": "property", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify", "generateSecretKeyEncapsulation", "extractSecretKeyEncapsulation" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configura [...] "autowiredEnabled": { "index": 3, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...] - "keyPair": { "index": 4, "kind": "property", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, - "signatureAlgorithm": { "index": 5, "kind": "property", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair o [...] - "signer": { "index": 6, "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" }, - "healthCheckConsumerEnabled": { "index": 7, "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": 8, "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 producer [...] + "keyEncapsulationAlgorithm": { "index": 4, "kind": "property", "displayName": "Key Encapsulation Algorithm", "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": "In case there is no keyGenerator, we specify an algorithm t [...] + "keyGenerator": { "index": 5, "kind": "property", "displayName": "Key Generator", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.crypto.KeyGenerator", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The Key Generator to be used in encapsulation and extraction" }, + "keyPair": { "index": 6, "kind": "property", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, + "signatureAlgorithm": { "index": 7, "kind": "property", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair o [...] + "signer": { "index": 8, "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" }, + "symmetricKeyAlgorithm": { "index": 9, "kind": "property", "displayName": "Symmetric Key Algorithm", "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": "In case we are using KEM operations, we need a Symmetric algorithm [...] + "healthCheckConsumerEnabled": { "index": 10, "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": 11, "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" }, @@ -41,10 +44,13 @@ }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "Logical name" }, - "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The operation to perform" }, + "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify", "generateSecretKeyEncapsulation", "extractSecretKeyEncapsulation" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configur [...] "lazyStartProducer": { "index": 2, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...] - "keyPair": { "index": 3, "kind": "parameter", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, - "signatureAlgorithm": { "index": 4, "kind": "parameter", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair [...] - "signer": { "index": 5, "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" } + "keyEncapsulationAlgorithm": { "index": 3, "kind": "parameter", "displayName": "Key Encapsulation Algorithm", "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": "In case there is no keyGenerator, we specify an algorithm [...] + "keyGenerator": { "index": 4, "kind": "parameter", "displayName": "Key Generator", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "javax.crypto.KeyGenerator", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The Key Generator to be used in encapsulation and extraction" }, + "keyPair": { "index": 5, "kind": "parameter", "displayName": "Key Pair", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.security.KeyPair", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The KeyPair to be used" }, + "signatureAlgorithm": { "index": 6, "kind": "parameter", "displayName": "Signature Algorithm", "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": "In case there is no signer, we specify an algorithm to build the KeyPair [...] + "signer": { "index": 7, "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" }, + "symmetricKeyAlgorithm": { "index": 8, "kind": "parameter", "displayName": "Symmetric Key Algorithm", "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": "In case we are using KEM operations, we need a Symmetric algorithm [...] } } 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 35fad553e73..b0f0fa92983 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 @@ -19,6 +19,8 @@ package org.apache.camel.component.pqc; import java.security.KeyPair; import java.security.Signature; +import javax.crypto.KeyGenerator; + import org.apache.camel.RuntimeCamelException; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriParam; @@ -43,6 +45,15 @@ public class PQCConfiguration implements Cloneable { @UriParam @Metadata(label = "advanced") private String signatureAlgorithm; + @UriParam + @Metadata(label = "advanced", autowired = true) + private KeyGenerator keyGenerator; + @UriParam + @Metadata(label = "advanced") + private String keyEncapsulationAlgorithm; + @UriParam + @Metadata(label = "advanced") + private String symmetricKeyAlgorithm; public PQCOperations getOperation() { return operation; @@ -88,6 +99,39 @@ public class PQCConfiguration implements Cloneable { this.signatureAlgorithm = signatureAlgorithm; } + public KeyGenerator getKeyGenerator() { + return keyGenerator; + } + + /** + * The Key Generator to be used in encapsulation and extraction + */ + public void setKeyGenerator(KeyGenerator keyGenerator) { + this.keyGenerator = keyGenerator; + } + + public String getKeyEncapsulationAlgorithm() { + return keyEncapsulationAlgorithm; + } + + /** + * In case there is no keyGenerator, we specify an algorithm to build the KeyGenerator + */ + public void setKeyEncapsulationAlgorithm(String keyEncapsulationAlgorithm) { + this.keyEncapsulationAlgorithm = keyEncapsulationAlgorithm; + } + + public String getSymmetricKeyAlgorithm() { + return symmetricKeyAlgorithm; + } + + /** + * In case we are using KEM operations, we need a Symmetric algorithm to be defined for the flow to work. + */ + public void setSymmetricKeyAlgorithm(String symmetricKeyAlgorithm) { + this.symmetricKeyAlgorithm = symmetricKeyAlgorithm; + } + // ************************************************* // // ************************************************* diff --git a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCKeyEncapsulationAlgorithms.java similarity index 71% copy from components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java copy to components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCKeyEncapsulationAlgorithms.java index 37052290228..65880e60a16 100644 --- a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java +++ b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCKeyEncapsulationAlgorithms.java @@ -16,9 +16,21 @@ */ package org.apache.camel.component.pqc; -public enum PQCOperations { +public enum PQCKeyEncapsulationAlgorithms { - sign, - verify + // Standardized and implemented + MLKEM("ML-KEM"); + + // Experimental and non-standardized + + private final String algorithm; + + PQCKeyEncapsulationAlgorithms(String algorithm) { + this.algorithm = algorithm; + } + + public String getAlgorithm() { + return algorithm; + } } diff --git a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java index 37052290228..45d6abdc5c1 100644 --- a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java +++ b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java @@ -17,8 +17,8 @@ package org.apache.camel.component.pqc; public enum PQCOperations { - sign, - verify - + verify, + generateSecretKeyEncapsulation, + extractSecretKeyEncapsulation } 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 a63280cda0c..28768490d67 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 @@ -18,11 +18,16 @@ package org.apache.camel.component.pqc; import java.security.*; +import javax.crypto.KeyGenerator; + import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.InvalidPayloadException; import org.apache.camel.support.DefaultProducer; import org.apache.camel.util.ObjectHelper; +import org.bouncycastle.jcajce.SecretKeyWithEncapsulation; +import org.bouncycastle.jcajce.spec.KEMExtractSpec; +import org.bouncycastle.jcajce.spec.KEMGenerateSpec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,6 +39,7 @@ public class PQCProducer extends DefaultProducer { private static final Logger LOG = LoggerFactory.getLogger(PQCProducer.class); private Signature signer; + private KeyGenerator keyGenerator; public PQCProducer(Endpoint endpoint) { super(endpoint); @@ -48,6 +54,12 @@ public class PQCProducer extends DefaultProducer { case verify: verification(exchange); break; + case generateSecretKeyEncapsulation: + generateEncapsulation(exchange); + break; + case extractSecretKeyEncapsulation: + extractEncapsulation(exchange); + break; default: throw new IllegalArgumentException("Unsupported operation"); } @@ -74,11 +86,25 @@ public class PQCProducer extends DefaultProducer { protected void doStart() throws Exception { super.doStart(); - signer = getEndpoint().getConfiguration().getSigner(); + if (getConfiguration().getOperation().equals(PQCOperations.sign) + || getConfiguration().getOperation().equals(PQCOperations.verify)) { + signer = getEndpoint().getConfiguration().getSigner(); + + if (ObjectHelper.isEmpty(signer)) { + signer = Signature + .getInstance(PQCSignatureAlgorithms.valueOf(getConfiguration().getSignatureAlgorithm()).getAlgorithm()); + } + } + + if (getConfiguration().getOperation().equals(PQCOperations.generateSecretKeyEncapsulation) + || getConfiguration().getOperation().equals(PQCOperations.extractSecretKeyEncapsulation)) { + keyGenerator = getEndpoint().getConfiguration().getKeyGenerator(); - if (ObjectHelper.isEmpty(signer)) { - signer = Signature - .getInstance(PQCSignatureAlgorithms.valueOf(getConfiguration().getSignatureAlgorithm()).getAlgorithm()); + if (ObjectHelper.isEmpty(keyGenerator)) { + keyGenerator = KeyGenerator + .getInstance(PQCKeyEncapsulationAlgorithms.valueOf(getConfiguration().getKeyEncapsulationAlgorithm()) + .getAlgorithm()); + } } } @@ -106,4 +132,38 @@ public class PQCProducer extends DefaultProducer { } } + private void generateEncapsulation(Exchange exchange) + throws InvalidAlgorithmParameterException { + // initialise for creating an encapsulation and shared secret. + keyGenerator.init(new KEMGenerateSpec(getEndpoint().getConfiguration().getKeyPair().getPublic(), "AES", 128), + new SecureRandom()); + // SecretKeyWithEncapsulation is the class to use as the secret key, it has additional + // methods on it for recovering the encapsulation as well. + SecretKeyWithEncapsulation secEnc1 = (SecretKeyWithEncapsulation) keyGenerator.generateKey(); + + exchange.getMessage().setBody(secEnc1, SecretKeyWithEncapsulation.class); + } + + private void extractEncapsulation(Exchange exchange) + throws InvalidAlgorithmParameterException, + InvalidPayloadException { + // initialise for creating an encapsulation and shared secret. + SecretKeyWithEncapsulation payload = exchange.getMessage().getMandatoryBody(SecretKeyWithEncapsulation.class); + + if (ObjectHelper.isEmpty(getConfiguration().getSymmetricKeyAlgorithm())) { + throw new IllegalArgumentException("Symmetric Algorithm needs to be specified"); + } + + keyGenerator.init( + new KEMExtractSpec( + getEndpoint().getConfiguration().getKeyPair().getPrivate(), payload.getEncapsulation(), + PQCSymmetricAlgorithms.valueOf(getConfiguration().getSymmetricKeyAlgorithm()).getAlgorithm(), 128), + new SecureRandom()); + + // initialise for extracting the shared secret from the encapsulation. + SecretKeyWithEncapsulation secEnc2 = (SecretKeyWithEncapsulation) keyGenerator.generateKey(); + + exchange.getMessage().setBody(secEnc2, SecretKeyWithEncapsulation.class); + } + } diff --git a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCSymmetricAlgorithms.java similarity index 74% copy from components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java copy to components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCSymmetricAlgorithms.java index 37052290228..543512332bc 100644 --- a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCOperations.java +++ b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCSymmetricAlgorithms.java @@ -16,9 +16,19 @@ */ package org.apache.camel.component.pqc; -public enum PQCOperations { +public enum PQCSymmetricAlgorithms { - sign, - verify + // Standardized and implemented + AES("AES"); + + private final String algorithm; + + PQCSymmetricAlgorithms(String algorithm) { + this.algorithm = algorithm; + } + + public String getAlgorithm() { + return algorithm; + } } diff --git a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationAESTest.java b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationAESTest.java new file mode 100644 index 00000000000..237b129c6f1 --- /dev/null +++ b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationAESTest.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.*; + +import javax.crypto.KeyGenerator; + +import org.apache.camel.BindToRegistry; +import org.apache.camel.EndpointInject; +import org.apache.camel.Produce; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit5.CamelTestSupport; +import org.bouncycastle.jcajce.SecretKeyWithEncapsulation; +import org.bouncycastle.jcajce.spec.MLKEMParameterSpec; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider; +import org.bouncycastle.util.Arrays; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class PQCMLKEMGenerateEncapsulationAESTest extends CamelTestSupport { + + @EndpointInject("mock:sign") + protected MockEndpoint resultSign; + + @Produce("direct:sign") + protected ProducerTemplate templateSign; + + @EndpointInject("mock:verify") + protected MockEndpoint resultVerify; + + public PQCMLKEMGenerateEncapsulationAESTest() throws NoSuchAlgorithmException { + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:sign").to("pqc:keyenc?operation=generateEncapsulation&symmetricKeyAlgorithm=AES").to("mock:sign") + .to("pqc:keyenc?operation=extractEncapsulation&symmetricKeyAlgorithm=AES").to("mock:verify"); + } + }; + } + + @BeforeAll + public static void startup() throws Exception { + Security.addProvider(new BouncyCastleProvider()); + Security.addProvider(new BouncyCastlePQCProvider()); + } + + @Test + void testSignAndVerify() throws Exception { + resultSign.expectedMessageCount(1); + resultVerify.expectedMessageCount(1); + templateSign.sendBody("Hello"); + resultSign.assertIsSatisfied(); + assertNotNull(resultSign.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class)); + assertEquals(PQCSymmetricAlgorithms.AES.getAlgorithm(), + resultSign.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm()); + SecretKeyWithEncapsulation secEncrypted + = resultSign.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class); + assertNotNull(resultVerify.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class)); + assertEquals(PQCSymmetricAlgorithms.AES.getAlgorithm(), + resultVerify.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm()); + SecretKeyWithEncapsulation secEncryptedExtracted + = resultVerify.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class); + assertTrue(Arrays.areEqual(secEncrypted.getEncoded(), secEncryptedExtracted.getEncoded())); + } + + @BindToRegistry("Keypair") + public KeyPair setKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM", "BC"); + kpg.initialize(MLKEMParameterSpec.ml_kem_512, new SecureRandom()); + KeyPair kp = kpg.generateKeyPair(); + return kp; + } + + @BindToRegistry("KeyGenerator") + public KeyGenerator setKeyGenerator() + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { + KeyGenerator kg = KeyGenerator.getInstance("ML-KEM", "BC"); + return kg; + } +} 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 5cbe68cfa86..e0c6a1d5bbf 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 @@ -130,6 +130,38 @@ public interface PqcComponentBuilderFactory { return this; } + /** + * In case there is no keyGenerator, we specify an algorithm to build + * the KeyGenerator. + * + * The option is a: <code>java.lang.String</code> type. + * + * Group: advanced + * + * @param keyEncapsulationAlgorithm the value to set + * @return the dsl builder + */ + default PqcComponentBuilder keyEncapsulationAlgorithm(java.lang.String keyEncapsulationAlgorithm) { + doSetProperty("keyEncapsulationAlgorithm", keyEncapsulationAlgorithm); + return this; + } + + /** + * The Key Generator to be used in encapsulation and extraction. + * + * The option is a: <code>javax.crypto.KeyGenerator</code> + * type. + * + * Group: advanced + * + * @param keyGenerator the value to set + * @return the dsl builder + */ + default PqcComponentBuilder keyGenerator(javax.crypto.KeyGenerator keyGenerator) { + doSetProperty("keyGenerator", keyGenerator); + return this; + } + /** * The KeyPair to be used. * @@ -177,6 +209,22 @@ public interface PqcComponentBuilderFactory { return this; } + /** + * In case we are using KEM operations, we need a Symmetric algorithm to + * be defined for the flow to work. + * + * The option is a: <code>java.lang.String</code> type. + * + * Group: advanced + * + * @param symmetricKeyAlgorithm the value to set + * @return the dsl builder + */ + default PqcComponentBuilder symmetricKeyAlgorithm(java.lang.String symmetricKeyAlgorithm) { + doSetProperty("symmetricKeyAlgorithm", symmetricKeyAlgorithm); + return this; + } + /** * Used for enabling or disabling all consumer based health checks from @@ -239,9 +287,12 @@ public interface PqcComponentBuilderFactory { case "lazyStartProducer": ((PQCComponent) component).setLazyStartProducer((boolean) value); return true; case "operation": getOrCreateConfiguration((PQCComponent) component).setOperation((org.apache.camel.component.pqc.PQCOperations) value); return true; case "autowiredEnabled": ((PQCComponent) component).setAutowiredEnabled((boolean) value); return true; + case "keyEncapsulationAlgorithm": getOrCreateConfiguration((PQCComponent) component).setKeyEncapsulationAlgorithm((java.lang.String) value); return true; + case "keyGenerator": getOrCreateConfiguration((PQCComponent) component).setKeyGenerator((javax.crypto.KeyGenerator) value); return true; case "keyPair": getOrCreateConfiguration((PQCComponent) component).setKeyPair((java.security.KeyPair) 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 "symmetricKeyAlgorithm": getOrCreateConfiguration((PQCComponent) component).setSymmetricKeyAlgorithm((java.lang.String) value); return true; case "healthCheckConsumerEnabled": ((PQCComponent) component).setHealthCheckConsumerEnabled((boolean) value); return true; case "healthCheckProducerEnabled": ((PQCComponent) component).setHealthCheckProducerEnabled((boolean) value); return true; default: return false; 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 b572c379ae7..52375322438 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 @@ -134,6 +134,50 @@ public interface PQCEndpointBuilderFactory { doSetProperty("lazyStartProducer", lazyStartProducer); return this; } + /** + * In case there is no keyGenerator, we specify an algorithm to build + * the KeyGenerator. + * + * The option is a: <code>java.lang.String</code> type. + * + * Group: advanced + * + * @param keyEncapsulationAlgorithm the value to set + * @return the dsl builder + */ + default AdvancedPQCEndpointBuilder keyEncapsulationAlgorithm(String keyEncapsulationAlgorithm) { + doSetProperty("keyEncapsulationAlgorithm", keyEncapsulationAlgorithm); + return this; + } + /** + * The Key Generator to be used in encapsulation and extraction. + * + * The option is a: <code>javax.crypto.KeyGenerator</code> type. + * + * Group: advanced + * + * @param keyGenerator the value to set + * @return the dsl builder + */ + default AdvancedPQCEndpointBuilder keyGenerator(javax.crypto.KeyGenerator keyGenerator) { + doSetProperty("keyGenerator", keyGenerator); + return this; + } + /** + * The Key Generator to be used in encapsulation and extraction. + * + * The option will be converted to a + * <code>javax.crypto.KeyGenerator</code> type. + * + * Group: advanced + * + * @param keyGenerator the value to set + * @return the dsl builder + */ + default AdvancedPQCEndpointBuilder keyGenerator(String keyGenerator) { + doSetProperty("keyGenerator", keyGenerator); + return this; + } /** * The KeyPair to be used. * @@ -207,6 +251,21 @@ public interface PQCEndpointBuilderFactory { doSetProperty("signer", signer); return this; } + /** + * In case we are using KEM operations, we need a Symmetric algorithm to + * be defined for the flow to work. + * + * The option is a: <code>java.lang.String</code> type. + * + * Group: advanced + * + * @param symmetricKeyAlgorithm the value to set + * @return the dsl builder + */ + default AdvancedPQCEndpointBuilder symmetricKeyAlgorithm(String symmetricKeyAlgorithm) { + doSetProperty("symmetricKeyAlgorithm", symmetricKeyAlgorithm); + return this; + } } public interface PQCBuilders {