[
https://issues.apache.org/jira/browse/CAMEL-25799?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18128675#comment-18128675
]
Andrea Cosentino commented on CAMEL-25799:
------------------------------------------
Noted while writing the regression test, and worth a look separately.
Both {{keyPair}} and {{classicalKeyPair}} are declared {{@Metadata(autowired =
true)}} (PQCConfiguration lines 39-41 and 90-92), as are
{{signer}}/{{classicalSigner}} and {{keyGenerator}}/{{classicalKeyAgreement}}.
A registry holding a single {{KeyPair}} bean therefore has it autowired into
*both* fields.
Two consequences:
# On a hybrid endpoint this silently uses one key pair for both halves - an
ML-DSA key pair ends up as the classical ECDSA key pair, which then fails at
signing time.
# It masks this very issue: with {{classicalKeyPair}} autowired, the classical
branch of {{configureHybridSignatureMaterial}} is skipped entirely and the
overwrite never happens. The first version of my regression test passed against
unpatched code for exactly that reason; it now sets
{{context.setAutowiredEnabled(false)}} so the branch under test is actually
reached.
Not fixed here - this ticket is scoped to the guard. Flagging it because the
autowiring-by-type collision between the classical and PQC halves looks
unintended, and a user hitting consequence 1 would get a confusing failure.
> camel-pqc - hybrid auto-configuration overwrites a user-supplied PQC signer
> and key pair
> ----------------------------------------------------------------------------------------
>
> Key: CAMEL-25799
> URL: https://issues.apache.org/jira/browse/CAMEL-25799
> Project: Camel
> Issue Type: Bug
> Components: camel-pqc
> Reporter: Andrea Cosentino
> Assignee: Andrea Cosentino
> Priority: Major
>
> {{PQCComponent.configureHybridSignatureMaterial}} guards on the *classical*
> material but then overwrites the *PQC* material.
> {{PQCComponent.java:313-333}}:
> {code:java}
> // Configure classical signature material if not already set
> if (ObjectHelper.isEmpty(configuration.getClassicalSigner())
> && ObjectHelper.isEmpty(configuration.getClassicalKeyPair()))
> {
> if
> (ObjectHelper.isNotEmpty(configuration.getClassicalSignatureAlgorithm())) {
> ...
> if ("ECDSA_P256".equals(classicalAlg) &&
> "MLDSA".equals(pqcAlg)) {
>
> configuration.setClassicalSigner(PQCDefaultECDSAMLDSAMaterial.classicalSigner);
>
> configuration.setClassicalKeyPair(PQCDefaultECDSAMLDSAMaterial.classicalKeyPair);
>
> configuration.setSigner(PQCDefaultECDSAMLDSAMaterial.pqcSigner);
>
> configuration.setKeyPair(PQCDefaultECDSAMLDSAMaterial.pqcKeyPair);
> {code}
> The condition inspects {{classicalSigner}} and {{classicalKeyPair}}; the body
> calls {{setSigner}} and {{setKeyPair}}. An earlier block ({{:289-311}})
> correctly guards the PQC half, but this block then overwrites whatever that
> block preserved.
> h3. Effect
> A route configured as
> {{hybridSign&signatureAlgorithm=MLDSA&classicalSignatureAlgorithm=ECDSA_P256}}
> with its own {{keyPair}} bean in the registry has that key pair silently
> replaced by the shared static default material. It signs with a key the user
> never chose, and verification against the user's real public key fails with
> no diagnostic.
> h3. Same shape in the KEM path
> {{PQCComponent.java:361-379}} — the guard tests {{classicalKeyAgreement}} and
> {{classicalKeyPair}}, the body calls {{setKeyGenerator}} and {{setKeyPair}}.
> h3. Suggested fix
> Split the two concerns: only set the classical material under the classical
> guard, and only set the PQC material under the PQC guard ({{getSigner()}} /
> {{getKeyPair()}} empty, or {{getKeyGenerator()}} / {{getKeyPair()}} empty).
> Log at INFO when default material is autowired so the substitution is visible.
> h3. Test gap
> No test configures a hybrid endpoint with an explicit PQC {{keyPair}} bean
> and asserts it survives endpoint creation.
> ----
> _Reported by Claude Code (AI agent) on behalf of [~oscerd]. Every code
> reference was verified against commit {{7aae27315946}} on {{main}}._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)