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

   ## Backport of #27768
   
   Cherry-pick of #27768 onto `camel-4.18.x`.
   
   **Original PR:** #27768 - CAMEL-25603: camel-pqc - do not share a 
KeyGenerator or KeyAgreement across concurrent KEM operations
   **Original author:** @oscerd
   **Target branch:** `camel-4.18.x`
   
   ### Port notes
   
   This is a hand port, not a straight cherry-pick. `camel-4.18.x` differs from 
`main` here:
   
   - There is no `HybridKEM` and there are no hybrid KEM operations, so the 
`HybridKEM` and `KeyAgreement` parts of the change, `HybridKEMConcurrencyTest` 
and `ProbedKeyAgreement` are left out.
   - `PQCProducer` and `PQCDataFormat` were ported by hand onto the 4.18.x 
code, which still passes `new SecureRandom()`. The change is the same: a new 
`KeyGenerator` per operation when Camel creates it (the producer keeps the 
`Provider` object), and the lock held from `init()` to `generateKey()` on a 
configured or shared instance.
   - `pqc-component.adoc` gets the same note, without the hybrid 
`KeyAgreement`. `pqc-dataformat.adoc` on 4.18.x is a short page with no 
"Caching KeyGenerator" tip, so it is unchanged. There are no catalog doc copies 
on this branch.
   - The new tests use the JUnit 5 `CamelTestSupport`. 
`PQCDataFormatConcurrencyTest` converts the unmarshal result with the type 
converter, because the 4.18.x data format returns a stream cache rather than a 
byte array.
   - The new tests fail on `camel-4.18.x` without the change (wrong secrets, 
the other operation's encapsulation, failed decryption) and pass with it. 
`camel-pqc`: 119 tests, 0 failures, 1 skipped (a JDK 25-only test).
   - The upgrade guides stay on `main`, which already has the 4.18.6 note (in 
`camel-4x-upgrade-guide-4_18.adoc`, "Upgrading from 4.18.5 to 4.18.6").
   
   ### Original description
   
   Fixes [CAMEL-25603](https://issues.apache.org/jira/browse/CAMEL-25603).
   
   A KEM `KeyGenerator` keeps the spec passed to `init()` until `generateKey()` 
reads it, and a `KeyAgreement` keeps its state from `init()` to 
`generateSecret()`. Neither is thread-safe, but:
   
   - `PQCProducer` held one `KeyGenerator` for `generateSecretKeyEncapsulation` 
/ `extractSecretKeyEncapsulation`, and one `KeyGenerator` plus one 
`KeyAgreement` for the hybrid KEM operations, for all exchanges.
   - `HybridKEM` ran the init-to-result sequences on whatever instances it was 
given.
   - `PQCDataFormat` cached one `KeyGenerator` at start, also when none was 
configured, and used it for every marshal and unmarshal.
   
   Overlapping exchanges could get a result computed from another exchange's 
parameters, or fail (`AEADBadTagException`, or a `NullPointerException` from 
the Bouncy Castle SPI).
   
   ## Change
   
   Same approach as CAMEL-24445 for `Signature`:
   
   - `PQCProducer` creates a new `KeyGenerator` / `KeyAgreement` for every 
exchange when it created them itself. It keeps the `Provider` object of the 
generator created at start, so creating another one does not depend on the 
provider still being registered (`PQCEndpoint.doStop()` removes the Bouncy 
Castle providers from the JVM).
   - A configured instance (an autowired registry bean, or the 
`PQCDefault*Material` defaults, which are shared JVM-wide) is used as-is, and 
each init-to-result sequence holds its monitor: in `PQCProducer`, in 
`HybridKEM` (so callers of the public utility are covered too) and in 
`PQCDataFormat`.
   - `PQCDataFormat` creates a `KeyGenerator` for every operation unless one is 
configured; `doStart()` still fails fast on an unknown algorithm or provider. 
As a side effect, the documented `CamelPQCKemAlgorithm` header now applies to a 
started data format.
   - Instances that `PQCComponent` puts into the configuration itself (the 
`parameterSpec` path, and the `PQCDefault*Material` defaults) count as 
configured and are used one at a time. Letting the producer create its own 
instead is a throughput improvement for `main`, tracked in 
[CAMEL-25624](https://issues.apache.org/jira/browse/CAMEL-25624).
   
   ## Tests
   
   New tests, all failing without the change:
   
   - `PQCKemSharedKeyGeneratorIsolationTest`: a configured `KeyGenerator` 
shared by a generate and an extract endpoint. Overlapping extractions, and an 
overlapping generation and extraction, each keep their own result. A small test 
helper (`InterleavingProbe`, with `ProbedKeyGenerator` / `ProbedKeyAgreement` 
wrappers) holds the first caller between `init()` and the result and records 
whether another `init()` got in.
   - `PQCKemConcurrentExtractionIsolationTest`: 8 threads x 40 extractions 
through one producer that created its own generator.
   - `HybridKEMConcurrencyTest`: overlapping extractions and encapsulations on 
a shared `KeyAgreement` and `KeyGenerator`.
   - `PQCDataFormatConcurrencyTest`: concurrent round trips through one data 
format with no `KeyGenerator` configured, and an overlapping marshal and 
unmarshal on a configured one.
   
   `camel-pqc`: 239 tests, 0 failures, 1 skipped (pre-existing). Full reactor 
`clean install -DskipTests -DskipITs`: BUILD SUCCESS (703 modules); the only 
regenerated files are the catalog copies of the two pqc docs.
   
   ## Docs
   
   - `pqc-component.adoc`: a note on how KEM `KeyGenerator` / `KeyAgreement` 
instances are used; registering a `KeyGenerator` bean is optional.
   - `pqc-dataformat.adoc`: the "Caching KeyGenerator" tip is replaced, since a 
shared instance now runs one operation at a time.
   - Upgrade guide notes for 4.24, 4.22.2 and 4.18.6, all on `main`. Backports 
to `camel-4.22.x` and `camel-4.18.x` will be opened by hand once this is 
merged, without `port/*` labels on purpose: the guide files stay on `main`, and 
on `camel-4.18.x` a straight cherry-pick does not compile (no hybrid KEM, 
different `PQCProducer` / `PQCDataFormat`, JUnit 5 tests).
   
   _Claude Code 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