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 294e7f543c38 Camel-PQC - Document Digital Signature EIP usage with PQC 
algorithms (#22113)
294e7f543c38 is described below

commit 294e7f543c38258d8db58b0f646f893ecd8549fa
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Mar 19 18:19:23 2026 +0100

    Camel-PQC - Document Digital Signature EIP usage with PQC algorithms 
(#22113)
    
    * Camel-PQC - Document Digital Signature EIP usage with PQC algorithms
    
    Add comprehensive documentation to crypto-component.adoc showing how
    to use post-quantum cryptography algorithms with the camel-crypto
    Digital Signature EIP:
    
    - ML-DSA (NIST FIPS 204) examples with Java DSL and YAML DSL
    - SLH-DSA (NIST FIPS 205) examples with Bouncy Castle provider
    - Hybrid signatures (ECDSA+ML-DSA) using camel-pqc component
    - Manual hybrid chaining with separate signature headers
    - ML-DSA parameter set comparison table
    - Feature comparison between camel-crypto and camel-pqc approaches
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * Camel-PQC - Document Digital Signature EIP usage with PQC algorithms
    
    Add comprehensive documentation to crypto-component.adoc showing how
    to use post-quantum cryptography algorithms with the camel-crypto
    Digital Signature EIP:
    
    - ML-DSA (NIST FIPS 204) examples with Java DSL and YAML DSL
    - SLH-DSA (NIST FIPS 205) examples with Bouncy Castle provider
    - Hybrid signatures (ECDSA+ML-DSA) using camel-pqc component
    - Manual hybrid chaining with separate signature headers
    - ML-DSA parameter set comparison table
    - Feature comparison between camel-crypto and camel-pqc approaches
    
    Fix key pair examples to generate a single KeyPair and extract both
    private and public keys from it, avoiding mismatched key pairs.
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../src/main/docs/crypto-component.adoc            | 316 +++++++++++++++++++++
 1 file changed, 316 insertions(+)

diff --git a/components/camel-crypto/src/main/docs/crypto-component.adoc 
b/components/camel-crypto/src/main/docs/crypto-component.adoc
index 29de3ff5261f..0edd86f56868 100644
--- a/components/camel-crypto/src/main/docs/crypto-component.adoc
+++ b/components/camel-crypto/src/main/docs/crypto-component.adoc
@@ -223,6 +223,322 @@ 
signed.getIn().setHeader(DigitalSignatureConstants.KEYSTORE_ALIAS, "bob");
 template.send("direct:alias-verify", signed);
 
-------------------------------------------------------------------------------------------------
 
+== Using Post-Quantum Cryptography (PQC) Algorithms
 
+The Digital Signature EIP supports Post-Quantum Cryptography algorithms 
through the standard JCE provider mechanism.
+Since the `algorithm` and `provider` options accept any value supported by the 
underlying JCE implementation, you can use PQC signature algorithms such as 
ML-DSA (NIST FIPS 204) by registering a Bouncy Castle provider and supplying 
the corresponding keys.
+
+This approach is useful when you want to apply PQC signatures directly using 
the `crypto:sign` / `crypto:verify` pair without the full `camel-pqc` component.
+For hybrid signatures (combining classical + PQC) or key lifecycle management, 
use the xref:components::pqc-component.adoc[PQC component] instead.
+
+=== Prerequisites
+
+Add the Bouncy Castle provider dependencies to your project:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.bouncycastle</groupId>
+    <artifactId>bcprov-jdk18on</artifactId>
+    <version>${bouncycastle.version}</version>
+</dependency>
+<dependency>
+    <groupId>org.bouncycastle</groupId>
+    <artifactId>bcpkix-jdk18on</artifactId>
+    <version>${bouncycastle.version}</version>
+</dependency>
+----
+
+Register the Bouncy Castle provider at application startup:
+
+[source,java]
+----
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+Security.addProvider(new BouncyCastleProvider());
+----
+
+=== ML-DSA (NIST FIPS 204)
+
+ML-DSA (Module-Lattice Digital Signature Algorithm, formerly Dilithium) is the 
primary NIST-standardized post-quantum signature algorithm.
+
+==== Java DSL
+
+[tabs]
+====
+Raw keys::
++
+[source,java]
+----
+private KeyPair mlDsaKeyPair;
+
+private KeyPair getMlDsaKeyPair() throws Exception {
+    if (mlDsaKeyPair == null) {
+        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("ML-DSA", "BC");
+        kpGen.initialize(MLDSAParameterSpec.ml_dsa_65);
+        mlDsaKeyPair = kpGen.generateKeyPair();
+    }
+    return mlDsaKeyPair;
+}
+
+@BindToRegistry("mlDsaPrivateKey")
+public PrivateKey mlDsaPrivateKey() throws Exception {
+    return getMlDsaKeyPair().getPrivate();
+}
+
+@BindToRegistry("mlDsaPublicKey")
+public PublicKey mlDsaPublicKey() throws Exception {
+    return getMlDsaKeyPair().getPublic();
+}
+
+from("direct:sign")
+    
.to("crypto:sign:pqc?algorithm=ML-DSA&provider=BC&privateKeyName=#mlDsaPrivateKey")
+    .to("direct:verify");
+
+from("direct:verify")
+    
.to("crypto:verify:pqc?algorithm=ML-DSA&provider=BC&publicKeyName=#mlDsaPublicKey")
+    .to("mock:result");
+----
+
+Dynamic keys via headers::
++
+[source,java]
+----
+KeyPairGenerator kpGen = KeyPairGenerator.getInstance("ML-DSA", "BC");
+kpGen.initialize(MLDSAParameterSpec.ml_dsa_65);
+KeyPair kp = kpGen.generateKeyPair();
+
+from("direct:sign")
+    .setHeader(DigitalSignatureConstants.SIGNATURE_PRIVATE_KEY, 
constant(kp.getPrivate()))
+    .to("crypto:sign:pqc?algorithm=ML-DSA&provider=BC")
+    .to("direct:verify");
+
+from("direct:verify")
+    .setHeader(DigitalSignatureConstants.SIGNATURE_PUBLIC_KEY_OR_CERT, 
constant(kp.getPublic()))
+    .to("crypto:verify:pqc?algorithm=ML-DSA&provider=BC")
+    .to("mock:result");
+----
+====
+
+==== YAML DSL
+
+[source,yaml]
+----
+- route:
+    id: sign-route
+    from:
+      uri: direct:sign
+    steps:
+      - to:
+          uri: crypto:sign:pqc
+          parameters:
+            algorithm: ML-DSA
+            provider: BC
+            privateKeyName: "#mlDsaPrivateKey"
+      - to:
+          uri: direct:verify
+
+- route:
+    id: verify-route
+    from:
+      uri: direct:verify
+    steps:
+      - to:
+          uri: crypto:verify:pqc
+          parameters:
+            algorithm: ML-DSA
+            provider: BC
+            publicKeyName: "#mlDsaPublicKey"
+      - to:
+          uri: mock:result
+----
+
+==== ML-DSA parameter sets
+
+The following ML-DSA parameter sets are available:
+
+[cols="1,1,1,1"]
+|===
+| Parameter Set | Security Level | Signature Size | Use Case
+
+| `ml_dsa_44`
+| NIST Level 2
+| ~2,420 bytes
+| General-purpose signing
+
+| `ml_dsa_65`
+| NIST Level 3
+| ~3,309 bytes
+| Recommended default
+
+| `ml_dsa_87`
+| NIST Level 5
+| ~4,627 bytes
+| Highest security
+|===
+
+=== SLH-DSA (NIST FIPS 205)
+
+SLH-DSA (Stateless Hash-Based Digital Signature Algorithm, formerly SPHINCS+) 
is the secondary NIST-standardized PQC signature algorithm, based on hash 
functions.
+
+[source,java]
+----
+private KeyPair slhDsaKeyPair;
+
+private KeyPair getSlhDsaKeyPair() throws Exception {
+    if (slhDsaKeyPair == null) {
+        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("SLH-DSA", "BC");
+        kpGen.initialize(SLHDSAParameterSpec.slh_dsa_sha2_128s);
+        slhDsaKeyPair = kpGen.generateKeyPair();
+    }
+    return slhDsaKeyPair;
+}
+
+@BindToRegistry("slhDsaPrivateKey")
+public PrivateKey slhDsaPrivateKey() throws Exception {
+    return getSlhDsaKeyPair().getPrivate();
+}
+
+@BindToRegistry("slhDsaPublicKey")
+public PublicKey slhDsaPublicKey() throws Exception {
+    return getSlhDsaKeyPair().getPublic();
+}
+
+from("direct:sign")
+    
.to("crypto:sign:pqc?algorithm=SLH-DSA&provider=BC&privateKeyName=#slhDsaPrivateKey")
+    .to("direct:verify");
+
+from("direct:verify")
+    
.to("crypto:verify:pqc?algorithm=SLH-DSA&provider=BC&publicKeyName=#slhDsaPublicKey")
+    .to("mock:result");
+----
+
+=== Hybrid Signatures (Classical + PQC)
+
+For hybrid signatures that combine a classical algorithm (e.g., ECDSA) with a 
PQC algorithm (e.g., ML-DSA) in a single route, the recommended approach is to 
use the xref:components::pqc-component.adoc[PQC component] which provides 
built-in hybrid operations.
+
+==== Using the PQC component (recommended)
+
+The `camel-pqc` component has dedicated `hybridSign` and `hybridVerify` 
operations that produce a single combined signature:
+
+[tabs]
+====
+Java DSL::
++
+[source,java]
+----
+from("direct:sign")
+    .to("pqc:hybrid?operation=hybridSign"
+        + "&signatureAlgorithm=MLDSA"
+        + "&classicalSignatureAlgorithm=ECDSA_P256")
+    .to("direct:verify");
+
+from("direct:verify")
+    .to("pqc:hybrid?operation=hybridVerify"
+        + "&signatureAlgorithm=MLDSA"
+        + "&classicalSignatureAlgorithm=ECDSA_P256")
+    .to("mock:result");
+----
+
+YAML DSL::
++
+[source,yaml]
+----
+- route:
+    id: hybrid-sign-route
+    from:
+      uri: direct:sign
+    steps:
+      - to:
+          uri: pqc:hybrid
+          parameters:
+            operation: hybridSign
+            signatureAlgorithm: MLDSA
+            classicalSignatureAlgorithm: ECDSA_P256
+      - to:
+          uri: direct:verify
+
+- route:
+    id: hybrid-verify-route
+    from:
+      uri: direct:verify
+    steps:
+      - to:
+          uri: pqc:hybrid
+          parameters:
+            operation: hybridVerify
+            signatureAlgorithm: MLDSA
+            classicalSignatureAlgorithm: ECDSA_P256
+      - to:
+          uri: mock:result
+----
+====
+
+Other hybrid combinations include:
+
+* `ED25519` + `MLDSA` — Edwards curve + ML-DSA
+* `RSA_3072` + `MLDSA` — RSA 3072-bit + ML-DSA
+* `ECDSA_P384` + `SLHDSA` — ECDSA P-384 + SLH-DSA
+
+See the xref:components::pqc-component.adoc#_hybrid_cryptography[PQC Hybrid 
Cryptography] section for the full list of supported classical algorithms and 
details on the hybrid wire format.
+
+==== Chaining crypto: endpoints (manual approach)
+
+Alternatively, you can chain two `crypto:sign` / `crypto:verify` endpoints to 
produce both a classical and a PQC signature, storing each in a separate header:
+
+[source,java]
+----
+from("direct:sign")
+    // Classical ECDSA signature
+    
.to("crypto:sign:classical?algorithm=SHA256withECDSA&privateKeyName=#ecPrivateKey"
+        + "&signatureHeaderName=ClassicalSignature")
+    // PQC ML-DSA signature
+    
.to("crypto:sign:pqc?algorithm=ML-DSA&provider=BC&privateKeyName=#mlDsaPrivateKey"
+        + "&signatureHeaderName=PQCSignature")
+    .to("direct:verify");
+
+from("direct:verify")
+    // Verify classical signature
+    
.to("crypto:verify:classical?algorithm=SHA256withECDSA&publicKeyName=#ecPublicKey"
+        + "&signatureHeaderName=ClassicalSignature")
+    // Verify PQC signature
+    
.to("crypto:verify:pqc?algorithm=ML-DSA&provider=BC&publicKeyName=#mlDsaPublicKey"
+        + "&signatureHeaderName=PQCSignature")
+    .to("mock:result");
+----
+
+NOTE: The chaining approach stores two independent signatures in separate 
headers, while the PQC component's hybrid operations produce a single combined 
signature.
+For new implementations, the PQC component's hybrid operations are recommended 
as they handle the wire format, key management, and verification logic in a 
single step.
+
+=== Choosing Between camel-crypto and camel-pqc
+
+[cols="1,1,1"]
+|===
+| Feature | `camel-crypto` (Digital Signature EIP) | `camel-pqc` component
+
+| PQC-only signatures
+| Supported (set `algorithm` and `provider`)
+| Supported (built-in algorithm support)
+
+| Hybrid signatures
+| Manual chaining of two endpoints
+| Built-in `hybridSign` / `hybridVerify`
+
+| Key lifecycle management
+| Not included
+| Generate, rotate, expire, revoke keys
+
+| Key encapsulation (KEM)
+| Not supported
+| Built-in support
+
+| Additional dependencies
+| Only Bouncy Castle
+| Only Bouncy Castle
+
+| Best for
+| Adding PQC to existing crypto: routes
+| New PQC-focused implementations
+|===
 
 include::spring-boot:partial$starter.adoc[]

Reply via email to