Skip to content

Add MLKEM1024-P384 hybrid KEM support in HPKE#14722

Merged
reaperhulk merged 2 commits into
mainfrom
claude/add-ml-kem-hybrid-kem-c9Ks1
Apr 24, 2026
Merged

Add MLKEM1024-P384 hybrid KEM support in HPKE#14722
reaperhulk merged 2 commits into
mainfrom
claude/add-ml-kem-hybrid-kem-c9Ks1

Conversation

@alex

@alex alex commented Apr 23, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds the MLKEM1024-P384 hybrid KEM (KEM ID 0x0051) from
    draft-ietf-hpke-pq
    to HPKE, combining ML-KEM-1024 with ECDH over NIST P-384 using the
    QSF-style SHA3-256 combiner:

    ss = SHA3-256(ss_PQ || ss_T || ct_T || ek_T || "MLKEM1024-P384")
    
  • Exposes MLKEM1024P384PrivateKey / MLKEM1024P384PublicKey which take
    an MLKEM1024Private/PublicKey plus a SECP384R1
    EllipticCurvePrivate/PublicKey, wired through the new
    KEM.MLKEM1024_P384 variant. Mirrors the existing
    MLKEM768X25519PrivateKey / MLKEM768X25519PublicKey pattern from
    Add MLKEM768-X25519 hybrid KEM support in HPKE #14695.

  • Validated end-to-end against the draft-ietf-hpke-pq vectors in
    vectors/cryptography_vectors/HPKE/hpke-pq-test-vectors.json via the
    existing test_vector_decryption test (now covering KEM ID 0x0051),
    plus new format/type-error/round-trip tests.

Like MLKEM768_X25519, this KEM is only available on backends with both
ML-KEM and SHA3-256 (so: AWS-LC; skipped on BoringSSL because it lacks
SHA3).

Test plan

  • OPENSSL_DIR=/path/to/aws-lc nox -e local passes (ruff, clippy,
    mypy, pytest, cargo tests)
  • test_hpke.py passes, including test_vector_decryption against
    the IETF draft vectors
  • New per-KEM tests pass:
    test_ciphertext_format_mlkem1024_p384,
    test_wrong_key_mlkem1024_p384,
    test_mlkem1024_p384_wrong_kem_with_ec,
    test_mlkem1024_p384_constructor_type_errors

https://claude.ai/code/session_01WMt6uNpXMN2skhuiEtEMx7


Generated by Claude Code

Implements the MLKEM1024-P384 hybrid KEM (KEM ID 0x0051) as specified in
draft-ietf-hpke-pq. This combines ML-KEM-1024 with ECDH over NIST P-384,
using the QSF-style SHA3-256 combiner:

    ss = SHA3-256(ss_PQ || ss_T || ct_T || ek_T || "MLKEM1024-P384")

Exposes MLKEM1024P384PrivateKey / MLKEM1024P384PublicKey, which accept
an MLKEM1024Private/PublicKey plus a SECP384R1 EllipticCurvePrivate/
PublicKey, and wires them through the new KEM.MLKEM1024_P384 variant.
Validated end-to-end against the draft-ietf-hpke-pq test vectors via
test_vector_decryption.

https://claude.ai/code/session_01WMt6uNpXMN2skhuiEtEMx7
Comment thread src/cryptography/hazmat/primitives/hpke.py Outdated
Comment thread src/rust/src/backend/hpke.rs Outdated
- Consolidate mlkem768_x25519_combine and mlkem1024_p384_combine into a
  single hybrid_kem_combine helper that takes the label as an argument.
  Both KEMs use the same QSF-style SHA3-256 combiner structure
  (ss_PQ || ss_T || ct_T || ek_T || Label), so the duplication wasn't
  pulling its weight.
- Move MLKEM1024P384Private/PublicKey assignments under the
  MLKEM768X25519 ones in cryptography/hazmat/primitives/hpke.py to match
  the ordering of __all__.

https://claude.ai/code/session_01WMt6uNpXMN2skhuiEtEMx7
@reaperhulk reaperhulk merged commit 9025578 into main Apr 24, 2026
70 checks passed
@reaperhulk reaperhulk deleted the claude/add-ml-kem-hybrid-kem-c9Ks1 branch April 24, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants