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

NTCP 2

Proposal 111
Закрыто
Author EinMByte, orignal, psi, str4d, zzz
Created 2014-02-13
Last Updated 2019-08-13
Target Version 0.9.36
Implemented In 0.9.36
Supercedes: 106

Примечание

Фаза предложения закрыта. Смотрите SPEC для официальной спецификации. Это предложение может быть использовано для справочной информации.

Обзор

В этом предложении описывается протокол аутентифицированного согласования ключей, призванный повысить устойчивость NTCP к различным формам автоматической идентификации и атак.

Предложение организовано следующим образом: сначала представлены цели безопасности, затем обсуждается базовый протокол. Далее приводится полная спецификация всех сообщений протокола. Наконец, рассматриваются адреса маршрутизаторов и идентификация версий. Также включено приложение, посвящённое общей атаке на распространённые схемы дополнения, и приложение с рядом кандидатов на аутентифицированный шифр.

Как и другие транспорты I2P, NTCP2 определён исключительно для транспорта сообщений I2NP «точка-точка» (маршрутизатор-к-маршрутизатору). Это не универсальный канал передачи данных.

Мотивация

Данные NTCP шифруются после первого сообщения (и первое сообщение выглядит как случайные данные), что предотвращает идентификацию протокола через «анализ полезной нагрузки». Однако он всё ещё уязвим к идентификации протокола через «анализ потока». Причина в том, что первые 4 сообщения (т.е. рукопожатие) имеют фиксированную длину (288, 304, 448 и 48 байт).

Добавляя случайные объёмы случайных данных к каждому из сообщений, мы можем значительно затруднить распознавание.

Авторы признают, что стандартные практики безопасности предполагают использование существующего протокола, такого как TLS, но это Prop104 , и у него есть собственные проблемы. Там, где уместно, добавлены абзацы «будущей работы», чтобы указать на отсутствующие функции или темы для обсуждения.

Цели проектирования

  • Поддержка NTCP 1 и 2 на одном порту, автоматическое определение и публикация как одного «транспорта» (т.е. RouterAddress) в NetDB .

  • Публикация в NetDB поддержки версии 1, только 2 или 1+2 в отдельном поле, по умолчанию — только версия 1 (не привязывать поддержку версии к конкретной версии маршрутизатора).

  • Обеспечение того, чтобы все реализации (Java/i2pd/Kovri/go) могли добавлять поддержку версии 2 (или не добавлять) по своему собственному графику.

  • Добавление случайного дополнения ко всем сообщениям NTCP, включая сообщения рукопожатия и данных (т.е. маскировка длины, чтобы все сообщения не были кратны 16 байтам). Предусмотреть механизм опций, позволяющий обеим сторонам запрашивать минимальное и максимальное дополнение и/или распределение дополнения. Конкретики распределения дополнения зависят от реализации и могут быть не указаны в самом протоколе.

  • Маскировка содержимого сообщений, которые не шифруются (1 и 2), в достаточной степени, чтобы DPI-устройства и сигнатуры антивирусов не могли легко их классифицировать. Также обеспечить, чтобы сообщения, отправляемые одному или группе пиров, не имели схожего битового шаблона.

  • Исправление потери битов в DH из-за формата Java Ticket1112 , возможно (вероятно?) путём перехода на X25519.

  • Переход на настоящую функцию выработки ключей (KDF) вместо использования результата DH «как есть»?

  • Добавление «устойчивости к зондированию» (как называет это Tor); включая устойчивость к повторной передаче.

  • Поддержание двустороннего аутентифицированного обмена ключами (2W-AKE). 1W-AKE недостаточно для нашего приложения.

  • Продолжать использовать подписи переменного типа и переменной длины (от опубликованного ключа подписи RouterIdentity) как часть аутентификации. Полагаться на статический открытый ключ, опубликованный в RouterInfo, как на другую часть аутентификации.

  • Добавить опции/версию в рукопожатие для будущей расширяемости.

  • Добавить устойчивость к злонамеренному TCP-сегментированию посредником (MitM), если возможно.

  • Не значительно увеличивать CPU-нагрузку при установке соединения; если возможно, значительно снизить её.

  • Добавить аутентификацию сообщений (MAC), возможно HMAC-SHA256 и Poly1305, и удалить контрольную сумму Adler.

  • Сократить и упростить заголовок I2NP: Сократить срок действия до 4 байт, как в SSU. Удалить однобайтовую усечённую контрольную сумму SHA256.

  • Если возможно, сократить 4-сообщное, двухэтапное рукопожатие до 3-сообщного, одноэтапного, как в SSU . Это потребует переместить подпись Боба из сообщения 4 в сообщение 2. Исследовать причину 4 сообщений в десятилетних архивах электронной почты/статуса/встреч.

  • Минимизировать накладные расходы протокола до дополнения. Хотя дополнение будет добавлено, и, возможно, много, накладные расходы до дополнения всё ещё являются накладными расходами. Узлы с низкой пропускной способностью должны иметь возможность использовать NTCP2.

  • Поддерживать временные метки для обнаружения повторной передачи и рассинхронизации.

  • Избегать любых проблем с 2038 годом во временных метках, должно работать как минимум до 2106 года.

  • Увеличить максимальный размер сообщения с 16 Кб до 32 Кб или 64 Кб.

  • Любые новые криптографические примитивы должны быть легко доступны в библиотеках для использования в реализациях маршрутизаторов на Java (1.7), C++ и Go.

  • Включить представителей разработчиков маршрутизаторов на Java, C++ и Go в процесс проектирования.

  • Минимизировать изменения (но их всё равно будет много).

  • Поддержка обеих версий в общем наборе кода (это может быть невозможно и зависит от реализации).

Нецели

  • Абсолютная устойчивость к DPI… это были бы подключаемые транспорты, Prop109 .

  • Транспорт на основе TLS (или похожий на HTTPS)… это было бы Prop104 .

  • Можно изменить симметричную потоковую криптографию.

  • Устойчивость к DPI на основе времени (интервалы между сообщениями/задержки могут зависеть от реализации; внутрисообщенческие задержки могут быть введены в любой точке, включая перед отправкой случайного дополнения, например). Искусственные задержки (которые obfs4 называет IAT или inter-arrival time) независимы от самого протокола.

  • Отрицание участия в сессии (там есть подписи).

Нецели, которые могут быть частично пересмотрены или обсуждены:

  • Степень защиты от глубокого анализа пакетов (DPI)

  • Защита от квантовых компьютеров (PQ)

  • Отрицание

Связанные цели

  • Реализовать тестовую установку NTCP 1/2

Цели безопасности

Мы рассматриваем три стороны:

  • Алиса, которая хочет установить новую сессию.
  • Боб, с которым Алиса хочет установить сессию.
  • Мэллори, «человек посередине» между Алисой и Бобом.

Максимум две стороны могут участвовать в активных атаках.

Алиса и Боб оба обладают статической парой ключей, которая содержится в их RouterIdentity.

Предлагаемый протокол пытается позволить Алисе и Бобу договориться о общем секретном ключе (K) при следующих требованиях:

  1. Безопасность закрытого ключа: ни Боб, ни Мэллори не узнают ничего о статическом закрытом ключе Алисы. Симметрично, Алиса не узнаёт ничего о статическом закрытом ключе Боба.

  2. Ключ сессии K известен только Алисе и Бобу.

  3. Совершенная секретность в будущем: согласованный ключ сессии остаётся секретным в будущем, даже если статические закрытые ключи Алисы и/или Боба станут известны после того, как ключ был согласован.

  4. Двусторонняя аутентификация: Алиса уверена, что установила сессию с Бобом, и наоборот.

  5. Защита от онлайн-DPI: обеспечить, чтобы не было тривиальным обнаружить, что Алиса и Боб участвуют в протоколе, используя только прямые методы глубокого анализа пакетов (DPI). См. ниже.

  6. Ограниченная возможность отрицания: ни Алиса, ни Боб не могут отрицать участие в протоколе, но если кто-либо из них утечёт общий ключ, другая сторона может отрицать подлинность содержимого передаваемых данных.

Настоящее предложение пытается обеспечить все пять требований на основе протокола Station-To-Station (STS). Обратите внимание, что этот протокол также является основой для протокола SSU .

Дополнительное обсуждение DPI

Мы предполагаем два компонента DPI:

1) Онлайн-DPI

Онлайн-DPI анализирует все потоки в реальном времени. Соединения могут быть заблокированы или иным образом изменены. Данные соединения или метаданные могут быть идентифицированы и сохранены для оффлайн-анализа. Онлайн-DPI не имеет доступа к базе данных сети I2P. Онлайн-DPI имеет только ограниченные возможности реального времени, включая вычисление длины, проверку полей и простые вычисления, такие как XOR. Онлайн-DPI имеет возможность быстрых криптографических функций в реальном времени, таких как AES, AEAD и хеширование, но их применение к большинству или всем потокам было бы слишком дорогостоящим. Любое применение этих криптографических операций будет применяться только к потокам на комбинациях IP/Port, ранее идентифицированных оффлайн-анализом. Онлайн-DPI не имеет возможности выполнять криптографические функции с высокими накладными расходами, такие как DH или elligator2. Онлайн-DPI не предназначен специально для обнаружения I2P, хотя может иметь ограниченные правила классификации для этой цели.

Цель — предотвратить идентификацию протокола онлайн-DPI.

Понятие онлайн- или «прямого» DPI здесь включает следующие возможности противника:

  1. Способность проверять все данные, отправленные или полученные целью.

  2. Способность выполнять операции над наблюдаемыми данными, такие как применение блочных шифров или хеш-функций.

  3. Способность хранить и сравнивать с ранее отправленными сообщениями.

  4. Способность изменять, задерживать или фрагментировать пакеты.

Однако предполагается, что онлайн-DPI имеет следующие ограничения:

  1. Невозможность сопоставлять IP-адреса с хешами маршрутизаторов. Хотя это тривиально при реальном доступе к базе данных сети, это потребовало бы системы DPI, специально разработанной для атаки на I2P.

  2. Невозможность использовать временную информацию для обнаружения протокола.

  3. В целом, инструментарий онлайн-DPI не содержит встроенных инструментов, специально разработанных для обнаружения I2P. Это включает создание «ловушек», которые, например, включали бы нерандомизированное дополнение в своих сообщениях. Обратите внимание, что это не исключает системы машинного обучения или высоко настраиваемые инструменты DPI, если они соответствуют другим требованиям.

Чтобы противостоять анализу полезной нагрузки, обеспечивается, чтобы все сообщения были неотличимы от случайных. Это также требует, чтобы их длина была случайной, что сложнее, чем просто добавление случайного дополнения. На самом деле, в Приложении A авторы утверждают, что наивная (т.е. равномерная) схема дополнения не решает проблему. Поэтому в Приложении A предлагается включить либо случайные задержки, либо разработать альтернативную схему дополнения, которая может обеспечить разумную защиту от предложенной атаки.

Для защиты от шестого пункта выше реализации должны включать случайные задержки в протокол. Такие методы не охвачены этим предложением, но они также могут решить проблемы длины дополнения. В итоге, предложение обеспечивает хорошую защиту от анализа полезной нагрузки (если учитывать соображения из Приложения A), но только ограниченную защиту от анализа потока.

2) Оффлайн-DPI

Оффлайн-DPI анализирует данные, сохранённые онлайн-DPI, для последующего анализа. Оффлайн-DPI может быть специально разработан для обнаружения I2P. Оффлайн-DPI имеет реальный доступ к базе данных сети I2P. Оффлайн-DPI имеет доступ к этой и другим спецификациям I2P. Оффлайн-DPI имеет неограниченные вычислительные возможности, включая все криптографические функции, определённые в этой спецификации.

Оффлайн-DPI не имеет возможности блокировать существующие соединения. Оффлайн-DPI имеет возможность отправлять в хост/порт сторон в почти реальном времени (в течение минут после установки), например TCP RST. Оффлайн-DPI имеет возможность в почти реальном времени (в течение минут после установки) повторно отправлять предыдущие сообщения (изменённые или нет) для «зондирования» или других целей.

Целью не является предотвращение идентификации протокола оффлайн-DPI. Все декодирования замаскированных данных в первых двух сообщениях, которые реализованы маршрутизаторами I2P, также могут быть реализованы оффлайн-DPI.

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

Будущая работа

  • Рассмотреть поведение протокола, когда пакеты теряются или переупорядочиваются атакующим. Недавние интересные работы в этой области можно найти в IACR-1150 .

  • Предоставить более точную классификацию систем DPI, принимая во внимание существующую литературу по теме.

  • Обсудить формальную безопасность предложенного протокола, идеально учитывая модель атакующего DPI.

Фреймворк протокола Noise

Это предложение определяет требования на основе фреймворка протокола Noise NOISE (Revision 33, 2017-10-04). Noise имеет схожие свойства с протоколом Station-To-Station, который является основой для протокола SSU . В терминологии Noise Алиса — инициатор, а Боб — ответчик.

NTCP2 основан на протоколе Noise Noise_XK_25519_ChaChaPoly_SHA256. (Фактический идентификатор для начальной функции выработки ключей — “Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256”, чтобы указать расширения I2P — см. раздел KDF 1 ниже) Этот протокол Noise использует следующие примитивы:

  • Шаблон рукопожатия: XK Алиса передаёт свой ключ Бобу (X) Алиса уже знает статический ключ Боба (K)

  • Функция DH: X25519 X25519 DH с длиной ключа 32 байта, как указано в RFC-7748 .

  • Функция шифрования: ChaChaPoly AEAD_CHACHA20_POLY1305, как указано в RFC-7539 раздел 2.8. 12-байтовый счётчик, первые 4 байта которого установлены в ноль.

  • Хеш-функция: SHA256 Стандартный 32-байтовый хеш, уже широко используемый в I2P.

Дополнения к фреймворку

Это предложение определяет следующие улучшения к Noise_XK_25519_ChaChaPoly_SHA256. В целом они следуют рекомендациям из NOISE раздел 13.

  1. Открытые эфемерные ключи маскируются с помощью шифрования AES с известным ключом и IV. Это быстрее, чем elligator2.

  2. К сообщениям 1 и 2 добавляется случайное дополнение в открытом виде. Дополнение в открытом виде включается в расчёт хеша рукопожатия (MixHash). См. разделы KDF ниже для сообщения 2 и части 1 сообщения 3. Случайное дополнение AEAD добавляется к сообщению 3 и сообщениям фазы данных.

  3. Добавляется двухбайтовое поле длины кадра, как требуется для Noise по TCP, и как в obfs4. Используется только в сообщениях фазы данных. Сообщения 1 и 2 AEAD имеют фиксированную длину. Часть 1 сообщения 3 AEAD имеет фиксированную длину. Длина части 2 сообщения 3 AEAD указывается в сообщении 1.

  4. Двухбайтовое поле длины кадра маскируется с помощью SipHash-2-4, как в obfs4.

  5. Определяется формат полезной нагрузки для сообщений 1,2,3 и фазы данных. Конечно, это не определено в Noise.

Новые криптографические примитивы для I2P

Существующим реализациям маршрутизаторов I2P потребуются реализации следующих стандартных криптографических примитивов, которые не требуются для текущих протоколов I2P:

  1. Генерация ключей X25519 и DH

  2. AEAD_ChaCha20_Poly1305 (сокращённо как ChaChaPoly ниже)

  3. SipHash-2-4

Оценка накладных расходов на обработку

Размеры сообщений для 3 сообщений:

  1. 64 байта + дополнение (в NTCP было 288 байт)
  2. 64 байта + дополнение (в NTCP было 304 байта)
  3. приблизительно 64 байта + информация о маршрутизаторе Алисы + дополнение. Средний размер информации о маршрутизаторе — около 750 байт. Итого средний размер 814 байт до дополнения (в NTCP было 448 байт)
  4. не требуется в NTCP2 (в NTCP было 48 байт)

Итого до дополнения: NTCP2: 942 байта NTCP: 1088 байт Обратите внимание, что если Алиса подключилась к Бобу с целью отправки сообщения DatabaseStore своей RouterInfo, это сообщение не требуется, что экономит примерно 800 байт.

Следующие криптографические операции требуются каждой стороне для завершения рукопожатия и начала фазы данных:

  • AES: 2
  • SHA256: 7 (Алиса), 6 (Боб) (не включая 1 Алиса, 2 Боб предварительно рассчитаны для всех соединений) (не включая HMAC-SHA256)
  • HMAC-SHA256: 19
  • ChaChaPoly: 4
  • Генерация ключа X25519: 1
  • DH X25519: 3
  • Проверка подписи: 1 (Боб) (Алиса ранее подписала при генерации своего RI) Предположительно Ed25519 (зависит от типа подписи RI)

Следующие криптографические операции требуются каждой стороне для каждого сообщения фазы данных:

  • SipHash: 1
  • ChaChaPoly: 1

Сообщения

Все сообщения NTCP2 имеют длину меньше или равную 65537 байт. Формат сообщения основан на сообщениях Noise с модификациями для фрейминга и неотличимости. Реализации, использующие стандартные библиотеки Noise, могут потребовать предварительной обработки полученных сообщений к/из формата сообщений Noise. Все зашифрованные поля являются AEAD-шифротекстами.

Последовательность установления следующая:

Алиса                           Боб

  SessionRequest ------------------->
  <------------------- SessionCreated
  SessionConfirmed ----------------->

Используя терминологию Noise, последовательность установления и данных следующая: (Свойства безопасности полезной нагрузки)

XK(s, rs):           Аутентификация   Конфиденциальность
    <- s
    ...
    -> e, es                  0                2
    <- e, ee                  2                1
    -> s, se                  2                5
    <-                        2                5

После установления сессии Алиса и Боб могут обмениваться сообщениями Data.

Все типы сообщений (SessionRequest, SessionCreated, SessionConfirmed, Data и TimeSync) указаны в этом разделе.

Некоторые обозначения:

  • RH_A = Хеш маршрутизатора для Алисы (32 байта)
  • RH_B = Хеш маршрутизатора для Боба (32 байта)

Аутентифицированное шифрование

Существуют три отдельных экземпляра аутентифицированного шифрования (CipherStates). Один во время фазы рукопожатия и два (передача и приём) для фазы данных. Каждый имеет свой собственный ключ из KDF.

Зашифрованные/аутентифицированные данные будут представлены как

+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   Зашифрованные и аутентифицированные данные    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

ChaCha20/Poly1305

Формат зашифрованных и аутентифицированных данных.

Входные данные для функций шифрования/дешифрования:

k :: 32-байтовый ключ шифрования, как сгенерировано из KDF

  nonce :: Счётчик на основе nonce, 12 байт.
           Начинается с 0 и увеличивается для каждого сообщения.
           Первые четыре байта всегда нули.
           Последние восемь байт — счётчик, закодированный little-endian.
           Максимальное значение — 2**64 - 2.
           Соединение должно быть разорвано и перезапущено после
           достижения этого значения.
           Значение 2**64 - 1 никогда не должно отправляться.

  ad :: В фазе рукопожатия:
        Сопутствующие данные, 32 байта.
        Хеш SHA256 всех предыдущих данных.
        В фазе данных:
        Нулевые байты

  data :: Открытый текст данных, 0 или более байт

Выход функции шифрования, вход функции дешифрования:

+----+----+----+----+----+----+----+----+
  |Obfs Len |                             |
  +----+----+                             +
  |       Зашифрованные данные ChaCha20         |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Код аутентификации сообщения Poly1305 |
  +              (MAC)                    +
  |             16 байт                  |
  +----+----+----+----+----+----+----+----+

  Obfs Len :: Длина (зашифрованные данные + MAC), следующие, 16 - 65535
              Маскировка с помощью SipHash (см. ниже)
              Не используется в сообщении 1 или 2, или части 1 сообщения 3, где длина фиксирована
              Не используется в части 1 сообщения 3, так как длина указана в сообщении 1

  зашифрованные данные :: Такого же размера, как открытый текст, 0 - 65519 байт

  MAC :: Код аутентификации сообщения Poly1305, 16 байт

Для ChaCha20 то, что описано здесь, соответствует RFC-7539 , который также используется аналогично в TLS RFC-7905 .

Примечания

  • Поскольку ChaCha20 является потоковым шифром, открытым текстам не нужно дополнение. Дополнительные байты гаммы отбрасываются.

  • Ключ для шифра (256 бит) согласуется с помощью KDF SHA256. Подробности KDF для каждого сообщения приведены в отдельных разделах ниже.

  • Кадры ChaChaPoly для сообщений 1, 2 и первой части сообщения 3 имеют известный размер. Начиная со второй части сообщения 3, кадры имеют переменный размер. Размер части 1 сообщения 3 указывается в сообщении 1. Начиная с фазы данных, кадры предваряются двухбайтовой длиной, маскированной с помощью SipHash, как в obfs4.

  • Дополнение находится вне аутентифицированного кадра данных для сообщений 1 и 2. Дополнение используется в KDF для следующего сообщения, поэтому любое изменение будет обнаружено. Начиная с сообщения 3, дополнение находится внутри аутентифицированного кадра данных.

Обработка ошибок AEAD

  • В сообщениях 1, 2 и частях 1 и 2 сообщения 3 размер сообщения AEAD известен заранее. При сбое аутентификации AEAD получатель должен прекратить дальнейшую обработку сообщений и закрыть соединение без ответа. Это должно быть аварийное закрытие (TCP RST).

  • Для устойчивости к зондированию, в сообщении 1, после сбоя AEAD, Боб должен установить случайный таймаут (диапазон TBD) и затем прочитать случайное количество байт (диапазон TBD) перед закрытием сокета. Боб должен вести чёрный список IP с повторяющимися сбоями.

  • В фазе данных размер сообщения AEAD «зашифрован» (замаскирован) с помощью SipHash. Необходимо соблюдать осторожность, чтобы не создавать оракул дешифрования. При сбое аутентификации AEAD в фазе данных получатель должен установить случайный таймаут (диапазон TBD) и затем прочитать случайное количество байт (диапазон TBD). После чтения или по таймауту чтения получатель должен отправить полезную нагрузку с блоком завершения, содержащим код причины «сбой AEAD», и закрыть соединение.

  • Принять те же действия при неверном значении поля длины в фазе данных.

Функция выработки ключей (KDF) (для сообщения рукопожатия 1)

KDF генерирует ключ шифрования фазы рукопожатия k из результата DH, используя HMAC-SHA256(key, data), как определено в RFC-2104 . Это функции InitializeSymmetric(), MixHash() и MixKey(), точно как определено в спецификации Noise.

Это шаблон сообщения "e":

  // Определить protocol_name.
  Установить protocol_name = "Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256"
   (48 байт, кодировка US-ASCII, без завершающего NULL).

  // Определить Hash h = 32 байта
  h = SHA256(protocol_name);

  Определить ck = 32-байтовый цепочный ключ. Скопировать данные h в ck.
  Установить ck = h

  Определить rs = 32-байтовый статический ключ Боба, как опубликовано в RouterInfo

  // MixHash(null prologue)
  h = SHA256(h);

  // до этого момента всё может быть предварительно рассчитано Алисой для всех исходящих соединений

  // Алиса должна проверить, что статический ключ Боба является допустимой точкой на кривой здесь.

  // Статический ключ Боба
  // MixHash(rs)
  // || ниже означает присоединение
  h = SHA256(h || rs);

  // до этого момента всё может быть предварительно рассчитано Бобом для всех входящих соединений

  Это шаблон сообщения "e":

  Алиса генерирует свою эфемерную пару ключей DH e.

  // Открытый ключ Алисы X
  // MixHash(e.pubkey)
  // || ниже означает присоединение
  h = SHA256(h || e.pubkey);

  // h используется как сопутствующие данные для AEAD в сообщении 1
  // Сохранить хеш h для KDF сообщения 2


  Конец шаблона "e".

  Это шаблон сообщения "es":

  // DH(e, rs) == DH(s, re)
  Определить input_key_material = 32-байтовый результат DH пары эфемерного ключа Алисы и статического ключа Боба
  Установить input_key_material = результат X25519 DH

  // MixKey(DH())

  Определить temp_key = 32 байта
  Определить HMAC-SHA256(key, data) как в [RFC-2104](https://tools.ietf.org/html/rfc2104)
  // Сгенерировать временный ключ из цепочного ключа и результата DH
  // ck — цепочный ключ, определённый выше
  temp_key = HMAC-SHA256(ck, input_key_material)
  // перезаписать результат DH в памяти, больше не нужен
  input_key_material = (все нули)

  // Выход 1
  // Установить новый цепочный ключ из временного ключа
  // byte() ниже означает один байт
  ck =       HMAC-SHA256(temp_key, byte(0x01)).

  // Выход 2
  // Сгенерировать ключ шифрования k
  Определить k = 32 байта
  // || ниже означает присоединение
  // byte() ниже означает один байт
  k =        HMAC-SHA256(temp_key, ck || byte(0x02)).
  // перезаписать temp_key в памяти, больше не нужен
  temp_key = (все нули)

  // сохранить цепочный ключ ck для KDF сообщения 2


  Конец шаблона "es".

1) SessionRequest

Алиса отправляет Бобу.

Содержимое Noise: Эфемерный ключ Алисы X Полезная нагрузка Noise: 16-байтовый блок опций Полезная нагрузка вне Noise: Случайное дополнение

(Свойства безопасности полезной нагрузки)

XK(s, rs):           Аутентификация   Конфиденциальность
    -> e, es                  0                2

    Аутентификация: Нет (0).
    Это полезная нагрузка может быть отправлена любой стороной, включая активного атакующего.

    Конфиденциальность: 2.
    Шифрование для известного получателя, совершенная секретность только при компрометации отправителя,
    уязвимо к повторной передаче. Эта полезная нагрузка шифруется только на основе DH,
    включающих статическую пару ключей получателя. Если статический
    закрытый ключ получателя скомпрометирован, даже в более позднее время, эта полезная нагрузка может быть
    расшифрована. Это сообщение также может быть повторно передано, так как нет эфемерного
    вклада от получателя.

    "e": Алиса генерирует новую эфемерную пару ключей и сохраняет её в переменной e,
         записывает открытый эфемерный ключ в буфер сообщения и хеширует открытый ключ вместе со старым h, чтобы
         вывести новый h.

    "es": Выполняется DH между эфемерной парой ключей Алисы и
          статической парой ключей Боба. Результат хешируется вместе со старым ck, чтобы
          вывести новый ck и k, и n устанавливается в ноль.

Значение X шифруется для обеспечения неотличимости и уникальности полезной нагрузки, что необходимо для противодействия DPI. Мы используем шифрование AES для достижения этого, вместо более сложных и медленных альтернатив, таких как elligator2. Асимметричное шифрование для открытого ключа маршрутизатора Боба было бы слишком медленным. Шифрование AES использует хеш маршрутизатора Боба в качестве ключа и IV Боба, как опубликовано в базе данных сети.

Шифрование AES предназначено только для сопротивления DPI. Любая сторона, знающая хеш маршрутизатора Боба и IV, которые опубликованы в базе данных сети, может расшифровать значение X в этом сообщении.

Дополнение не шифруется Алисой. Может потребоваться, чтобы Боб расшифровал дополнение, чтобы предотвратить атаки по времени.

Сырые содержимое:

+----+----+----+----+----+----+----+----+
|                                       |
+        маскировано с RH_B           +
|       AES-CBC-256 зашифрованный X         |
+             (32 байта)                +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|   кадр ChaChaPoly                    |
+             (32 байта)                +
|   k определён в KDF для сообщения 1      |
+   n = 0                               +
|   см. KDF для сопутствующих данных         |
+----+----+----+----+----+----+----+----+
|     незашифрованное аутентифицированное         |
~         дополнение (опционально)            ~
|     длина определена в блоке опций   |
+----+----+----+----+----+----+----+----+

X :: 32 байта, X25519 эфемерный ключ, зашифрованный AES-256-CBC, little endian
        ключ: RH_B
        iv: Как опубликовано в записи Боба в базе данных сети

дополнение :: Случайные данные, 0 или более байт.
           Общая длина сообщения должна быть 65535 байт или меньше.
           Общая длина сообщения должна быть 287 байт или меньше, если
           Боб публикует свой адрес как NTCP
           (см. раздел Определение версии ниже).
           Алиса и Боб будут использовать данные дополнения в KDF для сообщения 2.
           Оно аутентифицировано, поэтому любое изменение вызовет сбой
           следующего сообщения.

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|                   X                   |
+              (32 байта)               +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|               опции                 |
+              (16 байт)               +
|                                       |
+----+----+----+----+----+----+----+----+
|     незашифрованное аутентифицированное         |
+         дополнение (опционально)            +
|     длина определена в блоке опций   |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

X :: 32 байта, X25519 эфемерный ключ, little endian

опции :: блок опций, 16 байт, см. ниже

дополнение :: Случайные данные, 0 или более байт.
           Общая длина сообщения должна быть 65535 байт или меньше.
           Общая длина сообщения должна быть 287 байт или меньше, если
           Боб публикует свой адрес как "NTCP"
           (см. раздел Определение версии ниже)
           Алиса и Боб будут использовать данные дополнения в KDF для сообщения 2.
           Оно аутентифицировано, поэтому любое изменение вызовет сбой
           следующего сообщения.

Блок опций: Примечание: Все поля big-endian.

+----+----+----+----+----+----+----+----+
| id | ver|  padLen | m3p2len | Rsvd(0) |
+----+----+----+----+----+----+----+----+
|        tsA        |   Reserved (0)    |
+----+----+----+----+----+----+----+----+

id :: 1 байт, сетевой ID (в настоящее время 2, кроме тестовых сетей)
      Начиная с 0.9.42. См. предложение 147.

ver :: 1 байт, версия протокола (в настоящее время 2)

padLen :: 2 байта, длина дополнения, 0 или более
          Рекомендации по мин/макс TBD. Случайный размер от 0 до 31 байт минимум?
          (Распределение будет определено, см. Приложение A.)

m3p2Len :: 2 байта, длина второго кадра AEAD в SessionConfirmed
           (часть 2 сообщения 3) См. примечания ниже

Rsvd :: 2 байта, установлено в 0 для совместимости с будущими опциями

tsA :: 4 байта, временная метка Unix, беззнаковые секунды.
       Переполняется в 2106

Reserved :: 4 байта, установлено в 0 для совместимости с будущими опциями

Примечания

  • Когда опубликованный адрес — “NTCP”, Боб поддерживает как NTCP, так и NTCP2 на одном порту. Для совместимости, при инициации соединения с адресом, опубликованным как “NTCP”, Алиса должна ограничить максимальный размер этого сообщения, включая дополнение, до 287 байт или меньше. Это облегчает автоматическое определение протокола Бобом. Когда опубликовано как “NTCP2”, ограничений по размеру нет. См. разделы Опубликованные адреса и Определение версии ниже.

  • Уникальное значение X в начальном блоке AES гарантирует, что шифротекст будет разным для каждой сессии.

  • Боб должен отклонять соединения, где значение временной метки слишком сильно отклоняется от текущего времени. Назовём максимальную дельту времени “D”. Боб должен вести локальный кэш ранее использованных значений рукопожатия и отклонять дубликаты, чтобы предотвратить атаки повторной передачи. Значения в кэше должны иметь срок жизни не менее 2*D. Значения кэша зависят от реализации, однако 32-байтовое значение X (или его зашифрованный эквивалент) может быть использовано.

  • Эфемерные ключи Диффи-Хеллмана никогда не должны повторно использоваться, чтобы предотвратить криптографические атаки, и повторное использование будет отклонено как атака повторной передачи.

  • Опции “KE” и “auth” должны быть совместимы, т.е. общий секрет K должен быть соответствующего размера. Если будут добавлены дополнительные опции “auth”, это может неявно изменить значение флага “KE” для использования другого KDF или другого размера усечения.

  • Боб должен проверить, что эфемерный ключ Алисы является допустимой точкой на кривой здесь.

  • Дополнение должно быть ограничено разумным объёмом. Боб может отклонять соединения с чрезмерным дополнением. Боб укажет свои параметры дополнения в сообщении 2. Рекомендации по мин/макс TBD. Случайный размер от 0 до 31 байт минимум? (Распределение будет определено, см. Приложение A.)

  • При любой ошибке, включая AEAD, DH, временную метку, очевидную повторную передачу или сбой проверки ключа, Боб должен прекратить дальнейшую обработку сообщений и закрыть соединение без ответа. Это должно быть аварийное закрытие (TCP RST). Для устойчивости к зондированию, после сбоя AEAD, Боб должен установить случайный таймаут (диапазон TBD) и затем прочитать случайное количество байт (диапазон TBD), перед закрытием сокета.

  • Смягчение DoS: DH — относительно дорогостоящая операция. Как и в предыдущем протоколе NTCP, маршрутизаторы должны принимать все необходимые меры для предотвращения исчерпания CPU или соединений. Установить ограничения на максимальное количество активных соединений и максимальное количество настройки соединений в процессе. Обеспечить таймауты чтения (как на отдельное чтение, так и на общее для “slowloris”). Ограничить повторные или одновременные соединения с одного источника. Вести чёрные списки источников, которые повторно не проходят проверку. Не отвечать на сбой AEAD.

  • Для облегчения быстрого определения версии и рукопожатия реализации должны обеспечить, чтобы Алиса буферизовала и затем сбрасывала всё содержимое первого сообщения сразу, включая дополнение. Это увеличивает вероятность того, что данные будут содержаться в одном TCP-пакете (если только не сегментированы ОС или промежуточными устройствами), и будут получены Бобом сразу. Кроме того, реализации должны обеспечить, чтобы Боб буферизовал и затем сбрасывал всё содержимое второго сообщения сразу, включая дополнение, и чтобы Боб буферизовал и затем сбрасывал всё содержимое третьего сообщения сразу. Это также для эффективности и для обеспечения эффективности случайного дополнения.

  • Поле “ver”: Общий протокол Noise, расширения и протокол NTCP, включая спецификации полезной нагрузки, указывающие NTCP2. Это поле может использоваться для указания поддержки будущих изменений.

  • Длина части 2 сообщения 3: Это размер второго кадра AEAD (включая 16-байтовый MAC), содержащего Router Info Алисы и опциональное дополнение, который будет отправлен в сообщении SessionConfirmed. Поскольку маршрутизаторы периодически пересоздают и повторно публикуют свою Router Info, размер текущей Router Info может измениться до отправки сообщения 3. Реализации должны выбрать одну из двух стратегий: a) сохранить текущую Router Info для отправки в сообщении 3, чтобы размер был известен, и опционально добавить место для дополнения; b) увеличить указанный размер достаточно, чтобы позволить возможное увеличение размера Router Info, и всегда добавлять дополнение при фактической отправке сообщения 3. В любом случае, длина “m3p2len”, включённая в сообщение 1, должна быть точно такой же, как размер этого кадра при отправке в сообщении 3.

  • Боб должен прервать соединение, если после проверки сообщения 1 и чтения дополнения остаются входящие данные. Не должно быть дополнительных данных от Алисы, так как Боб ещё не ответил сообщением 2.

  • Поле сетевого ID используется для быстрой идентификации межсетевых соединений. Если это поле ненулевое и не совпадает с сетевым ID Боба, Боб должен отключиться и заблокировать будущие соединения. Начиная с 0.9.42. См. предложение 147 для получения дополнительной информации.

Функция выработки ключей (KDF) (для сообщения рукопожатия 2 и части 1 сообщения 3)


// взять h, сохранённый из KDF сообщения 1
// MixHash(зашифрованные данные)
h = SHA256(h || 32-байтовые зашифрованные данные из сообщения 1)

// MixHash(дополнение)
// Только если длина дополнения ненулевая
h = SHA256(h || случайное дополнение из сообщения 1)

Это шаблон сообщения "e":

Боб генерирует свою эфемерную пару ключей DH e.

// h из KDF для сообщения рукопожатия 1
// Эфемерный ключ Боба Y
// MixHash(e.pubkey)
// || ниже означает присоединение
h = SHA256(h || e.pubkey);

// h используется как сопутствующие данные для AEAD в сообщении 2
// Сохранить хеш h для KDF сообщения 3

Конец шаблона "e".

Это шаблон сообщения "ee":

// DH(e, re)
Определить input_key_material = 32-байтовый результат DH эфемерного ключа Алисы и эфемерного ключа Боба
Установить input_key_material = результат X25519 DH
// перезаписать эфемерный ключ Алисы в памяти, больше не нужен
// Алиса:
e(открытый и закрытый) = (все нули)
// Боб:
re = (все нули)

// MixKey(DH())

Определить temp_key = 32 байта
Определить HMAC-SHA256(key, data) как в [RFC-2104](https://tools.ietf.org/html/rfc2104)
// Сгенерировать временный ключ из цепочного ключа и результата DH
// ck — цепочный ключ, из KDF для сообщения рукопожатия 1
temp_key = HMAC-SHA256(ck, input_key_material)
// перезаписать результат DH в памяти, больше не нужен
input_key_material = (все нули)

// Выход 1
// Установить новый цепочный ключ из временного ключа
// byte() ниже означает один байт
ck =       HMAC-SHA256(temp_key, byte(0x01)).

// Выход 2
// Сгенерировать ключ шифрования k
Определить k = 32 байта
// || ниже означает присоединение
// byte() ниже означает один байт
k =        HMAC-SHA256(temp_key, ck || byte(0x02)).
// перезаписать temp_key в памяти, больше не нужен
temp_key = (все нули)

// сохранить цепочный ключ ck для KDF сообщения 3

Конец шаблона "ee".

2) SessionCreated

Боб отправляет Алисе.

Содержимое Noise: Эфемерный ключ Боба Y Полезная нагрузка Noise: 16-байтовый блок опций Полезная нагрузка вне Noise: Случайное дополнение

(Свойства безопасности полезной нагрузки)

XK(s, rs):           Аутентификация   Конфиденциальность
  <- e, ee                  2                1

  Аутентификация: 2.
  Аутентификация отправителя, устойчивая к имитации при компрометации ключа (KCI).
  Аутентификация отправителя основана на эфемерно-статическом DH ("es" или "se")
  между статической парой ключей отправителя и эфемерной парой ключей получателя.
  При условии, что соответствующие закрытые ключи защищены, эта аутентификация не может быть подделана.

  Конфиденциальность: 1.
  Шифрование для эфемерного получателя.
  Эта полезная нагрузка имеет совершенную секретность, так как шифрование включает эфемерно-эфемерный DH ("ee").
  Однако отправитель не аутентифицировал получателя,
  поэтому эта полезная нагрузка может быть отправлена любой стороне, включая активного атакующего.


  "e": Боб генерирует новую эфемерную пару ключей и сохраняет её в переменной e,
  записывает открытый эфемерный ключ в буфер сообщения,
  и хеширует открытый ключ вместе со старым h, чтобы вывести новый h.

  "ee": Выполняется DH между эфемерной парой ключей Боба и эфемерной парой ключей Алисы.
  Результат хешируется вместе со старым ck, чтобы вывести новый ck и k, и n устанавливается в ноль.

Значение Y шифруется для обеспечения неотличимости и уникальности полезной нагрузки, что необходимо для противодействия DPI. Мы используем шифрование AES для достижения этого, вместо более сложных и медленных альтернатив, таких как elligator2. Асимметричное шифрование для открытого ключа маршрутизатора Алисы было бы слишком медленным. Шифрование AES использует хеш маршрутизатора Боба в качестве ключа и состояние AES из сообщения 1 (которое было инициализировано с IV Боба, как опубликовано в базе данных сети).

Шифрование AES предназначено только для сопротивления DPI. Любая сторона, знающая хеш маршрутизатора Боба и IV, которые опубликованы в базе данных сети, и перехватившая первые 32 байта сообщения 1, может расшифровать значение Y в этом сообщении.

Сырые содержимое:

+----+----+----+----+----+----+----+----+
|                                       |
+        маскировано с RH_B           +
|       AES-CBC-256 зашифрованный Y         |
+              (32 байта)               +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|   кадр ChaChaPoly                    |
+   Зашифрованные и аутентифицированные данные    +
|   32 байта                            |
+   k определён в KDF для сообщения 2      +
|   n = 0; см. KDF для сопутствующих данных  |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|     незашифрованное аутентифицированное         |
+         дополнение (опционально)            +
|     длина определена в блоке опций   |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

Y :: 32 байта, X25519 эфемерный ключ, зашифрованный AES-256-CBC, little endian
        ключ: RH_B
        iv: Используя состояние AES из сообщения 1

Незашифрованные данные (тег аутентификации Poly1305 не показан):

+----+----+----+----+----+----+----+----+
|                                       |
+                                       +
|                  Y                    |
+              (32 байта)               |
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|               опции                 |
+              (16 байт)               +
|                                       |
+----+----+----+----+----+----+----+----+
|     незашифрованное аутентифицированное         |
+         дополнение (опционально)            +
|     длина определена в блоке опций   |
~               .   .   .               ~
|                                       |
+----+----+----+----+----+----+----+----+

Y :: 32 байта, X25519 эфемерный ключ, little endian

опции :: блок опций, 16 байт, см. ниже

дополнение :: Случайные данные, 0 или более байт.
           Общая длина сообщения должна быть 65535 байт или меньше.
           Алиса и Боб будут использовать данные дополнения в KDF для части 1 сообщения 3.
           Оно аутентифицировано, поэтому любое изменение вызовет сбой
           следующего сообщения.

Примечания

  • Алиса должна проверить, что эфемерный ключ Боба является допустимой точкой на кривой здесь.

  • Дополнение должно быть ограничено разумным объёмом. Алиса может отклонять соединения с чрезмерным дополнением. Алиса укажет свои параметры дополнения в сообщении 3. Рекомендации по мин/макс TBD. Случайный размер от 0 до 31 байт минимум? (Распределение будет определено, см. Приложение A.)

  • При любой ошибке, включая AEAD, DH, временную метку, очевидную повторную передачу или сбой проверки ключа, Алиса должна прекратить дальнейшую обработку сообщений и закрыть соединение без ответа. Это должно быть аварийное закрытие (TCP RST).

  • Для облегчения быстрого рукопожатия реализации должны обеспечить, чтобы Боб буферизовал и затем сбрасывал всё содержимое первого сообщения сразу, включая дополнение. Это увеличивает вероятность того, что данные будут содержаться в одном TCP-пакете (если только не сегментированы ОС или промежуточными устройствами), и будут получены Алисой сразу. Это также для эффективности и для обеспечения эффективности случайного дополнения.

  • Алиса должна прервать соединение, если после проверки сообщения 2 и чтения дополнения остаются входящие данные. Не должно быть дополнительных данных от Боба, так как Алиса ещё не ответила сообщением 3.

Блок опций: Примечание: Все поля big-endian.


+----+----+----+----+----+----+----+----+
| Rsvd(0) | padLen  |   Reserved (0)    |
+----+----+----+----+----+----+----+----+
|        tsB        |   Reserved (0)    |
+----+----+----+----+----+----+----+----+

Reserved :: Всего 10 байт, установлено в 0 для совместимости с будущими опциями

padLen :: 2 байта, big endian, длина дополнения, 0 или более
          Рекомендации по мин/макс TBD. Случайный размер от 0 до 31 байт минимум?
          (Распределение будет определено, см. Приложение A.)

tsB :: 4 байта, big endian, временная метка Unix, беззнаковые секунды.
       Переполняется в 2106

Примечания

  • Алиса должна отклонять соединения, где значение временной метки слишком сильно отклоняется от текущего времени. Назовём максимальную дельту времени “D”. Алиса должна вести локальный кэш ранее использованных значений рукопожатия и отклонять дубликаты, чтобы предотвратить атаки повторной передачи. Значения в кэше должны иметь срок жизни не менее 2*D. Значения кэша зависят от реализации, однако 32-байтовое значение Y (или его зашифрованный эквивалент) может быть использовано.

Проблемы

  • Включить здесь опции мин/макс дополнения?

Шифрование для части 1 сообщения рукопожатия 3, используя KDF сообщения 2)


// взять h, сохранённый из KDF сообщения 2
// MixHash(зашифрованные данные)
h = SHA256(h || 24-байтовые зашифрованные данные из сообщения 2)

// MixHash(дополнение)
// Только если длина дополнения ненулевая
h = SHA256(h || случайное дополнение из сообщения 2)
// h используется как сопутствующие данные для AEAD в части 1 сообщения 3, ниже

Это шаблон сообщения "s":

Определить s = статический открытый ключ Алисы, 32 байта

// EncryptAndHash(s.publickey)
// EncryptWithAd(h, s.publickey)
// AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data)
// k из сообщения рукопожатия 1
// n = 1
зашифрованные_данные = AEAD_ChaCha20_Poly1305(k, n++, h, s.publickey)
// MixHash(зашифрованные_данные)
// || ниже означает присоединение
h = SHA256(h || зашифрованные_данные);

// h используется как сопутствующие данные для AEAD в части 2 сообщения 3

Конец шаблона "s".

Функция выработки ключей (KDF) (для части 2 сообщения рукопожатия 3)


Это шаблон сообщения "se":

// DH(s, re) == DH(e, rs)
Определить input_key_material = 32-байтовый результат DH статического ключа Алисы и эфемерного ключа Боба
Установить input_key_material = результат X25519 DH
// перезаписать эфемерный ключ Боба в памяти, больше не нужен
// Алиса:
re = (все нули)
// Боб:
e(открытый и закрытый) = (все нули)

// MixKey(DH())

Определить temp_key = 32 байта
Определить HMAC-SHA256(key, data) как в [RFC-2104](https://tools.ietf.org/html/rfc2104)
// Сгенерировать временный ключ из цепочного ключа и результата DH
// ck — цепочный ключ, из KDF для сообщения рукопожатия 1
temp_key = HMAC-SHA256(ck, input_key_material)
// перезаписать результат DH в памяти, больше не нужен
input_key_material = (все нули)

// Выход 1
// Установить новый цепочный ключ из временного ключа
// byte() ниже означает один байт
ck =       HMAC-SHA256(temp_key, byte(0x01)).

// Выход 2
// Сгенерировать ключ шифрования k
Определить k = 32 байта
// || ниже означает присоединение
// byte() ниже означает один байт
k =        HMAC-SHA256(temp_key, ck || byte(0x02)).

// h из части 1 сообщения 3 используется как сопутствующие данные для AEAD в части 2 сообщения 3

// EncryptAndHash(полезная нагрузка)
// EncryptWithAd(h, полезная нагрузка)
// AEAD_ChaCha20_Poly1305(key, nonce,