oscerd opened a new pull request, #28090:
URL: https://github.com/apache/camel/pull/28090

   Fixes [CAMEL-25800](https://issues.apache.org/jira/browse/CAMEL-25800).
   
   ## Problem
   
   `HybridKEM.encapsulate()` generated the classical ephemeral key from the 
recipient key's *algorithm name*:
   
   ```java
   KeyPair ephemeralKeyPair = 
generateEphemeralKeyPair(classicalPublicKey.getAlgorithm());
   ...
   if ("EC".equals(algorithm)) {
       kpg = KeyPairGenerator.getInstance("EC");
       // Default to P-256
       kpg.initialize(new ECGenParameterSpec("secp256r1"), 
SecureRandomHelper.getSecureRandom());
   ```
   
   `getAlgorithm()` returns a bare `EC` for *every* curve, so the ephemeral key 
was always secp256r1. Against a P-384 or
   P-521 recipient key, `classicalKA.doPhase(classicalPublicKey, true)` fails 
on mismatched domain parameters.
   
   Both curves are advertised — `@UriParam(enums = 
"ECDH_P256,ECDH_P384,ECDH_P521,X25519,X448", ...)` — and documented in
   `pqc-hybrid.adoc`. `PQCClassicalKEMAlgorithms.getCurveSpec()`, 
`getSharedSecretSize()` and `isECDH()` have zero callers
   anywhere in `src/main`, which is why this went unnoticed.
   
   ### Correction to the original report
   
   The Jira initially also claimed X448 was broken. **It is not**, and I have 
amended the ticket. `BCXDHPublicKey.getAlgorithm()`
   returns the concrete name (`X25519` / `X448`) unless 
`org.bouncycastle.emulate.oracle` is set, so that branch was always
   reachable. The parameterised test proves it — against unpatched code, 
`secp256r1` and `X448` pass while `secp384r1` and
   `secp521r1` fail.
   
   There is a genuine but narrower X448 case: when a key reports only the 
generic `XDH` (Oracle emulation, or a SunEC
   `XECPublicKey`), `"XDH".equals(algorithm)` mapped unconditionally to X25519.
   
   ## Fix
   
   The group is taken from the recipient key itself rather than from its name:
   
   - `ECPublicKey.getParams()` for EC — works for both BouncyCastle and SunEC 
keys, and covers every curve;
   - `XECPublicKey.getParams()` when the provider exposes it;
   - an `XDH` key that exposes neither is rejected with `InvalidKeyException` 
instead of being silently paired with an
     X25519 ephemeral key.
   
   `reconstructPublicKey()` no longer pins `X25519` for a generic `XDH` key — 
the X.509 encoding carries its own
   parameters, so the family key factory decodes both groups.
   
   Two items in the KDF path, folded in because they sit in the same method:
   
   - an unrecognised `hybridKdfAlgorithm` now throws rather than silently 
falling back to `HKDF-SHA256`. The old behaviour
     meant a typo on one side only still "succeeded" on both ends while 
deriving the key with different digests;
   - the HKDF `info` string is encoded as UTF-8 instead of the platform default 
charset.
   
   ## Tests
   
   New `HybridKEMCurveTest`:
   
   - `hybridKemRoundTripsOnEveryNistCurve` — parameterised over secp256r1 / 
secp384r1 / secp521r1, asserting sender and
     recipient derive the same secret;
   - `x448RoundTrips` — guards the X448 path that already worked, so it stays 
working;
   - `anUnknownKdfAlgorithmIsRejected`.
   
   Against `main` this is 1 failure + 2 errors out of 5; with the change all 
pass. Full `camel-pqc` build is green:
   244 tests, 0 failures, no regenerated-file drift.
   
   ## Upgrade guide
   
   Added a 4.24 entry for the `hybridKdfAlgorithm` rejection, which is the one 
user-visible behaviour change.
   
   ---
   _Reported, analysed and fixed by Claude Code (AI agent) on behalf of 
@oscerd._
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to