[
https://issues.apache.org/jira/browse/CAMEL-25803?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Andrea Cosentino reassigned CAMEL-25803:
----------------------------------------
Assignee: Andrea Cosentino
> camel-pqc - the hybrid wire format v2 is documented but not implemented
> -----------------------------------------------------------------------
>
> Key: CAMEL-25803
> URL: https://issues.apache.org/jira/browse/CAMEL-25803
> Project: Camel
> Issue Type: Bug
> Components: camel-pqc
> Reporter: Andrea Cosentino
> Assignee: Andrea Cosentino
> Priority: Major
>
> {{src/main/docs/pqc-hybrid.adoc}} documents a self-describing "wire format
> v2" for hybrid signatures and encapsulations, in a dedicated hundred-line
> section. The code implements only v1.
> h3. What the documentation claims
> {{pqc-hybrid.adoc:104}}:
> {noformat}
> Since Camel 4.19, hybrid signatures use wire format v2 which includes magic
> bytes, version, and algorithm identifiers (see <<Wire Format v2 and Algorithm
> Identification>>). The v1 format `[4 bytes: classical sig length][classical
> sig][pqc sig]` is still accepted on input for backward compatibility.
> {noformat}
> The same sentence appears for encapsulations at {{:217}}, with the format
> laid out under {{== Wire Format v2 and Algorithm Identification}} ({{:289}})
> and {{=== Wire Format v2 Layout}} ({{:364}}).
> h3. What the code does
> {{HybridSignature.java:73-74}}:
> {code:java}
> // Combine: [4 bytes length][classical sig][pqc sig]
> return combineSignatures(classicalSignature, pqcSignature);
> {code}
> That is the v1 format. {{HybridKEM}} is the same. There are no magic bytes,
> no version byte and no algorithm identifiers anywhere in either class.
> h3. {{PQCAlgorithmId}} is public, documented and referenced by nothing
> {{PQCAlgorithmId.java:36}} declares a public enum of about fifty constants
> whose Javadoc says it is "used in the wire format header to make hybrid
> cryptographic outputs self-describing". A repository-wide grep finds *zero*
> references outside its own file — no production caller, no test, only the
> adoc. It is untested public API surface.
> It is also internally inconsistent with the algorithm enums, so
> {{fromJcaName()}} returns {{UNKNOWN}} for the real JCE names.
> {{PQCAlgorithmId.java:77}}:
> {code:java}
> FRODO(0x0406, "FRODO"),
> {code}
> versus {{PQCKeyEncapsulationAlgorithms.java:29}}:
> {code:java}
> FRODO("FrodoKEM", "BC"),
> {code}
> Same for {{KYBER}} ({{"KYBER"}} vs {{"ML-KEM"}}), {{DILITHIUM}} and
> {{SPHINCSPLUS}}. The enum is also missing HSS and seven
> {{PQCSymmetricAlgorithms}} constants, and carries a {{PICNIC}} constant that
> exists in no other enum (Picnic was removed from Bouncy Castle).
> h3. The documented API does not compile
> {{pqc-hybrid.adoc:357}}:
> {code:java}
> PQCAlgorithmId classical = components.classicalAlgorithmId(); // e.g.
> SHA256_WITH_ECDSA
> {code}
> {{HybridSignature.java:216}}:
> {code:java}
> public record HybridSignatureComponents(byte[] classicalSignature, byte[]
> pqcSignature) {
> {code}
> There is no {{classicalAlgorithmId()}} accessor. A user following the
> published snippet gets a compile error.
> h3. Decision needed
> Either implement v2 — magic bytes, version, algorithm ids, with v1 still
> accepted on input as the docs already promise — and give
> {{HybridSignatureComponents}} the documented accessors; or delete
> {{PQCAlgorithmId}} and the entire v2 section of the documentation and
> describe the v1 format that actually ships. Shipping a documented format that
> does not exist is worse than either.
> If v2 is implemented, it would also be the natural place to fix the related
> gap in {{PQCDataFormat}} ({{:182-185}}), whose output carries neither the
> symmetric algorithm nor the key length even though both can be overridden per
> message via {{CamelPQCSymmetricAlgorithm}} — a mismatch currently surfaces as
> a misleading "may have been tampered with" at {{:240-243}}.
> h3. Note on the combiner itself
> For the record, the hybrid construction is sound in kind and should not
> change as part of this: both secrets are fed through HKDF
> ({{HybridKEM.java:260-266}}, not XOR and not single-secret),
> {{HybridSignature.verify}} correctly uses {{&&}} ({{:118}}), and the v1 wire
> format is length-prefixed and bounds-checked on parse. Two smaller hardening
> items worth folding in: the HKDF {{salt}} is {{null}} and {{info}} is only
> the cipher name, where the established combiners also bind the PQ ciphertext
> and the public keys; and {{info.getBytes()}} uses the platform default
> charset inside a key derivation.
> h3. Test gap
> The only negative hybrid-signature test tampers with the data, which
> invalidates *both* signatures — it would pass identically if the verification
> operator were {{||}}. A test that forges exactly one half (valid classical
> signature spliced onto a garbage PQC signature) is the highest-value missing
> test in this area.
> ----
> _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)