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

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

commit 0bb06c4f9c4d70071cf0d03ef48167115c6060d2
Author: Andrea Cosentino <anco...@gmail.com>
AuthorDate: Fri Apr 18 14:12:30 2025 +0200

    Camel-PQC: Add a test for roundtrip of encapsulated secret key and usage 
with Camel-Crypto
    
    Signed-off-by: Andrea Cosentino <anco...@gmail.com>
---
 components/camel-pqc/pom.xml                       |   5 +
 ...EMGenerateEncapsulationCryptoRoundTripTest.java | 128 +++++++++++++++++++++
 2 files changed, 133 insertions(+)

diff --git a/components/camel-pqc/pom.xml b/components/camel-pqc/pom.xml
index b7a4a71e636..55c0f1d7184 100644
--- a/components/camel-pqc/pom.xml
+++ b/components/camel-pqc/pom.xml
@@ -52,5 +52,10 @@
             <artifactId>camel-test-junit5</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-crypto</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripTest.java
 
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripTest.java
new file mode 100644
index 00000000000..61c5ead452c
--- /dev/null
+++ 
b/components/camel-pqc/src/test/java/org/apache/camel/component/pqc/PQCMLKEMGenerateEncapsulationCryptoRoundTripTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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 javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+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.*;
+
+public class PQCMLKEMGenerateEncapsulationCryptoRoundTripTest 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 PQCMLKEMGenerateEncapsulationCryptoRoundTripTest() throws 
NoSuchAlgorithmException {
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        CryptoDataFormat cryptoFormat = new CryptoDataFormat("AES", null);
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                
from("direct:encapsulate").to("pqc:keyenc?operation=generateSecretKeyEncapsulation&symmetricKeyAlgorithm=AES")
+                        .to("mock:encapsulate")
+                        
.to("pqc:keyenc?operation=extractSecretKeyEncapsulation&symmetricKeyAlgorithm=AES")
+                        .log("${body}")
+                        .process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws 
Exception {
+                                SecretKeyWithEncapsulation encapsulatedSecret
+                                        = 
exchange.getMessage().getBody(SecretKeyWithEncapsulation.class);
+                                SecretKey restoredKey = new 
SecretKeySpec(encapsulatedSecret.getEncoded(), "AES");
+                                
exchange.getMessage().setHeader(CryptoDataFormat.KEY, restoredKey);
+                                exchange.getMessage().setBody("Hello", 
String.class);
+                            }
+                        })
+                        .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.AES.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;
+    }
+}

Reply via email to