-
CSR
-
Resolution: Unresolved
-
P2
-
None
-
None
-
behavioral
-
minimal
-
ML-KEM is new in JDK 24.
-
File or wire format
-
Implementation
Summary
Update the ML-KEM and ML-DSA private key encodings to align with Section 6 of draft-ietf-lamps-kyber-certificates-11 and Section 6 of draft-ietf-lamps-dilithium-certificates-12. Specifically, the privateKey
field inside the PKCS #8 encoding will follow the DER-encoded CHOICE structure as defined. All 3 CHOICEs will be supported at encoding and decoding.
Problem
When ML-KEM and ML-DSA were initially introduced in OpenJDK, earlier versions of draft-ietf-lamps-kyber-certificates and draft-ietf-lamps-dilithium-certificates described the private key simply as βan opaque byte sequence,β without specifying a concrete format. Based on that, we adopted the encoding defined in NIST FIPS 203 β specifically, the private key output from the ML-KEM.KeyGen function (Section 7.1 of FIPS 203), and NIST FIPS 204 β specifically, the private key part of the return value from the ML-DSA.KeyGen function (Section 5.1 of FIPS 204).
In the latest revision of the drafts, the private key format is defined as a DER-encoded ASN.1 CHOICE. For ML-KEM-512, for example:
ML-KEM-512-PrivateKey ::= CHOICE {
seed [0] OCTET STRING (SIZE (64)),
expandedKey OCTET STRING (SIZE (1632)),
both SEQUENCE {
seed OCTET STRING (SIZE (64)),
expandedKey OCTET STRING (SIZE (1632))
}
}
Similar structures are defined for ML-KEM-768, ML-KEM-1024, ML-DSA-44, ML-DSA-65, and ML-DSA-87.
Our current implementation corresponds to the second choice, expandedKey OCTET STRING
. To comply with the updated specification, we need to update our implementation to support the other two choices as well.
Solution
For reading, all three CHOICEs are accepted when parsing an existing PKCS #8 encoded private key.
For writing, two security properties control which of the three CHOICEs is used when creating a new private key:
When KeyPairGenerator::generateKey
or KeyFactory::translateKey
is called, the resulting private key will be encoded using the selected format.
Note: If KeyFactory::translateKey
is used to convert a key that does not contain a seed into a format that requires the seed, the operation will fail with an InvalidKeyException
.
Specification
New security properties, jdk.mlkem.pkcs8.encoding
and jdk.mldsa.pkcs8.encoding
, are introduced to control the PKCS #8 encoding of newly created ML-KEM and ML-DSA private keys.
The following is added to the java.security
file:
#
# Newly created ML-KEM and ML-DSA private key formats in PKCS #8
#
# The draft-ietf-lamps-kyber-certificates and draft-ietf-lamps-dilithium-certificates
# specifications define three formats for a private key: a seed (64 bytes for ML-KEM,
# 32 bytes for ML-DSA), an expanded private key, or a sequence containing both.
#
# Valid values for these properties are "seed", "expandedKey", and "both"
# (case-insensitive). The default is "seed".
#
# These properties determine the encoding format used when a new keypair is generated
# using a KeyPairGenerator, as well as the output of the translateKey method on an
# existing key using a ML-KEM or ML-DSA KeyFactory.
#
# If a system property of the same name is also specified, it supersedes the
# security property value defined here.
#
# Note: These properties are currently used by the SunJCE (for ML-KEM) and SUN
# (for ML-DSA) providers in the JDK Reference implementation. They are not guaranteed
# to be supported by other SE implementations or third-party security providers.
#
#jdk.mlkem.pkcs8.encoding = seed
#jdk.mldsa.pkcs8.encoding = seed
- csr of
-
JDK-8347938 Switch to latest ML-KEM private key encoding
-
- Open
-