本文へスキップ
ecdsa.com

ML-KEM ラボ:Kyber、X-Wing、ハイブリッド方式 X25519MLKEM768

ML-KEM、X-Wing、TLS ハイブリッド方式の公開鍵宛てに共有秘密をカプセル化し、それを再びデカプセル化します。鍵、暗号文、共有秘密の各部分にはすべてラベルが付きます。ClientHello または ServerHello から取得したキーシェアを貼り付けて分解したり、暗号文の 1 ビットを反転させて ML-KEM の暗黙的拒否を確認したりできます。

100% ローカル:鍵、乱数、共有秘密はブラウザー内にとどまります。エンジンはこのサイトから読み込まれる Web Worker で動作し、どこにも何も送信しません

X25519MLKEM768 の概要

定義元
RFC 10024
NIST セキュリティカテゴリ
3
カプセル化鍵(クライアントのキーシェア)
1,216 バイト
暗号文(サーバーのキーシェア)
1,120 バイト
共有秘密
64 バイト
TLS の NamedGroup
0x11ec(IANA に登録済み)
HPKE の KEM ID
なし
X.509 の OID
なし
カプセル化鍵・クライアントのキーシェア
アルゴリズムサイズ
X25519MLKEM768
1,216 バイトX25519 の 38 倍
X25519
32 バイト
ECDH P-256
65 バイト
ECDH P-384
97 バイト
暗号文・サーバーのキーシェア
アルゴリズムサイズ
X25519MLKEM768
1,120 バイトX25519 の 35 倍
X25519
32 バイト
ECDH P-256
65 バイト
ECDH P-384
97 バイト

この鍵交換では、TLS 1.3 のハンドシェイクで 2,336 バイトが送られます。X25519 では 64 バイトです。 X25519 と ECDH では、「暗号文」は一時公開鍵です(P-256 と P-384 では非圧縮形式の点)。

実行する内容

1 · 受信者:鍵ペア

鍵の形式
非公開:このブラウザー内にとどまり、共有リンクには含まれません

2 · 送信者:カプセル化

空欄のままにすると、新しい乱数が生成されます。入力するのはテストベクトルを再現するときだけです。この値を知っている人は誰でも共有秘密を知ることができます。

3 · 受信者:デカプセル化

Key encapsulation in three steps

A key encapsulation mechanism agrees on a secret in one round trip. The recipient generates a key pair and publishes the encapsulation key. The sender runs Encaps on it and gets two values: a ciphertext to send and a shared secret to keep. The recipient runs Decaps on the ciphertext with the decapsulation key and arrives at the same secret. The lab walks through exactly these three steps, with every value labelled and sized.

ML-KEM is the KEM NIST standardized in FIPS 203 on 13 August 2024, derived from CRYSTALS-Kyber. FIPS 203 changed Kyber in small ways, so round-3 Kyber and ML-KEM do not interoperate. It has three parameter sets. ML-KEM-768, the one TLS uses, has an encapsulation key of 1,184 bytes and a ciphertext of 1,088 bytes; X25519 needs 32 bytes for each. The shared secret is 32 bytes in every set.

The hybrids TLS 1.3 actually sends

Browsers did not switch to ML-KEM alone. They negotiate a hybrid: the client sends an ML-KEM encapsulation key and an ECDH public key in one key share, the server answers with an ML-KEM ciphertext and its own ECDH key, and both secrets go into the key schedule. The connection stays confidential as long as either algorithm holds, which is the point while ML-KEM is young. RFC 10024 (August 2026) defines three such groups:

GroupCode pointClient shareServer shareSecretOrder
X25519MLKEM7680x11EC1,216 B1,120 B64 BML-KEM first
SecP256r1MLKEM7680x11EB1,249 B1,153 B64 BECDH first
SecP384r1MLKEM10240x11ED1,665 B1,665 B80 BECDH first

The order is the detail that breaks home-grown implementations: X25519MLKEM768 puts the ML-KEM part first in the client share, the server share and the shared secret, against the order its name suggests, for historical reasons. The NIST-curve groups put the ECDH part first, and use only the x-coordinate of the ECDH result. The lab shows the byte ranges of each part, so a key share captured with Wireshark or openssl s_client -trace can be checked against the RFC: paste it in "Take apart a TLS key share", with or without its four-byte group and length header.

The lab also runs X-Wing (draft-connolly-cfrg-xwing-kem-11), a hybrid designed as a single KEM: ML-KEM-768 and X25519 combined through SHA3-256 into one 32-byte secret, with a 32-byte seed as its whole private key. It is registered as HPKE KEM 0x647A and has an OID, but it is still an Internet-Draft, and its TLS code point is only requested.

What the lab checks

  • Encapsulation keys. FIPS 203 §7.2 requires a type check (the length) and a modulus check: every 12-bit coefficient of the key must already be reduced modulo 3329. A key that fails is rejected before encapsulation, as a conforming peer would reject it. For hybrids, the ECDH half is checked too: X25519 small-order points, which force an all-zero secret, and P-256 or P-384 points off the curve or not in uncompressed form, as RFC 8446 requires.
  • Decapsulation keys. FIPS 203 §7.3: the stored hash of the encapsulation key must match, and a pairwise test encapsulates and decapsulates once. Keys in PKCS #8 follow RFC 9935, where a private key can be the 64-byte seed, the expanded key or both; when both are present, they must agree, including the implicit-rejection secret z that a pairwise test alone would miss.
  • Implicit rejection. Decaps never reports a damaged ciphertext. It returns a pseudo-random value derived from the secret z and the ciphertext instead, so an attacker learns nothing from error messages. Flip one bit of the ciphertext and decapsulate: the lab detects that this happened and shows that the two sides now hold different secrets.

Known-answer examples

The ML-KEM examples are NIST ACVP-Server encapsulation tests. Each carries the 32-byte encapsulation randomness m, so the lab's Encapsulate reproduces the expected ciphertext and shared secret byte for byte. The hybrid examples join the ML-KEM-768 or ML-KEM-1024 test with the X25519 vector of RFC 7748 §6.1 or the P-256 and P-384 vectors of RFC 5903, in the order RFC 10024 prescribes. The X-Wing example is Appendix C of its draft. Supplying randomness is for test vectors only. Whoever knows it knows the secret, so the field is never put into a share link.

Further reading

How the hybrid fits into the TLS 1.3 handshake, and who enables it by default, is covered in X25519MLKEM768 explained and shown byte by byte in the illustrated post-quantum handshake. X25519MLKEM768 vs X25519 weighs the cost. To check what your own browser negotiates, use the browser post-quantum check; to use ML-KEM for encrypting data rather than for a handshake, try the HPKE playground.