Этот перевод был создан с помощью машинного обучения и может быть не на 100% точным. Просмотреть английскую версию

PQ Hybrid SSU2

Постквантовый гибридный вариант транспортного протокола SSU2 с использованием ML-KEM

Статус

Бета Q2 2026, релиз Q3 2026

Обзор

Это гибридный пост-квантовый вариант транспортного протокола SSU2, разработанный в рамках Proposal 169. Дополнительные сведения см. в этом предложении.

PQ Hybrid SSU2 определяется только на том же адресе и порту, что и стандартный SSU2. Работа на другом порту или без поддержки стандартного SSU2 не разрешена и не будет разрешена в течение нескольких лет, пока стандартный SSU2 не будет признан устаревшим.

Данная спецификация описывает только изменения, необходимые для поддержки PQ Hybrid в стандартном SSU2. Подробности базовой реализации см. в спецификации SSU2.

Дизайн

Мы поддерживаем стандарты NIST FIPS 203 и 204 FIPS 203 FIPS 204 , которые основаны на CRYSTALS-Kyber и CRYSTALS-Dilithium (версии 3.1, 3 и более ранние), но НЕ совместимы с ними.

Обмен ключами

PQ KEM обеспечивает только эфемерные ключи и не поддерживает напрямую рукопожатия со статическими ключами, такие как Noise XK и IK. Типы шифрования совпадают с используемыми в PQ Hybrid Ratchet и определены в документе общих структур /docs/specs/common-structures/ ; как и в FIPS 203 , гибридные типы определяются только в сочетании с X25519.

Типы шифрования:

TypeCodeSSU2 Version
MLKEM512_X2551953
MLKEM768_X2551964
### Допустимые комбинации

Новые типы шифрования указываются в RouterAddresses. Тип шифрования в ключевом сертификате по-прежнему будет иметь тип 4.

Спецификация

Паттерны рукопожатия

Рукопожатия используют паттерны рукопожатий 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 ->


  e1 and ekem1 are encrypted. See pattern definitions below.
  NOTE: e1 and ekem1 are different sizes (unlike X25519)

Паттерн e1 определяется следующим образом, как указано в разделе 4 спецификации Noise HFS :

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 определяется следующим образом, как указано в разделе 4 спецификации Noise HFS :

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)

KDF для рукопожатия Noise

Обзор

Гибридное рукопожатие определено в спецификации 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, так и шифртекст зашифрованы внутри блоков ChaCha/Poly в сообщениях Noise-рукопожатия 1 и 2. Они будут расшифрованы в ходе процесса рукопожатия.

kem_shared_key подмешивается в цепочечный ключ с помощью MixHash(). Подробности см. ниже.

KDF Алисы для Сообщения 1

После шаблона сообщения ’es’ и перед полезной нагрузкой добавьте:

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

KDF Боба для сообщения 1

После шаблона сообщения ’es’ и перед полезной нагрузкой добавьте:

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

KDF Боба для сообщения 2

Для XK: после паттерна сообщения «ee» и перед полезной нагрузкой добавить:

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.

KDF Алисы для сообщения 2

После шаблона сообщения ’ee’ добавьте:

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 для сообщения 3

без изменений

KDF для split()

без изменений

Детали рукопожатия

Идентификаторы Noise

  • “Noise_XKhfschaobfse+hs1+hs2+hs3_25519+MLKEM512_ChaChaPoly_SHA256”
  • “Noise_XKhfschaobfse+hs1+hs2+hs3_25519+MLKEM768_ChaChaPoly_SHA256”

Обратите внимание, что MLKEM-1024 НЕ поддерживается для SSU2, поскольку ключи слишком велики для размещения в стандартной датаграмме размером 1500 байт.

Длинный заголовок

Длинный заголовок занимает 32 байта. Он используется до установления сессии — для сообщений Token Request, SessionRequest, SessionCreated и Retry. Также он применяется для внесессионных сообщений Peer Test и Hole Punch.

В следующих сообщениях установите поле ver (версия) в длинном заголовке равным 3 или 4, чтобы указать MLKEM-512 или MLKEM-768.

  • (0) Запрос сессии
  • (1) Сессия создана
  • (9) Повтор
  • (10) Запрос токена
  • (11) Hole Punch

В следующих сообщениях устанавливайте поле ver (версия) в длинном заголовке равным 2, как обычно, даже если поддерживается MLKEM-512 или MLKEM-768. Реализации также могут устанавливать значение 3 или 4, если другая сторона поддерживает это, однако это не обязательно. Реализации должны принимать любое значение от 2 до 4.

  • (7) Peer Test (внесессионные сообщения 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 для защиты от спуфинга: для решения проблем, поднятых в Proposal 165 [Prop165]_, но с использованием иного подхода, мы модифицируем KDF для Session Request. Это применяется только для PQ-сессий. KDF для не-PQ-сессий остаётся без изменений.


// 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
X2551943280+pl16+plplpl
MLKEM512_X25519532896+pl832+pl800+pl800pl
MLKEM768_X255196321280+pl1216+pl1184+pl1184pl
MLKEM1024_X255197н/дслишком большой
Примечание: коды типов предназначены только для внутреннего использования. Routers останутся типа 4, а поддержка будет указана в адресах router.

Минимальный MTU для MLKEM768_X25519: 1318 для IPv4 и 1338 для IPv6. См. ниже.

SessionCreated (Тип 1)

Изменения: в текущей реализации SSU2 раздел ChaCha содержит только блочные данные. С введением ML-KEM раздел ChaCha будет также содержать зашифрованный постквантовый открытый ключ.

Необработанное содержимое:

  +----+----+----+----+----+----+----+----+
  |  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
X2551943280+pl16+plplpl
MLKEM512_X25519532864+pl800+pl768+pl768pl
MLKEM768_X255196321184+pl1118+pl1088+pl1088pl
MLKEM1024_X255197н/дслишком большой
Примечание: коды типов предназначены только для внутреннего использования. Routers останутся типа 4, а поддержка будет указана в адресах router.

Минимальный MTU для MLKEM768_X25519: 1318 для IPv4 и 1338 для IPv6. См. ниже.

SessionConfirmed (Тип 2)

без изменений

KDF для фазы передачи данных

без изменений

Ретрансляция и тестирование узлов

Следующие блоки содержат поля версии. Они останутся версии 2 (для совместимости с Bob без постквантовой защиты) и не будут изменены на версию 3/4 для постквантового режима.

  • Relay Request (запрос ретрансляции)
  • Relay Response (ответ ретрансляции)
  • Relay Intro (представление через ретранслятор)
  • Peer Test (тест узла)

PQ-подписи: блоки Relay, блоки Peer Test и сообщения Peer Test — все они содержат подписи. К сожалению, PQ-подписи превышают размер MTU. В настоящее время не существует механизма для фрагментации блоков или сообщений Relay и Peer Test по нескольким UDP-пакетам. Протокол должен быть расширен для поддержки фрагментации. Это будет реализовано в отдельном предложении (TBD). До завершения этой работы поддержка Relay и Peer Test осуществляться не будет.

Опубликованные адреса

Во всех случаях используйте имя транспорта SSU2 как обычно. MLKEM-1024 не поддерживается.

Используйте тот же адрес/порт, что и для не-PQ, не заблокированного брандмауэром варианта. Поддерживается один или оба PQ-варианта. В адресе router опубликуйте v=2 (как обычно) и новый параметр pq=[3|4|3,4|4,3], чтобы указать MLKEM 512/768/оба. Роутеры с MTU меньше минимального значения, указанного ниже, не должны публиковать параметр «pq», содержащий «4». Публикуйте 4,3 для указания предпочтения MLKEM-768 или 3,4 для указания предпочтения MLKEM-512. Фактическая версия определяется инициатором, и предпочтение может не учитываться. Роутеры с MTU меньше минимального значения, указанного ниже, не должны устанавливать соединение с использованием MLKEM768. Старые роутеры будут игнорировать параметр pq и подключаться в обычном не-PQ режиме.

Использование другого адреса/порта для не-PQ вариантов, или режим только-PQ без файрвола НЕ поддерживается. Эта функция не будет реализована до отключения не-PQ SSU2, что произойдёт через несколько лет. После отключения не-PQ будет поддерживаться один или оба PQ-варианта. В адресе router публикуйте v=[3|4|3,4|4,3], чтобы указать поддержку MLKEM 512/768/обоих вариантов. Старые router’ы проверят параметр v и пропустят этот адрес как неподдерживаемый.

Адреса за межсетевым экраном (IP не публикуется): в адресе router публикуется v=2 (как обычно). Параметр pq ДОЛЖЕН быть опубликован в адресах за межсетевым экраном для поддержки ретрансляции.

Алиса может подключиться к Bob с постквантовой поддержкой (PQ Bob), используя PQ-вариант, который публикует Bob, независимо от того, рекламирует ли Алиса поддержку PQ в своём router info и поддерживает ли она тот же вариант.

MTU

Соблюдайте осторожность, чтобы не превысить MTU при использовании MLKEM768. Минимальный MTU для MLKEM768_X25519 составляет 1318 для IPv4 и 1338 для IPv6 (при условии минимальной полезной нагрузки 10 байт с блоком DateTime и блоком Padding или RelayTagRequest). Минимальный MTU для SSU2 в целом равен 1280, поэтому не все узлы могут использовать MLKEM768. Не публикуйте и не используйте MLKEM768, если фактический MTU — как локальный, так и объявленный удалённым узлом — меньше минимального значения. Следите за тем, чтобы добавление padding не приводило к превышению локального или удалённого MTU для сообщений 1 или 2.

Анализ накладных расходов

Обмен ключами

Увеличение размера (байты):

TypePubkey (Msg 1)Ciphertext (Msg 2)
MLKEM512_X25519+816+784
MLKEM768_X25519+1200+1104
## Анализ безопасности

Категории безопасности NIST кратко изложены в презентации NIST на слайде 10. Предварительные критерии: минимальная категория безопасности NIST должна быть не ниже 2 для гибридных протоколов и не ниже 3 для протоколов, использующих исключительно постквантовую криптографию (PQ-only).

CategoryAs Secure As
1AES128
2SHA256
3AES192
4SHA384
5AES256
### Процедуры установления соединения (Handshakes)

Все это гибридные протоколы. Реализациям следует отдавать предпочтение MLKEM768; MLKEM512 недостаточно безопасен.

Категории безопасности NIST FIPS 203 :

AlgorithmSecurity Category
MLKEM5121
MLKEM7683
## Примечания по реализации

Поддержка библиотек

Библиотеки Bouncycastle, BoringSSL и WolfSSL уже поддерживают MLKEM и MLDSA. Поддержка в OpenSSL появится в релизе 3.5, запланированном на 8 апреля 2025 года OpenSSL .

Идентификация входящего трафика

Мы устанавливаем старший бит эфемерного ключа (key[31] & 0x80) в запросе сессии, чтобы обозначить, что это гибридное соединение. Это позволяет запускать как стандартный NTCP, так и гибридный NTCP на одном и том же порту. Для входящих соединений поддерживается только один гибридный вариант, который и объявляется в адресе router. Например, pq=3 или pq=4.

Обфускация

Для Алисы при PQ-соединении перед обфускацией установите X[31] |= 0x80. Это делает X недопустимым открытым ключом X25519. После обфускации AES-CBC рандомизирует его. Старший бит X будет случайным после обфускации.

Как Bob, проверьте, выполняется ли условие (X[31] & 0x80) != 0 после деобфускации. Если да, это PQ-соединение.

Минимальная версия router, необходимая для NTCP2-PQ, будет определена позднее.

Примечание: коды типов предназначены только для внутреннего использования. Routers останутся типа 4, а поддержка будет указана в адресах router.

Совместимость роутеров

Названия транспортов

Во всех случаях используйте имя транспорта NTCP2 как обычно. Старые роутеры будут игнорировать параметр pq и подключаться с помощью стандартного NTCP2 как обычно.

Ссылки

Was this page helpful?