RFR: 8347938: Switch to latest ML-KEM private key encoding [v5]
Weijun Wang
weijun at openjdk.org
Mon Aug 4 16:51:58 UTC 2025
On Mon, 4 Aug 2025 11:12:11 GMT, Sebastian Stenzel <duke at openjdk.org> wrote:
>> Weijun Wang has updated the pull request incrementally with one additional commit since the last revision:
>>
>> combine security properties description; remove one test
>
> src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java line 132:
>
>> 130: if (nk instanceof NamedPKCS8Key npk) {
>> 131: var type = KeyChoices.getPreferred("mlkem");
>> 132: if (KeyChoices.typeOfChoice(npk.getRawBytes()) != type) {
>
>> ```
>> /// 1. If only `privKeyMaterial` is present, it's also the expanded format.
>> /// 2. If both `privKeyMaterial` and `expanded` are available, `privKeyMaterial`
>> /// is the encoding format, and `expanded` is the expanded format.
>> ```
>
> This in mind, the result of `getRawBytes()` differs. In the first case, it is in fact raw bytes, as the method name suggests. (See also usage of `privKeyMaterial` in `PKCS8Key.generateEncoding()`).
>
> Therefore, the ASN.1 envelope may be missing, causing
>
>
> java.security.InvalidKeyException: Wrong tag: -39
> at java.base/sun.security.util.KeyChoices.typeOfChoice(KeyChoices.java:144)
> at java.base/com.sun.crypto.provider.ML_KEM_Impls$KF.engineTranslateKey(ML_KEM_Impls.java:132)
> at java.base/java.security.KeyFactory.translateKey(KeyFactory.java:475)
>
>
> Isn't `getEncoded()` the safer bet?
>
> Suggestion:
>
> if (KeyChoices.typeOfChoice(npk.getEncoded()) != type) {
`getEncoded` is the whole PKCS #8 encoding.
`getRawBytes` returns the content of the `privateKey` field inside the PKCS #8 encoding.
`getExpanded` is not related to encoding. It's what the underlying `NamedKEM` or `NamedSignature` will use.
For ML-KEM, `getRawBytes` might be any of the 3 CHOICEs: seed, expandedKey, or both. `getExpanded` is always the expanded format (defined in FIPS 203). There is a slight difference even if `getRawBytes` is using the expandedKey choice: it has the OCTET STRING header but `getExpanded` does not.
`engineTranslateKey` can re-encode the key depending on the "jdk.mlkem.pkcs8.encoding" security property. Therefore it works on the `getRawBytes` level.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/24969#discussion_r2252029114
More information about the security-dev
mailing list