This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch CAMEL-21994 in repository https://gitbox.apache.org/repos/asf/camel.git
commit 360a4a92ebbdebc2788948c26ebd622a9f27fdee Author: Andrea Cosentino <[email protected]> AuthorDate: Tue Apr 22 10:11:13 2025 +0200 CAMEL-21994 - Camel-PQC: Add more Symmetric Algorithms 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; + } +}
