10 KiB
Рукопожатие
На рукопожатие возложена задача выяснить способность узлов устанавливать соединение по описываемому протоколу и согласовать подключение с избранными параметрами каждой стороны. На выбор существует два типа хэндшейка: открытый и зашифрованный. Второй дополнительно требует знать публичный ключ целевого узла.
Запрос рукопожатия
После успешного подключения к целевому узлу через избранный транспорт происходит обмен параметрами обоих сторон. Инициирующий соединение узел отправляет пакет с магический числом, флагом шифрования и сериализованными данными в формат LBM. В случае с зашифрованным хэндшейком, сериализованные данные дополнительно зашифровываются с помощью публичного ключа целевого узла.
Структура пакета с запросом рукопожатия выглядит следующим образом:
[magic number: 8B][encryption flag: 1B][LBM-formatted data: >0B]
Магическое число
Магическим числом является следующая последовательность байт:
HEX: 0x53 0x74 0x61 0x64 0x69 0x75 0x6d 0x50
DEC: 83 116 97 100 105 117 109 80
ASCII: S t a d i u m P
Если узел получает пакет, который не содержит магического числа на указанной позиции, то он должен молча закрыть соединение.
Флаг шифрования
Запрос шифрованного хэндшейка предполагает установку этого флага в значение 0x7a
. Все остальные значения должны интерпретироваться как запрос открытого хэндшейка.
Данные
Данные в формате LBM содержат следующие ячейки:
-
Версия протокола
- Ключ:
0x01
- Тип:
uint8_t
- Обязательна: да
- Поддерживаемая запрашивающим узлом версия протокола.
0b10000000
: зарезервировано0b01111111
: номер версии
- Ключ:
-
Алгоритмы хэширования полезной нагрузки
- Ключ:
0x02
- Тип:
Crypto::Algorithm[]
- Обязательна: только для шифрованного ХШ
- Описывает запрашиваемые к использованию в этом соединении хэш-функции для формирования хэша полезной нагрузки.
- Ключ:
-
Алгоритм подписи
- Ключ:
0x03
- Тип:
Crypto::Algorithm
- Обязательна: только для шифрованного ХШ
- Описывает используемый запрашивающим узлом алгоритм подписи.
- Ключ:
-
Публичный ключ подписи
- Ключ:
0x04
- Тип:
char[]
- Обязательна: только для шифрованного ХШ
- Публичный ключ подписи запрашивающего узла, который будет использован для проверки достоверности событий в соединении.
- Ключ:
-
Алгоритмы симметричного шифрования
- Ключ:
0x05
- Тип:
Crypto::Algorithm[]
- Обязательна: только для шифрованного ХШ
- Описывает запрашиваемые к использованию в этом соединении симметричные алгоритмы шифрования.
- Ключ:
-
Приватный ключ
- Ключ:
0x06
- Тип:
char[]
- Обязательна: только для шифрованного ХШ
- Используемый в этом соединении приватный ключ, размера соответствующего избранному алгоритму симметричного шифрования.
- Ключ:
-
Параметры шума
- Ключ:
0x07
- Тип:
uint8_t
- Обязательна: нет
- Описывает параметры шума в соединении:
0b11100000
: выделено под настройку количества шумовых пакетов0b000
: отсутствие шумовых пакетов0b001
: соотношение шумовых пакетов к реальным - 1:80b010
: соотношение - 1:40b011
: 1:20b100
: 1:10b101
: 2:10b110
: 4:10b111
: зарезервировано
0b00011000
: выделено под настройку размера шумовых пакетов0b00
: случайный размер, в пределах от минимального пакета с нулевой полезной нагрузкой, до размера пакета с полезной нагрузкой размерности, которую должен передать целевой узел при одобрении рукопожатия0b01
: случайный размер, на основе среднего размера передаваемого пакета +- 25% (но всегда меньше максимального)0b10
: случайный размер, в пределах от минимального, до максимального / 20b11
: зарезервировано
0b00000110
: выделено под настройку размера шумовых данных в обычных пакетах0b00
: без шумовых данных0b01
: заполнение шумовыми данными до лимита полезной нагрузки0b10
: заполнение шумовыми данными в случайном количестве, от нуля, до лимита полезной нагрузки0b11
: зарезервировано
0b00000001
: зарезервировано
- Ключ:
Ответ на рукопожатие
На запрос рукопожатия с корректным магическим числом целевой узел должен ответить пакетом либо с согласием, либо с ошибкой. Если это ответ с согласием, то данные в пакете должны быть зашифрованы с помощью переданного в запросе хэндшейка симметричного шифра и переданного приватного ключа. Если это ответ с ошибкой, то он может быть незашифрован, в случае, если ошибка связанна с инициализацией шифрования или версией протокола. Таким образом, запрашивающий узел должен быть готов обработать оба варианта развития событий, исходя из значения флага шифрования. Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными параметрами.
Пакет ответа имеет следующую структуру:
[magic number: 8B][encryption flag: 1B][LBM-formatted data: >0B]
Данные
Данные в формате LBM содержат следующие ячейки:
-
Максимальный размер полезной нагрузки
- Ключ:
0x71
- Тип:
uint16_t
- Обязательна: только для соглашения
- Всегда больше нуля. Оба узла должны соблюдать размерность полезной нагрузки в событии, она всегда должна быть равна или меньше этого значения.
- Ключ:
-
Код ошибки
- Ключ:
0x72
- Тип:
uint8_t
- Обязательна: только для ошибки
- Код, описывающий тип ошибки:
0x01
: магическое число ложно0x02
: неподдерживаемая версия протокола0x03
: недопустимый алгоритм хэширования0x04
: недопустимый алгоритм подписи0x05
: недопустимый алгоритм симметричного шифрования0x06
: некорректный приватный ключ0x07
: некорректный публичный ключ подписи0x08
: недопустимые параметры шума0x09
: невозможно корректно расшифровать данные (ложный публичный ключ целевого узла)
- Ключ:
-
Описание ошибки
- Ключ:
0x73
- Тип:
char[]
- Обязательна: нет
- Строка в кодировке ASCII, описывающая ошибку в человекочитаемом виде.
- Ключ: