Каждый новый узел I2P при первом запуске должен откуда-то получить первоначальный список узлов.
Для этого существуют специальные серверы (reseed), адреса которых жестко зашиты в коде.
Раньше закачка осуществлялась по http, но в последнее время ресиды стали переходить на https. Для успешной работы «фиолетовый» I2P также необходимо было внести соответствующие изменения.
Используемая там криптографическая библиотека крипто++ не поддерживает SSL. Вместо использования дополнительной библиотеки типа openssl, которая фактически дублирует криптографию, был выбран вариант, обсуждаемый ниже.
Bootstrap — единственное место в I2P, где используется https. С другой стороны, статья будет интересна тем, кому интересно понять, как работает ssl, и попробовать его самостоятельно.
Изобретение колеса заново
Наша цель — получить файл i2pseeds.su3 размером около 100 КБ с одного из повторно заполняемых узлов I2P. Этот файл подписан отдельным сертификатом, независимым от сертификата хоста, поэтому проверку сертификата можно исключить.Сравнительно небольшая длина получаемых данных позволяет не реализовывать механизмы сжатия и восстановления нарушенных соединений.
Будет использоваться исключительно ТЛС 1.2 и набор шифров TLS_RSA_WITH_AES_256_CBC_SHA256. Другими словами, AES256 в режиме CBC используется для шифрования данных, а RSA — для согласования ключей.
Этот выбор обусловлен тем, что AES256-CBC является наиболее используемым шифрованием в I2P, а RSA упрощает реализацию протокола за счет уменьшения количества сообщений, необходимых для согласования ключей.
Помимо RSA и AES, вам также потребуются следующие криптографические функции из crypto++:
- HMAC для вычисления контрольных сумм зашифрованных сообщений и псевдослучайных функций.
Обратите внимание, что используется стандартная реализация HMAC, а не I2P.
- Хэш SHA256 для использования с HMAC и для расчета контрольной суммы всех сообщений, участвующих в установлении соединения.
- Функции для работы с описаниями на языке ASN.1 в кодировке DER. Требуется для извлечения открытого ключа из сертификата X.509.
Передача сообщений через SSL
Абсолютно все передаваемые сообщения начинаются с 5-байтового заголовка, первый байт которого содержит тип сообщения, следующие 2 байта — номер версии протокола (0x03, 0x03 для TSL 1.2) и далее длину оставшейся части (контента).сообщения - 2 байта в Big Endian, тем самым определяя границы сообщений.
Таким образом, при получении новых данных сначала следует прочитать 5 байт заголовка, а затем сколько байт содержится в поле длины.
Существует 4 типа сообщений:
- 0x17 — данные.
Содержимое представляет собой зашифрованные HTTP-сообщения, в нашем случае с использованием AES256, ключ которого рассчитывается в процессе установления соединения.
Размер данных должен быть кратен 16 байтам.
- 0x16 – установление соединения.
Несколько типов, определяемых соответствующим полем внутри контента.
Незашифрованное, за исключением «законченного» сообщения, отправленного последним.
- 0x15 — предупреждение.
Сообщение о том, что «что-то пошло не так».
Закрываем соединение.
Содержит коды того, что именно пошло не так, можно использовать для отладки.
- 0x14 — изменить шифр.
Отправлено сразу после согласования ключей.
Содержимое составляет 1 байт и всегда содержит 0x01. На самом деле это часть процесса установления соединения.
Все в BigEndian. Ключ для HMAC также рассчитывается во время установки соединения; заполнитель, так что длина зашифрованных данных кратна 16 байтам, последний байт содержит количество байт заполнителя без учета самого заполнителя.
Если длина сообщения кратна 16 байтам, то к этому последнему байту длины будут добавлены еще 16 байтов.
Установление соединения
В процессе установки нам предстоит решить две задачи:- Согласование и вычисление ключей для шифрования и HMAC.
- Отправьте правильную последовательность сообщений, чтобы другая сторона не закрыла соединение, а перешла в режим обмена данными.
Содержимое сообщения этого типа начинается с собственного 4-байтового заголовка, первый байт которого представляет собой тип сообщения установки соединения, как указано выше, и 3 байта длины оставшегося сообщения, самый старший байт которого в наш случай всегда равен нулю.
Давайте рассмотрим эти сообщения подробно.
КлиентПривет
Первое сообщение, которое мы отправляем на сервер после успешного подключения.Поскольку мы используем один конкретный набор шифров, в нашем случае он будет постоянным.
Так:
Теги: #i2p #tls 1.2 #HTTPS #C++ #crypto #programming #i2pstatic uint8_t clientHello[] = {
-
Заслуживает Ли Поиск На Рабочем Столе?
19 Oct, 24 -
Плакат Silverlight 2 Для Разработчиков
19 Oct, 24 -
Дайджест Kolibrios №3: Начало Весны
19 Oct, 24 -
Nokia Запатентовала Новый Дизайн Телефона
19 Oct, 24