Diese Übersetzung wurde mittels maschinellem Lernen erstellt und ist möglicherweise nicht 100% korrekt. Englische Version anzeigen

PQ Hybrid NTCP2

Post-Quanten-Hybrid-Variante des NTCP2 Transportprotokolls unter Verwendung von ML-KEM

Status

Beta Q1 2026, Veröffentlichung Q2 2026

Übersicht

Dies ist die hybride Post-Quantum-Variante des NTCP2-Transportprotokolls, wie in Vorschlag 169 entworfen. Siehe diesen Vorschlag für zusätzliche Hintergrundinformationen.

PQ Hybrid NTCP2 ist nur auf derselben Adresse und demselben Port wie Standard-NTCP2 definiert. Der Betrieb auf einem anderen Port oder ohne Standard-NTCP2-Unterstützung ist nicht erlaubt und wird es auch für mehrere Jahre nicht sein, bis Standard-NTCP2 als veraltet eingestuft wird.

Diese Spezifikation dokumentiert nur die Änderungen, die am Standard-NTCP2 erforderlich sind, um PQ Hybrid zu unterstützen. Siehe die NTCP2-Spezifikation für die grundlegenden Implementierungsdetails.

Design

Wir unterstützen die NIST FIPS 203 und 204 Standards FIPS 203 FIPS 204 , die auf CRYSTALS-Kyber und CRYSTALS-Dilithium basieren, aber NICHT kompatibel sind mit den Versionen 3.1, 3 und älteren.

Schlüsselaustausch

PQ KEM stellt nur ephemerale Schlüssel zur Verfügung und unterstützt nicht direkt Static-Key-Handshakes wie Noise XK und IK. Die Verschlüsselungstypen sind die gleichen wie in PQ Hybrid Ratchet verwendet und sind im Dokument für gemeinsame Strukturen /docs/specs/common-structures/ definiert, wie in FIPS 203 . Hybride Typen sind nur in Kombination mit X25519 definiert.

Die Verschlüsselungstypen sind:

TypCode
MLKEM512_X255195
MLKEM768_X255196
MLKEM1024_X255197

Zulässige Kombinationen

Die neuen Verschlüsselungstypen werden in den RouterAddresses angegeben. Der Verschlüsselungstyp im Schlüsselzertifikat wird weiterhin Typ 4 sein.

Spezifikation

Handshake-Muster

Handshakes verwenden Noise Protocol Handshake-Muster.

Die folgende Buchstabenzuordnung wird verwendet:

  • e = einmaliger ephemerer Schlüssel
  • s = statischer Schlüssel
  • p = Nachrichten-Payload
  • e1 = einmaliger ephemerer PQ-Schlüssel, von Alice an Bob gesendet
  • ekem1 = der KEM-Chiffretext, von Bob an Alice gesendet

Die folgenden Änderungen an XK und IK für hybride Forward Secrecy (hfs) sind wie in der Noise HFS Spezifikation Abschnitt 5 spezifiziert:

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)

Das e1-Muster ist wie folgt definiert, wie in der Noise HFS-Spezifikation Abschnitt 4 angegeben:

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)

Das ekem1-Muster ist wie folgt definiert, wie in der Noise HFS-Spezifikation Abschnitt 4 spezifiziert:

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

Überblick

Der Hybrid-Handshake ist in der Noise HFS Spezifikation definiert. Die erste Nachricht von Alice an Bob enthält e1, den Encapsulation-Schlüssel, vor der Nachrichtenutzlast. Dieser wird als zusätzlicher statischer Schlüssel behandelt; rufen Sie EncryptAndHash() darauf auf (als Alice) oder DecryptAndHash() (als Bob). Verarbeiten Sie dann die Nachrichtenutzlast wie üblich.

Die zweite Nachricht, von Bob an Alice, enthält ekem1, den Chiffretext, vor der Nachrichten-Payload. Dies wird als zusätzlicher statischer Schlüssel behandelt; rufe EncryptAndHash() darauf auf (als Bob) oder DecryptAndHash() (als Alice). Berechne dann den kem_shared_key und rufe MixKey(kem_shared_key) auf. Verarbeite dann die Nachrichten-Payload wie üblich.

Definierte ML-KEM-Operationen

Wir definieren die folgenden Funktionen entsprechend den kryptographischen Bausteinen, die wie in FIPS 203 definiert verwendet werden.

(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.

Beachten Sie, dass sowohl der encap_key als auch der ciphertext innerhalb von ChaCha/Poly-Blöcken in den Noise-Handshake-Nachrichten 1 und 2 verschlüsselt sind. Sie werden als Teil des Handshake-Prozesses entschlüsselt.

Der kem_shared_key wird mit MixHash() in den chaining key eingemischt. Siehe unten für Details.

Alice KDF für Nachricht 1

Nach dem ’es’ Nachrichtenmuster und vor der Nutzdaten, füge hinzu:

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 für Nachricht 1

Nach dem ’es’ Nachrichtenmuster und vor der Nutzlast, fügen Sie hinzu:

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 KDF für Nachricht 2

Für XK: Nach dem ’ee’ Nachrichtenmuster und vor der Payload, hinzufügen:

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 für Nachricht 2

Nach dem ’ee’ Nachrichtenmuster hinzufügen:

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.

KDF für Nachricht 3 (nur XK)

unverändert

KDF für split()

unverändert

Handshake-Details

Noise-Kennungen

  • “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

Änderungen: Das aktuelle NTCP2 enthält nur die Optionen im ChaCha-Abschnitt. Mit ML-KEM wird der ChaCha-Abschnitt auch den verschlüsselten PQ-Public-Key enthalten.

Damit PQ und Nicht-PQ NTCP2 auf derselben router-Adresse und demselben Port unterstützt werden können, verwenden wir das höchstwertige Bit des X-Werts (X25519 ephemeral public key), um zu kennzeichnen, dass es sich um eine PQ-Verbindung handelt. Dieses Bit ist bei Nicht-PQ-Verbindungen immer nicht gesetzt.

Für Alice wird nach der Verschlüsselung der Nachricht durch Noise, aber vor der AES-Verschleierung von X, X[31] |= 0x7f gesetzt.

Für Bob, nach der AES-Entschleierung von X, teste X[31] & 0x80. Wenn das Bit gesetzt ist, lösche es mit X[31] &= 0x7f und entschlüssele über Noise als PQ-Verbindung. Wenn das Bit nicht gesetzt ist, entschlüssele über Noise als Nicht-PQ-Verbindung wie gewohnt.

Für PQ NTCP2, das auf einer anderen router-Adresse und einem anderen Port angekündigt wird, ist dies nicht erforderlich.

Für weitere Informationen siehe den Abschnitt “Published Addresses” unten.

Rohinhalte:

  +----+----+----+----+----+----+----+----+
  |        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

Unverschlüsselte Daten (Poly1305-Authentifizierungs-Tag nicht angezeigt):

  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                   X                   |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |           ML-KEM encap_key            |
  +      (see table below for length)     +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |               options                 |
  +              (16 bytes)               +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     unencrypted authenticated         |
  +         padding (optional)            +
  |     length defined in options block   |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

Hinweis: Das Versionsfeld im Optionsblock von Nachricht 1 muss auf 2 gesetzt werden, auch für PQ-Verbindungen.

Größen:

TypTyp CodeX LängeMsg 1 LängeMsg 1 Verschl LängeMsg 1 Entschl LängePQ Schlüssel Längeopt Länge
X2551943264+pad3216--16
MLKEM512_X25519532880+pad84881680016
MLKEM768_X255196321264+pad12321200118416
MLKEM1024_X255197321648+pad16161584156816

Hinweis: Typencodes sind nur für den internen Gebrauch bestimmt. Router bleiben Typ 4, und die Unterstützung wird in den router-Adressen angezeigt.

2) SessionCreated

Roher Inhalt:

  +----+----+----+----+----+----+----+----+
  |                                       |
  +        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

Unverschlüsselte Daten (Poly1305 Auth-Tag nicht gezeigt):

  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                  Y                    |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |           ML-KEM Ciphertext           |
  +      (see table below for length)     +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |               options                 |
  +              (16 bytes)               +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     unencrypted authenticated         |
  +         padding (optional)            +
  |     length defined in options block   |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

Größen:

TypTyp CodeY lenMsg 2 lenMsg 2 Enc lenMsg 2 Dec lenPQ CT lenopt len
X2551943264+pad3216--16
MLKEM512_X25519532848+pad81678476816
MLKEM768_X255196321136+pad11041104108816
MLKEM1024_X255197321616+pad15841584156816

Hinweis: Typcodes sind nur für den internen Gebrauch bestimmt. Router bleiben Typ 4, und die Unterstützung wird in den Router-Adressen angezeigt.

3) SessionConfirmed

Unverändert

Schlüsselableitungsfunktion (KDF) (für die Datenphase)

Unverändert

Veröffentlichte Adressen

In allen Fällen verwenden Sie wie gewohnt den NTCP2-Transportnamen.

Verwende dieselbe Adresse/Port wie non-PQ, non-firewalled. Nur eine PQ-Variante wird unterstützt. In der Router-Adresse veröffentliche v=2 (wie üblich) und den neuen Parameter pq=[3|4|5] um MLKEM 512/768/1024 anzuzeigen. Alice setzt das MSB des ephemeral key (key[31] & 0x80) in der Session-Anfrage, um anzuzeigen, dass dies eine Hybrid-Verbindung ist. Siehe oben. Ältere Router ignorieren den pq-Parameter und verbinden sich non-pq wie üblich.

Unterschiedliche Adresse/Port als Nicht-PQ, oder nur-PQ, nicht-firewalled wird NICHT unterstützt. Dies wird nicht implementiert werden, bis Nicht-PQ NTCP2 deaktiviert wird, was erst in einigen Jahren der Fall sein wird. Wenn Nicht-PQ deaktiviert ist, können mehrere PQ-Varianten unterstützt werden, aber nur eine pro Adresse. Wenn es unterstützt wird, veröffentliche in der router-Adresse v=[3|4|5] um MLKEM 512/768/1024 anzugeben. Alice setzt nicht das MSB des ephemeral key. Ältere router werden den v-Parameter prüfen und diese Adresse als nicht unterstützt überspringen.

Firewall-geschützte Adressen (keine IP veröffentlicht): In der router-Adresse v=2 veröffentlichen (wie gewöhnlich). Es ist nicht erforderlich, einen pq-Parameter zu veröffentlichen.

Alice kann sich mit einem PQ Bob über die PQ-Variante verbinden, die Bob veröffentlicht, unabhängig davon, ob Alice pq-Unterstützung in ihren router-Informationen bewirbt oder ob sie dieselbe Variante bewirbt.

Maximale Polsterung

In der aktuellen Spezifikation sind die Nachrichten 1 und 2 definiert, um eine “angemessene” Menge an Padding zu haben, mit einem empfohlenen Bereich von 0-31 Bytes und ohne spezifiziertes Maximum.

Bis API 0.9.68 (Release 2.11.0) implementierte Java I2P maximal 256 Bytes Padding für Nicht-PQ-Verbindungen, dies war jedoch zuvor nicht dokumentiert. Ab API 0.9.69 (Release 2.12.0) implementiert Java I2P das gleiche maximale Padding für Nicht-PQ-Verbindungen wie für MLKEM-512. Siehe Tabelle unten.

Verwende die definierte Nachrichtengröße als maximales Padding, das heißt, das maximale Padding wird die Nachrichtengröße für PQ-Verbindungen verdoppeln, wie folgt:

Nachrichten Max Paddingnon-PQ (bis 0.9.68)non-PQ (ab 0.9.69)MLKEM-512MLKEM-768MLKEM-1024
Session Request25688088012641648
Session Created25684884811361616

Overhead-Analyse

Schlüsselaustausch

Größenzunahme (Bytes):

TypPubkey (Msg 1)Chiffretext (Msg 2)
MLKEM512_X25519+816+784
MLKEM768_X25519+1200+1104
MLKEM1024_X25519+1584+1584

Sicherheitsanalyse

NIST-Sicherheitskategorien sind in der NIST-Präsentation auf Folie 10 zusammengefasst. Vorläufige Kriterien: Unsere minimale NIST-Sicherheitskategorie sollte 2 für hybride Protokolle und 3 für reine PQ-Protokolle sein.

KategorieSo sicher wie
1AES128
2SHA256
3AES192
4SHA384
5AES256

Handshakes

Dies sind alles Hybrid-Protokolle. Implementierungen sollten MLKEM768 bevorzugen; MLKEM512 ist nicht sicher genug.

NIST-Sicherheitskategorien FIPS 203 :

AlgorithmusSicherheitskategorie
MLKEM5121
MLKEM7683
MLKEM10245

Implementierungshinweise

Bibliotheksunterstützung

Bouncycastle, BoringSSL und WolfSSL Bibliotheken unterstützen jetzt MLKEM und MLDSA. OpenSSL Unterstützung wird in ihrer 3.5 Version am 8. April 2025 verfügbar sein OpenSSL .

Identifikation des eingehenden Datenverkehrs

Wir setzen das MSB des ephemeren Schlüssels (key[31] & 0x80) in der Session-Anfrage, um anzuzeigen, dass dies eine Hybrid-Verbindung ist. Dies ermöglicht es uns, sowohl Standard-NTCP als auch Hybrid-NTCP auf demselben Port zu betreiben. Nur eine Hybrid-Variante wird für eingehende Verbindungen unterstützt und in der Router-Adresse angekündigt. Zum Beispiel pq=3 oder pq=4.

Verschleierung

Als Alice, für eine PQ-Verbindung, vor der Verschleierung, setze X[31] |= 0x80. Dies macht X zu einem ungültigen X25519 öffentlichen Schlüssel. Nach der Verschleierung wird AES-CBC ihn randomisieren. Das MSB von X wird nach der Verschleierung zufällig sein.

Als Bob testen, ob (X[31] & 0x80) != 0 nach der Entschleierung. Wenn ja, ist es eine PQ-Verbindung.

Die mindestens erforderliche Router-Version für NTCP2-PQ ist noch zu bestimmen.

Hinweis: Typ-Codes sind nur für den internen Gebrauch bestimmt. Router bleiben Typ 4, und die Unterstützung wird in den Router-Adressen angezeigt.

Router-Kompatibilität

Transport-Namen

Verwenden Sie in allen Fällen den NTCP2-Transportnamen wie gewohnt. Ältere Router werden den pq-Parameter ignorieren und sich wie gewohnt mit Standard-NTCP2 verbinden.

Referenzen

Was this page helpful?