状态
| 协议/功能 | 状态 |
|---|---|
| Ratchet | 在 Java I2P 和 i2pd 中已完成 |
| NTCP2 | 2026年第一季度测试版 |
| SSU2 | 即将开始实施,2026年第二三季度测试版 |
| MLDSA SigTypes | 优先级较低,可能在2027年以后 |
概述
虽然对合适的后量子(PQ)密码学的研究和竞争已经进行了十年,但直到最近选择才变得明确。
我们在2022年开始研究PQ密码学的影响 zzz.i2p 。
TLS 标准在过去两年中增加了混合加密支持,由于 Chrome 和 Firefox 的支持,现在它被用于互联网上很大一部分加密流量 Cloudflare 。
NIST 最近最终确定并发布了后量子密码学的推荐算法 NIST 。几个常用的密码学库现在已经支持 NIST 标准,或将在不久的将来发布支持。
Cloudflare 和 NIST 都建议立即开始迁移。另请参见 2022 年 NSA PQ 常见问题解答 NSA 。I2P 应该在安全性和密码学方面保持领先地位。现在是实现推荐算法的时候了。利用我们灵活的加密类型和签名类型系统,我们将添加混合加密以及后量子和混合签名的类型。
目标
- 选择抗量子算法
- 在适当的 I2P 协议中添加纯量子和混合算法
- 定义多个变体
- 在实现、测试、分析和研究后选择最佳变体
- 逐步添加支持并保持向后兼容性
非目标
- 不要更改单向(Noise N)加密协议
- 不要放弃SHA256,近期内不受PQ威胁
- 此时不要选择最终首选变体
威胁模型
- 位于 OBEP 或 IBGW 的 router,可能串通合作, 存储 garlic 消息以供后续解密(前向保密性)
- 网络观察者 存储传输消息以供后续解密(前向保密性)
- 网络参与者为 RI、LS、流传输、数据报 或其他结构伪造签名
受影响的协议
我们将修改以下协议,大致按照开发顺序排列。整体推出时间可能从2025年底到2027年中期。详情请参阅下面的优先级和推出部分。
| 协议/功能 | 状态 |
|---|---|
| 混合 MLKEM Ratchet 和 LS | 2025年6月批准;2025年8月测试版;2025年11月发布 |
| 混合 MLKEM NTCP2 | 已在实际网络测试,2026年2月批准;2026年5月测试版目标;2026年8月发布目标 |
| 混合 MLKEM SSU2 | 2026年2月批准;2026年8月测试版目标;2026年11月发布目标 |
| MLDSA SigTypes 12-14 | 提案稳定但可能要到2027年才最终确定 |
| MLDSA Dests | 已在实际网络测试,需要网络升级以支持 floodfill |
| 混合 SigTypes 15-17 | 初步阶段 |
| 混合 Dests |
设计
我们将支持 NIST FIPS 203 和 204 标准 FIPS 203 FIPS 204 ,这些标准基于但不兼容 CRYSTALS-Kyber 和 CRYSTALS-Dilithium(版本 3.1、3 及更早版本)。
密钥交换
我们将在以下协议中支持混合密钥交换:
| 协议 | Noise 类型 | 仅支持 PQ? | 支持混合? |
|---|---|---|---|
| NTCP2 | XK | no | yes |
| SSU2 | XK | no | yes |
| Ratchet | IK | no | yes |
| TBM | N | no | no |
| NetDB | N | no | no |
| PQ KEM 仅提供临时密钥,不直接支持静态密钥握手,如 Noise XK 和 IK。 |
Noise N 不使用双向密钥交换,因此不适用于混合加密。
因此,我们将仅支持混合加密,用于 NTCP2、SSU2 和 Ratchet。我们将按照 FIPS 203 中的定义来定义三种 ML-KEM 变体,总共 3 种新的加密类型。混合类型将仅与 X25519 结合定义。
新的加密类型包括:
| Type | Code |
|---|---|
| MLKEM512_X25519 | 5 |
| MLKEM768_X25519 | 6 |
| MLKEM1024_X25519 | 7 |
| 开销将会很大。典型的消息1和消息2大小(对于XK和IK)目前约为100字节(在任何额外载荷之前)。根据算法的不同,这将增加8倍到15倍。 |
签名
我们将在以下结构中支持PQ和混合签名:
| 类型 | 仅支持 PQ? | 支持混合? |
|---|---|---|
| RouterInfo | 是 | 是 |
| LeaseSet | 是 | 是 |
| Streaming SYN/SYNACK/Close | 是 | 是 |
| Repliable Datagrams | 是 | 是 |
| Datagram2 (prop. 163) | 是 | 是 |
| I2CP create session msg | 是 | 是 |
| SU3 文件 | 是 | 是 |
| X.509 证书 | 是 | 是 |
| Java keystores | 是 | 是 |
| 因此我们将同时支持仅PQ和混合签名。我们将按照FIPS 204 定义三种ML-DSA变体、三种与Ed25519结合的混合变体,以及三种仅用于SU3文件的带预哈希的仅PQ变体,总共9种新的签名类型。混合类型将仅与Ed25519结合定义。我们将使用标准ML-DSA,而不是预哈希变体(HashML-DSA),除了SU3文件。 |
我们将使用"对冲"或随机化签名变体,而不是"确定性"变体,如 FIPS 204 第 3.4 节所定义。这确保了每个签名都是不同的,即使是对相同的数据签名,并提供了额外的侧信道攻击防护。有关算法选择(包括编码和上下文)的更多详细信息,请参见下面的实现说明部分。
新的签名类型包括:
| 类型 | 代码 |
|---|---|
| MLDSA44 | 12 |
| MLDSA65 | 13 |
| MLDSA87 | 14 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 15 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 16 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 17 |
| MLDSA44ph | 18 |
| MLDSA65ph | 19 |
| MLDSA87ph | 20 |
| X.509 证书和其他 DER 编码将使用 IETF draft 中定义的复合结构和 OID。 |
开销将会很大。典型的 Ed25519 目标和 router 身份大小为 391 字节。根据算法不同,这些将增加 3.5 倍到 6.8 倍。Ed25519 签名为 64 字节。根据算法不同,这些将增加 38 倍到 76 倍。典型的已签名 RouterInfo、LeaseSet、可回复数据报和已签名流消息大约为 1KB。根据算法不同,这些将增加 3 倍到 8 倍。
由于新的destination和router identity类型不包含填充,它们将无法被压缩。在传输过程中进行gzip压缩的destination和router identity的大小将增加12倍至38倍,具体取决于算法。
合法组合
对于目的地,新的签名类型在 leaseset 中支持所有加密类型。在密钥证书中将加密类型设置为 NONE (255)。
对于 RouterIdentities,ElGamal 加密类型已被弃用。新的签名类型仅支持 X25519(类型 4)加密。新的加密类型将在 RouterAddresses 中指示。密钥证书中的加密类型将继续为类型 4。
需要新的加密算法
- ML-KEM(原 CRYSTALS-Kyber)FIPS 203
- ML-DSA(原 CRYSTALS-Dilithium)FIPS 204
- SHA3-128(原 Keccak-256)FIPS 202 仅用于 SHAKE128
- SHA3-256(原 Keccak-512)FIPS 202
- SHAKE128 和 SHAKE256(SHA3-128 和 SHA3-256 的 XOF 扩展)FIPS 202
SHA3-256、SHAKE128 和 SHAKE256 的测试向量可在 NIST 获取。
请注意,Java bouncycastle 库支持上述所有功能。C++ 库支持在 OpenSSL 3.5 中提供 OpenSSL 。
替代方案
我们不会支持 FIPS 205 (Sphincs+),它比 ML-DSA 慢得多且占用空间大得多。我们不会支持即将推出的 FIPS206 (Falcon),它尚未标准化。我们不会支持 NTRU 或其他未被 NIST 标准化的后量子候选算法。
Rosenpass
有一些研究论文 探讨了将Wireguard (IK)适配为纯后量子密码学的方法,但该论文中仍有几个开放性问题。后来,这种方法被实现为Rosenpass Rosenpass 白皮书 ,用于后量子Wireguard。
Rosenpass 使用类似 Noise KK 的握手协议,采用预共享的 Classic McEliece 460896 静态密钥(每个 500 KB)和 Kyber-512(本质上是 MLKEM-512)临时密钥。由于 Classic McEliece 密文只有 188 字节,而 Kyber-512 公钥和密文都比较合理,两个握手消息都能放入标准 UDP MTU 中。来自 PQ KK 握手的输出共享密钥(osk)被用作标准 Wireguard IK 握手的输入预共享密钥(psk)。因此总共有两个完整的握手过程,一个是纯 PQ 的,另一个是纯 X25519 的。
我们无法通过任何这些方法来替换我们的XK和IK握手,因为:
- 我们无法执行KK模式,Bob没有Alice的静态密钥
- 500KB的静态密钥太大了
- 我们不希望有额外的往返通信
白皮书中有很多有价值的信息,我们将审查它以获取想法和灵感。TODO。
规范
通用结构
按照以下方式更新通用结构文档 /docs/specs/common-structures/ 中的章节和表格:
PublicKey
新的公钥类型包括:
| 类型 | 公钥长度 | 起始版本 | 用途 |
|---|---|---|---|
| MLKEM512_X25519 | 32 | 0.9.xx | 参见提案 169,仅用于 leaseSet,不用于 RI 或 destination |
| MLKEM768_X25519 | 32 | 0.9.xx | 参见提案 169,仅用于 leaseSet,不用于 RI 或 destination |
| MLKEM1024_X25519 | 32 | 0.9.xx | 参见提案 169,仅用于 leaseSet,不用于 RI 或 destination |
| MLKEM512 | 800 | 0.9.xx | 参见提案 169,仅用于握手,不用于 leaseSet、RI 或 destination |
| MLKEM768 | 1184 | 0.9.xx | 参见提案 169,仅用于握手,不用于 leaseSet、RI 或 destination |
| MLKEM1024 | 1568 | 0.9.xx | 参见提案 169,仅用于握手,不用于 leaseSet、RI 或 destination |
| MLKEM512_CT | 768 | 0.9.xx | 参见提案 169,仅用于握手,不用于 leaseSet、RI 或 destination |
| MLKEM768_CT | 1088 | 0.9.xx | 参见提案 169,仅用于握手,不用于 leaseSet、RI 或 destination |
| MLKEM1024_CT | 1568 | 0.9.xx | 参见提案 169,仅用于握手,不用于 leaseSet、RI 或 destination |
| NONE | 0 | 0.9.xx | 参见提案 169,仅用于具有 PQ 签名类型的 destination,不用于 RI 或 leaseSet |
| 混合公钥是 X25519 密钥。KEM 公钥是从 Alice 发送给 Bob 的临时 PQ 密钥。编码和字节顺序在 FIPS 203 中定义。 |
MLKEM*_CT 密钥实际上并不是公钥,它们是在 Noise 握手中从 Bob 发送给 Alice 的"密文"。在此列出它们是为了完整性。
私钥
新的私钥类型有:
| 类型 | 私钥长度 | 版本 | 用途 |
|---|---|---|---|
| MLKEM512_X25519 | 32 | 0.9.xx | 见提案169,仅用于 leaseSet,不用于 RI 或 Destination |
| MLKEM768_X25519 | 32 | 0.9.xx | 见提案169,仅用于 leaseSet,不用于 RI 或 Destination |
| MLKEM1024_X25519 | 32 | 0.9.xx | 见提案169,仅用于 leaseSet,不用于 RI 或 Destination |
| MLKEM512 | 1632 | 0.9.xx | 见提案169,仅用于握手,不用于 leaseSet、RI 或 Destination |
| MLKEM768 | 2400 | 0.9.xx | 见提案169,仅用于握手,不用于 leaseSet、RI 或 Destination |
| MLKEM1024 | 3168 | 0.9.xx | 见提案169,仅用于握手,不用于 leaseSet、RI 或 Destination |
| 混合私钥是 X25519 密钥。KEM 私钥仅供 Alice 使用。KEM 编码和字节顺序在 FIPS 203 中定义。 |
SigningPublicKey
新的签名公钥类型包括:
| 类型 | 长度(字节) | 起始版本 | 用法 |
|---|---|---|---|
| MLDSA44 | 1312 | 0.9.xx | 见提案 169 |
| MLDSA65 | 1952 | 0.9.xx | 见提案 169 |
| MLDSA87 | 2592 | 0.9.xx | 见提案 169 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 1344 | 0.9.xx | 见提案 169 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 1984 | 0.9.xx | 见提案 169 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 2624 | 0.9.xx | 见提案 169 |
| MLDSA44ph | 1344 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构 |
| MLDSA65ph | 1984 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构 |
| MLDSA87ph | 2624 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构 |
| 混合签名公钥是 Ed25519 密钥后跟 PQ 密钥,如 IETF draft 中所述。编码和字节顺序在 FIPS 204 中定义。 |
SigningPrivateKey
新的签名私钥类型有:
| 类型 | 长度(字节) | 起始版本 | 用途 |
|---|---|---|---|
| MLDSA44 | 2560 | 0.9.xx | 参见提案 169 |
| MLDSA65 | 4032 | 0.9.xx | 参见提案 169 |
| MLDSA87 | 4896 | 0.9.xx | 参见提案 169 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 2592 | 0.9.xx | 参见提案 169 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 4064 | 0.9.xx | 参见提案 169 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 4928 | 0.9.xx | 参见提案 169 |
| MLDSA44ph | 2592 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构。参见提案 169 |
| MLDSA65ph | 4064 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构。参见提案 169 |
| MLDSA87ph | 4928 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构。参见提案 169 |
| 混合签名私钥是 Ed25519 密钥后跟 PQ 密钥,如 IETF draft 中所述。编码和字节顺序在 FIPS 204 中定义。 |
签名
新的签名类型包括:
| 类型 | 长度(字节) | 起始版本 | 用途 |
|---|---|---|---|
| MLDSA44 | 2420 | 0.9.xx | 参见提案 169 |
| MLDSA65 | 3309 | 0.9.xx | 参见提案 169 |
| MLDSA87 | 4627 | 0.9.xx | 参见提案 169 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 2484 | 0.9.xx | 参见提案 169 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 3373 | 0.9.xx | 参见提案 169 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 4691 | 0.9.xx | 参见提案 169 |
| MLDSA44ph | 2484 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构。参见提案 169 |
| MLDSA65ph | 3373 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构。参见提案 169 |
| MLDSA87ph | 4691 | 0.9.xx | 仅用于 SU3 文件,不用于 netDb 结构。参见提案 169 |
| 混合签名是 Ed25519 签名后跟 PQ 签名,如 IETF draft 中所述。混合签名通过验证两个签名来进行验证,如果任一签名失败则验证失败。编码和字节顺序在 FIPS 204 中定义。 |
密钥证书
新的签名公钥类型包括:
| 类型 | 类型代码 | 总公钥长度 | 起始版本 | 用途 |
|---|---|---|---|---|
| MLDSA44 | 12 | 1312 | 0.9.xx | 参见提案 169 |
| MLDSA65 | 13 | 1952 | 0.9.xx | 参见提案 169 |
| MLDSA87 | 14 | 2592 | 0.9.xx | 参见提案 169 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 15 | 1344 | 0.9.xx | 参见提案 169 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 16 | 1984 | 0.9.xx | 参见提案 169 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 17 | 2624 | 0.9.xx | 参见提案 169 |
| MLDSA44ph | 18 | n/a | 0.9.xx | 仅用于 SU3 文件 |
| MLDSA65ph | 19 | n/a | 0.9.xx | 仅用于 SU3 文件 |
| MLDSA87ph | 20 | n/a | 0.9.xx | 仅用于 SU3 文件 |
| 新的加密公钥类型包括: |
| 类型 | 类型代码 | 总公钥长度 | 起始版本 | 用途 |
|---|---|---|---|---|
| MLKEM512_X25519 | 5 | 32 | 0.9.xx | 参见提案 169,仅用于 Leasesets,不适用于 RIs 或 Destinations |
| MLKEM768_X25519 | 6 | 32 | 0.9.xx | 参见提案 169,仅用于 Leasesets,不适用于 RIs 或 Destinations |
| MLKEM1024_X25519 | 7 | 32 | 0.9.xx | 参见提案 169,仅用于 Leasesets,不适用于 RIs 或 Destinations |
| NONE | 255 | 0 | 0.9.xx | 参见提案 169 |
| 混合密钥类型绝不会包含在密钥证书中;只会包含在 leaseSet 中。 |
对于使用混合或PQ签名类型的目标,加密类型使用NONE(类型255),但没有加密密钥,整个384字节的主要部分用于签名密钥。
目标地址大小
以下是新 Destination 类型的长度。所有类型的加密类型都是 NONE(类型 255),加密密钥长度被视为 0。整个 384 字节部分用于签名公钥的第一部分。注意:这与 ECDSA_SHA512_P521 和 RSA 签名类型的规范不同,在那些类型中,我们在 destination 中保留了 256 字节的 ElGamal 密钥,即使它未被使用。
无填充。总长度为 7 + 总密钥长度。密钥证书长度为 4 + 额外密钥长度。
MLDSA44 的示例 1319 字节目标字节流:
skey[0:383] 5 (932 » 8) (932 & 0xff) 00 12 00 255 skey[384:1311]
| 类型 | 类型代码 | 总公钥长度 | 主要部分 | 超出部分 | 总目标长度 |
|---|---|---|---|---|---|
| MLDSA44 | 12 | 1312 | 384 | 928 | 1319 |
| MLDSA65 | 13 | 1952 | 384 | 1568 | 1959 |
| MLDSA87 | 14 | 2592 | 384 | 2208 | 2599 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 15 | 1344 | 384 | 960 | 1351 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 16 | 1984 | 384 | 1600 | 1991 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 17 | 2624 | 384 | 2240 | 2631 |
RouterIdent 大小
以下是新 Destination 类型的长度。所有类型的加密类型都是 X25519(类型 4)。X25519 公钥后面的整个 352 字节部分用于签名公钥的第一部分。无填充。总长度为 39 + 总密钥长度。密钥证书长度为 4 + 超出密钥长度。
MLDSA44 的示例 1351 字节 router 身份字节流:
enckey[0:31] skey[0:351] 5 (960 » 8) (960 & 0xff) 00 12 00 4 skey[352:1311]
| 类型 | 类型代码 | 总公钥长度 | 主要 | 多余 | 总RouterIdent长度 |
|---|---|---|---|---|---|
| MLDSA44 | 12 | 1312 | 352 | 960 | 1351 |
| MLDSA65 | 13 | 1952 | 352 | 1600 | 1991 |
| MLDSA87 | 14 | 2592 | 352 | 2240 | 2631 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 15 | 1344 | 352 | 992 | 1383 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 16 | 1984 | 352 | 1632 | 2023 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 17 | 2624 | 352 | 2272 | 2663 |
握手模式
握手使用 Noise Protocol 握手模式。
使用以下字母映射:
- e = 一次性临时密钥
- s = 静态密钥
- p = 消息载荷
- e1 = 一次性临时 PQ 密钥,从 Alice 发送到 Bob
- ekem1 = KEM 密文,从 Bob 发送到 Alice
以下对 XK 和 IK 的修改用于混合前向保密 (hfs),如 Noise HFS spec 第 5 节所规定:
XK: XKhfs:
<- s <- s
... ...
-> e, es, p -> e, es, e1, p
<- e, ee, p <- e, ee, ekem1, p
-> s, se -> s, se
<- p <- p
p -> p ->
IK: IKhfs:
<- s <- s
... ...
-> e, es, s, ss, p -> e, es, e1, s, ss, p
<- tag, e, ee, se, p <- tag, e, ee, ekem1, se, p
<- p <- p
p -> p ->
e1 and ekem1 are encrypted. See pattern definitions below.
NOTE: e1 and ekem1 are different sizes (unlike X25519)
e1 模式定义如下,如 Noise HFS spec 第 4 节所述:
For Alice:
(encap_key, decap_key) = PQ_KEYGEN()
// EncryptAndHash(encap_key)
ciphertext = ENCRYPT(k, n, encap_key, ad)
n++
MixHash(ciphertext)
For Bob:
// DecryptAndHash(ciphertext)
encap_key = DECRYPT(k, n, ciphertext, ad)
n++
MixHash(ciphertext)
ekem1 模式的定义如下,如 Noise HFS spec 第4节所述:
For Bob:
(kem_ciphertext, kem_shared_key) = ENCAPS(encap_key)
// EncryptAndHash(kem_ciphertext)
ciphertext = ENCRYPT(k, n, kem_ciphertext, ad)
MixHash(ciphertext)
// MixKey
MixKey(kem_shared_key)
For Alice:
// DecryptAndHash(ciphertext)
kem_ciphertext = DECRYPT(k, n, ciphertext, ad)
MixHash(ciphertext)
// MixKey
kem_shared_key = DECAPS(kem_ciphertext, decap_key)
MixKey(kem_shared_key)
Noise 握手密钥派生函数
问题
- 我们是否应该更改握手哈希函数?请参见比较 。 SHA256不易受到后量子攻击,但如果我们确实想升级 哈希函数,现在是时候了,趁我们正在更改其他东西。 当前的IETF SSH提案IETF草案 是将MLKEM768 与SHA256一起使用,将MLKEM1024与SHA384一起使用。该提案包含 安全考虑的讨论。
- 我们是否应该停止发送0-RTT棘轮数据(除了LS之外)?
- 如果我们不发送0-RTT数据,我们是否应该将棘轮从IK切换到XK?
概述
本节适用于 IK 和 XK 协议。
混合握手在 Noise HFS 规范 中定义。第一条消息从 Alice 发送到 Bob,在消息载荷之前包含 e1(封装密钥)。这被视为额外的静态密钥;对其调用 EncryptAndHash()(作为 Alice)或 DecryptAndHash()(作为 Bob)。然后像往常一样处理消息载荷。
第二条消息,从 Bob 到 Alice,在消息载荷之前包含 ekem1,即密文。这被视为一个额外的静态密钥;对其调用 EncryptAndHash()(作为 Bob)或 DecryptAndHash()(作为 Alice)。然后,计算 kem_shared_key 并调用 MixKey(kem_shared_key)。接着按常规处理消息载荷。
定义的 ML-KEM 操作
我们定义以下函数,对应于 FIPS 203 中定义的加密构建块。
(encap_key, decap_key) = PQ_KEYGEN()
Alice creates the encapsulation and decapsulation keys
The encapsulation key is sent in message 1.
encap_key and decap_key sizes vary based on ML-KEM variant.
(ciphertext, kem_shared_key) = ENCAPS(encap_key)
Bob calculates the ciphertext and shared key,
using the ciphertext received in message 1.
The ciphertext is sent in message 2.
ciphertext size varies based on ML-KEM variant.
The kem_shared_key is always 32 bytes.
kem_shared_key = DECAPS(ciphertext, decap_key)
Alice calculates the shared key,
using the ciphertext received in message 2.
The kem_shared_key is always 32 bytes.
请注意,encap_key 和 ciphertext 都在 Noise 握手消息 1 和 2 的 ChaCha/Poly 块内进行了加密。它们将作为握手过程的一部分被解密。
kem_shared_key 通过 MixHash() 混合到链式密钥中。详情请参见下文。
Alice 密钥派生函数用于消息 1
对于 XK:在 ’es’ 消息模式之后和负载之前,添加:
或者
对于 IK:在 ’es’ 消息模式之后和 ’s’ 消息模式之前,添加:
This is the "e1" message pattern:
(encap_key, decap_key) = PQ_KEYGEN()
// EncryptAndHash(encap_key)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, encap_key, ad)
n++
// MixHash(ciphertext)
h = SHA256(h || ciphertext)
End of "e1" message pattern.
NOTE: For the next section (payload for XK or static key for IK),
the keydata and chain key remain the same,
and n now equals 1 (instead of 0 for non-hybrid).
消息1的Bob密钥派生函数
对于 XK:在 ’es’ 消息模式之后和载荷之前,添加:
或
对于 IK:在 ’es’ 消息模式之后和 ’s’ 消息模式之前,添加:
This is the "e1" message pattern:
// DecryptAndHash(encap_key_section)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
encap_key = DECRYPT(k, n, encap_key_section, ad)
n++
// MixHash(encap_key_section)
h = SHA256(h || encap_key_section)
End of "e1" message pattern.
NOTE: For the next section (payload for XK or static key for IK),
the keydata and chain key remain the same,
and n now equals 1 (instead of 0 for non-hybrid).
消息 2 的 Bob KDF
对于 XK:在 ’ee’ 消息模式之后和载荷之前,添加:
或
对于 IK:在 ’ee’ 消息模式之后和 ‘se’ 消息模式之前,添加:
This is the "ekem1" message pattern:
(kem_ciphertext, kem_shared_key) = ENCAPS(encap_key)
// EncryptAndHash(kem_ciphertext)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, kem_ciphertext, ad)
// MixHash(ciphertext)
h = SHA256(h || ciphertext)
// MixKey(kem_shared_key)
keydata = HKDF(chainKey, kem_shared_key, "", 64)
chainKey = keydata[0:31]
End of "ekem1" message pattern.
Alice KDF for Message 2
在 ’ee’ 消息模式之后(以及在 IK 的 ‘ss’ 消息模式之前),添加:
This is the "ekem1" message pattern:
// DecryptAndHash(kem_ciphertext_section)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
kem_ciphertext = DECRYPT(k, n, kem_ciphertext_section, ad)
// MixHash(kem_ciphertext_section)
h = SHA256(h || kem_ciphertext_section)
// MixKey(kem_shared_key)
kem_shared_key = DECAPS(kem_ciphertext, decap_key)
keydata = HKDF(chainKey, kem_shared_key, "", 64)
chainKey = keydata[0:31]
End of "ekem1" message pattern.
消息3的KDF(仅XK)
未更改
用于 split() 的 KDF
未更改
棘轮
按如下方式更新 ECIES-Ratchet 规范 /docs/specs/ecies/ :
Noise 标识符
- “Noise_IKhfselg2_25519+MLKEM512_ChaChaPoly_SHA256”
- “Noise_IKhfselg2_25519+MLKEM768_ChaChaPoly_SHA256”
- “Noise_IKhfselg2_25519+MLKEM1024_ChaChaPoly_SHA256”
1b) 新会话格式(带绑定)
变更:当前的 ratchet 在第一个 ChaCha 部分包含静态密钥,在第二部分包含有效载荷。使用 ML-KEM 后,现在有三个部分。第一部分包含加密的 PQ 公钥。第二部分包含静态密钥。第三部分包含有效载荷。
加密格式:
+----+----+----+----+----+----+----+----+
| |
+ +
| New Session Ephemeral Public Key |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ ML-KEM encap_key +
| ChaCha20 encrypted data |
+ (see table below for length) +
| |
~ ~
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for encap_key Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ X25519 Static Key +
| ChaCha20 encrypted data |
+ 32 bytes +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Static Key Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
解密格式:
Payload Part 1:
+----+----+----+----+----+----+----+----+
| |
+ ML-KEM encap_key +
| |
+ (see table below for length) +
| |
~ ~
| |
+----+----+----+----+----+----+----+----+
Payload Part 2:
+----+----+----+----+----+----+----+----+
| |
+ X25519 Static Key +
| |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
Payload Part 3:
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
尺寸:
| 类型 | 类型代码 | X长度 | 消息1长度 | 消息1加密长度 | 消息1解密长度 | PQ密钥长度 | pl长度 |
|---|---|---|---|---|---|---|---|
| X25519 | 4 | 32 | 96+pl | 64+pl | pl | – | pl |
| MLKEM512_X25519 | 5 | 32 | 912+pl | 880+pl | 800+pl | 800 | pl |
| MLKEM768_X25519 | 6 | 32 | 1296+pl | 1360+pl | 1184+pl | 1184 | pl |
| MLKEM1024_X25519 | 7 | 32 | 1680+pl | 1648+pl | 1568+pl | 1568 | pl |
| 请注意,载荷必须包含一个DateTime块,因此最小载荷大小为7。最小消息1大小可以相应计算。 |
1g) 新会话回复格式
变更:当前的 ratchet 在第一个 ChaCha 部分有空载荷,载荷在第二部分中。使用 ML-KEM 后,现在有三个部分。第一部分包含加密的 PQ 密文。第二部分有空载荷。第三部分包含载荷。
加密格式:
+----+----+----+----+----+----+----+----+
| Session Tag 8 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Ephemeral Public Key +
| |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaCha20 encrypted ML-KEM ciphertext |
+ (see table below for length) +
~ ~
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for ciphertext Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for key Section (no data) +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
解密后的格式:
Payload Part 1:
+----+----+----+----+----+----+----+----+
| |
+ ML-KEM ciphertext +
| |
+ (see table below for length) +
| |
~ ~
| |
+----+----+----+----+----+----+----+----+
Payload Part 2:
empty
Payload Part 3:
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
大小:
| 类型 | 类型代码 | Y长度 | 消息2长度 | 消息2加密长度 | 消息2解密长度 | PQ CT长度 | 可选长度 |
|---|---|---|---|---|---|---|---|
| X25519 | 4 | 32 | 72+pl | 32+pl | pl | – | pl |
| MLKEM512_X25519 | 5 | 32 | 856+pl | 816+pl | 768+pl | 768 | pl |
| MLKEM768_X25519 | 6 | 32 | 1176+pl | 1136+pl | 1088+pl | 1088 | pl |
| MLKEM1024_X25519 | 7 | 32 | 1656+pl | 1616+pl | 1568+pl | 1568 | pl |
| 请注意,虽然消息 2 通常会有非零载荷,但 ratchet 规范 /docs/specs/ecies/ 并不要求如此,因此最小载荷大小为 0。可以相应地计算消息 2 的最小大小。 |
NTCP2
按如下方式更新 NTCP2 规范 /docs/specs/ntcp2/ :
Noise 标识符
- “Noise_XKhfsaesobfse+hs2+hs3_25519+MLKEM512_ChaChaPoly_SHA256”
- “Noise_XKhfsaesobfse+hs2+hs3_25519+MLKEM768_ChaChaPoly_SHA256”
- “Noise_XKhfsaesobfse+hs2+hs3_25519+MLKEM1024_ChaChaPoly_SHA256”
1) SessionRequest
变更:当前的 NTCP2 仅包含 ChaCha 部分中的选项。使用 ML-KEM 时,ChaCha 部分还将包含加密的 PQ 公钥。
为了让 PQ 和非 PQ 的 NTCP2 能够在同一个 router 地址和端口上得到支持,我们使用 X 值(X25519 临时公钥)的最高有效位来标记这是一个 PQ 连接。对于非 PQ 连接,这个位总是未设置的。
对于 Alice,在消息经过 Noise 加密之后,但在对 X 进行 AES 混淆之前,设置 X[31] |= 0x7f。
对于Bob,在对X进行AES去混淆后,测试X[31] & 0x80。如果该位被设置,则用X[31] &= 0x7f清除它,并通过Noise作为PQ连接进行解密。如果该位是清零的,则像往常一样通过Noise作为非PQ连接进行解密。
对于在不同 router 地址和端口上发布的 PQ NTCP2,这不是必需的。
有关更多信息,请参阅下面的已发布地址部分。
原始内容:
+----+----+----+----+----+----+----+----+
| MS bit set to 1 and then |
+ obfuscated with RH_B +
| AES-CBC-256 encrypted X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaChaPoly frame (MLKEM) |
+ (see table below for length) +
| k defined in KDF for message 1 |
+ n = 0 +
| see KDF for associated data |
~ n = 0 ~
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaChaPoly frame (options) |
+ 32 bytes +
| k defined in KDF for message 1 |
+ n = 0 +
| see KDF for associated data |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
~ padding (optional) ~
| length defined in options block |
+----+----+----+----+----+----+----+----+
Same as current specification except add a second ChaChaPoly frame
未加密数据(未显示 Poly1305 认证标签):
+----+----+----+----+----+----+----+----+
| |
+ +
| X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ML-KEM encap_key |
+ (see table below for length) +
| |
+----+----+----+----+----+----+----+----+
| options |
+ (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
注意:消息 1 选项块中的版本字段必须设置为 2,即使对于 PQ 连接也是如此。
大小:
| 类型 | 类型代码 | X 长度 | 消息 1 长度 | 消息 1 加密长度 | 消息 1 解密长度 | PQ 密钥长度 | 可选长度 |
|---|---|---|---|---|---|---|---|
| X25519 | 4 | 32 | 64+pad | 32 | 16 | – | 16 |
| MLKEM512_X25519 | 5 | 32 | 880+pad | 848 | 816 | 800 | 16 |
| MLKEM768_X25519 | 6 | 32 | 1264+pad | 1232 | 1200 | 1184 | 16 |
| MLKEM1024_X25519 | 7 | 32 | 1648+pad | 1616 | 1584 | 1568 | 16 |
| 注意:类型代码仅供内部使用。router 将保持类型 4,并且支持情况将在 router 地址中指示。 |
2) SessionCreated
原始内容:
+----+----+----+----+----+----+----+----+
| |
+ obfuscated with RH_B +
| AES-CBC-256 encrypted Y |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaChaPoly frame (MLKEM) |
+ Encrypted and authenticated data +
- (see table below for length) -
+ k defined in KDF for message 2 +
| n = 0; see KDF for associated data |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaChaPoly frame (options) |
+ Encrypted and authenticated data +
- 32 bytes -
+ k defined in KDF for message 2 +
| n = 0; see KDF for associated data |
+ +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
Same as current specification except add a second ChaChaPoly frame
未加密数据(未显示 Poly1305 认证标签):
+----+----+----+----+----+----+----+----+
| |
+ +
| Y |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ML-KEM Ciphertext |
+ (see table below for length) +
| |
+----+----+----+----+----+----+----+----+
| options |
+ (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
大小:
| 类型 | 类型代码 | Y 长度 | 消息 2 长度 | 消息 2 加密长度 | 消息 2 解密长度 | PQ CT 长度 | 可选长度 |
|---|---|---|---|---|---|---|---|
| X25519 | 4 | 32 | 64+pad | 32 | 16 | – | 16 |
| MLKEM512_X25519 | 5 | 32 | 848+pad | 816 | 784 | 768 | 16 |
| MLKEM768_X25519 | 6 | 32 | 1136+pad | 1104 | 1104 | 1088 | 16 |
| MLKEM1024_X25519 | 7 | 32 | 1616+pad | 1584 | 1584 | 1568 | 16 |
| 注意:类型代码仅供内部使用。Router 将保持类型 4,支持情况将在 router 地址中指示。 |
3) SessionConfirmed
未更改
密钥派生函数 (KDF)(用于数据阶段)
未更改
已发布地址
在所有情况下,像往常一样使用 NTCP2 传输名称。
使用与非PQ、非防火墙相同的地址/端口。仅支持一种PQ变体。在router地址中,发布v=2(如常)和新参数pq=[3|4|5]来指示MLKEM 512/768/1024。Alice在会话请求中设置临时密钥的MSB(key[31] & 0x80)来指示这是一个混合连接。见上文。较旧的router将忽略pq参数并照常连接非pq。
不同地址/端口作为非PQ,或仅PQ、非防火墙模式不受支持。这将不会被实现,直到非PQ NTCP2被禁用,也就是几年后。当非PQ被禁用时,可能会支持多个PQ变体,但每个地址只支持一个。在router地址中,发布v=[3|4|5]来表示MLKEM 512/768/1024。Alice不设置临时密钥的MSB。较旧的router会检查v参数并跳过此地址,因为不受支持。
防火墙地址(未发布IP):在router地址中,发布v=2(如常)。无需发布pq参数。
Alice 可以使用 Bob 发布的 PQ 变体连接到 PQ Bob,无论 Alice 是否在她的 router 信息中宣传 pq 支持,或者她是否宣传相同的变体。
最大填充
在当前规范中,消息1和消息2被定义为具有"合理"数量的填充,建议范围为0-31字节,且未指定最大值。
Java I2P 为非 PQ 连接实现了最大 256 字节的填充,但这一点之前没有记录在文档中。
使用定义的消息大小作为最大填充量,也就是说,最大填充量将使消息大小翻倍,如下所示:
| Message Max Padding | MLKEM-512 | MLKEM-768 | MLKEM-1024 |
|---|---|---|---|
| Session Request | 880 | 1264 | 1648 |
| Session Created | 848 | 1136 | 1616 |
SSU2
按以下方式更新 SSU2 规范 /docs/specs/ssu2/ :
噪声标识符
- “Noise_XKhfschaobfse+hs1+hs2+hs3_25519+MLKEM512_ChaChaPoly_SHA256”
- “Noise_XKhfschaobfse+hs1+hs2+hs3_25519+MLKEM768_ChaChaPoly_SHA256”
请注意,SSU2 不支持 MLKEM-1024,因为密钥过大,无法适配标准的 1500 字节数据报。
长标头
长头部为32字节。它在会话创建之前使用,用于Token Request、SessionRequest、SessionCreated和Retry。它也用于会话外的Peer Test和Hole Punch消息。
在以下消息中,将长头部中的 ver(版本)字段设置为 3 或 4,以指示 MLKEM-512 或 MLKEM-768。
- (0) 会话请求
- (1) 会话已创建
- (9) 重试
- (10) 令牌请求
- (11) 打洞
在以下消息中,像往常一样将长报头中的 ver(版本)字段设置为 2,即使支持 MLKEM-512 或 MLKEM-768。如果对端支持,实现也可以将值设置为 3 或 4,但这不是必需的。实现应该接受任何 2-4 的值。
- (7) 节点测试(会话外消息 5-7)
讨论:对于所有消息类型,将版本字段设置为 3 或 4 可能并非严格必要,但这样做有助于对不支持的后量子连接进行更早的故障检测。Token Request 和 Retry(类型 9 和 10)应该使用版本 3/4 以保持一致性。Hole Punch 消息(类型 11)可能不需要这种处理,但我们将遵循相同的模式以保持统一性。Peer Test 消息(类型 7)是会话外的,不表示启动会话的意图。
头部加密前:
+----+----+----+----+----+----+----+----+
| Destination Connection ID |
+----+----+----+----+----+----+----+----+
| Packet Number |type| ver| id |flag|
+----+----+----+----+----+----+----+----+
| Source Connection ID |
+----+----+----+----+----+----+----+----+
| Token |
+----+----+----+----+----+----+----+----+
Destination Connection ID :: 8 bytes, unsigned big endian integer
Packet Number :: 4 bytes, unsigned big endian integer
type :: The message type = 0, 1, 7, 9, 10, or 11
ver :: The protocol version = 2, 3, or 4 for non-PQ, MLKEM512, MLKEM768
id :: 1 byte, the network ID (currently 2, except for test networks)
flag :: 1 byte, unused, set to 0 for future compatibility
Source Connection ID :: 8 bytes, unsigned big endian integer
Token :: 8 bytes, unsigned big endian integer
短标头
未更改
SessionRequest (类型 0)
变更:当前的 SSU2 在 ChaCha 部分只包含区块数据。使用 ML-KEM 后,ChaCha 部分还将包含加密的后量子公钥。
用于欺骗保护的KDF更改:为了解决提案165 [Prop165]_ 中提出的问题,但采用不同的解决方案,我们修改了会话请求的KDF。这仅适用于PQ会话。非PQ会话的KDF保持不变。
// End of KDF for initial chain key (unchanged)
// Bob static key
// MixHash(bpk)
h = SHA256(h || bpk);
// Start of KDF for session request
// NEW for PQ only
// bhash = Bob router hash (32 bytes)
// MixHash(bhash)
h = SHA256(h || bhash);
// Rest of KDF for session request, unchanged, as in SSU2 spec
// MixHash(header)
h = SHA256(h || header)
...
原始内容:
+----+----+----+----+----+----+----+----+
| Long Header bytes 0-15, ChaCha20 |
+ encrypted with Bob intro key +
| See Header Encryption KDF |
+----+----+----+----+----+----+----+----+
| Long Header bytes 16-31, ChaCha20 |
+ encrypted with Bob intro key n=0 +
| |
+----+----+----+----+----+----+----+----+
| |
+ X, ChaCha20 encrypted +
| with Bob intro key n=0 |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaCha20 encrypted data (MLKEM) |
+ (length varies) +
| k defined in KDF for Session Request |
+ n = 0 +
| see KDF for associated data |
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaCha20 encrypted data (payload) |
+ (length varies) +
| k defined in KDF for Session Request |
+ n = 0 +
| see KDF for associated data |
+----+----+----+----+----+----+----+----+
| |
+ Poly1305 MAC (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
未加密数据(未显示 Poly1305 认证标签):
+----+----+----+----+----+----+----+----+
| Destination Connection ID |
+----+----+----+----+----+----+----+----+
| Packet Number |type| ver| id |flag|
+----+----+----+----+----+----+----+----+
| Source Connection ID |
+----+----+----+----+----+----+----+----+
| Token |
+----+----+----+----+----+----+----+----+
| |
+ +
| X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ML-KEM encap_key |
+ (see table below for length) +
| |
+----+----+----+----+----+----+----+----+
| Noise payload (block data) |
+ (length varies) +
| see below for allowed blocks |
+----+----+----+----+----+----+----+----+
大小,不包括 IP 开销:
| 类型 | 类型代码 | X 长度 | 消息 1 长度 | 消息 1 加密长度 | 消息 1 解密长度 | PQ 密钥长度 | pl 长度 |
|---|---|---|---|---|---|---|---|
| X25519 | 4 | 32 | 80+pl | 16+pl | pl | – | pl |
| MLKEM512_X25519 | 5 | 32 | 896+pl | 832+pl | 800+pl | 800 | pl |
| MLKEM768_X25519 | 6 | 32 | 1280+pl | 1216+pl | 1184+pl | 1184 | pl |
| MLKEM1024_X25519 | 7 | 不适用 | 太大 | ||||
| 注意:类型代码仅供内部使用。Router 将保持为类型 4,支持情况将在 router 地址中指示。 |
MLKEM768_X25519 的最小 MTU:IPv4 约为 1316,IPv6 约为 1336。
SessionCreated(类型 1)
变更:当前的 SSU2 在 ChaCha 部分仅包含块数据。使用 ML-KEM 后,ChaCha 部分还将包含加密的 PQ 公钥。
原始内容:
+----+----+----+----+----+----+----+----+
| Long Header bytes 0-15, ChaCha20 |
+ encrypted with Bob intro key and +
| derived key, see Header Encryption KDF|
+----+----+----+----+----+----+----+----+
| Long Header bytes 16-31, ChaCha20 |
+ encrypted with derived key n=0 +
| See Header Encryption KDF |
+----+----+----+----+----+----+----+----+
| |
+ Y, ChaCha20 encrypted +
| with derived key n=0 |
+ (32 bytes) +
| See Header Encryption KDF |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaCha20 data (MLKEM) |
+ Encrypted and authenticated data +
| length varies |
+ k defined in KDF for Session Created +
| n = 0; see KDF for associated data |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaCha20 data (payload) |
+ Encrypted and authenticated data +
| length varies |
+ k defined in KDF for Session Created +
| n = 0; see KDF for associated data |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ Poly1305 MAC (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
未加密数据(未显示 Poly1305 认证标签):
+----+----+----+----+----+----+----+----+
| Destination Connection ID |
+----+----+----+----+----+----+----+----+
| Packet Number |type| ver| id |flag|
+----+----+----+----+----+----+----+----+
| Source Connection ID |
+----+----+----+----+----+----+----+----+
| Token |
+----+----+----+----+----+----+----+----+
| |
+ +
| Y |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ML-KEM Ciphertext |
+ (see table below for length) +
| |
+----+----+----+----+----+----+----+----+
| Noise payload (block data) |
+ (length varies) +
| see below for allowed blocks |
+----+----+----+----+----+----+----+----+
大小,不包括 IP 开销:
| 类型 | 类型代码 | Y 长度 | 消息 2 长度 | 消息 2 加密长度 | 消息 2 解密长度 | PQ CT 长度 | pl 长度 |
|---|---|---|---|---|---|---|---|
| X25519 | 4 | 32 | 80+pl | 16+pl | pl | – | pl |
| MLKEM512_X25519 | 5 | 32 | 864+pl | 800+pl | 768+pl | 768 | pl |
| MLKEM768_X25519 | 6 | 32 | 1184+pl | 1118+pl | 1088+pl | 1088 | pl |
| MLKEM1024_X25519 | 7 | n/a | 太大 | ||||
| 注意:类型代码仅供内部使用。Router 将保持类型 4,支持情况将在 router 地址中指示。 |
MLKEM768_X25519 的最小 MTU:IPv4 约为 1316,IPv6 约为 1336。
SessionConfirmed (类型 2)
未更改
数据阶段的 KDF
未改变
中继和对等测试
以下区块包含版本字段。它们将保持版本2(为了与非PQ Bob兼容),并且不会为PQ更改为版本3/4。
- 中继请求
- 中继响应
- 中继介绍
- 对等测试
PQ 签名:Relay 块、Peer Test 块和 Peer Test 消息都包含签名。不幸的是,PQ 签名比 MTU 更大。目前没有机制可以将 Relay 或 Peer Test 块或消息分片到多个 UDP 数据包中。协议必须扩展以支持分片。这将在一个单独的待定提案中完成。在此完成之前,将不支持 Relay 和 Peer Test。
已发布地址
在所有情况下,像往常一样使用 SSU2 传输名称。不支持 MLKEM-1024。
使用与非PQ、非防火墙相同的地址/端口。支持一种或两种PQ变体。在router地址中,发布v=2(照常)和新参数pq=[3|4|3,4]来表示MLKEM 512/768/两者。较旧的router将忽略pq参数并照常连接非pq。
不支持与非PQ使用不同地址/端口,或仅PQ、非防火墙模式。这将不会实现,直到非PQ SSU2被禁用,即几年后。当非PQ被禁用时,支持一个或两个PQ变体。在router地址中,发布v=[3|4|3,4]以指示MLKEM 512/768/两者。较旧的router将检查v参数并跳过此地址,因为不受支持。
防火墙地址(不发布 IP):在 router 地址中,发布 v=2(如常)。防火墙地址中必须发布 pq 参数,以支持中继。
Alice 可以使用 Bob 发布的 PQ 变体连接到 PQ Bob,无论 Alice 是否在其 router 信息中宣告 pq 支持,或者她是否宣告相同的变体。
MTU
使用 MLKEM768 时请注意不要超过 MTU。SSU2 的最小 MTU 为 1280,这是消息 1 不含填充的大小。如果 Alice 或 Bob 的 MTU 为 1280,请不要在消息 1 中包含填充。
问题
我们可以在内部使用版本字段,对 MLKEM512 使用版本 3,对 MLKEM768 使用版本 4。
对于消息1和消息2,MLKEM768会使数据包大小超过1280的最小MTU。如果MTU太低,可能就不支持该连接。
对于消息1和消息2,MLKEM1024会使数据包大小超过1500字节的最大MTU限制。这将需要对消息1和消息2进行分片处理,这会带来很大的复杂性。可能不会采用这种方案。
中继和对等测试:见上文
流媒体
TODO: 是否有更高效的方式来定义签名/验证以避免复制签名?
SU3 文件
待办事项
IETF 草案 第 8.1 节不允许在 X.509 证书中使用 HashML-DSA,也不为 HashML-DSA 分配 OID,这是因为实现复杂性和安全性降低的缘故。
对于 SU3 文件的纯 PQ 签名,请使用 IETF 草案 中为证书定义的非预哈希变体 OID。我们不定义 SU3 文件的混合签名,因为我们可能需要对文件进行两次哈希(尽管 HashML-DSA 和 X2559 使用相同的哈希函数 SHA512)。此外,在 X.509 证书中连接两个密钥和签名将完全不符合标准。
请注意,我们不允许使用 Ed25519 签名 SU3 文件,虽然我们已经定义了 Ed25519ph 签名,但我们从未就其 OID 达成一致,也从未使用过它。
SU3 文件不允许使用普通的签名类型;请使用 ph(预哈希)变体。
其他规格
新的最大 Destination 大小将是 2599(base 64 中为 3468)。
更新其他提供 Destination 大小指导的文档,包括:
- SAMv3
- Bittorrent
- 开发者指南
- 命名 / 地址簿 / 跳转服务器
- 其他文档
开销分析
密钥交换
大小增加(字节):
| Type | Pubkey (Msg 1) | Cipertext (Msg 2) |
|---|---|---|
| MLKEM512_X25519 | +816 | +784 |
| MLKEM768_X25519 | +1200 | +1104 |
| MLKEM1024_X25519 | +1584 | +1584 |
| 速度: |
根据 Cloudflare 报告的速度:
| 类型 | 相对速度 |
|---|---|
| X25519 DH/keygen | 基准 |
| MLKEM512 | 快2.25倍 |
| MLKEM768 | 快1.5倍 |
| MLKEM1024 | 1倍(相同) |
| XK | 4倍 DH(keygen + 3 DH) |
| MLKEM512_X25519 | 4倍 DH + 2倍 PQ(keygen + enc/dec)= 4.9倍 DH = 慢22% |
| MLKEM768_X25519 | 4倍 DH + 2倍 PQ(keygen + enc/dec)= 5.3倍 DH = 慢32% |
| MLKEM1024_X25519 | 4倍 DH + 2倍 PQ(keygen + enc/dec)= 6倍 DH = 慢50% |
| Java 中的初步测试结果: |
| 类型 | 相对 DH/encaps | DH/decaps | keygen |
|---|---|---|---|
| X25519 | 基准 | 基准 | 基准 |
| MLKEM512 | 快29倍 | 快22倍 | 快17倍 |
| MLKEM768 | 快17倍 | 快14倍 | 快9倍 |
| MLKEM1024 | 快12倍 | 快10倍 | 快6倍 |
签名
大小:
典型的密钥、签名、RIdent、Dest 大小或大小增量(包含 Ed25519 作为参考),假设 RI 使用 X25519 加密类型。列出了 Router Info、LeaseSet、可回复数据报以及两个流传输(SYN 和 SYN ACK)数据包各自的增加大小。当前的 Destination 和 Leasesets 包含重复填充,在传输过程中可压缩。新类型不包含填充且无法压缩,导致传输中的大小增量要高得多。请参见上述设计部分。
| 类型 | 公钥 | 签名 | 密钥+签名 | RIdent | Dest | RInfo | LS/Streaming/Datagram (每条消息) |
|---|---|---|---|---|---|---|---|
| EdDSA_SHA512_Ed25519 | 32 | 64 | 96 | 391 | 391 | baseline | baseline |
| MLDSA44 | 1312 | 2420 | 3732 | 1351 | 1319 | +3316 | +3284 |
| MLDSA65 | 1952 | 3309 | 5261 | 1991 | 1959 | +5668 | +5636 |
| MLDSA87 | 2592 | 4627 | 7219 | 2631 | 2599 | +7072 | +7040 |
| MLDSA44_EdDSA_SHA512_Ed25519 | 1344 | 2484 | 3828 | 1383 | 1351 | +3412 | +3380 |
| MLDSA65_EdDSA_SHA512_Ed25519 | 1984 | 3373 | 5357 | 2023 | 1991 | +5668 | +5636 |
| MLDSA87_EdDSA_SHA512_Ed25519 | 2624 | 4691 | 7315 | 2663 | 2631 | +7488 | +7456 |
| 速度: |
据 Cloudflare 报告的速度:
| 类型 | 相对速度标识 | 验证 |
|---|---|---|
| EdDSA_SHA512_Ed25519 | 基准线 | 基准线 |
| MLDSA44 | 慢5倍 | 快2倍 |
| MLDSA65 | ??? | ??? |
| MLDSA87 | ??? | ??? |
| Java 中的初步测试结果: |
| 类型 | 相对签名速度 | 验证 | 密钥生成 |
|---|---|---|---|
| EdDSA_SHA512_Ed25519 | 基准 | 基准 | 基准 |
| MLDSA44 | 4.6倍慢 | 1.7倍快 | 2.6倍快 |
| MLDSA65 | 8.1倍慢 | 相同 | 1.5倍快 |
| MLDSA87 | 11.1倍慢 | 1.5倍慢 | 相同 |
安全分析
NIST安全类别在NIST演示文稿 第10页中进行了总结。初步标准:对于混合协议,我们的最低NIST安全类别应为2级,对于仅PQ的协议应为3级。
| 类别 | 安全级别等同于 |
|---|---|
| 1 | AES128 |
| 2 | SHA256 |
| 3 | AES192 |
| 4 | SHA384 |
| 5 | AES256 |
握手
这些都是混合协议。实现应该优先选择 MLKEM768;MLKEM512 的安全性不够。
NIST 安全类别 FIPS 203 :
| 算法 | 安全类别 |
|---|---|
| MLKEM512 | 1 |
| MLKEM768 | 3 |
| MLKEM1024 | 5 |
签名
该提案定义了混合签名类型和仅PQ签名类型。MLDSA44混合签名比MLDSA65仅PQ签名更可取。MLDSA65和MLDSA87的密钥和签名大小对我们来说可能太大了,至少在一开始是这样。
NIST 安全类别 FIPS 204 :
| 算法 | 安全类别 |
|---|---|
| MLDSA44 | 2 |
| MLKEM67 | 3 |
| MLKEM87 | 5 |
类型偏好设置
虽然我们将定义并实现3种加密类型和9种签名类型,但我们计划在开发过程中测量性能,并进一步分析增加的结构大小所带来的影响。我们还将继续研究并监控其他项目和协议的发展动态。
经过一年或更长时间的开发后,我们将尝试为每个用例确定首选类型或默认选项。选择时需要在带宽、CPU和预估安全级别之间进行权衡。并非所有类型都适用或允许用于所有用例。
初步偏好设置如下,可能会有变更:
加密算法:MLKEM768_X25519
签名:MLDSA44_EdDSA_SHA512_Ed25519
初步限制如下,可能会有变更:
加密:SSU2 不允许使用 MLKEM1024_X25519
签名:MLDSA87和混合变体可能过大;MLDSA65和混合变体可能也过大
实现说明
库支持
Bouncycastle、BoringSSL 和 WolfSSL 库现在都支持 MLKEM 和 MLDSA。OpenSSL 的支持将在 2025 年 4 月 8 日发布的 3.5 版本中提供 OpenSSL 。
Java I2P 改编的 southernstorm.com Noise 库包含了对混合握手的初步支持,但我们将其作为未使用的代码移除了;我们将需要重新添加它并更新以匹配 Noise HFS 规范 。
签名变体
我们将使用"对冲"或随机化签名变体,而不是"确定性"变体,如 FIPS 204 第 3.4 节所定义。这确保每个签名都是不同的,即使对相同数据进行签名也是如此,并提供额外的侧信道攻击保护。虽然 FIPS 204 规定"对冲"变体是默认选项,但在各种库中这可能是也可能不是这样。实现者必须确保在签名时使用"对冲"变体。
我们使用标准的签名过程(称为纯 ML-DSA 签名生成),该过程在内部将消息编码为 0x00 || len(ctx) || ctx || message,其中 ctx 是大小为 0x00..0xFF 的可选值。我们没有使用任何可选上下文。len(ctx) == 0。此过程在 FIPS 204 算法 2 步骤 10 和算法 3 步骤 5 中定义。注意,某些已发布的测试向量可能需要设置一种模式,在该模式下消息不进行编码。
可靠性
大小增加将导致 NetDB 存储、流式握手和其他消息的 tunnel 分片大幅增加。请检查性能和可靠性变化。
结构大小
查找并检查任何限制 router info 和 leaseSet 字节大小的代码。
NetDB
审查并可能减少在内存或磁盘中存储的最大 LS/RI 数量,以限制存储增长。提高 floodfill 的最低带宽要求?
棘轮
共享 Tunnel
基于消息1(新会话消息)的长度检查,应该可以在相同tunnel上自动分类/检测多个协议。以MLKEM512_X25519为例,消息1的长度比当前ratchet协议大816字节,最小消息1大小(仅包含DateTime载荷)为919字节。当前ratchet的大多数消息1载荷都小于816字节,因此可以将它们分类为非混合ratchet。大消息可能是POST请求,这种情况比较少见。
因此推荐的策略是:
- 如果消息1小于919字节,则为当前的ratchet协议。
- 如果消息1大于或等于919字节,则可能是MLKEM512_X25519。 先尝试MLKEM512_X25519,如果失败,再尝试当前的ratchet协议。
这应该允许我们在同一个目标上有效地支持标准 ratchet 和混合 ratchet,就像我们之前在同一个目标上支持 ElGamal 和 ratchet 一样。因此,我们可以比不能为同一目标支持双协议的情况下更快地迁移到 MLKEM 混合协议,因为我们可以为现有目标添加 MLKEM 支持。
必需支持的组合有:
- X25519 + MLKEM512
- X25519 + MLKEM768
- X25519 + MLKEM1024
以下组合可能比较复杂,不是必须支持的,但可能会支持,这取决于具体实现:
- 多个 MLKEM
- ElG + 一个或多个 MLKEM
- X25519 + 一个或多个 MLKEM
- ElG + X25519 + 一个或多个 MLKEM
我们可能不会尝试在同一个目标上支持多个 MLKEM 算法(例如,MLKEM512_X25519 和 MLKEM_768_X25519)。只选择一个;但是,这取决于我们选择首选的 MLKEM 变体,以便 HTTP 客户端 tunnel 可以使用。依赖于具体实现。
我们可能会尝试在同一个目标上支持三种算法(例如 X25519、MLKEM512_X25519 和 MLKEM769_X25519)。分类和重试策略可能过于复杂。配置和配置界面可能过于复杂。这取决于具体实现。
我们很可能不会尝试在同一个目标上同时支持 ElGamal 和混合算法。ElGamal 已经过时,而且仅支持 ElGamal + 混合算法(没有 X25519)意义不大。此外,ElGamal 和混合新会话消息都很大,因此分类策略通常必须尝试两种解密方式,这会很低效。具体实现取决于实现方。
客户端可以在相同的 tunnel 上为 X25519 和混合协议使用相同或不同的 X25519 静态密钥,这取决于具体实现。
前向保密性
ECIES规范允许在新会话消息载荷中包含Garlic消息,这使得可以实现0-RTT传输初始流数据包(通常是HTTP GET)以及客户端的leaseset。然而,新会话消息载荷不具备前向保密性。由于本提案强调增强ratchet的前向保密性,实现可能会或应该推迟包含流载荷或完整流消息,直到第一个现有会话消息。这将以牺牲0-RTT传输为代价。策略也可能取决于流量类型或tunnel类型,或者例如GET与POST的区别。具体实现可自行决定。
新会话大小
在同一目标上使用MLKEM、MLDSA或两者都使用,将显著增加新会话消息的大小,如上所述。这可能会大幅降低新会话消息通过tunnel传递的可靠性,因为消息必须被分片为多个1024字节的tunnel消息。传递成功率与分片数量成指数关系。实现可以使用各种策略来限制消息大小,但会以牺牲0-RTT传递为代价。具体取决于实现。
NTCP2
我们在会话请求中设置临时密钥的最高位(key[31] & 0x80)来表示这是一个混合连接。这允许我们在同一端口上同时运行标准 NTCP 和混合 NTCP。只支持一种混合变体,并在 router 地址中公告。例如,v=2,3 或 v=2,4 或 v=2,5。
混淆
作为 Alice,对于 PQ 连接,在混淆之前,设置 X[31] |= 0x80。这使得 X 成为一个无效的 X25519 公钥。混淆后,AES-CBC 会将其随机化。混淆后 X 的最高有效位将是随机的。
作为 Bob,在去混淆后测试 (X[31] & 0x80) != 0。如果是这样,则这是一个 PQ 连接。
NTCP2-PQ 所需的最低 router 版本待定。
注意:类型代码仅供内部使用。Router将保持为类型4,支持将在router地址中指示。
SSU2
我们在长头部中使用版本字段,对于 MLKEM512 设置为 3,对于 MLKEM768 设置为 4。地址中使用 v=2,3,4 就足够了。
检查并验证 SSU2 能够处理跨多个数据包(6-8个?)分片的 MLDSA 签名 RI。
注意:类型代码仅供内部使用。Router将保持为类型4,支持情况将在router地址中指示。
Router 兼容性
传输名称
在所有情况下,请照常使用 NTCP2 和 SSU2 传输名称。
Router 加密类型
我们有几个备选方案需要考虑:
Type 5/6/7 Router
不推荐。仅使用上面列出的与 router 类型匹配的新传输协议。旧版 router 无法连接、构建 tunnel 或发送 netDb 消息。需要几个发布周期来调试并确保支持,然后才能默认启用。相比下面的替代方案,可能会将推出时间延长一年或更多。
Type 4 Router
推荐。由于 PQ 不影响 X25519 静态密钥或 N 握手协议,我们可以让 router 保持类型 4,只是公布新的传输方式。旧版本的 router 仍然可以连接、构建 tunnel 通过,或向其发送 netDb 消息。
建议
推荐在 Ratchet、NTCP2 和 SSU2 中使用 MLKEM-768,因为它在安全性和密钥长度之间提供了最佳平衡。
Router 签名类型
类型 12-17 Router
较旧的router会验证RI,因此无法连接、通过其构建tunnel或向其发送netDb消息。在默认启用之前,需要经过多个发布周期来调试和确保支持。这将面临与enc. type 5/6/7推出相同的问题;相比上面列出的type 4 enc. type推出替代方案,可能会将推出时间延长一年或更久。
无替代方案。
LS 加密类型
类型 5-7 LS 密钥
这些可能存在于带有较旧类型 4 X25519 密钥的 LS 中。较旧的 router 会忽略未知的密钥。
目标节点可以支持多种密钥类型,但只能通过对消息1使用每个密钥进行试解密来实现。可以通过维护每个密钥成功解密的计数,并优先尝试使用最多的密钥来减轻开销。Java I2P在同一目标节点上使用ElGamal+X25519时采用了这种策略。
目标签名类型
Type 12-17 目标
Router 会验证 leaseSet 签名,因此无法连接或接收类型 12-17 目标的 leaseSet。需要经过几个发布周期来调试并确保支持后才能默认启用。
没有替代方案。
优先级和发布
最有价值的数据是端到端流量,使用棘轮加密进行加密。作为tunnel跳跃之间的外部观察者,这些数据被额外加密两次,分别使用tunnel加密和传输加密。作为OBEP和IBGW之间的外部观察者,数据只被额外加密一次,使用传输加密。作为OBEP或IBGW参与者,棘轮是唯一的加密方式。然而,由于tunnel是单向的,要捕获棘轮握手中的两个消息需要串通的router,除非tunnel是在同一个router上构建OBEP和IBGW。
目前最令人担忧的后量子威胁模型是今天存储流量,然后在很多很多年后进行解密(前向保密)。混合方法可以防护这种威胁。
PQ威胁模型中,在合理时间内(比如几个月)破解认证密钥,然后冒充认证或近实时解密,这种情况还很遥远?那时我们才需要迁移到PQC静态密钥。
因此,最早的PQ威胁模型是OBEP/IBGW存储流量以供后续解密。我们应该首先实现混合棘轮。
Ratchet 是最高优先级。传输层次之。签名是最低优先级。
签名推广也将比加密推广晚一年或更长时间,因为不可能实现向后兼容。此外,MLDSA 在行业中的采用将由 CA/Browser Forum 和证书颁发机构标准化。CA 首先需要硬件安全模块 (HSM) 支持,但目前尚不可用 CA/Browser Forum 。我们预期 CA/Browser Forum 将推动关于特定参数选择的决策,包括是否支持或要求复合签名 IETF draft 。
| 里程碑 | 目标时间 |
|---|---|
| Ratchet beta | 2025年底 |
| 选择最佳加密类型 | 2026年初 |
| NTCP2 beta | 2026年初 |
| SSU2 beta | 2026年中 |
| Ratchet 生产版 | 2026年中 |
| Ratchet 默认 | 2026年底 |
| 签名 beta | 2026年底 |
| NTCP2 生产版 | 2026年底 |
| SSU2 生产版 | 2027年初 |
| 选择最佳签名类型 | 2027年初 |
| NTCP2 默认 | 2027年初 |
| SSU2 默认 | 2027年中 |
| 签名生产版 | 2027年中 |
迁移
如果我们无法在同一个 tunnel 上同时支持新旧 ratchet 协议,迁移将会变得困难得多。
我们应该能够像处理 X25519 那样,依次尝试不同的方法,这一点有待验证。
问题
- Noise Hash 选择 - 继续使用 SHA256 还是升级? SHA256 应该在未来 20-30 年内都是安全的,不会受到量子计算威胁, 参见 NIST 演示文稿 和 NCCOE 演示文稿 。 如果 SHA256 被破解,我们会面临更严重的问题 (netDb)。
- NTCP2 独立端口,独立 router 地址
- SSU2 中继 / 对等测试
- SSU2 版本字段
- SSU2 router 地址版本