Conversation
• add dependency to pkcs8 and const-oid crate and define features pkcs8 & alloc
• implement AssociatedOid and AssociatedAlgorithmIdentifier
for ML-KEM parameter sets {MlKem512Params,MlKem768Params,MlKem1024Params}
• implement AssociatedAlgorithmIdentifier
for EncapsulationKey & DecapsulationKey
• serialization:
implement EncodePublicKey for EncapsulationKey
implement EncodePrivateKey for DecapsulationKey
• deserialization:
implement TryFrom<pkcs8::SubjectPublicKeyInfoRef> for EncapsulationKey
implement TryFrom<pkcs8::PrivateKeyInfoRef> for DecapsulationKey
• add testcase with DER serialization roundtrip
REMARK:
The encapsulation key is serialized into a Subject Public Key Info
as defined in RFC 5280 § 4.1.2.7 or more specifically for ML-KEM,
draft-ietf-lamps-kyber-certificates-latest from 2025-05-27 § 4:
https://lamps-wg.github.io/kyber-certificates/draft-ietf-lamps-kyber-certificates.html#name-subject-public-key-fields
The decapsulation key is serialized into a Private Key Info
as defined in RFC 5958 § 2 or more specifically for ML-KEM,
draft-ietf-lamps-kyber-certificates-latest from 2025-05-27 § 6:
https://lamps-wg.github.io/kyber-certificates/draft-ietf-lamps-kyber-certificates.html#name-private-key-format
• previously, the associated type Error was defined to be
pkcs8::spki::Error instead of pkcs8::Error
• As a result, the blanket implementation
"""
impl<T> DecodePrivateKey for T
where
T: for<'a> TryFrom<PrivateKeyInfoRef<'a>, Error = Error>,
"""
https://docs.rs/pkcs8/0.11.0-rc.4/pkcs8/trait.DecodePrivateKey.html#impl-DecodePrivateKey-for-T
was not effective and DecodePrivateKey was not implemented for
DecapsulationKey
…PublicKey • these traits are supported through blanket implementations and shall be tested as well
Let us consider the test vectors from this repository: https://github.com/lamps-wg/kyber-certificates/tree/624bcaa4bd9ea9e72de5b51d81ce2d90cbd7e54a This implementation uses a seed of values [0, 1, …, 63]. Now let us generate the public and private keys. My previous implementation generated an OCTET STRING of length 1632 for ML-KEM 512: $ openssl asn1parse -in ml-kem-512-private-key-generated.pem -dump | head -n6 | tail -n2 20:d=1 hl=4 l=1632 prim: OCTET STRING 0000 - 70 55 4f d4 36 34 4f 27-85 b1 b3 b1 ba c1 84 b6 pUO.64O'........ The IETF draft specification suggests a structure involving ASN.1 CHOICE to distinguish between seed, expanded, and both formats: https://lamps-wg.github.io/kyber-certificates/draft-ietf-lamps-kyber-certificates.html#name-private-key-format This leads to four additional bytes: $ openssl asn1parse -in ML-KEM-512-expanded.priv -dump | head -n6 | tail -n2 20:d=1 hl=4 l=1636 prim: OCTET STRING 0000 - 04 82 06 60 70 55 4f d4-36 34 4f 27 85 b1 b3 b1 ...`pUO.64O'.... This implementation now introduces the CHOICE discriminator. Recognize that the draft suggests serialization to the seed format per default. Sadly we cannot implement this. The data stored in EncapsulationKey does not store the seed which lead to this encapsulation key. As a result, the expanded format is always used. The previous text talked about changes in the serialization. In terms of deserialization all three formats must be supported which also I implemented.
We can re-add support for expanded decapsulation keys and "both" the former and seeds if it ends up shipping in the final document. For now though, we should discourage use of anything but seeds as wasteful and needlessly complex (it was added to the draft to sate HSM vendors who shipped expanded keys before the final FIPS 203 document and who refuse to fix their mistakes).
Member
Author
|
cc @meisterluk |
This was referenced Oct 25, 2025
Closed
|
LGTM. Cheers! |
Merged
tarcieri
added a commit
that referenced
this pull request
Apr 28, 2026
## Added - `Seed` support e.g. `DecapsulationKey::from_seed` (#133, #138) - PKCS#8 support (#135) - `KeyInit`, `KeySizeUser`, and `KeyExport` impls for decapsulation keys (#156, #228) - Parameter set modules: `ml_kem_512`, `mk_kem_768`, `mk_kem_1024` (#162) - `DecapsulationKey::from_expanded` deprecated compatibility support (#163) - `TryKeyInit` and `KeyExport` impls for encapsulation keys (#188) - Validations against Wycheproof test vectors (#213, #214, #215, #217) - Implement `kem::Kem` trait (#223) - Support for `kem::FromSeed` trait (#255) ## Changed - Edition changed to 2024 and MSRV bumped to 1.85 (#118) - Relax MSRV policy and allow MSRV bumps in patch releases - Upgrade `hybrid-array` dependency to 0.4 (#129) - Extract `module-lattice` crate (#199, #202, #204, #209, #210, #211, #212, #218, #219, #220) - Replace `EncodedSizeUser` with `ExpandedKeyEncoding` (#226) - Bump `getrandom` to v0.4 (#245) - Bump `rand_core` to v0.10 (#245) - Migrate from `subtle` to `ctutils` (#277) - Bump `sha3` dependency to v0.11 (#282) - Bump `kem` dependency to v0.3 (#283) - Bump `pkcs8` dependency to v0.11 (#291) ## Fixed - Validate encryption/encapsulation keys (#179) - Validate expanded decapsulation key hash (#207) ## Removed - `Kem` struct and `KemCore` trait - replaced by `kem::Kem` (#223)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is #124, rebased on
master, and modified to remove support for expanded decapsulation keys and the option to encode both the seed and the expanded decapsulation key, to discourage proliferation of these options which were added to sate HSM vendors who shipped expanded keys prior to the final FIPS 203 draft. We should not encourage the proliferation of their mistakes.Additionally, the encoding of PKCS#8 private keys now includes only the seed, making them significantly smaller.
Closes #54