This is an automated email from the ASF dual-hosted git repository.
acosentino 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 0868c5a4c02 CAMEL-21994 - Camel-PQC: Add more Symmetric Algorithms
(#17821)
0868c5a4c02 is described below
commit 0868c5a4c02756ab481cc4c6fe3ea3d170c9b49e
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Apr 22 10:38:15 2025 +0200
CAMEL-21994 - Camel-PQC: Add more Symmetric Algorithms (#17821)
Signed-off-by: Andrea Cosentino <[email protected]>
---
.../component/pqc/PQCSymmetricAlgorithms.java | 13 ++-
...rateEncapsulationCryptoRoundTripDESedeTest.java | 118 ++++++++++++++++++++
...teEncapsulationCryptoRoundTripDSTU7624Test.java | 118 ++++++++++++++++++++
...eEncapsulationCryptoRoundTripGOST28147Test.java | 118 ++++++++++++++++++++
...erateEncapsulationCryptoRoundTripGRAINTest.java | 120 +++++++++++++++++++++
...enerateEncapsulationCryptoRoundTripRC2Test.java | 118 ++++++++++++++++++++
...enerateEncapsulationCryptoRoundTripSM4Test.java | 118 ++++++++++++++++++++
7 files changed, 722 insertions(+), 1 deletion(-)
diff --git
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCSymmetricAlgorithms.java
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCSymmetricAlgorithms.java
index 60c8d9ec692..03bfad6b4ba 100644
---
a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCSymmetricAlgorithms.java
+++
b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCSymmetricAlgorithms.java
@@ -20,12 +20,23 @@ public enum PQCSymmetricAlgorithms {
// Standardized and implemented
AES("AES"),
+ RC2("RC2"),
RC5("RC5"),
ARIA("ARIA"),
CAMELLIA("CAMELLIA"),
CAST5("CAST5"),
CAST6("CAST6"),
- CHACHA7539("CHACHA7539");
+ CHACHA7539("CHACHA7539"),
+ DSTU7624("DSTU7624"),
+ GOST28147("GOST28147"),
+ GOST3412_2015("GOST3412-2015"),
+ GRAIN128("GRAIN128"),
+ HC128("HC128"),
+ HC256("HC256"),
+ SALSA20("SALSA20"),
+ SEED("SEED"),
+ SM4("SM4"),
+ DESEDE("DESede");
private final String algorithm;
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripDESedeTest.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripDESedeTest.java
new file mode 100644
index 00000000000..88cd25474fd
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripDESedeTest.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.*;
+
+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.converter.crypto.CryptoDataFormat;
+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.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PQCMLKEMGenerateEncapsulationCryptoRoundTripDESedeTest extends
CamelTestSupport {
+
+ @EndpointInject("mock:encapsulate")
+ protected MockEndpoint resultEncapsulate;
+
+ @Produce("direct:encapsulate")
+ protected ProducerTemplate templateEncapsulate;
+
+ @EndpointInject("mock:encrypted")
+ protected MockEndpoint resultEncrypted;
+
+ @EndpointInject("mock:unencrypted")
+ protected MockEndpoint resultDecrypted;
+
+ public PQCMLKEMGenerateEncapsulationCryptoRoundTripDESedeTest() throws
NoSuchAlgorithmException {
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ CryptoDataFormat cryptoFormat = new CryptoDataFormat("DESede", null);
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:encapsulate")
+
.to("pqc:keyenc?operation=generateSecretKeyEncapsulation&symmetricKeyAlgorithm=DESEDE")
+ .to("mock:encapsulate")
+
.to("pqc:keyenc?operation=extractSecretKeyEncapsulation&symmetricKeyAlgorithm=DESEDE")
+
.to("pqc:keyenc?operation=extractSecretKeyFromEncapsulation&symmetricKeyAlgorithm=DESEDE")
+ .setHeader(CryptoDataFormat.KEY, body())
+ .setBody(constant("Hello"))
+ .marshal(cryptoFormat)
+ .log("Encrypted ${body}")
+ .to("mock:encrypted")
+ .unmarshal(cryptoFormat)
+ .log("Unencrypted ${body}")
+ .to("mock:unencrypted");
+ ;
+ }
+ };
+ }
+
+ @BeforeAll
+ public static void startup() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+ Security.addProvider(new BouncyCastlePQCProvider());
+ }
+
+ @Test
+ void testSignAndVerify() throws Exception {
+ resultEncapsulate.expectedMessageCount(1);
+ resultEncrypted.expectedMessageCount(1);
+ resultDecrypted.expectedMessageCount(1);
+ templateEncapsulate.sendBody("Hello");
+ resultEncapsulate.assertIsSatisfied();
+
assertNotNull(resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class));
+ assertEquals("DESEDE",
+
resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm());
+
assertNotNull(resultEncrypted.getExchanges().get(0).getMessage().getBody());
+ assertEquals("Hello",
resultDecrypted.getExchanges().get(0).getMessage().getBody(String.class));
+ }
+
+ @BindToRegistry("Keypair")
+ public KeyPair setKeyPair() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
+ KeyPairGenerator kpg =
KeyPairGenerator.getInstance(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ 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(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ return kg;
+ }
+}
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripDSTU7624Test.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripDSTU7624Test.java
new file mode 100644
index 00000000000..2fc9386dcf8
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripDSTU7624Test.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.*;
+
+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.converter.crypto.CryptoDataFormat;
+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.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PQCMLKEMGenerateEncapsulationCryptoRoundTripDSTU7624Test extends
CamelTestSupport {
+
+ @EndpointInject("mock:encapsulate")
+ protected MockEndpoint resultEncapsulate;
+
+ @Produce("direct:encapsulate")
+ protected ProducerTemplate templateEncapsulate;
+
+ @EndpointInject("mock:encrypted")
+ protected MockEndpoint resultEncrypted;
+
+ @EndpointInject("mock:unencrypted")
+ protected MockEndpoint resultDecrypted;
+
+ public PQCMLKEMGenerateEncapsulationCryptoRoundTripDSTU7624Test() throws
NoSuchAlgorithmException {
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ CryptoDataFormat cryptoFormat = new CryptoDataFormat("DSTU7624", null);
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:encapsulate")
+
.to("pqc:keyenc?operation=generateSecretKeyEncapsulation&symmetricKeyAlgorithm=DSTU7624&symmetricKeyLength=128")
+ .to("mock:encapsulate")
+
.to("pqc:keyenc?operation=extractSecretKeyEncapsulation&symmetricKeyAlgorithm=DSTU7624&symmetricKeyLength=128")
+
.to("pqc:keyenc?operation=extractSecretKeyFromEncapsulation&symmetricKeyAlgorithm=DSTU7624&symmetricKeyLength=128")
+ .setHeader(CryptoDataFormat.KEY, body())
+ .setBody(constant("Hello"))
+ .marshal(cryptoFormat)
+ .log("Encrypted ${body}")
+ .to("mock:encrypted")
+ .unmarshal(cryptoFormat)
+ .log("Unencrypted ${body}")
+ .to("mock:unencrypted");
+ ;
+ }
+ };
+ }
+
+ @BeforeAll
+ public static void startup() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+ Security.addProvider(new BouncyCastlePQCProvider());
+ }
+
+ @Test
+ void testSignAndVerify() throws Exception {
+ resultEncapsulate.expectedMessageCount(1);
+ resultEncrypted.expectedMessageCount(1);
+ resultDecrypted.expectedMessageCount(1);
+ templateEncapsulate.sendBody("Hello");
+ resultEncapsulate.assertIsSatisfied();
+
assertNotNull(resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class));
+ assertEquals(PQCSymmetricAlgorithms.DSTU7624.getAlgorithm(),
+
resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm());
+
assertNotNull(resultEncrypted.getExchanges().get(0).getMessage().getBody());
+ assertEquals("Hello",
resultDecrypted.getExchanges().get(0).getMessage().getBody(String.class));
+ }
+
+ @BindToRegistry("Keypair")
+ public KeyPair setKeyPair() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
+ KeyPairGenerator kpg =
KeyPairGenerator.getInstance(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ 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(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ return kg;
+ }
+}
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripGOST28147Test.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripGOST28147Test.java
new file mode 100644
index 00000000000..321c139538f
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripGOST28147Test.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.*;
+
+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.converter.crypto.CryptoDataFormat;
+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.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PQCMLKEMGenerateEncapsulationCryptoRoundTripGOST28147Test extends
CamelTestSupport {
+
+ @EndpointInject("mock:encapsulate")
+ protected MockEndpoint resultEncapsulate;
+
+ @Produce("direct:encapsulate")
+ protected ProducerTemplate templateEncapsulate;
+
+ @EndpointInject("mock:encrypted")
+ protected MockEndpoint resultEncrypted;
+
+ @EndpointInject("mock:unencrypted")
+ protected MockEndpoint resultDecrypted;
+
+ public PQCMLKEMGenerateEncapsulationCryptoRoundTripGOST28147Test() throws
NoSuchAlgorithmException {
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ CryptoDataFormat cryptoFormat = new CryptoDataFormat("GOST28147",
null);
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:encapsulate")
+
.to("pqc:keyenc?operation=generateSecretKeyEncapsulation&symmetricKeyAlgorithm=GOST28147&symmetricKeyLength=256")
+ .to("mock:encapsulate")
+
.to("pqc:keyenc?operation=extractSecretKeyEncapsulation&symmetricKeyAlgorithm=GOST28147&symmetricKeyLength=256")
+
.to("pqc:keyenc?operation=extractSecretKeyFromEncapsulation&symmetricKeyAlgorithm=GOST28147&symmetricKeyLength=256")
+ .setHeader(CryptoDataFormat.KEY, body())
+ .setBody(constant("Hello"))
+ .marshal(cryptoFormat)
+ .log("Encrypted ${body}")
+ .to("mock:encrypted")
+ .unmarshal(cryptoFormat)
+ .log("Unencrypted ${body}")
+ .to("mock:unencrypted");
+ ;
+ }
+ };
+ }
+
+ @BeforeAll
+ public static void startup() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+ Security.addProvider(new BouncyCastlePQCProvider());
+ }
+
+ @Test
+ void testSignAndVerify() throws Exception {
+ resultEncapsulate.expectedMessageCount(1);
+ resultEncrypted.expectedMessageCount(1);
+ resultDecrypted.expectedMessageCount(1);
+ templateEncapsulate.sendBody("Hello");
+ resultEncapsulate.assertIsSatisfied();
+
assertNotNull(resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class));
+ assertEquals(PQCSymmetricAlgorithms.GOST28147.getAlgorithm(),
+
resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm());
+
assertNotNull(resultEncrypted.getExchanges().get(0).getMessage().getBody());
+ assertEquals("Hello",
resultDecrypted.getExchanges().get(0).getMessage().getBody(String.class));
+ }
+
+ @BindToRegistry("Keypair")
+ public KeyPair setKeyPair() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
+ KeyPairGenerator kpg =
KeyPairGenerator.getInstance(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ 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(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ return kg;
+ }
+}
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripGRAINTest.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripGRAINTest.java
new file mode 100644
index 00000000000..03e35bd374f
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripGRAINTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.converter.crypto.CryptoDataFormat;
+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.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PQCMLKEMGenerateEncapsulationCryptoRoundTripGRAINTest extends
CamelTestSupport {
+
+ @EndpointInject("mock:encapsulate")
+ protected MockEndpoint resultEncapsulate;
+
+ @Produce("direct:encapsulate")
+ protected ProducerTemplate templateEncapsulate;
+
+ @EndpointInject("mock:encrypted")
+ protected MockEndpoint resultEncrypted;
+
+ @EndpointInject("mock:unencrypted")
+ protected MockEndpoint resultDecrypted;
+
+ public PQCMLKEMGenerateEncapsulationCryptoRoundTripGRAINTest() throws
NoSuchAlgorithmException {
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ CryptoDataFormat cryptoFormat = new CryptoDataFormat("GRAIN128", null);
+ byte[] initializationVector = new byte[] { 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b };
+ cryptoFormat.setInitializationVector(initializationVector);
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:encapsulate")
+
.to("pqc:keyenc?operation=generateSecretKeyEncapsulation&symmetricKeyAlgorithm=GRAIN128&symmetricKeyLength=128")
+ .to("mock:encapsulate")
+
.to("pqc:keyenc?operation=extractSecretKeyEncapsulation&symmetricKeyAlgorithm=GRAIN128&symmetricKeyLength=128")
+
.to("pqc:keyenc?operation=extractSecretKeyFromEncapsulation&symmetricKeyAlgorithm=GRAIN128&symmetricKeyLength=128")
+ .setHeader(CryptoDataFormat.KEY, body())
+ .setBody(constant("Hello"))
+ .marshal(cryptoFormat)
+ .log("Encrypted ${body}")
+ .to("mock:encrypted")
+ .unmarshal(cryptoFormat)
+ .log("Unencrypted ${body}")
+ .to("mock:unencrypted");
+ ;
+ }
+ };
+ }
+
+ @BeforeAll
+ public static void startup() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+ Security.addProvider(new BouncyCastlePQCProvider());
+ }
+
+ @Test
+ void testSignAndVerify() throws Exception {
+ resultEncapsulate.expectedMessageCount(1);
+ resultEncrypted.expectedMessageCount(1);
+ resultDecrypted.expectedMessageCount(1);
+ templateEncapsulate.sendBody("Hello");
+ resultEncapsulate.assertIsSatisfied();
+
assertNotNull(resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class));
+ assertEquals(PQCSymmetricAlgorithms.GRAIN128.getAlgorithm(),
+
resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm());
+
assertNotNull(resultEncrypted.getExchanges().get(0).getMessage().getBody());
+ assertEquals("Hello",
resultDecrypted.getExchanges().get(0).getMessage().getBody(String.class));
+ }
+
+ @BindToRegistry("Keypair")
+ public KeyPair setKeyPair() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
+ KeyPairGenerator kpg =
KeyPairGenerator.getInstance(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ 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(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ return kg;
+ }
+}
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripRC2Test.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripRC2Test.java
new file mode 100644
index 00000000000..dd3b3c4685d
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripRC2Test.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.*;
+
+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.converter.crypto.CryptoDataFormat;
+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.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PQCMLKEMGenerateEncapsulationCryptoRoundTripRC2Test extends
CamelTestSupport {
+
+ @EndpointInject("mock:encapsulate")
+ protected MockEndpoint resultEncapsulate;
+
+ @Produce("direct:encapsulate")
+ protected ProducerTemplate templateEncapsulate;
+
+ @EndpointInject("mock:encrypted")
+ protected MockEndpoint resultEncrypted;
+
+ @EndpointInject("mock:unencrypted")
+ protected MockEndpoint resultDecrypted;
+
+ public PQCMLKEMGenerateEncapsulationCryptoRoundTripRC2Test() throws
NoSuchAlgorithmException {
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ CryptoDataFormat cryptoFormat = new CryptoDataFormat("RC2", null);
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:encapsulate")
+
.to("pqc:keyenc?operation=generateSecretKeyEncapsulation&symmetricKeyAlgorithm=RC2")
+ .to("mock:encapsulate")
+
.to("pqc:keyenc?operation=extractSecretKeyEncapsulation&symmetricKeyAlgorithm=RC2")
+
.to("pqc:keyenc?operation=extractSecretKeyFromEncapsulation&symmetricKeyAlgorithm=RC2")
+ .setHeader(CryptoDataFormat.KEY, body())
+ .setBody(constant("Hello"))
+ .marshal(cryptoFormat)
+ .log("Encrypted ${body}")
+ .to("mock:encrypted")
+ .unmarshal(cryptoFormat)
+ .log("Unencrypted ${body}")
+ .to("mock:unencrypted");
+ ;
+ }
+ };
+ }
+
+ @BeforeAll
+ public static void startup() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+ Security.addProvider(new BouncyCastlePQCProvider());
+ }
+
+ @Test
+ void testSignAndVerify() throws Exception {
+ resultEncapsulate.expectedMessageCount(1);
+ resultEncrypted.expectedMessageCount(1);
+ resultDecrypted.expectedMessageCount(1);
+ templateEncapsulate.sendBody("Hello");
+ resultEncapsulate.assertIsSatisfied();
+
assertNotNull(resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class));
+ assertEquals(PQCSymmetricAlgorithms.RC2.getAlgorithm(),
+
resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm());
+
assertNotNull(resultEncrypted.getExchanges().get(0).getMessage().getBody());
+ assertEquals("Hello",
resultDecrypted.getExchanges().get(0).getMessage().getBody(String.class));
+ }
+
+ @BindToRegistry("Keypair")
+ public KeyPair setKeyPair() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
+ KeyPairGenerator kpg =
KeyPairGenerator.getInstance(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ 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(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ return kg;
+ }
+}
diff --git
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripSM4Test.java
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripSM4Test.java
new file mode 100644
index 00000000000..71dce511595
--- /dev/null
+++
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripSM4Test.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.*;
+
+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.converter.crypto.CryptoDataFormat;
+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.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class PQCMLKEMGenerateEncapsulationCryptoRoundTripSM4Test extends
CamelTestSupport {
+
+ @EndpointInject("mock:encapsulate")
+ protected MockEndpoint resultEncapsulate;
+
+ @Produce("direct:encapsulate")
+ protected ProducerTemplate templateEncapsulate;
+
+ @EndpointInject("mock:encrypted")
+ protected MockEndpoint resultEncrypted;
+
+ @EndpointInject("mock:unencrypted")
+ protected MockEndpoint resultDecrypted;
+
+ public PQCMLKEMGenerateEncapsulationCryptoRoundTripSM4Test() throws
NoSuchAlgorithmException {
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ CryptoDataFormat cryptoFormat = new CryptoDataFormat("SM4", null);
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:encapsulate")
+
.to("pqc:keyenc?operation=generateSecretKeyEncapsulation&symmetricKeyAlgorithm=SM4")
+ .to("mock:encapsulate")
+
.to("pqc:keyenc?operation=extractSecretKeyEncapsulation&symmetricKeyAlgorithm=SM4")
+
.to("pqc:keyenc?operation=extractSecretKeyFromEncapsulation&symmetricKeyAlgorithm=SM4")
+ .setHeader(CryptoDataFormat.KEY, body())
+ .setBody(constant("Hello"))
+ .marshal(cryptoFormat)
+ .log("Encrypted ${body}")
+ .to("mock:encrypted")
+ .unmarshal(cryptoFormat)
+ .log("Unencrypted ${body}")
+ .to("mock:unencrypted");
+ ;
+ }
+ };
+ }
+
+ @BeforeAll
+ public static void startup() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+ Security.addProvider(new BouncyCastlePQCProvider());
+ }
+
+ @Test
+ void testSignAndVerify() throws Exception {
+ resultEncapsulate.expectedMessageCount(1);
+ resultEncrypted.expectedMessageCount(1);
+ resultDecrypted.expectedMessageCount(1);
+ templateEncapsulate.sendBody("Hello");
+ resultEncapsulate.assertIsSatisfied();
+
assertNotNull(resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class));
+ assertEquals(PQCSymmetricAlgorithms.SM4.getAlgorithm(),
+
resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm());
+
assertNotNull(resultEncrypted.getExchanges().get(0).getMessage().getBody());
+ assertEquals("Hello",
resultDecrypted.getExchanges().get(0).getMessage().getBody(String.class));
+ }
+
+ @BindToRegistry("Keypair")
+ public KeyPair setKeyPair() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
+ KeyPairGenerator kpg =
KeyPairGenerator.getInstance(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ 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(PQCKeyEncapsulationAlgorithms.MLKEM.getAlgorithm(),
+ PQCKeyEncapsulationAlgorithms.MLKEM.getBcProvider());
+ return kg;
+ }
+}