На рукопожатие возложена задача выяснить способность _узлов_ устанавливать соединение по описываемому протоколу и согласовать подключение с избранными параметрами каждой стороны. На выбор существует два типа хэндшейка: открытый и зашифрованный. Второй дополнительно требует знать публичный ключ целевого _узла_.
## Запрос рукопожатия
После успешного подключения к целевому _узлу_ через избранный транспорт происходит обмен параметрами обоих сторон. Инициирующий соединение _узел_ отправляет пакет с магический числом, флагом шифрования и сериализованными данными в формат _LBM_. В случае с зашифрованным хэндшейком, сериализованные данные дополнительно зашифровываются с помощью публичного ключа целевого _узла_.
Структура пакета с запросом рукопожатия выглядит следующим образом:
Магическим числом является следующая последовательность байт:
```
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[]`
- _Обязательна:_ только для шифрованного ХШ
- Описывает запрашиваемые к использованию в этом соединении хэш-функции для формирования хэша полезной нагрузки. <!--TODO: упомянуть в структуре события использование нескольких алгоритмов совместно-->
- Алгоритм подписи
- _Ключ:_ `0x03`
- _Тип:_ `Crypto::Algorithm`
- _Обязательна:_ только для шифрованного ХШ
- Описывает используемый запрашивающим _узлом_ алгоритм подписи.
- Публичный ключ подписи
- _Ключ:_ `0x04`
- _Тип:_ `char[]`
- _Обязательна:_ только для шифрованного ХШ
- Публичный ключ подписи запрашивающего _узла_, который будет использован для проверки достоверности событий в соединении.
- Алгоритмы симметричного шифрования
- _Ключ:_ `0x05`
- _Тип:_ `Crypto::Algorithm[]`
- _Обязательна:_ только для шифрованного ХШ
- Описывает запрашиваемые к использованию в этом соединении симметричные алгоритмы шифрования.
- Приватный ключ
- _Ключ:_ `0x06`
- _Тип:_ `char[]`
- _Обязательна:_ только для шифрованного ХШ
- Используемый в этом соединении приватный ключ, размера соответствующего избранному алгоритму симметричного шифрования.
- Параметры шума
- _Ключ:_ `0x07`
- _Тип:_ `uint8_t`
- _Обязательна:_ нет
- Описывает параметры шума в соединении:
-`0b11100000`: выделено под настройку количества _шумовых пакетов_
-`0b000`: отсутствие _шумовых пакетов_
-`0b001`: соотношение _шумовых пакетов_ к реальным - 1:8
-`0b010`: соотношение - 1:4
-`0b011`: 1:2
-`0b100`: 1:1
-`0b101`: 2:1
-`0b110`: 4:1
-`0b111`: зарезервировано
-`0b00011000`: выделено под настройку размера _шумовых пакетов_
-`0b00`: случайный размер, в пределах от минимального _пакета_с нулевой полезной нагрузкой, до размера _пакета_с полезной нагрузкой размерности, которую должен передать целевой _узел_ при одобрении рукопожатия
-`0b01`: случайный размер, на основе среднего размера передаваемого пакета +- 25% (но всегда меньше максимального)
-`0b10`: случайный размер, в пределах от минимального, до максимального / 2
-`0b11`: зарезервировано
-`0b00000110`: выделено под настройку размера _шумовых данных_ в обычных _пакетах_
-`0b00`: без шумовых данных
-`0b01`: заполнение шумовыми данными до лимита полезной нагрузки
-`0b10`: заполнение шумовыми данными в случайном количестве, от нуля, до лимита полезной нагрузки
-`0b11`: зарезервировано
-`0b00000001`: зарезервировано
<!--
- Запрос транспорта (опционально)
- _Ключ:_ `0x05`
- _Тип:_ `uint8_t`
- Если существует, то интерпретируется как запрос переподключения к другому виду транспорта. TODO: Надо сделать енум.
-->
## Ответ на рукопожатие
На запрос рукопожатия с корректным магическим числом целевой _узел_ должен ответить пакетом либо с согласием, либо с ошибкой. Если это ответ с согласием, то данные в пакете должны быть зашифрованы с помощью переданного в запросе хэндшейка симметричного шифра и переданного приватного ключа. Если это ответ с ошибкой, то он может быть незашифрован, в случае, если ошибка связанна с инициализацией шифрования или версией протокола. Таким образом, запрашивающий _узел_ должен быть готов обработать оба варианта развития событий, исходя из значения флага шифрования. Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными параметрами.