Собственную реализацию https с использованием crypto++ для bootstrap I2P

Собственную реализацию https с использованием crypto++ для bootstrap I2P

519

Для удачной работы «фиолетовый» I2P также нужно внести надлежащие конфигурации. Загрузчик-это единственное место в I2P, который употребляет https. Используемые криптографические библиотеки crypto++ не поддерживает ssl. С иной стороны, статья будет увлекательна для тех, кто заинтересован, чтоб осознать, как ssl работает и попытайтесь сами. До перегрузки осуществляется по протоколу http, но в крайнее время reseed-х начал двигаться к https. Каждый новейший узел I2P при первом запуске нужно , где взять начальный перечень узлов. Заместо того, чтоб применять доп библиотеки, такие как openssl, практически дублирует криптографии, был избран вариант дискуссируется ниже. Для данной цели есть особые сервера (reseed) — адреса агрессивно прописаны в коде.

Иными словами, для шифрования данных с помощью AES256 в режиме CBC, и RSA для обмена ключами. Относительно маленькая длина приобретенных данных дозволяет не использовать механизмы сжатия и вернуть нарушенные соединения. Будет употребляться только TLS 1.2 и набор шифров TLS_RSA_WITH_AES_256_CBC_SHA256. В дополнение к RSA и AES также потребуются последующие криптографические функции crypto++: Изобретать колесо
Наша цель-получить файл i2pseeds.su3 размером около 100К с 1-го повторного наполнения узлов I2P. Этот выбор обоснован тем, что AES256-CBC является более обширно употребляется шифрование в I2P, и RSA для упрощения реализации протокола методом уменьшения количества Сообщений, нужных для согласования ключа. Этот файл подписан отдельный сертификат, независящего веб-сайта сертификат, так и сертификат проверки могут быть устранены.

Следует отметить, что реализация по умолчанию HMAC, а не от I2P HMAC для вычисления контрольной суммы зашифрованного сообщения и псевдослучайных функций.
SHA256 хэш для использования с HMAC и для вычисления контрольной суммы всех сообщений, участвующих в соединении
Для вас необходимо будет извлечь открытый ключ из сертификата X. 509 Функции для работы с языком описания ASN.1 DER-шифровке.

Длина ключа может быть хоть какой и определяется сертификат. Используемая реализация на базе RSA PKCS v1.5.

Потому, когда вы получите новейшие данные, для вас поначалу необходимо прочесть 5 б заголовка и потом, сколько байтов, содержащихся в поле длина. Отправка сообщений по протоколу SSL
Полностью все сообщения начинаются с 5-байтовый Заголовок, 1-ый б которого содержит Тип сообщения, последующие 2 б-номер версии протокола (0x03, 0x03 TSL 1.2), а потом длину оставшейся части(Содержание сообщения 2 б в Big Endian, тем самым определяя границы Сообщений. Есть сообщения из 4-х типов:
Содержимое зашифрованного HTTP-сообщения, и в нашем случае с помощью AES256, ключ от которой рассчитывается в процессе установки соединения. Размер данных должен быть кратен 16 б 0x17 данных.
В незашифрованном виде, за исключением сообщений типа «готово», мы имеем в виду крайнее. 0x16 — соединение. Несколько типов, определяемых подходящим поля в Контент.
0x15 предупреждение. Содержит коды, что конкретно пошло не так, вы сможете применять для отладки. Закрытие соединения. Сообщение, что «что-то пошло не так».
Содержимое 1 б, постоянно содержит 0x01. 0x14 — изменение шифра. Выслан сходу опосля главных переговоров. Практически является частью процесса соединения.

Все в BigEndian. Раз длина сообщения кратна 16 б, что добавит еще 16 б крайний б в длину. Ключ для HMAC также рассчитывается в процессе соединения;
наполнитель, так что длина зашифрованных данных не кратен 16 б, крайний б содержит число байтов наполнителя без учета сам. В нашей реализации, зашифрованные данные последующим образом:
16 б IV для CBC, TSL 1.2 для каждого сообщения своя IV;
длина данных до 64 Кб — длина заголовка;
32 б MAC, рассчитанные по 13 б заголовка и данных, Заголовок состоит из 8 б последовательности чисел, начиная с нуля, типа сообщения (0x17 либо 0x16), версия и длина данных.
Подключение
Во время установки, мы должны решить две трудности:
Для координации и для вычисления ключей для шифрования и HMAC
Выслать правильную последовательность Сообщений, так что иная сторона не закроет соединение, а потом перебежал в режим обмена данными

Содержание сообщения начинается с своим 4-байтовый Заголовок, 1-ый б которого является сообщение типа соединения, как указано выше, и 3 б для длины других Сообщений, б, в нашем случае постоянно равен нулю. Разглядим эти сообщения в деталях. Все сообщения, не считая ChangeChiperSpec-это тип сообщения 0x16 — соединение. В нашем случае последовательность Сообщений последующим образом:
ClientHello—> (0x01)
<—ServerHello (0x02)
<—Сертификат (0x0B)
<—ServerHelloDone (0x0E)
—>ClientKeyExchange (0x10)
—>ChangeCipherSpec
—>Finished (0x14)
<—ChangeCipherSpec
<—Окончил (0x14)
где «—>» значит отправку сообщения, и «<—» — получение.
ClientHello
1-ое сообщение, которое отчаливает на наш сервер опосля удачного подключения. Так:
статические __u8 clientHello[] =
{
0x16, // рукопожатие
0x03, 0x03, // версия (TLS 1.2)
0x00, 0x2F, // длина рукопожатие
// рукопожатие
0x01, // Тип установки соединения (client hello)
0x00, 0x00, 0x2B, // длина рукопожатие полезной перегрузки
// client hello
0x03, 0x03, // высшей версии поддерживается (TLS 1.2)
0x45, 0xFA, 0x01, 0x19, 0x74, 0x55, 0x18, 0x36,
0x42, 0x05, 0xC1, 0xDD, 0x4A, 0x21, 0x80, 0x80,
0xEC, 0x37, 0x11, 0x93, 0x16, 0xF4, 0x66, 0x00,
0x12, 0x67, 0xab ошибка, 0xBA, 0xFF, 0x29, 0x13, 0x9E, // 32 случайных байтов
0x00, // идентификатор сеанса длина
0x00, 0x02, // chiper suites длина
0x00, 0x3D, // RSA_WITH_AES_256_CBC_SHA256
0x01, // способы сжатия длина
0x00, // без сжатия
0x00, 0x00, / / длина расширения
}; Так как мы используем один определенный набор шифров, в нашем случае это будет неизменным.
Раз эти байты являются вправду случайными, то им нужно где-то уяснить, поэтому что они пригодятся в будущем. Мы также передаем набор из 32 случайных байтов для генерации ключей. Это сообщение показывает серверу, что мы поддержка TLS 1.2, это новое подключение (длина идентификатора сеанса равна нулю) и поддерживает единый набор шифров RSA с AES256.
Из этого сообщения, нужно лишь 32 случайных байтов. ServerHello
«Брат-близнец» ClientHello, за исключением того, что Тип сообщения 0x02 заместо 0x01, и не пустой идентификатор сессии.
Сертификат
Может содержать несколько сертификатов, во-первых, это длина всей группы сертификаты, то перед каждый сертификат имеет свою длину. Сертификат X. От него нам нужен общественный ключ RSA. 509 в шифровке DER. Нас интересует лишь 1-ый сертификат и прочитайте его длина обязана быть в 2 раза.
ServerHelloDone
Не содержит ничего полезного, но, учитывается при вычислении хэш готовой.
Не считая того, эти 48 б зашифрованных с помощью открытого ключа RSA, и наряду с длина зашифрованного блока отчаливает на сервер. Случайный скрытый ключ-это 48 б, 1-ые 2 из которых являются номером версии (0x03, 0x03), а оставшиеся 46 генерируются случайным образом. ClientKeyExchange
На данный момент мы имеем довольно инфы для выработки и согласования ключей, проходит в 3 шага: генерации случайного секретного ключа и вычисления «мастер-ключ», расширение, мастер-ключ, чтоб получить ключи шифрования и Контрольные суммы. Следует отметить, что длина зашифрованного блока будет равна длине ключа, заместо 48 б. К примеру, для сертификатов с 2048-битным ключом эта длина составляет 256, а длина передаваемых данных — 258.
ChangeCipherSpec
Отчаливает сходу опосля ClientKeyExchange. Постоянно один и тот же:
статические __u8 changeCipherSpecs[] =
{
0x14, // шифра конфигурации спецификации
0x03, 0x03, // версия (TLS 1.2)
0x00, 0x01, // длина
0x01 // Тип
};

Этот тип сообщения 0x14 и вычисление хэша для готового не участвует.
То есть, на каждом шаге, мы пересчитываем контрольную сумму из предшествующего шага, а потом рассчитанную контрольную сумму от сочетания текстовой строчки и исходные данные, повторяя это до тех пор, пока вы не получите желаемую длину. В TLS 1.2 определяется последующим образом:
PRF(секрет, этикетки, семя) = P_SHA256(секрет, метка + семя);
P_SHA256(секрет, семя) = HMAC_SHA256(secret, A(1) + семя) +
HMAC_SHA256(secret, A(2) + семя) +
HMAC_SH256(secret, A(3) + семя) +… Псевдослучайная функция (PRF)
Для дальнейших расчетов ключей мы должны псевдослучайную функцию, которая воспринимает на вход 4 параметра: скрытый ключ, который послан лишь к серверу, метка в виде текстовой строчки, начальный блок данных и требуемую длину результата. где определяется индукция
A(0) = семя,
A(i) = HMAC_SHA256 (secret, A(i -1)).
Главные MAC, чтоб нас не употребляется. Она обязана быть расширена до 128-байтовый блок, содержащий 4 32-байтный ключ в последующей последовательности: key MAC передать, key MAC, чтоб получить ключ шифрования для передачи ключа расшифровки, чтоб получить. Сейчас «мастер-ключ» рассчитывается по формуле
PRF(секрет, «основной секрет», clientRandom + serverRadom, 48);
где clientRandom 32 случайных байтов от ClientHello и serverRandom от ServerHello. Ключ расширения рассчитывается по формуле
PRF(masterSecret, «key expansion», serverRandom + clientRadom, 128)
clientRadom и serverRadom тут изменяются местами.
Мы тогда сервер готов к обмену данными и мы отправляем HTTP-запрос и получить ответ. Само сообщение содержит 1-ые 12 б от
PRT(masterSecret, «client finished», хэш, 12)
где хэш SHA256 от последующую последовательность Сообщений:
ClientHello, ServerHello, Сертификат, ServerHelloDone, ClientKeyExchange. Раз все прошлые посты были очень элементарными, потом окончил труднее. Все сообщения записываются без 5 б заголовка. Раз сообщение верно сформирован, сервер будет отвечать ChangeCipherSpec и готовой, по другому сообщение о ошибке. Окончил
На данный момент у нас есть все, что необходимо, чтоб начать разговаривать, но, к огорчению, мы должны выслать готовые сообщения, содержащие правильные данные, по другому сервер порвет соединение. 1-ый тип 0x16, но его содержание на сто процентов шифруется, раз подсчет контрольной суммы также рекомендуемые 0x16, не 0x17, как и для остальных зашифрованных Сообщений.
Выводы
В статье подход дозволяет нам отлично работать с https для приложений, которые не требуют полной реализации. Заместо посторониих реализаций ssl, вытягивая собственный криптографии, вы сможете применять уже находится в проекте, как показано на примере crypto++, который уменьшает количество зависимостей, улучшает поддержку и переносимости. Внедрено и употребляется в практически i2pd — C++ реализация I2P habrahabr.ru