Stav
Beta Q1 2026, vydání Q2 2026
Přehled
Toto je hybridní post-kvantová varianta protokolu přenosu NTCP2, navržená v Návrhu 169. Další informace naleznete v tomto návrhu.
PQ Hybrid NTCP2 je definován pouze na stejné adrese a portu jako standardní NTCP2. Provoz na jiném portu nebo bez podpory standardního NTCP2 není povolen a nebudete jej moci používat po několik let, dokud nebude standardní NTCP2 zastaralý.
Tato specifikace popisuje pouze změny potřebné pro standard NTCP2, aby podporoval PQ Hybrid. Základní implementační detaily naleznete v specifikaci NTCP2.
Návrh
Podporujeme standardy NIST FIPS 203 a 204 FIPS 203 FIPS 204 , které jsou založeny na, ale NEJSOU kompatibilní s, CRYSTALS-Kyber a CRYSTALS-Dilithium (verze 3.1, 3 a starší).
Výměna klíčů
PQ KEM poskytuje pouze dočasné klíče a přímo nepodporuje handshaky se statickými klíči, jako jsou Noise XK a IK. Typy šifrování jsou stejné jako v PQ Hybrid Ratchet a jsou definovány v dokumentu společných struktur /docs/specs/common-structures/ , podle FIPS 203 . Hybridní typy jsou definovány pouze ve spojení s X25519.
Typy šifrování jsou:
| Type | Code | NTCP2 Version |
|---|---|---|
| MLKEM512_X25519 | 5 | 3 |
| MLKEM768_X25519 | 6 | 4 |
| MLKEM1024_X25519 | 7 | 5 |
Nové typy šifrování jsou uvedeny v RouterAddresses. Typ šifrování v certifikátu klíče bude nadále typ 4.
Specifikace
Vzory navazování spojení
Handshakes používají vzory handshake protokolu Noise Protocol .
Používá se následující mapování písmen:
- e = jednorázový efemérní klíč
- s = statický klíč
- p = užitečné datové zatížení zprávy
- e1 = jednorázový efemérní PQ klíč, odeslaný od Alice k Bobovi
- ekem1 = KEM šifrový text, odeslaný od Boba k Alici
Následující modifikace XK a IK pro hybridní dopřednou tajnost (hfs) jsou uvedeny v sekci 5 Noise HFS spec :
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 ->
e1 and ekem1 are encrypted. See pattern definitions below.
NOTE: e1 and ekem1 are different sizes (unlike X25519)
Vzor e1 je definován následovně, jak je uvedeno v části 4 specifikace Noise HFS spec :
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)
Vzor ekem1 je definován následovně, jak je uvedeno v Noise HFS spec , část 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 Handshake KDF
Přehled
Hybridní handshake je definován ve specifikaci Noise HFS . První zpráva, od Alice k Bobovi, obsahuje e1, klíč pro encapsulaci, před datovou částí zprávy. Tento klíč je považován za dodatečný statický klíč; aplikujte na něj funkci EncryptAndHash() (jako Alice) nebo DecryptAndHash() (jako Bob). Poté zpracujte datovou část zprávy běžným způsobem.
Druhá zpráva, od Boba k Alici, obsahuje ekem1, šifrovaný text, před datovou částí zprávy. Toto je považováno za dodatečný statický klíč; zavolejte na něj EncryptAndHash() (jako Bob) nebo DecryptAndHash() (jako Alice). Poté vypočítejte kem_shared_key a zavolejte MixKey(kem_shared_key). Následně zpracujte datovou část zprávy obvyklým způsobem.
Definované operace ML-KEM
Definujeme následující funkce odpovídající kryptografickým stavebním blokům, jak jsou definovány v 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.
Všimněte si, že jak encap_key, tak šifrovací text jsou zašifrovány uvnitř bloků ChaCha/Poly ve zprávách handshake protokolu Noise 1 a 2. Budou dešifrovány jako součást procesu handshake.
kem_shared_key je kombinován do řetězového klíče pomocí MixHash(). Podrobnosti viz níže.
Alice KDF pro zprávu 1
Za vzor zprávy „es“ a před užitečný obsah přidejte:
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).
Bob KDF pro zprávu 1
Za vzor zprávy „es“ a před užitečný obsah přidejte:
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).
Bobův KDF pro zprávu 2
Pro XK: Po vzoru zprávy „ee“ a před daty přidejte:
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.
// AEAD parameters for payload section
... as in standard SSU2 ...
k = keydata[32:63]
...
Alice KDF pro zprávu 2
Po vzoru zprávy „ee“ přidejte:
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.
// AEAD parameters for payload section
... as in standard SSU2 ...
k = keydata[32:63]
...
KDF pro zprávu 3 (pouze XK)
unchanged
KDF pro split()
unchanged
Podrobnosti o handshake
Identifikátory šumu
- “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
Změny: Současný NTCP2 obsahuje pouze možnosti v jedné sekci ChaCha. S ML-KEM bude před těmito možnostmi přidána nová sekce ChaCha, obsahující zašifrovaný kvantově odolný veřejný klíč.
Aby bylo možné podporovat PQ i non-PQ NTCP2 na stejné adrese a portu směrovače, používáme nejvýznamnější bit hodnoty X (X25519 efemérní veřejný klíč) k označení, že se jedná o PQ spojení. U non-PQ spojení je tento bit vždy vynulován.
U Alice, po zašifrování zprávy pomocí Noise, ale před AES zamaskováním X, nastavte X[31] |= 0x7f.
Pro Boba po deobfuskaci X pomocí AES otestujte X[31] & 0x80. Je-li bit nastaven, vymažte jej pomocí X[31] &= 0x7f a dešifrujte pomocí Noise jako PQ spojení. Je-li bit vymazán, dešifrujte pomocí Noise jako běžné (ne-PQ) spojení.
U PQ NTCP2 inzerovaného na různé adrese a portu směrovače toto není vyžadováno.
Další informace naleznete v části Publikované adresy níže.
Surový obsah:
+----+----+----+----+----+----+----+----+
| MS bit set to 1 and then |
+ obfuscated with RH_B +
| AES-CBC-256 encrypted X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaChaPoly encrypted data (MLKEM) |
+ (see table below for length) +
| k defined in KDF for message 1 |
+ n = 0 +
| see KDF for associated data |
~ ~
+----+----+----+----+----+----+----+----+
| |
+ Poly1305 MAC (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaCha20 encrypted data (options) |
+ 16 bytes +
| k defined in KDF for message 1 |
+ n = 1 +
| see KDF for associated data |
+----+----+----+----+----+----+----+----+
| |
+ Poly1305 MAC (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
~ padding (optional) ~
| length defined in options block |
+----+----+----+----+----+----+----+----+
Same as current specification except add a second ChaChaPoly frame
Nezašifrovaná data (ověřovací značka Poly1305 není zobrazena):
+----+----+----+----+----+----+----+----+
| |
+ +
| X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ML-KEM encap_key |
+ (see table below for length) +
| |
+----+----+----+----+----+----+----+----+
| options |
+ (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
Poznámka: pole verze v bloku možností zprávy 1 musí být nastaveno na hodnotu 2, i pro PQ připojení.
Velikosti:
| Type | Type Code | X len | Msg 1 len | Msg 1 Enc len | Msg 1 Dec len | PQ key len | opt len |
|---|---|---|---|---|---|---|---|
| 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 |
2) SessionCreated
Změny: Aktuální NTCP2 obsahuje pouze možnosti v jedné sekci ChaCha. U ML-KEM bude před možnostmi nová sekce ChaCha obsahující zašifrovaný PQ šifrový text.
Surový obsah:
+----+----+----+----+----+----+----+----+
| |
+ obfuscated with RH_B +
| AES-CBC-256 encrypted Y |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaCha20 encrypted data (MLKEM) |
- (see table below for length) -
+ k defined in KDF for message 2 +
| (before mixKey) |
+ n = 0; see KDF for associated data +
| |
+----+----+----+----+----+----+----+----+
| |
+ Poly1305 MAC (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| ChaCha20 encrypted data (options) |
- 16 bytes -
+ k defined in KDF for message 2 +
| (after mixKey) |
+ n = 0; see KDF for associated data +
| |
+----+----+----+----+----+----+----+----+
| |
+ Poly1305 MAC (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
Same as current specification except add a second ChaChaPoly frame
Nešifrovaná data (ověřovací značka Poly1305 není zobrazena):
+----+----+----+----+----+----+----+----+
| |
+ +
| Y |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ML-KEM Ciphertext |
+ (see table below for length) +
| |
+----+----+----+----+----+----+----+----+
| options |
+ (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
Velikosti:
| Type | Type Code | Y len | Msg 2 len | Msg 2 Enc len | Msg 2 Dec len | PQ CT len | opt len |
|---|---|---|---|---|---|---|---|
| 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 |
3) SessionConfirmed
Nezměněno
Funkce odvození klíče (KDF) (pro datovou fázi)
Nezměněno
Publikované adresy
Ve všech případech používejte název přenosu NTCP2 jako obvykle.
Použijte stejnou adresu/port jako u nepřekvapivé (non-PQ), nefiltrované verze. Podporován je pouze jeden typ PQ varianty. V adrese routeru publikujte v=2 (jako obvykle) a nový parametr pq=[3|4|5] pro označení MLKEM 512/768/1024. Alice nastaví nejvyšší bit (MSB) dočasného klíče (key[31] & 0x80) ve žádosti o relaci, čímž indikuje, že se jedná o hybridní připojení. Viz výše. Starší routery parametr pq ignorují a připojí se klasicky bez PQ, jak je zvykem.
Různé adresy/porty pro nepostkvantové (non-PQ) a pouze postkvantové (PQ) připojení, které není za firewallem, NEJSOU podporovány. Tato funkce nebude implementována, dokud nebude nepostkvantový NTCP2 zakázán – což nastane až za několik let. Až bude nepostkvantové spojení zakázáno, mohou být podporovány více varianty PQ, ale pouze jedna na jednu adresu. Až bude tato funkce podporována, v adrese routeru uveďte v=[3|4|5] pro označení MLKEM 512/768/1024. Alice NEnastavuje MSB (nejvyšší bit) dočasného klíče. Starší routery zkontrolují parametr v a adresu přeskočí jako nepodporovanou.
Adresy za firewallem (žádná IP nezveřejněna): Ve směrovači zveřejněte v=2 (jako obvykle). Není třeba zveřejňovat parametr pq.
Alice se může připojit k PQ Bobovi pomocí PQ varianty, kterou Bob publikuje, bez ohledu na to, zda Alice propaguje podporu PQ ve svých informacích o routeru nebo zda propaguje stejnou variantu.
Maximální doplnění
V současné specifikaci je u zpráv 1 a 2 definováno, že by měly mít „rozumné“ množství doplňovacích bajtů, doporučuje se rozsah 0–31 bajtů a žádné maximum není stanoveno.
Do API 0.9.68 (verze 2.11.0) implementoval Java I2P maximální doplnění o 256 bajtů pro nepost-kvantové spojení, avšak dříve to nebylo zdokumentováno. Od API 0.9.69 (verze 2.12.0) implementuje Java I2P stejné maximální doplnění pro nepost-kvantová spojení jako pro MLKEM-512. Viz níže uvedená tabulka.
Použijte definovanou velikost zprávy jako maximální doplnění, to znamená, že maximální doplnění zdvojnásobí velikost zprávy pro PQ připojení, a to následovně:
| Message Max Padding | non-PQ (thru 0.9.68) | non-PQ (as of 0.9.69) | MLKEM-512 | MLKEM-768 | MLKEM-1024 |
|---|---|---|---|---|---|
| Session Request | 256 | 880 | 880 | 1264 | 1648 |
| Session Created | 256 | 848 | 848 | 1136 | 1616 |
Výměna klíčů
Zvýšení velikosti (bajty):
| Type | Pubkey (Msg 1) | Ciphertext (Msg 2) |
|---|---|---|
| MLKEM512_X25519 | +816 | +784 |
| MLKEM768_X25519 | +1200 | +1104 |
| MLKEM1024_X25519 | +1584 | +1584 |
Kategorie bezpečnosti NIST jsou shrnuty na prezentaci NIST , snímek 10. Předběžná kritéria: Naše minimální kategorie bezpečnosti NIST by měla být 2 pro hybridní protokoly a 3 pro pouze PQ protokoly.
| Category | As Secure As |
|---|---|
| 1 | AES128 |
| 2 | SHA256 |
| 3 | AES192 |
| 4 | SHA384 |
| 5 | AES256 |
To jsou všechno hybridní protokoly. Implementace by měly dávat přednost MLKEM768; MLKEM512 není dostatečně bezpečný.
Bezpečnostní kategorie NIST FIPS 203 :
| Algorithm | Security Category |
|---|---|
| MLKEM512 | 1 |
| MLKEM768 | 3 |
| MLKEM1024 | 5 |
Podpora knihoven
Knihovny Bouncycastle, BoringSSL a WolfSSL nyní podporují MLKEM a MLDSA. Podpora v OpenSSL bude k dispozici v jejich verzi 3.5, která vyjde 8. dubna 2025 OpenSSL .
Identifikace příchozího provozu
Nastavíme nejvýznamnější bit (MSB) dočasného klíče (key[31] & 0x80) ve vyžádání relace, abychom indikovali, že se jedná o hybridní připojení. To nám umožňuje spouštět jak standardní NTCP, tak hybridní NTCP na stejném portu. Pro příchozí spojení je podporována pouze jedna hybridní varianta, která je inzerována v adrese směrovače. Například pq=3 nebo pq=4.
Zakrývání
Jako Alice pro PQ spojení před zamaskováním nastavte X[31] |= 0x80. Tím se X stane neplatným veřejným klíčem X25519. Po zamaskování jej AES-CBC náhodně promíchá. Nejvýznamnější bit (MSB) hodnoty X bude po zamaskování náhodný.
Jako Bob otestujte, zda po deobfuskaci platí (X[31] & 0x80) != 0. Pokud ano, jedná se o PQ spojení.
Minimální verze směrovače vyžadovaná pro NTCP2-PQ je stanovena později (TBD).
Poznámka: Kódy typů jsou určeny pouze pro vnitřní použití. Směrovače zůstanou typu 4 a podpora bude indikována v adresách směrovače.
Kompatibilita směrovače
Názvy přenosových protokolů
Ve všech případech používejte název přenosu NTCP2 jako obvykle. Starší směrovače budou parametr pq ignorovat a připojí se standardním způsobem přes NTCP2.