Примечание
Фаза предложения закрыта. См. SPEC для официальной спецификации. На это предложение все еще можно ссылаться для получения справочной информации.
Обзор
Это предложение описывает протокол аутентифицированного согласования ключей для повышения устойчивости NTCP к различным формам автоматической идентификации и атак.
Предложение организовано следующим образом: представлены цели безопасности, за которыми следует обсуждение базового протокола. Далее дается полная спецификация всех сообщений протокола. Наконец, обсуждаются адреса router’ов и идентификация версий. Также включено приложение, обсуждающее общую атаку на распространенные схемы дополнения, а также приложение, содержащее ряд кандидатов для аутентифицированного шифра.
Как и другие транспорты I2P, NTCP2 предназначен исключительно для точка-к-точке (router-к-router) транспорта I2NP сообщений. Это не универсальный канал передачи данных.
Мотивация
Данные NTCP шифруются после первого сообщения (и первое сообщение выглядит как случайные данные), что предотвращает идентификацию протокола через “анализ полезной нагрузки”. Однако протокол по-прежнему уязвим для идентификации через “анализ потока”. Это происходит потому, что первые 4 сообщения (то есть рукопожатие) имеют фиксированную длину (288, 304, 448 и 48 байт).
Добавляя случайные объемы случайных данных к каждому из сообщений, мы можем значительно усложнить задачу.
Авторы признают, что стандартные практики безопасности предполагают использование существующего протокола, такого как TLS, но это Prop104, и у него есть свои проблемы. Где это уместно, добавлены параграфы «будущая работа» для указания отсутствующих функций или предметов для обсуждения.
Цели дизайна
Поддержка NTCP 1 и 2 на одном порту с автоопределением и публикацией как единого “транспорта” (т.е. RouterAddress) в NetDB.
Публиковать поддержку только версии 1, только 2, или 1+2 в NetDB в отдельном поле, и по умолчанию использовать только версию 1 (не привязывать поддержку версий к конкретной версии router)
Убедиться, что все реализации (Java/i2pd/Kovri/go) могут добавить поддержку версии 2 (или не добавлять) по своему собственному графику
Добавить случайное заполнение ко всем NTCP сообщениям, включая сообщения рукопожатия и данных (т.е. обфускация длины, чтобы все сообщения не были кратными 16 байтам) Предоставить механизм опций для обеих сторон для запроса минимального и максимального заполнения и/или распределения заполнения. Специфика распределения заполнения зависит от реализации и может быть указана или не указана в самом протоколе.
Обфусцировать содержимое сообщений, которые не зашифрованы (1 и 2), достаточно для того, чтобы DPI-устройства и AV-сигнатуры не могли легко их классифицировать. Также обеспечить, чтобы сообщения, отправляемые одному peer или группе peers, не имели схожих битовых паттернов.
Исправить потерю битов в DH из-за формата Java Ticket1112, возможно (вероятно?) путем перехода на X25519.
Переключиться на настоящую функцию вывода ключей (KDF) вместо использования результата DH как есть?
Добавить “устойчивость к зондированию” (как это называется в Tor); это включает защиту от replay-атак.
Поддерживать двусторонний аутентифицированный обмен ключами (2W-AKE). 1W-AKE недостаточно для нашего приложения.
Продолжить использовать подписи переменного типа и переменной длины (из опубликованного ключа подписи RouterIdentity) как часть аутентификации. Полагаться на статический публичный ключ, опубликованный в RouterInfo, как на другую часть аутентификации.
Добавить опции/версию в handshake для будущей расширяемости.
Добавить защиту от вредоносной TCP-сегментации MitM, если это возможно.
Не должны значительно увеличивать требования к CPU для установки соединения; по возможности, должны значительно их снизить.
Добавить аутентификацию сообщений (MAC), возможно HMAC-SHA256 и Poly1305, и удалить контрольную сумму Adler.
Сократить и упростить заголовок I2NP: Сократить срок действия до 4 байт, как в SSU. Удалить однобайтовую усеченную контрольную сумму SHA256.
По возможности сократить 4-сообщенческое рукопожатие с двумя циклами обмена до 3-сообщенческого рукопожатия с одним циклом обмена, как в SSU. Это потребует перемещения подписи Боба из сообщения 4 в сообщение 2. Изучить причину использования 4 сообщений в десятилетних архивах электронной почты/статусов/встреч.
Минимизировать накладные расходы протокола до добавления padding. Хотя padding будет добавлен, и возможно в больших количествах, накладные расходы до padding всё равно остаются накладными расходами. Узлы с низкой пропускной способностью должны иметь возможность использовать NTCP2.
Поддерживать временные метки для обнаружения повторов и рассинхронизации.
Избегать любых проблем 2038 года в временных метках, должно работать как минимум до 2106 года.
Увеличить максимальный размер сообщения с 16K до 32K или 64K.
Любые новые криптографические примитивы должны быть легко доступны в библиотеках для использования в реализациях router на Java (1.7), C++ и Go.
Включить представителей разработчиков router на Java, C++ и Go в проектирование.
Минимизировать изменения (но их всё равно будет много).
Поддержка обеих версий в общем наборе кода (это может быть невозможно и в любом случае зависит от реализации).
Non-Goals
Пуленепробиваемая устойчивость к DPI… это были бы подключаемые транспорты, Prop109.
Транспорт на основе TLS (или похожий на HTTPS)… это будет Prop104.
Можно изменить симметричное потоковое шифрование.
Сопротивление DPI на основе временных характеристик (межсообщенческие временные интервалы/задержки могут зависеть от реализации; внутрисообщенческие задержки могут быть введены в любой точке, включая перед отправкой случайного заполнения, например). Искусственные задержки (то, что obfs4 называет IAT или время между поступлениями) независимы от самого протокола.
Возможность отрицания участия в сессии (там есть подписи).
Нецели, которые могут быть частично пересмотрены или обсуждены:
Степень защиты от глубокого анализа пакетов (Deep Packet Inspection, DPI)
Постквантовая (PQ) безопасность
Отрицаемость
Related Goals
- Реализовать тестовую установку NTCP 1/2
Security Goals
Мы рассматриваем три стороны:
- Алиса, которая желает установить новую сессию.
- Боб, с которым Алиса желает установить сессию.
- Мэллори, “человек посередине” между Алисой и Бобом.
Максимум два участника могут участвовать в активных атаках.
Алиса и Боб оба обладают парой статических ключей, которая содержится в их RouterIdentity.
Предлагаемый протокол пытается позволить Алисе и Бобу согласовать общий секретный ключ (K) при следующих требованиях:
Безопасность приватного ключа: ни Bob, ни Mallory не узнают ничего о статическом приватном ключе Alice. Симметрично, Alice не узнает ничего о статическом приватном ключе Bob.
Ключ сеанса K известен только Алисе и Бобу.
Совершенная прямая секретность: согласованный ключ сессии остается секретным в будущем, даже когда статические приватные ключи Алисы и/или Боба раскрываются после того, как ключ был согласован.
Двусторонняя аутентификация: Алиса уверена, что она установила сессию с Бобом, и наоборот.
Защита от онлайн DPI: Обеспечить, чтобы не было тривиальным обнаружить, что Алиса и Боб участвуют в протоколе, используя только простые методы глубокой инспекции пакетов (DPI). См. ниже.
Ограниченная возможность отрицания: ни Алиса, ни Боб не могут отрицать участие в протоколе, но если любая из сторон раскроет общий ключ, другая сторона может отрицать подлинность содержимого переданных данных.
Данное предложение пытается обеспечить все пять требований на основе протокола Station-To-Station (STS). Обратите внимание, что этот протокол также является основой для протокола SSU.
Additional DPI Discussion
Мы предполагаем два DPI компонента:
1) Online DPI
Онлайн DPI инспектирует все потоки в режиме реального времени. Соединения могут быть заблокированы или подвергнуты иному вмешательству. Данные соединений или метаданные могут быть идентифицированы и сохранены для офлайн анализа. Онлайн DPI не имеет доступа к базе данных сети I2P. Онлайн DPI обладает только ограниченными вычислительными возможностями в реальном времени, включая вычисление длины, инспектирование полей и простые вычисления, такие как XOR. Онлайн DPI действительно имеет возможность быстрых криптографических функций реального времени, таких как AES, AEAD и хеширование, но их применение было бы слишком затратным для большинства или всех потоков. Любое применение этих криптографических операций применялось бы только к потокам на комбинациях IP/Port, предварительно идентифицированных офлайн анализом. Онлайн DPI не имеет возможности высокозатратных криптографических функций, таких как DH или elligator2. Онлайн DPI не предназначен специально для обнаружения I2P, хотя может иметь ограниченные правила классификации для этой цели.
Целью является предотвращение идентификации протокола онлайн DPI.
Понятие онлайн или “прямого” DPI здесь включает в себя следующие возможности противника:
Возможность проверять все данные, отправляемые или получаемые целью.
Возможность выполнять операции с наблюдаемыми данными, такие как применение блочных шифров или хеш-функций.
Возможность сохранять и сравнивать с ранее отправленными сообщениями.
Возможность изменять, задерживать или фрагментировать пакеты.
Однако предполагается, что онлайн DPI имеет следующие ограничения:
Невозможность сопоставления IP-адресов с хешами router. Хотя это тривиально при наличии доступа к базе данных сети в реальном времени, это потребовало бы системы DPI, специально разработанной для нацеливания на I2P.
Невозможность использования временной информации для обнаружения протокола.
В целом, онлайн-инструментарий DPI не содержит встроенных инструментов, специально предназначенных для обнаружения I2P. Это включает создание “honeypots” (приманок), которые, например, включали бы неслучайное заполнение в своих сообщениях. Обратите внимание, что это не исключает системы машинного обучения или высококонфигурируемые инструменты DPI, если они соответствуют остальным требованиям.
Для противодействия анализу полезной нагрузки обеспечивается, что все сообщения неотличимы от случайных данных. Это также требует, чтобы их длина была случайной, что сложнее, чем простое добавление случайного заполнения. Фактически, в Приложении А авторы утверждают, что наивная (т.е. равномерная) схема заполнения не решает проблему. Поэтому Приложение А предлагает включить либо случайные задержки, либо разработать альтернативную схему заполнения, которая может обеспечить разумную защиту от предлагаемой атаки.
Для защиты от шестого пункта выше реализации должны включать случайные задержки в протокол. Такие методы не рассматриваются в данном предложении, но они также могли бы решить проблемы с длиной заполнения. В заключение, предложение обеспечивает хорошую защиту от анализа полезной нагрузки (при учете соображений из Приложения A), но лишь ограниченную защиту от анализа потоков.
2) Offline DPI
Офлайн DPI анализирует данные, сохраненные онлайн DPI, для последующего анализа. Офлайн DPI может быть специально разработан для обнаружения I2P. Офлайн DPI имеет доступ в реальном времени к базе данных сети I2P. Офлайн DPI имеет доступ к этой и другим спецификациям I2P. Офлайн DPI обладает неограниченными вычислительными возможностями, включая все криптографические функции, определенные в данной спецификации.
Автономный DPI не имеет возможности блокировать существующие соединения. Автономный DPI имеет возможность выполнять отправку в почти реальном времени (в течение нескольких минут после настройки) на хост/порт сторон, например TCP RST. Автономный DPI имеет возможность выполнять в почти реальном времени (в течение нескольких минут после настройки) повтор предыдущих сообщений (измененных или неизмененных) для “зондирования” или других целей.
Не является целью предотвращение идентификации протокола оффлайн DPI. Все декодирование обфусцированных данных в первых двух сообщениях, которое реализуется I2P router’ами, может также быть реализовано оффлайн DPI.
Цель состоит в том, чтобы отклонять попытки подключения с использованием повторного воспроизведения предыдущих сообщений.
Future work
Рассмотрите поведение протокола при сбросе или изменении порядка пакетов атакующим. Недавние интересные исследования в этой области можно найти в IACR-1150.
Обеспечить более точную классификацию систем DPI с учетом существующей литературы по данной теме.
Обсудить формальную безопасность предлагаемого протокола, в идеале с учётом модели атакующего DPI.
Noise Protocol Framework
Данное предложение предоставляет требования, основанные на Noise Protocol Framework NOISE (Редакция 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 использует следующие примитивы:
Handshake Pattern: XK Алиса передает свой ключ Бобу (X) Алиса уже знает статический ключ Боба (K)
DH Function: X25519 X25519 DH с длиной ключа 32 байта, как указано в RFC-7748.
Cipher Function: ChaChaPoly AEAD_CHACHA20_POLY1305 как указано в RFC-7539 раздел 2.8. 12-байтовый nonce, с первыми 4 байтами установленными в ноль.
Hash Function: SHA256 Стандартный 32-байтный хеш, уже широко используемый в I2P.
Цели безопасности
Данное предложение определяет следующие улучшения для Noise_XK_25519_ChaChaPoly_SHA256. Они в целом следуют рекомендациям из раздела 13 NOISE.
Открытые эфемерные ключи обфусцируются с помощью AES-шифрования, используя известный ключ и IV. Это быстрее, чем elligator2.
К сообщениям 1 и 2 добавляется случайное заполнение открытого текста. Заполнение открытого текста включается в расчет хэша рукопожатия (MixHash). См. разделы KDF ниже для сообщения 2 и части 1 сообщения 3. Случайное заполнение AEAD добавляется к сообщению 3 и сообщениям фазы данных.
Добавляется двухбайтовое поле длины фрейма, как требуется для Noise over TCP, и как в obfs4. Это используется только в сообщениях фазы данных. AEAD фреймы сообщений 1 и 2 имеют фиксированную длину. AEAD фрейм части 1 сообщения 3 имеет фиксированную длину. Длина AEAD фрейма части 2 сообщения 3 указывается в сообщении 1.
Двухбайтовое поле длины кадра обфусцируется с помощью SipHash-2-4, как в obfs4.
Формат полезной нагрузки определен для сообщений 1, 2, 3 и фазы данных. Конечно, это не определено в Noise.
New Cryptographic Primitives for I2P
Существующие реализации I2P router потребуют реализации следующих стандартных криптографических примитивов, которые не требуются для текущих протоколов I2P:
Генерация ключей X25519 и DH
AEAD_ChaCha20_Poly1305 (сокращенно ChaChaPoly ниже)
SipHash-2-4
Processing overhead estimate
Размеры сообщений для 3 сообщений:
- 64 байта + заполнение (NTCP было 288 байт) 2) 64 байта + заполнение (NTCP было 304 байта) 3) приблиз. 64 байта + информация о маршрутизаторе Alice + заполнение Средняя информация о маршрутизаторе составляет около 750 байт Общий средний размер 814 байт до заполнения (NTCP было 448 байт) 4) не требуется в NTCP2 (NTCP было 48 байт)
Итого до дополнения: NTCP2: 942 байта NTCP: 1088 байт Обратите внимание, что если Алиса подключилась к Бобу с целью отправки сообщения DatabaseStore своей RouterInfo, это сообщение не требуется, что экономит примерно 800 байт.
Следующие криптографические операции требуются каждой стороной для завершения handshake и начала фазы передачи данных:
- AES: 2
- SHA256: 7 (Алиса), 6 (Боб) (не включая 1 Алиса, 2 Боб предвычисленных для всех соединений) (не включая HMAC-SHA256)
- HMAC-SHA256: 19
- ChaChaPoly: 4
- Генерация ключа X25519: 1
- X25519 DH: 3
- Проверка подписи: 1 (Боб) (Алиса ранее подписала при генерации своего RI) Предположительно Ed25519 (зависит от типа подписи RI)
Следующие криптографические операции требуются каждой стороной для каждого сообщения фазы данных:
- SipHash: 1
- ChaChaPoly: 1
Messages
Все NTCP2 сообщения имеют длину не более 65537 байт. Формат сообщения основан на Noise сообщениях с модификациями для фреймирования и неразличимости. Реализации, использующие стандартные Noise библиотеки, могут потребовать предварительной обработки получаемых сообщений в/из формата Noise сообщений. Все зашифрованные поля являются AEAD шифртекстами.
Последовательность установления соединения выглядит следующим образом:
Alice Bob
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->
Используя терминологию Noise, последовательность установления соединения и передачи данных выглядит следующим образом: (Свойства безопасности полезной нагрузки)
XK(s, rs): Authentication Confidentiality
<- 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 байта)
Authenticated Encryption
Существует три отдельных экземпляра аутентифицированного шифрования (CipherStates). Один используется во время фазы handshake, и два (для передачи и получения) для фазы данных. Каждый имеет свой собственный ключ из KDF.
Зашифрованные/аутентифицированные данные будут представлены как
+----+----+----+----+----+----+----+----+
| |
+ +
| Encrypted and authenticated data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
Не-цели
Формат шифрованных и аутентифицированных данных.
Входные данные для функций шифрования/дешифрования:
k :: 32 byte cipher key, as generated from KDF
nonce :: Counter-based nonce, 12 bytes.
Starts at 0 and incremented for each message.
First four bytes are always zero.
Last eight bytes are the counter, little-endian encoded.
Maximum value is 2**64 - 2.
Connection must be dropped and restarted after
it reaches that value.
The value 2**64 - 1 must never be sent.
ad :: In handshake phase:
Associated data, 32 bytes.
The SHA256 hash of all preceding data.
In data phase:
Zero bytes
data :: Plaintext data, 0 or more bytes
Результат функции шифрования, входные данные для функции расшифровки:
+----+----+----+----+----+----+----+----+
|Obfs Len | |
+----+----+ +
| ChaCha20 encrypted data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) +
| 16 bytes |
+----+----+----+----+----+----+----+----+
Obfs Len :: Length of (encrypted data + MAC) to follow, 16 - 65535
Obfuscation using SipHash (see below)
Not used in message 1 or 2, or message 3 part 1, where the length is fixed
Not used in message 3 part 1, as the length is specified in message 1
encrypted data :: Same size as plaintext data, 0 - 65519 bytes
MAC :: Poly1305 message authentication code, 16 bytes
Для ChaCha20 описанное здесь соответствует RFC-7539, который также аналогично используется в TLS RFC-7905.
Notes
Поскольку ChaCha20 является потоковым шифром, открытые тексты не нуждаются в дополнении. Дополнительные байты ключевого потока отбрасываются.
Ключ для шифра (256 бит) согласовывается с помощью SHA256 KDF. Детали KDF для каждого сообщения приведены в отдельных разделах ниже.
Фреймы ChaChaPoly для сообщений 1, 2 и первой части сообщения 3 имеют известный размер. Начиная со второй части сообщения 3, фреймы имеют переменный размер. Размер части 1 сообщения 3 указывается в сообщении 1. Начиная с фазы данных, фреймы предваряются двухбайтовой длиной, обфусцированной с помощью SipHash, как в obfs4.
Заполнение находится вне аутентифицированного фрейма данных для сообщений 1 и 2. Заполнение используется в KDF для следующего сообщения, поэтому вмешательство будет обнаружено. Начиная с сообщения 3, заполнение находится внутри аутентифицированного фрейма данных.
Сопутствующие цели
В сообщениях 1, 2 и частях 1 и 2 сообщения 3 размер AEAD сообщения известен заранее. При неудаче аутентификации AEAD получатель должен остановить дальнейшую обработку сообщений и закрыть соединение без ответа. Это должно быть аварийное закрытие (TCP RST).
Для сопротивления зондированию в сообщении 1, после сбоя AEAD, Bob должен установить случайный таймаут (диапазон TBD) и затем прочитать случайное количество байт (диапазон TBD) перед закрытием сокета. Bob должен поддерживать черный список IP-адресов с повторяющимися сбоями.
В фазе данных размер AEAD сообщения “зашифровывается” (обфускируется) с помощью SipHash. Необходимо соблюдать осторожность, чтобы избежать создания оракула расшифровки. При ошибке аутентификации AEAD в фазе данных получатель должен установить случайный таймаут (диапазон TBD) и затем прочитать случайное количество байт (диапазон TBD). После чтения или по истечении таймаута чтения получатель должен отправить полезную нагрузку с блоком завершения, содержащим код причины “AEAD failure”, и закрыть соединение.
Выполнить то же действие при ошибке для недопустимого значения поля длины в фазе данных.
Key Derivation Function (KDF) (for handshake message 1)
KDF генерирует ключ шифра фазы рукопожатия k из результата DH, используя HMAC-SHA256(key, data) как определено в RFC-2104. Это функции InitializeSymmetric(), MixHash() и MixKey(), точно как определено в спецификации Noise.
This is the "e" message pattern:
// Define protocol_name.
Set protocol_name = "Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256"
(48 bytes, US-ASCII encoded, no NULL termination).
// Define Hash h = 32 bytes
h = SHA256(protocol_name);
Define ck = 32 byte chaining key. Copy the h data to ck.
Set ck = h
Define rs = Bob's 32-byte static key as published in the RouterInfo
// MixHash(null prologue)
h = SHA256(h);
// up until here, can all be precalculated by Alice for all outgoing connections
// Alice must validate that Bob's static key is a valid point on the curve here.
// Bob static key
// MixHash(rs)
// || below means append
h = SHA256(h || rs);
// up until here, can all be precalculated by Bob for all incoming connections
This is the "e" message pattern:
Alice generates her ephemeral DH key pair e.
// Alice ephemeral key X
// MixHash(e.pubkey)
// || below means append
h = SHA256(h || e.pubkey);
// h is used as the associated data for the AEAD in message 1
// Retain the Hash h for the message 2 KDF
End of "e" message pattern.
This is the "es" message pattern:
// DH(e, rs) == DH(s, re)
Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's static key
Set input_key_material = X25519 DH result
// MixKey(DH())
Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104)
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, defined above
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)
// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck = HMAC-SHA256(temp_key, byte(0x01)).
// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
// retain the chaining key ck for message 2 KDF
End of "es" message pattern.
Дополнительное обсуждение DPI
Алиса отправляет Бобу.
Содержимое Noise: эфемерный ключ Alice X Полезная нагрузка Noise: 16-байтовый блок опций Полезная нагрузка не-Noise: Случайное заполнение
(Свойства безопасности полезной нагрузки)
XK(s, rs): Authentication Confidentiality
-> e, es 0 2
Authentication: None (0).
This payload may have been sent by any party, including an active attacker.
Confidentiality: 2.
Encryption to a known recipient, forward secrecy for sender compromise
only, vulnerable to replay. This payload is encrypted based only on DHs
involving the recipient's static key pair. If the recipient's static
private key is compromised, even at a later date, this payload can be
decrypted. This message can also be replayed, since there's no ephemeral
contribution from the recipient.
"e": Alice generates a new ephemeral key pair and stores it in the e
variable, writes the ephemeral public key as cleartext into the
message buffer, and hashes the public key along with the old h to
derive a new h.
"es": A DH is performed between the Alice's ephemeral key pair and the
Bob's static key pair. The result is hashed along with the old ck to
derive a new ck and k, and n is set to zero.
Значение X шифруется для обеспечения неразличимости и уникальности полезной нагрузки, что является необходимыми мерами противодействия DPI. Мы используем шифрование AES для достижения этой цели, а не более сложные и медленные альтернативы, такие как elligator2. Асимметричное шифрование с использованием публичного ключа router’а Bob было бы слишком медленным. Шифрование AES использует router hash Bob’а в качестве ключа и IV Bob’а, опубликованный в network database.
Шифрование AES предназначено только для защиты от DPI. Любая сторона, знающая router hash Боба и IV, которые публикуются в базе данных сети, может расшифровать значение X в данном сообщении.
Заполнение не шифруется Алисой. Бобу может потребоваться расшифровать заполнение для предотвращения атак по времени.
Исходное содержимое:
+----+----+----+----+----+----+----+----+
| |
+ obfuscated with RH_B +
| AES-CBC-256 encrypted X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaChaPoly frame |
+ (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 |
+----+----+----+----+----+----+----+----+
X :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian
key: RH_B
iv: As published in Bobs network database entry
padding :: Random data, 0 or more bytes.
Total message length must be 65535 bytes or less.
Total message length must be 287 bytes or less if
Bob is publishing his address as NTCP
(see Version Detection section below).
Alice and Bob will use the padding data in the KDF for message 2.
It is authenticated so that any tampering will cause the
next message to fail.
Незашифрованные данные (тег аутентификации Poly1305 не показан):
+----+----+----+----+----+----+----+----+
| |
+ +
| X |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| options |
+ (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
X :: 32 bytes, X25519 ephemeral key, little endian
options :: options block, 16 bytes, see below
padding :: Random data, 0 or more bytes.
Total message length must be 65535 bytes or less.
Total message length must be 287 bytes or less if
Bob is publishing his address as "NTCP"
(see Version Detection section below)
Alice and Bob will use the padding data in the KDF for message 2.
It is authenticated so that any tampering will cause the
next message to fail.
Блок опций: Примечание: Все поля имеют порядок байтов big-endian.
+----+----+----+----+----+----+----+----+
| id | ver| padLen | m3p2len | Rsvd(0) |
+----+----+----+----+----+----+----+----+
| tsA | Reserved (0) |
+----+----+----+----+----+----+----+----+
id :: 1 byte, the network ID (currently 2, except for test networks)
As of 0.9.42. See proposal 147.
ver :: 1 byte, protocol version (currently 2)
padLen :: 2 bytes, length of the padding, 0 or more
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
(Distribution to be determined, see Appendix A.)
m3p2Len :: 2 bytes, length of the the second AEAD frame in SessionConfirmed
(message 3 part 2) See notes below
Rsvd :: 2 bytes, set to 0 for compatibility with future options
tsA :: 4 bytes, Unix timestamp, unsigned seconds.
Wraps around in 2106
Reserved :: 4 bytes, set to 0 for compatibility with future options
Notes
Когда опубликованный адрес имеет тип “NTCP”, Bob поддерживает как NTCP, так и NTCP2 на одном и том же порту. Для совместимости, при инициации соединения с адресом, опубликованным как “NTCP”, Alice должна ограничить максимальный размер этого сообщения, включая дополнение, до 287 байт или меньше. Это облегчает автоматическое определение протокола со стороны Bob. Когда адрес опубликован как “NTCP2”, ограничения по размеру отсутствуют. См. разделы “Опубликованные адреса” и “Определение версии” ниже.
Уникальное значение X в начальном блоке AES гарантирует, что шифротекст будет различным для каждой сессии.
Боб должен отклонять соединения, где значение временной метки слишком сильно отличается от текущего времени. Назовем максимальную разность времени “D”. Боб должен поддерживать локальный кэш ранее использованных значений handshake и отклонять дубликаты для предотвращения атак повторного воспроизведения. Значения в кэше должны иметь время жизни не менее 2*D. Значения кэша зависят от реализации, однако может использоваться 32-байтное значение X (или его зашифрованный эквивалент).
Эфемерные ключи Diffie-Hellman никогда не должны использоваться повторно для предотвращения криптографических атак, и повторное использование будет отклонено как replay-атака.
Параметры “KE” и “auth” должны быть совместимыми, т.е. общий секрет K должен иметь соответствующий размер. Если будут добавлены дополнительные параметры “auth”, это может неявно изменить значение флага “KE” для использования другой KDF или другого размера усечения.
Bob должен проверить здесь, что эфемерный ключ Alice является действительной точкой на кривой.
Отступы должны быть ограничены разумным количеством. Bob может отклонять соединения с избыточными отступами. Bob укажет свои параметры отступов в сообщении 2. Рекомендации по min/max TBD. Случайный размер от 0 до 31 байта минимум? (Распределение будет определено, см. Приложение A.)
При любой ошибке, включая AEAD, DH, временную метку, очевидный повтор или сбой проверки ключа, Bob должен прекратить дальнейшую обработку сообщений и закрыть соединение без ответа. Это должно быть аномальное закрытие (TCP RST). Для сопротивления зондированию, после сбоя AEAD, Bob должен установить случайный тайм-аут (диапазон TBD) и затем прочитать случайное количество байтов (диапазон TBD), перед закрытием сокета.
Защита от DoS-атак: DH является относительно затратной операцией. Как и в случае с предыдущим протоколом NTCP, роутеры должны принимать все необходимые меры для предотвращения истощения CPU или соединений. Установите ограничения на максимальное количество активных соединений и максимальное количество настраиваемых соединений. Применяйте тайм-ауты чтения (как для отдельного чтения, так и общий для “slowloris”). Ограничивайте повторяющиеся или одновременные соединения с одного источника. Ведите черные списки источников, которые постоянно дают сбои. Не отвечайте на сбои AEAD.
Для облегчения быстрого определения версии и рукопожатия, реализации должны обеспечить, чтобы Alice буферизовала и затем отправляла все содержимое первого сообщения целиком за один раз, включая заполнение. Это увеличивает вероятность того, что данные будут содержаться в одном TCP-пакете (если только не сегментированы ОС или промежуточными устройствами) и получены Bob’ом за один раз. Кроме того, реализации должны обеспечить, чтобы Bob буферизовал и затем отправлял все содержимое второго сообщения целиком за один раз, включая заполнение, и чтобы Bob буферизовал и затем отправлял все содержимое третьего сообщения целиком за один раз. Это также делается для эффективности и обеспечения эффективности случайного заполнения.
Поле “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.
Bob должен закрыть соединение, если после проверки сообщения 1 и чтения заполнения остаются какие-либо входящие данные. Не должно быть никаких дополнительных данных от Alice, поскольку Bob еще не ответил сообщением 2.
Поле network ID используется для быстрой идентификации межсетевых соединений. Если это поле не равно нулю и не совпадает с network ID Боба, Боб должен разорвать соединение и заблокировать будущие подключения. Начиная с версии 0.9.42. См. предложение 147 для получения дополнительной информации.
Key Derivation Function (KDF) (for handshake message 2 and message 3 part 1)
// take h saved from message 1 KDF
// MixHash(ciphertext)
h = SHA256(h || 32 byte encrypted payload from message 1)
// MixHash(padding)
// Only if padding length is nonzero
h = SHA256(h || random padding from message 1)
This is the "e" message pattern:
Bob generates his ephemeral DH key pair e.
// h is from KDF for handshake message 1
// Bob ephemeral key Y
// MixHash(e.pubkey)
// || below means append
h = SHA256(h || e.pubkey);
// h is used as the associated data for the AEAD in message 2
// Retain the Hash h for the message 3 KDF
End of "e" message pattern.
This is the "ee" message pattern:
// DH(e, re)
Define input_key_material = 32 byte DH result of Alice's ephemeral key and Bob's ephemeral key
Set input_key_material = X25519 DH result
// overwrite Alice's ephemeral key in memory, no longer needed
// Alice:
e(public and private) = (all zeros)
// Bob:
re = (all zeros)
// MixKey(DH())
Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104)
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, from the KDF for handshake message 1
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)
// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck = HMAC-SHA256(temp_key, byte(0x01)).
// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
// retain the chaining key ck for message 3 KDF
End of "ee" message pattern.
2) SessionCreated
Боб отправляет Алисе.
Содержимое Noise: эфемерный ключ Bob Y Полезная нагрузка Noise: блок опций 16 байт Полезная нагрузка не-Noise: случайное заполнение
(Свойства безопасности полезной нагрузки)
XK(s, rs): Authentication Confidentiality
<- e, ee 2 1
Authentication: 2.
Sender authentication resistant to key-compromise impersonation (KCI).
The sender authentication is based on an ephemeral-static DH ("es" or "se")
between the sender's static key pair and the recipient's ephemeral key pair.
Assuming the corresponding private keys are secure, this authentication cannot be forged.
Confidentiality: 1.
Encryption to an ephemeral recipient.
This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee").
However, the sender has not authenticated the recipient,
so this payload might be sent to any party, including an active attacker.
"e": Bob generates a new ephemeral key pair and stores it in the e variable,
writes the ephemeral public key as cleartext into the message buffer,
and hashes the public key along with the old h to derive a new h.
"ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair.
The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.
Значение Y зашифровано для обеспечения неразличимости и уникальности полезной нагрузки, которые являются необходимыми контрмерами против DPI. Мы используем шифрование AES для достижения этой цели, а не более сложные и медленные альтернативы, такие как elligator2. Асимметричное шифрование с использованием публичного ключа router Alice было бы слишком медленным. Шифрование AES использует хеш router Bob в качестве ключа и состояние AES из сообщения 1 (которое было инициализировано с IV Bob, опубликованным в netDb).
Шифрование AES предназначено только для сопротивления DPI. Любая сторона, знающая хеш router’а Боба и IV, которые опубликованы в базе данных сети, и перехватившая первые 32 байта сообщения 1, может расшифровать значение Y в этом сообщении.
Необработанное содержимое:
+----+----+----+----+----+----+----+----+
| |
+ obfuscated with RH_B +
| AES-CBC-256 encrypted Y |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| ChaChaPoly frame |
+ 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 |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
Y :: 32 bytes, AES-256-CBC encrypted X25519 ephemeral key, little endian
key: RH_B
iv: Using AES state from message 1
Незашифрованные данные (тег аутентификации Poly1305 не показан):
+----+----+----+----+----+----+----+----+
| |
+ +
| Y |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| options |
+ (16 bytes) +
| |
+----+----+----+----+----+----+----+----+
| unencrypted authenticated |
+ padding (optional) +
| length defined in options block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
Y :: 32 bytes, X25519 ephemeral key, little endian
options :: options block, 16 bytes, see below
padding :: Random data, 0 or more bytes.
Total message length must be 65535 bytes or less.
Alice and Bob will use the padding data in the KDF for message 3 part 1.
It is authenticated so that any tampering will cause the
next message to fail.
Notes
Алиса должна проверить, что эфемерный ключ Боба является действительной точкой на кривой здесь.
Отступы должны быть ограничены разумным количеством. Алиса может отклонить соединения с чрезмерными отступами. Алиса укажет свои параметры отступов в сообщении 3. Рекомендации по мин/макс TBD. Случайный размер от 0 до 31 байта минимум? (Распределение будет определено, см. Приложение A.)
При любой ошибке, включая AEAD, DH, временную метку, очевидный повтор или сбой проверки ключа, Алиса должна остановить дальнейшую обработку сообщений и закрыть соединение без ответа. Это должно быть аномальное закрытие (TCP RST).
Для обеспечения быстрого handshaking, реализации должны гарантировать, что Bob буферизует и затем передает все содержимое первого сообщения сразу, включая padding. Это повышает вероятность того, что данные будут содержаться в одном TCP-пакете (если не сегментированы ОС или middlebox-устройствами), и получены Alice все сразу. Это также для эффективности и для обеспечения эффективности случайного padding.
Алиса должна закрыть соединение, если остаются какие-либо входящие данные после валидации сообщения 2 и чтения дополнения. Не должно быть дополнительных данных от Боба, поскольку Алиса еще не ответила сообщением 3.
Блок опций: Примечание: Все поля в формате big-endian.
+----+----+----+----+----+----+----+----+
| Rsvd(0) | padLen | Reserved (0) |
+----+----+----+----+----+----+----+----+
| tsB | Reserved (0) |
+----+----+----+----+----+----+----+----+
Reserved :: 10 bytes total, set to 0 for compatibility with future options
padLen :: 2 bytes, big endian, length of the padding, 0 or more
Min/max guidelines TBD. Random size from 0 to 31 bytes minimum?
(Distribution to be determined, see Appendix A.)
tsB :: 4 bytes, big endian, Unix timestamp, unsigned seconds.
Wraps around in 2106
Notes
- Алиса должна отклонять соединения, где значение timestamp слишком сильно отклоняется от текущего времени. Назовем максимальную дельта времени “D”. Алиса должна поддерживать локальный кэш ранее использованных значений handshake и отклонять дубликаты, чтобы предотвратить replay атаки. Значения в кэше должны иметь время жизни не менее 2*D. Значения кэша зависят от реализации, однако может использоваться 32-байтное значение Y (или его зашифрованный эквивалент).
Issues
- Включить здесь опции минимального/максимального заполнения?
Encryption for for handshake message 3 part 1, using message 2 KDF)
// take h saved from message 2 KDF
// MixHash(ciphertext)
h = SHA256(h || 24 byte encrypted payload from message 2)
// MixHash(padding)
// Only if padding length is nonzero
h = SHA256(h || random padding from message 2)
// h is used as the associated data for the AEAD in message 3 part 1, below
This is the "s" message pattern:
Define s = Alice's static public key, 32 bytes
// EncryptAndHash(s.publickey)
// EncryptWithAd(h, s.publickey)
// AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data)
// k is from handshake message 1
// n is 1
ciphertext = AEAD_ChaCha20_Poly1305(k, n++, h, s.publickey)
// MixHash(ciphertext)
// || below means append
h = SHA256(h || ciphertext);
// h is used as the associated data for the AEAD in message 3 part 2
End of "s" message pattern.
Key Derivation Function (KDF) (for handshake message 3 part 2)
This is the "se" message pattern:
// DH(s, re) == DH(e, rs)
Define input_key_material = 32 byte DH result of Alice's static key and Bob's ephemeral key
Set input_key_material = X25519 DH result
// overwrite Bob's ephemeral key in memory, no longer needed
// Alice:
re = (all zeros)
// Bob:
e(public and private) = (all zeros)
// MixKey(DH())
Define temp_key = 32 bytes
Define HMAC-SHA256(key, data) as in [RFC-2104](https://tools.ietf.org/html/rfc2104)
// Generate a temp key from the chaining key and DH result
// ck is the chaining key, from the KDF for handshake message 1
temp_key = HMAC-SHA256(ck, input_key_material)
// overwrite the DH result in memory, no longer needed
input_key_material = (all zeros)
// Output 1
// Set a new chaining key from the temp key
// byte() below means a single byte
ck = HMAC-SHA256(temp_key, byte(0x01)).
// Output 2
// Generate the cipher key k
Define k = 32 bytes
// || below means append
// byte() below means a single byte
k = HMAC-SHA256(temp_key, ck || byte(0x02)).
// h from message 3 part 1 is used as the associated data for the AEAD in message 3 part 2
// EncryptAndHash(payload)
// EncryptWithAd(h, payload)
// AEAD_ChaCha20_Poly1305(key, nonce, associatedData, data)
// n is 0
ciphertext = AEAD_ChaCha20_Poly1305(k, n++, h, payload)
// MixHash(ciphertext)
// || below means append
h = SHA256(h || ciphertext);
// retain the chaining key ck for the data phase KDF
// retain the hash h for the data phase Additional Symmetric Key (SipHash) KDF
End of "se" message pattern.
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
3) SessionConfirmed
Алиса отправляет Бобу.
Содержимое Noise: статический ключ Alice Полезная нагрузка Noise: RouterInfo Alice и случайное заполнение Полезная нагрузка вне Noise: отсутствует
(Свойства безопасности полезной нагрузки)
XK(s, rs): Authentication Confidentiality
-> s, se 2 5
Authentication: 2.
Sender authentication resistant to key-compromise impersonation (KCI). The
sender authentication is based on an ephemeral-static DH ("es" or "se")
between the sender's static key pair and the recipient's ephemeral key
pair. Assuming the corresponding private keys are secure, this
authentication cannot be forged.
Confidentiality: 5.
Encryption to a known recipient, strong forward secrecy. This payload is
encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static
DH with the recipient's static key pair. Assuming the ephemeral private
keys are secure, and the recipient is not being actively impersonated by an
attacker that has stolen its static private key, this payload cannot be
decrypted.
"s": Alice writes her static public key from the s variable into the
message buffer, encrypting it, and hashes the output along with the old h
to derive a new h.
"se": A DH is performed between the Alice's static key pair and the Bob's
ephemeral key pair. The result is hashed along with the old ck to derive a
new ck and k, and n is set to zero.
Это содержит два фрейма ChaChaPoly. Первый — это зашифрованный статический публичный ключ Алисы. Второй — это полезная нагрузка Noise: зашифрованная RouterInfo Алисы, опциональные опции и опциональное заполнение. Они используют разные ключи, поскольку между ними вызывается функция MixKey().
Необработанное содержимое:
+----+----+----+----+----+----+----+----+
| |
+ ChaChaPoly frame (48 bytes) +
| Encrypted and authenticated |
+ Alice static key S +
| (32 bytes) |
+ +
| k defined in KDF for message 2 |
+ n = 1 +
| see KDF for associated data |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ Length specified in message 1 +
| |
+ ChaChaPoly frame +
| Encrypted and authenticated |
+ +
| Alice RouterInfo |
+ using block format 2 +
| Alice Options (optional) |
+ using block format 1 +
| Arbitrary padding |
+ using block format 254 +
| |
+ +
| k defined in KDF for message 3 part 2 |
+ n = 0 +
| see KDF for associated data |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
S :: 32 bytes, ChaChaPoly encrypted Alice's X25519 static key, little endian
inside 48 byte ChaChaPoly frame
Незашифрованные данные (теги аутентификации Poly1305 не показаны):
+----+----+----+----+----+----+----+----+
| |
+ +
| S |
+ Alice static key +
| (32 bytes) |
+ +
| |
+ +
+----+----+----+----+----+----+----+----+
| |
+ +
| |
+ +
| Alice RouterInfo block |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ Optional Options block +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
| |
+ Optional Padding block +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
S :: 32 bytes, Alice's X25519 static key, little endian
1) Онлайн DPI
Bob должен выполнить обычную проверку Router Info. Убедиться, что тип подписи поддерживается, проверить подпись, проверить, что временная метка находится в допустимых пределах, и выполнить любые другие необходимые проверки.
Боб должен проверить, что статический ключ Алисы, полученный в первом кадре, соответствует статическому ключу в Router Info. Боб должен сначала найти в Router Info адрес NTCP или NTCP2 Router Address с соответствующей опцией версии (v). См. разделы Published Router Info и Unpublished Router Info ниже.
Если у Bob есть более старая версия RouterInfo Alice в его netDb, проверить, что статический ключ в router info одинаков в обеих версиях, если присутствует, и если старая версия не старше XXX (см. время ротации ключа ниже)
Боб должен проверить, что статический ключ Алисы является допустимой точкой на кривой здесь.
Следует включить опции для указания параметров padding.
При любой ошибке, включая сбои валидации AEAD, RI, DH, временных меток или ключей, Боб должен прекратить дальнейшую обработку сообщений и закрыть соединение без ответа. Это должно быть аварийное закрытие (TCP RST).
Для обеспечения быстрого установления соединения реализации должны гарантировать, что Alice буферизует, а затем отправляет всё содержимое третьего сообщения целиком, включая оба AEAD-фрейма. Это увеличивает вероятность того, что данные будут содержаться в одном TCP-пакете (если не сегментированы ОС или промежуточными устройствами) и получены Bob целиком. Это также делается для эффективности и обеспечения результативности случайного заполнения.
Длина кадра части 2 сообщения 3: Длина этого кадра (включая MAC) отправляется Алисой в сообщении 1. См. это сообщение для важных замечаний о предоставлении достаточного места для padding.
Сообщение 3 часть 2 содержимое кадра: Формат этого кадра такой же, как формат кадров фазы данных, за исключением того, что длина кадра отправляется Алисой в сообщении 1. См. ниже формат кадра фазы данных. Кадр должен содержать от 1 до 3 блоков в следующем порядке:
- Блок Router Info Алисы (обязательный)
- Блок Options (опциональный)
- Блок Padding (опциональный) Этот кадр никогда не должен содержать блоки других типов.
Заполнение части 2 сообщения 3 не требуется, если Алиса добавляет кадр фазы данных (дополнительно содержащий заполнение) в конец сообщения 3 и отправляет их одновременно, поскольку наблюдателю это будет выглядеть как один большой поток байтов. Поскольку Алиса обычно, но не всегда, имеет I2NP-сообщение для отправки Бобу (именно поэтому она к нему подключилась), это рекомендуемая реализация для эффективности и обеспечения действенности случайного заполнения.
Общая длина обеих AEAD-фреймов Message 3 (части 1 и 2) составляет 65535 байт; часть 1 составляет 48 байт, поэтому максимальная длина фрейма части 2 составляет 65487; максимальная длина открытого текста части 2, исключая MAC, составляет 65471.
Key Derivation Function (KDF) (for data phase)
Фаза данных использует ввод ассоциированных данных нулевой длины.
KDF генерирует два ключа шифрования k_ab и k_ba из цепочечного ключа ck, используя HMAC-SHA256(key, data) как определено в RFC-2104. Это функция Split(), точно как определено в спецификации Noise.
ck = from handshake phase
// k_ab, k_ba = HKDF(ck, zerolen)
// ask_master = HKDF(ck, zerolen, info="ask")
// zerolen is a zero-length byte array
temp_key = HMAC-SHA256(ck, zerolen)
// overwrite the chaining key in memory, no longer needed
ck = (all zeros)
// Output 1
// cipher key, for Alice transmits to Bob (Noise doesn't make clear which is which, but Java code does)
k_ab = HMAC-SHA256(temp_key, byte(0x01)).
// Output 2
// cipher key, for Bob transmits to Alice (Noise doesn't make clear which is which, but Java code does)
k_ba = HMAC-SHA256(temp_key, k_ab || byte(0x02)).
KDF for SipHash for length field:
Generate an Additional Symmetric Key (ask) for SipHash
SipHash uses two 8-byte keys (big endian) and 8 byte IV for first data.
// "ask" is 3 bytes, US-ASCII, no null termination
ask_master = HMAC-SHA256(temp_key, "ask" || byte(0x01))
// sip_master = HKDF(ask_master, h || "siphash")
// "siphash" is 7 bytes, US-ASCII, no null termination
// overwrite previous temp_key in memory
// h is from KDF for message 3 part 2
temp_key = HMAC-SHA256(ask_master, h || "siphash")
// overwrite ask_master in memory, no longer needed
ask_master = (all zeros)
sip_master = HMAC-SHA256(temp_key, byte(0x01))
Alice to Bob SipHash k1, k2, IV:
// sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen)
// overwrite previous temp_key in memory
temp_key = HMAC-SHA256(sip_master, zerolen)
// overwrite sip_master in memory, no longer needed
sip_master = (all zeros)
sipkeys_ab = HMAC-SHA256(temp_key, byte(0x01)).
sipk1_ab = sipkeys_ab[0:7], little endian
sipk2_ab = sipkeys_ab[8:15], little endian
sipiv_ab = sipkeys_ab[16:23]
Bob to Alice SipHash k1, k2, IV:
sipkeys_ba = HMAC-SHA256(temp_key, sipkeys_ab || byte(0x02)).
sipk1_ba = sipkeys_ba[0:7], little endian
sipk2_ba = sipkeys_ba[8:15], little endian
sipiv_ba = sipkeys_ba[16:23]
// overwrite the temp_key in memory, no longer needed
temp_key = (all zeros)
4) Data Phase
Noise payload: Как определено ниже, включая случайное заполнение Non-noise payload: отсутствует
Начиная со 2-й части сообщения 3, все сообщения находятся внутри аутентифицированного и зашифрованного “фрейма” ChaChaPoly с добавленной двухбайтовой обфусцированной длиной. Все заполнение находится внутри фрейма. Внутри фрейма находится стандартный формат с нулем или более “блоками”. Каждый блок имеет однобайтовый тип и двухбайтовую длину. Типы включают дата/время, I2NP сообщение, опции, завершение и заполнение.
Примечание: Bob может, но не обязан, отправить свою RouterInfo Alice в качестве первого сообщения Alice на этапе передачи данных.
(Свойства безопасности полезной нагрузки)
XK(s, rs): Authentication Confidentiality
<- 2 5
-> 2 5
Authentication: 2.
Sender authentication resistant to key-compromise impersonation (KCI).
The sender authentication is based on an ephemeral-static DH ("es" or "se")
between the sender's static key pair and the recipient's ephemeral key pair.
Assuming the corresponding private keys are secure, this authentication cannot be forged.
Confidentiality: 5.
Encryption to a known recipient, strong forward secrecy.
This payload is encrypted based on an ephemeral-ephemeral DH as well as
an ephemeral-static DH with the recipient's static key pair.
Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated
by an attacker that has stolen its static private key, this payload cannot be decrypted.
2) Offline DPI
Для эффективности и минимизации идентификации поля длины, реализации должны гарантировать, что отправитель буферизует, а затем сбрасывает все содержимое сообщений данных сразу, включая поле длины и AEAD кадр. Это увеличивает вероятность того, что данные будут содержаться в одном TCP пакете (если только не сегментированы ОС или промежуточными узлами), и получены сразу другой стороной. Это также необходимо для эффективности и обеспечения действенности случайного заполнения.
Маршрутизатор может выбрать завершение сессии при ошибке AEAD или может продолжить попытки связи. При продолжении маршрутизатор должен завершить сессию после повторяющихся ошибок.
SipHash obfuscated length
Справочник: SipHash
После того как обе стороны завершают handshake, они передают полезные нагрузки, которые затем шифруются и аутентифицируются в “кадрах” ChaChaPoly.
Каждому кадру предшествует двухбайтовая длина в формате big endian. Эта длина указывает количество зашифрованных байтов кадра, которые следуют далее, включая MAC. Чтобы избежать передачи идентифицируемых полей длины в потоке, длина кадра маскируется путем применения операции XOR с маской, полученной из SipHash, инициализированного из KDF фазы данных. Обратите внимание, что два направления имеют уникальные ключи SipHash и IV из KDF.
sipk1, sipk2 = The SipHash keys from the KDF. (two 8-byte long integers)
IV[0] = sipiv = The SipHash IV from the KDF. (8 bytes)
length is big endian.
For each frame:
IV[n] = SipHash-2-4(sipk1, sipk2, IV[n-1])
Mask[n] = First 2 bytes of IV[n]
obfuscatedLength = length ^ Mask[n]
The first length output will be XORed with with IV[1].
Получатель имеет идентичные ключи SipHash и IV. Декодирование длины выполняется путём выведения маски, используемой для сокрытия длины, и применения операции XOR к усечённому дайджесту для получения длины фрейма. Длина фрейма представляет собой общую длину зашифрованного фрейма, включая MAC.
Будущая работа
- Если вы используете функцию библиотеки SipHash, которая возвращает беззнаковое длинное целое число, используйте два младших байта в качестве Mask. Преобразуйте длинное целое число в следующий IV как little endian.
Аутентифицированное шифрование
+----+----+----+----+----+----+----+----+
|obf size | |
+----+----+ +
| |
+ ChaChaPoly frame +
| Encrypted and authenticated |
+ key is k_ab for Alice to Bob +
| key is k_ba for Bob to Alice |
+ as defined in KDF for data phase +
| n starts at 0 and increments |
+ for each frame in that direction +
| no associated data |
+ 16 bytes minimum +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
obf size :: 2 bytes length obfuscated with SipHash
when de-obfuscated: 16 - 65535
Minimum size including length field is 18 bytes.
Maximum size including length field is 65537 bytes.
Obfuscated length is 2 bytes.
Maximum ChaChaPoly frame is 65535 bytes.
ChaCha20/Poly1305
В зашифрованном кадре содержится ноль или более блоков. Каждый блок содержит однобайтовый идентификатор, двухбайтовую длину и ноль или более байт данных.
Для расширяемости получатели должны игнорировать блоки с неизвестными идентификаторами и обрабатывать их как заполнение.
Зашифрованные данные имеют максимальный размер 65535 байт, включая 16-байтовый заголовок аутентификации, поэтому максимальный размер незашифрованных данных составляет 65519 байт.
(Poly1305 тег аутентификации не показан):
+----+----+----+----+----+----+----+----+
|blk | size | data |
+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
|blk | size | data |
+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
~ . . . ~
blk :: 1 byte
0 for datetime
1 for options
2 for RouterInfo
3 for I2NP message
4 for termination
224-253 reserved for experimental features
254 for padding
255 reserved for future extension
size :: 2 bytes, big endian, size of data to follow, 0 - 65516
data :: the data
Maximum ChaChaPoly frame is 65535 bytes.
Poly1305 tag is 16 bytes
Maximum total block size is 65519 bytes
Maximum single block size is 65519 bytes
Block type is 1 byte
Block length is 2 bytes
Maximum single block data size is 65516 bytes.
Block Ordering Rules
В сообщении handshake 3 часть 2, порядок должен быть следующим: RouterInfo, затем Options если присутствуют, затем Padding если присутствует. Никакие другие блоки не допускаются.
В фазе данных порядок не определен, за исключением следующих требований: Padding, если присутствует, должен быть последним блоком. Termination, если присутствует, должен быть последним блоком, за исключением Padding.
В одном фрейме может содержаться несколько блоков I2NP. Несколько блоков Padding не допускаются в одном фрейме. Другие типы блоков, вероятно, не будут иметь несколько блоков в одном фрейме, но это не запрещено.
Обработка ошибок AEAD
Особый случай для синхронизации времени:
+----+----+----+----+----+----+----+
| 0 | 4 | timestamp |
+----+----+----+----+----+----+----+
blk :: 0
size :: 2 bytes, big endian, value = 4
timestamp :: Unix timestamp, unsigned seconds.
Wraps around in 2106
Функция деривации ключей (KDF) (для handshake сообщения 1)
Передать обновленные опции. Опции включают: минимальное и максимальное заполнение.
Блок опций будет иметь переменную длину.
+----+----+----+----+----+----+----+----+
| 1 | size |tmin|tmax|rmin|rmax|tdmy|
+----+----+----+----+----+----+----+----+
|tdmy| rdmy | tdelay | rdelay | |
~----+----+----+----+----+----+----+ ~
| more_options |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
blk :: 1
size :: 2 bytes, big endian, size of options to follow, 12 bytes minimum
tmin, tmax, rmin, rmax :: requested padding limits
tmin and rmin are for desired resistance to traffic analysis.
tmax and rmax are for bandwidth limits.
tmin and tmax are the transmit limits for the router sending this options block.
rmin and rmax are the receive limits for the router sending this options block.
Each is a 4.4 fixed-point float representing 0 to 15.9375
(or think of it as an unsigned 8-bit integer divided by 16.0).
This is the ratio of padding to data. Examples:
Value of 0x00 means no padding
Value of 0x01 means add 6 percent padding
Value of 0x10 means add 100 percent padding
Value of 0x80 means add 800 percent (8x) padding
Alice and Bob will negotiate the minimum and maximum in each direction.
These are guidelines, there is no enforcement.
Sender should honor receiver's maximum.
Sender may or may not honor receiver's minimum, within bandwidth constraints.
tdmy: Max dummy traffic willing to send, 2 bytes big endian, bytes/sec average
rdmy: Requested dummy traffic, 2 bytes big endian, bytes/sec average
tdelay: Max intra-message delay willing to insert, 2 bytes big endian, msec average
rdelay: Requested intra-message delay, 2 bytes big endian, msec average
Padding distribution specified as additional parameters?
Random delay specified as additional parameters?
more_options :: Format TBD
1) SessionRequest
- Формат опций пока не определен (TBD).
- Согласование опций пока не определено (TBD).
RouterInfo
Передать RouterInfo Алисы Бобу. Используется в сообщении рукопожатия 3 часть 2. Передать RouterInfo Алисы Бобу, или Боба Алисе. Используется опционально в фазе данных.
+----+----+----+----+----+----+----+----+
| 2 | size |flg | RouterInfo |
+----+----+----+----+ +
| (Alice RI in handshake msg 3 part 2) |
~ (Alice, Bob, or third-party ~
| RI in data phase) |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
blk :: 2
size :: 2 bytes, big endian, size of flag + router info to follow
flg :: 1 byte flags
bit order: 76543210
bit 0: 0 for local store, 1 for flood request
bits 7-1: Unused, set to 0 for future compatibility
routerinfo :: Alice's or Bob's RouterInfo
Notes
При использовании в фазе данных получатель (Alice или Bob) должен проверить, что это тот же Router Hash, который был изначально отправлен (для Alice) или отправлен к (для Bob). Затем обработать его как локальное I2NP DatabaseStore Message. Проверить подпись, проверить более свежую временную метку и сохранить в локальной netDb. Если флаг бит 0 равен 1, и принимающая сторона является floodfill, обработать его как DatabaseStore Message с ненулевым токеном ответа и распространить к ближайшим floodfill.
Router Info НЕ сжимается с помощью gzip (в отличие от DatabaseStore Message, где это происходит)
Флудинг не должен запрашиваться, если в RouterInfo отсутствуют опубликованные RouterAddresses. Принимающий router не должен выполнять флудинг RouterInfo, если в нем отсутствуют опубликованные RouterAddresses.
Разработчики должны обеспечить, что при чтении блока некорректные или вредоносные данные не приведут к тому, что операции чтения выйдут за границы в следующий блок.
Этот протокол не предоставляет подтверждения того, что RouterInfo была получена, сохранена или распространена (ни на этапе рукопожатия, ни на этапе данных). Если требуется подтверждение, и получатель является floodfill, отправитель должен вместо этого отправить стандартное I2NP DatabaseStoreMessage с токеном ответа.
Issues
Также может использоваться в фазе данных вместо I2NP DatabaseStoreMessage. Например, Bob может использовать его для запуска фазы данных.
Разрешено ли, чтобы это содержало RI для router’ов, отличных от инициатора, в качестве общей замены для DatabaseStoreMessages, например, для flooding’а floodfill’ами?
Функция выведения ключей (KDF) (для handshake сообщения 2 и сообщения 3 часть 1)
Одиночное I2NP сообщение с модифицированным заголовком. I2NP сообщения не могут быть фрагментированы между блоками или между ChaChaPoly фреймами.
Это использует первые 9 байт из стандартного NTCP I2NP заголовка и удаляет последние 7 байт заголовка следующим образом: обрезает время истечения с 8 до 4 байт, удаляет 2-байтовую длину (использует размер блока - 9) и удаляет однобайтовую контрольную сумму SHA256.
+----+----+----+----+----+----+----+----+
| 3 | size |type| msg id |
+----+----+----+----+----+----+----+----+
| short exp | message |
+----+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
blk :: 3
size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
I2NP message body size is (size - 9).
type :: 1 byte, I2NP msg type, see I2NP spec
msg id :: 4 bytes, big endian, I2NP message ID
short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
Wraps around in 2106
message :: I2NP message body
Notes
- Разработчики должны убедиться, что при чтении блока некорректные или вредоносные данные не приведут к тому, что чтение выйдет за границы в следующий блок.
2) SessionCreated
Noise рекомендует явное сообщение о завершении соединения. Оригинальный NTCP его не имеет. Разорвать соединение. Это должен быть последний блок без padding в кадре.
+----+----+----+----+----+----+----+----+
| 4 | size | valid data frames |
+----+----+----+----+----+----+----+----+
received | rsn| addl data |
+----+----+----+----+ +
~ . . . ~
+----+----+----+----+----+----+----+----+
blk :: 4
size :: 2 bytes, big endian, value = 9 or more
valid data frames received :: The number of valid AEAD data phase frames received
(current receive nonce value)
0 if error occurs in handshake phase
8 bytes, big endian
rsn :: reason, 1 byte:
0: normal close or unspecified
1: termination received
2: idle timeout
3: router shutdown
4: data phase AEAD failure
5: incompatible options
6: incompatible signature type
7: clock skew
8: padding violation
9: AEAD framing error
10: payload format error
11: message 1 error
12: message 2 error
13: message 3 error
14: intra-frame read timeout
15: RI signature verification fail
16: s parameter missing, invalid, or mismatched in RouterInfo
17: banned
addl data :: optional, 0 or more bytes, for future expansion, debugging,
or reason text.
Format unspecified and may vary based on reason code.
Notes
Не все причины могут фактически использоваться, зависит от реализации. Сбои handshake обычно приводят к закрытию с TCP RST вместо этого. См. примечания в разделах сообщений handshake выше. Дополнительные перечисленные причины предназначены для согласованности, логирования, отладки или в случае изменения политики.
Padding
Это для заполнения внутри AEAD-фреймов. Заполнение для сообщений 1 и 2 находится вне AEAD-фреймов. Все заполнение для сообщения 3 и фазы данных находится внутри AEAD-фреймов.
Padding внутри AEAD должно приблизительно соответствовать согласованным параметрам. Bob отправил свои запрошенные параметры tx/rx min/max в сообщении 2. Alice отправила свои запрошенные параметры tx/rx min/max в сообщении 3. Обновленные опции могут быть отправлены во время фазы данных. См. информацию о блоке опций выше.
Если присутствует, то должен быть последним блоком в кадре.
+----+----+----+----+----+----+----+----+
|254 | size | padding |
+----+----+----+ +
| |
~ . . . ~
| |
+----+----+----+----+----+----+----+----+
blk :: 254
size :: 2 bytes, big endian, size of padding to follow
padding :: random data
Notes
- Стратегии заполнения пока не определены.
- Минимальное заполнение пока не определено.
- Фреймы только с заполнением разрешены.
- Заполнение по умолчанию пока не определено.
- См. блок опций для согласования параметров заполнения
- См. блок опций для параметров минимального/максимального заполнения
- Noise ограничивает сообщения до 64КБ. Если необходимо больше заполнения, отправляйте несколько фреймов.
- Реакция router’а на нарушение согласованного заполнения зависит от реализации.
Other block types
Реализации должны игнорировать неизвестные типы блоков для обеспечения прямой совместимости, за исключением части 2 сообщения 3, где неизвестные блоки не допускаются.
Future work
- Длина дополнения должна определяться либо для каждого сообщения на основе оценок распределения длины, либо должны добавляться случайные задержки. Эти контрмеры должны быть включены для противодействия DPI, поскольку размеры сообщений в противном случае выдали бы, что трафик I2P переносится транспортным протоколом. Точная схема дополнения является областью будущей работы, Приложение A предоставляет дополнительную информацию по данной теме.
5) Termination
Соединения могут быть завершены через обычное или аномальное закрытие TCP-сокета, или, как рекомендует Noise, через явное сообщение завершения. Явное сообщение завершения определено в фазе данных выше.
При любом нормальном или аварийном завершении работы, router’ы должны обнулять все временные данные в памяти, включая эфемерные ключи handshake, симметричные криптографические ключи и связанную информацию.
Published Router Info
Шифрование для сообщения handshake 3 часть 1, используя KDF сообщения 2)
Опубликованный RouterAddress (часть RouterInfo) будет иметь идентификатор протокола либо “NTCP”, либо “NTCP2”.
RouterAddress должен содержать опции “host” и “port”, как в текущем протоколе NTCP.
RouterAddress должен содержать три опции для указания поддержки NTCP2:
s=(Base64 key) Текущий статический публичный ключ Noise (s) для данного RouterAddress. Кодируется в Base 64 с использованием стандартного алфавита I2P Base 64. 32 байта в двоичном формате, 44 байта в кодировке Base 64, публичный ключ X25519 в формате little-endian.
i=(Base64 IV) Текущий IV для шифрования значения X в сообщении 1 для данного RouterAddress. Кодируется в Base 64 с использованием стандартного алфавита I2P Base 64. 16 байт в двоичном формате, 24 байта в кодировке Base 64, big-endian.
v=2 Текущая версия (2). При публикации как “NTCP” подразумевается дополнительная поддержка версии 1. Поддержка будущих версий будет осуществляться через значения, разделенные запятыми, например v=2,3 Реализация должна проверять совместимость, включая несколько версий при наличии запятой. Версии, разделенные запятыми, должны быть в числовом порядке.
Алиса должна убедиться, что все три опции присутствуют и действительны перед подключением с использованием протокола NTCP2.
При публикации как “NTCP” с опциями “s”, “i” и “v”, роутер должен принимать входящие соединения на данном хосте и порту для обоих протоколов NTCP и NTCP2, и автоматически определять версию протокола.
Когда публикуется как “NTCP2” с опциями “s”, “i” и “v”, роутер принимает входящие соединения на этом хосте и порту только для протокола NTCP2.
Если router поддерживает как NTCP1, так и NTCP2 соединения, но не реализует автоматическое определение версии для входящих соединений, он должен объявлять как “NTCP”, так и “NTCP2” адреса, и включать опции NTCP2 только в “NTCP2” адрес. Router должен установить более низкое значение стоимости (более высокий приоритет) в “NTCP2” адресе, чем в “NTCP” адресе, чтобы NTCP2 имел предпочтение.
Если несколько NTCP2 RouterAddresses (либо как “NTCP”, либо как “NTCP2”) опубликованы в одном RouterInfo (для дополнительных IP-адресов или портов), все адреса, указывающие один и тот же порт, должны содержать идентичные NTCP2 опции и значения. В частности, все должны содержать один и тот же статический ключ и iv.
Функция выведения ключей (KDF) (для части 2 сообщения 3 рукопожатия)
Если Алиса не публикует свой NTCP2 адрес (как “NTCP” или “NTCP2”) для входящих соединений, она должна опубликовать router адрес “NTCP2”, содержащий только её статический ключ и версию NTCP2, чтобы Боб мог проверить ключ после получения RouterInfo Алисы в сообщении 3 часть 2.
s=(Base64 ключ) Как определено выше для опубликованных адресов.
v=2 Как определено выше для опубликованных адресов.
Этот адрес router не будет содержать опции “i”, “host” или “port”, поскольку они не требуются для исходящих NTCP2-соединений. Опубликованная стоимость для этого адреса не имеет строгого значения, так как он предназначен только для входящих соединений; однако, может быть полезным для других router’ов, если стоимость установлена выше (более низкий приоритет), чем у других адресов. Рекомендуемое значение — 14.
Алиса также может просто добавить опции “s” и “v” к существующему опубликованному адресу “NTCP”.
3) SessionConfirmed
Из-за кэширования RouterInfo’ов, router’ы не должны изменять статический публичный ключ или IV пока router работает, независимо от того, находится ли он в опубликованном адресе или нет. Router’ы должны постоянно хранить этот ключ и IV для повторного использования после немедленной перезагрузки, чтобы входящие соединения продолжали работать, и время перезагрузки не раскрывалось. Router’ы должны постоянно хранить или иным образом определять время последнего выключения, чтобы можно было рассчитать предыдущее время простоя при запуске.
С учетом опасений относительно раскрытия времени перезапуска, router’ы могут ротировать этот ключ или IV при запуске, если router ранее был отключен в течение некоторого времени (как минимум пару часов).
Если router имеет какие-либо опубликованные NTCP2 RouterAddresses (как NTCP или NTCP2), минимальное время простоя перед ротацией должно быть гораздо больше, например один месяц, если только не изменился локальный IP-адрес или router не выполнил “rekeys”.
Если у роутера есть какие-либо опубликованные SSU RouterAddresses, но нет NTCP2 (как NTCP или NTCP2), минимальное время простоя перед ротацией должно быть больше, например один день, если только не изменился локальный IP-адрес или роутер не выполнил “rekeys”. Это применимо даже если опубликованный SSU адрес имеет introducers.
Если router не имеет опубликованных RouterAddresses (NTCP, NTCP2 или SSU), минимальное время простоя перед ротацией может составлять всего два часа, даже если IP-адрес изменится, за исключением случаев, когда router выполняет “rekeys”.
Если router “перегенерирует ключи” на другой Router Hash, он также должен сгенерировать новый noise ключ и IV.
Реализации должны учитывать, что изменение статического публичного ключа или IV запретит входящие NTCP2-соединения от маршрутизаторов, которые закэшировали более старую RouterInfo. Публикация RouterInfo, выбор партнёров туннеля (включая как OBGW, так и IB ближайший hop), выбор zero-hop туннеля, выбор транспорта и другие стратегии реализации должны это учитывать.
Смена IV подчиняется тем же правилам, что и смена ключей, за исключением того, что IV присутствуют только в опубликованных RouterAddresses, поэтому для скрытых или защищённых брандмауэром router’ов IV отсутствует. Если что-либо изменяется (версия, ключ, параметры?), рекомендуется также изменить IV.
Примечание: Минимальное время простоя перед rekeying может быть изменено для обеспечения работоспособности сети и предотвращения reseeding router’ом, который был недоступен в течение умеренного времени.
Identity Hiding
Отрицание не является целью. См. обзор выше.
Каждому паттерну назначаются свойства, описывающие конфиденциальность, обеспечиваемую статическому публичному ключу инициатора и статическому публичному ключу отвечающей стороны. Базовые предположения заключаются в том, что эфемерные приватные ключи являются безопасными, и что стороны прерывают рукопожатие, если они получают статический публичный ключ от другой стороны, которому они не доверяют.
Данный раздел рассматривает только утечку идентификационных данных через статические поля открытых ключей в рукопожатиях. Конечно, идентичность участников Noise может быть раскрыта и другими способами, включая поля полезной нагрузки, анализ трафика или метаданные, такие как IP-адреса.
Алиса: (8) Зашифровано с прямой секретностью для аутентифицированной стороны.
Боб: (3) Не передается, но пассивный злоумышленник может проверить кандидатов для приватного ключа отвечающей стороны и определить, является ли кандидат корректным.
Боб публикует свой статический публичный ключ в netDb. Алиса может или не может?
Issues
- Если Боб изменит свой статический ключ, можно ли использовать в качестве запасного варианта паттерн “XX”?
Noise Protocol Framework
При публикации как “NTCP”, роутер должен автоматически определять версию протокола для входящих соединений.
Это обнаружение зависит от реализации, но вот некоторые общие рекомендации.
Для определения версии входящего NTCP соединения, Боб действует следующим образом:
Ждите не менее 64 байт (минимальный размер NTCP2 сообщения 1)
Если первоначально полученные данные составляют 288 или более байт, входящее соединение является версией 1.
Если менее 288 байт, то либо
Подождать короткое время для получения дополнительных данных (хорошая стратегия до широкого внедрения NTCP2), если получено как минимум 288 байт общих данных, это NTCP 1.
Попробуйте первые этапы декодирования как версию 2, если это не удается, подождите немного времени для получения дополнительных данных (хорошая стратегия после широкого внедрения NTCP2)
- Decrypt the first 32 bytes (the X key) of the SessionRequest packet using AES-256 with key RH_B. - Verify a valid point on the curve. If it fails, wait a short time for more data for NTCP 1 - Verify the AEAD frame. If it fails, wait a short time for more data for NTCP 1
Обратите внимание, что изменения или дополнительные стратегии могут быть рекомендованы, если мы обнаружим активные атаки сегментации TCP на NTCP 1.
Для облегчения быстрого обнаружения версии и установления соединения, реализации должны обеспечить, чтобы Алиса буферизировала, а затем отправляла все содержимое первого сообщения целиком, включая заполнение. Это повышает вероятность того, что данные будут содержаться в одном TCP-пакете (если не сегментированы ОС или промежуточными устройствами) и получены Бобом целиком. Это также необходимо для эффективности и обеспечения действенности случайного заполнения. Это применимо как к NTCP, так и к NTCP2 handshakes.
Дополнения к Framework
Если и Alice, и Bob поддерживают NTCP2, Alice должна подключаться через NTCP2.
Если Алисе не удается подключиться к Бобу с помощью NTCP2 по любой причине, соединение завершается неудачей. Алиса не может повторить попытку, используя NTCP 1.
Откат к паттерну XX, если Боб изменит свои ключи? Это потребует добавления байта типа в начало?
“Fall forward” к паттерну KK, если Алиса переподключается, предполагая, что у Боба всё ещё есть её статический ключ? Это не экономит раундов обмена и использует 4 DH раунда по сравнению с 3 для XK. Вероятно, нет.
KK(s, rs):
-> s
<- s
...
-> e, es, ss
<- e, ee, se
Новые криптографические примитивы для I2P
Данный раздел обсуждает атаку на типичные схемы дополнения, которая позволяет атакующим обнаружить распределение вероятности длины недополненных сообщений, наблюдая только длину дополненных сообщений. Пусть N будет случайной переменной, описывающей количество недополненных байтов, а P — количество байтов дополнения. Тогда общий размер сообщения составляет N + P.
Предположим, что для размера без паддинга n, добавляется как минимум P_min(n) >= 0 и как максимум P_max(n) >= P_min(n) байт паддинга в схеме паддинга. Очевидная схема использует паддинг длиной P, равномерно выбранный случайным образом:
Pr[P = p | N = n] = 1 / (P_max(n) - P_min(n)) if P_min(n) <= p <= P_max(n),
0 otherwise.
Наивная схема дополнения просто гарантировала бы, что размер дополненного сообщения не превышает N_max:
P_max(n) = N_max - n, n <= N_max
P_min(n) = 0.
Однако это раскрывает информацию о длине без дополнения.
Атакующий может легко оценить Pr[x <= N + P <= y], например, с помощью гистограммы.
- Исходя из этого, он также может попытаться оценить
Pr[n_1 <= N <= n_2], действительно:
Pr[N + P = m] = Σ_n Pr[N = n] Pr[P = m - n | N = n].
В наивной схеме,
Pr[N + P = m] = Σ_{n <= m} Pr[N = n] / (N_max - n).
Это довольно очевидно, как и было до проведения вышеуказанного расчета, что это раскрывает информацию о Pr[N = n]: если длина пакетов почти всегда больше m, то N + P <= m почти никогда не будет наблюдаться. Однако это не самая большая проблема, хотя возможность наблюдать минимальную длину сообщения сама по себе может рассматриваться как проблема.
Более серьёзная проблема заключается в том, что можно точно определить Pr[N = n]:
Pr[N + P = m] - Pr[N + P = m-1] = Pr[N = m] / (N_max - m),
то есть
Pr[N = n] = (N_max - n)(Pr[N + P = n] - Pr[N + P = n - 1])
Чтобы отличить NTCP2, атакующий может использовать любой из следующих методов:
Оцените
Pr[kB <= N <= (k + 1)B - 1]для положительных целых чисел k. Для NTCP2 это значение всегда будет равно нулю.Оцените
Pr[N = kB]и сравните со стандартным профилем I2P.
Данная простая атака частично разрушает цель padding’а, который пытается скрыть распределение размеров сообщений без padding’а. Количество сообщений, которое атакующий должен наблюдать для различения протокола, зависит от желаемой точности и от минимальных и максимальных размеров сообщений без padding’а, которые встречаются на практике. Стоит отметить, что атакующему легко собрать множество сообщений, поскольку он может использовать весь трафик, отправляемый с и на конкретный порт, который использует цель.
В некоторых формах (например, при оценке Pr[kB <= N <= (k + 1)B - 1]) атака требует всего лишь несколько байт памяти (достаточно одного целого числа), и можно утверждать, что такая атака может быть включена во многие несколько более продвинутые, но тем не менее стандартные DPI-фреймворки.
Данное предложение предлагает использовать одну из следующих контрмер:
Разработать альтернативную схему заполнения, которая учитывает (оценочное) распределение N путем использования неравномерного распределения длин заполнения. Хорошая схема заполнения, вероятно, потребует ведения гистограммы количества блоков на сообщение.
Добавлять случайные задержки между (случайно размеренными) фрагментами сообщений.
Второй вариант обычно предпочтительнее, поскольку он может одновременно использоваться как контрмера против анализа трафика. Однако такие задержки могут выходить за рамки протокола NTCP2, поэтому вместо него может быть предпочтен первый вариант, который также проще в реализации.
Оценка накладных расходов на обработку
Сопротивление DPI на основе временных параметров (межсообщенческие интервалы/задержки могут зависеть от реализации; внутрисообщенческие задержки могут быть введены в любой точке, включая период перед отправкой случайного заполнения, например). Искусственные задержки (то, что obfs4 называет IAT или inter-arrival time) независимы от самого протокола.