Andrea Cosentino created CAMEL-25798:
----------------------------------------

             Summary: camel-pqc - generateSecretKeyEncapsulation labels the 
secret key with the enum name, not the JCE name
                 Key: CAMEL-25798
                 URL: https://issues.apache.org/jira/browse/CAMEL-25798
             Project: Camel
          Issue Type: Bug
          Components: camel-pqc
            Reporter: Andrea Cosentino


The three KEM operations disagree about which name to stamp on the resulting 
secret key.

{{generateEncapsulation}} passes the raw configuration value — 
{{PQCProducer.java:671-678}}:
{code:java}
            generator.init(
                    new KEMGenerateSpec(
                            keyPair.getPublic(),
                            
getEndpoint().getConfiguration().getSymmetricKeyAlgorithm(),
{code}

{{extractEncapsulation}} maps it through the enum — 
{{PQCProducer.java:700-704}}:
{code:java}
                            
PQCSymmetricAlgorithms.valueOf(getConfiguration().getSymmetricKeyAlgorithm()).getAlgorithm(),
{code}

and {{extractSecretKeyFromEncapsulation}} does the same, with a comment stating 
exactly the rule that {{generateEncapsulation}} breaks — 
{{PQCProducer.java:723-726}}:
{code:java}
        // Use the mapped JCE algorithm name (as extractEncapsulation does), 
not the raw enum name: for algorithms
        // whose enum name differs from the JCE name (for example GOST3412_2015 
-> GOST3412-2015) the raw name is not a
        // resolvable cipher algorithm, so the restored key would carry an 
unusable algorithm label
{code}

h3. Which algorithms are affected

Two of the eighteen constants differ from their JCE name — 
{{PQCSymmetricAlgorithms.java:32,39}}:
{code:java}
    GOST3412_2015("GOST3412-2015"),
    DESEDE("DESede");
{code}

So for those two the generate side emits a {{SecretKeyWithEncapsulation}} whose 
{{getAlgorithm()}} is {{DESEDE}} / {{GOST3412_2015}} while the extract side 
emits {{DESede}} / {{GOST3412-2015}}. The generate-side label is not a 
resolvable cipher name, so handing that key to 
{{Cipher.getInstance(key.getAlgorithm())}} or to {{CryptoDataFormat}} fails, 
and the two ends of one KEM exchange disagree about the key's identity.

h3. Existing tests encode both answers

{{PQCMLKEMGenerateEncapsulationCryptoRoundTripDESedeTest.java:96-97}} asserts 
the wrong one:
{code:java}
        assertEquals("DESEDE",
                
resultEncapsulate.getExchanges().get(0).getMessage().getBody(SecretKeyWithEncapsulation.class).getAlgorithm());
{code}
while {{PQCExtractSecretKeyAlgorithmNameTest.java:126}} asserts 
{{assertEquals("DESede", restored.getAlgorithm());}} for the same configured 
algorithm. The first test needs updating with the fix.

h3. Related: a missing guard on the same method

Both extract operations reject an empty {{symmetricKeyAlgorithm}} — 
{{PQCProducer.java:693-695}}:
{code:java}
        if 
(ObjectHelper.isEmpty(getConfiguration().getSymmetricKeyAlgorithm())) {
            throw new IllegalArgumentException("Symmetric Algorithm needs to be 
specified");
        }
{code}
and both hybrid KEM paths guard it too ({{:834-836}}, {{:878-880}}). 
{{generateEncapsulation}} ({{:667-685}}) is the single unguarded sibling and 
passes the possibly-null value straight into {{new KEMGenerateSpec(...)}}. 
{{validateSymmetricKeyLength}} does not cover it either — it returns early when 
the algorithm is empty ({{:1241-1243}}).

h3. Suggested fix

Use {{PQCSymmetricAlgorithms.valueOf(...).getAlgorithm()}} in 
{{generateEncapsulation}}, add the missing guard, update the DESede test, and 
add a test that asserts the generate-side and extract-side {{getAlgorithm()}} 
agree (no GOST3412_2015 round-trip exists at all today).

----
_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)

Reply via email to