Skip to content

Add ekDer and dkPkcs8 DER key encodings to ML-KEM keygen_seed vectors - #272

Open
Arpan0995 wants to merge 1 commit into
C2SP:mainfrom
Arpan0995:mlkem-keygen-seed-der
Open

Add ekDer and dkPkcs8 DER key encodings to ML-KEM keygen_seed vectors#272
Arpan0995 wants to merge 1 commit into
C2SP:mainfrom
Arpan0995:mlkem-keygen-seed-der

Conversation

@Arpan0995

Copy link
Copy Markdown

This addresses the DER-encoding request in #184, scoped to the three ML-KEM keygen_seed files as the smallest useful first step.

What this adds

For each of the 300 cases in mlkem_512_keygen_seed_test.json, mlkem_768_keygen_seed_test.json, and mlkem_1024_keygen_seed_test.json, two fields are added next to the existing raw keys:

  • ekDer: the encapsulation key as a DER-encoded SubjectPublicKeyInfo (the ek bytes wrapped in an SPKI with the ML-KEM algorithm identifier).
  • dkPkcs8: the decapsulation key as a DER-encoded PrivateKeyInfo in the seed form (the seed wrapped in PKCS#8 with the [0] seed choice).

Both use "format": "Der", consistent with the publicKeyDer and privateKeyPkcs8 fields elsewhere in the corpus, and both are optional in the schema, the same choice made for privateKeyPkcs8 in mldsa_sign_seed. The names ekDer and dkPkcs8 follow the ek and dk fields already in these files and the naming used in the discussion above; I am happy to switch to publicKeyDer and privateKeyPkcs8 if you prefer the corpus-wide names.

Why keygen_seed only

This is the smallest slice that adds real value: the seed-form private key and the SPKI public key are what a consumer needs to load these vectors through the standard key-encoding APIs, and key generation is where both are naturally available. Per the sizing discussion above, adding the two fields across all twelve ML-KEM files is about +50% of the ML-KEM corpus, whereas this slice is +0.79 MB, which is +9.5% of the corpus and about +35% across just these three files. Extending the same two fields to the other ML-KEM files is a straightforward follow-up if wanted.

Encoding and verification

The DER is not hand-rolled. The SPKI and seed-form PKCS#8 headers are taken from keys produced by a real ML-KEM provider, so the algorithm identifiers (the NIST OIDs 2.16.840.1.101.3.4.4.1/2/3) and structure match what implementations emit. Every field was checked back through a provider:

  • All 600 encodings (300 ekDer and 300 dkPkcs8) import through java.security.KeyFactory for ML-KEM on JDK 27 and re-encode byte-identically. They also import cleanly under a second provider (BouncyCastle).
  • For all 300 cases, encapsulating to the ekDer public key and decapsulating with the dkPkcs8 seed-form private key yields matching shared secrets, so the two added fields are a working key pair.
  • The ek carried inside each ekDer equals the case's ek, and the seed inside each dkPkcs8 equals the case's seed, with no mismatches.
  • The three files validate against the updated schema, and tools/reformat_json.py leaves them unchanged, so the formatting is canonical.

The change is add-only: no existing field or value is modified (610 insertions, 0 deletions).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant