stadium-proto/Handshake.md

148 lines
10 KiB
Markdown
Raw Normal View History

2023-12-09 02:49:16 +05:30
# Рукопожатие
На рукопожатие возложена задача выяснить способность _узлов_ устанавливать соединение по описываемому протоколу и согласовать подключение с избранными параметрами каждой стороны. На выбор существует два типа хэндшейка: открытый и зашифрованный. Второй дополнительно требует знать публичный ключ целевого _узла_.
## Запрос рукопожатия
После успешного подключения к целевому _узлу_ через избранный транспорт происходит обмен параметрами обоих сторон. Инициирующий соединение _узел_ отправляет пакет с магический числом, флагом шифрования и сериализованными данными в формат _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[]`
- _Обязательна:_ только для шифрованного ХШ
- Описывает запрашиваемые к использованию в этом соединении хэш-функции для формирования хэша полезной нагрузки. <!--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: Надо сделать енум.
-->
## Ответ на рукопожатие
На запрос рукопожатия с корректным магическим числом целевой _узел_ должен ответить пакетом либо с согласием, либо с ошибкой. Если это ответ с согласием, то данные в пакете должны быть зашифрованы с помощью переданного в запросе хэндшейка симметричного шифра и переданного приватного ключа. Если это ответ с ошибкой, то он может быть незашифрован, в случае, если ошибка связанна с инициализацией шифрования или версией протокола. Таким образом, запрашивающий _узел_ должен быть готов обработать оба варианта развития событий, исходя из значения флага шифрования. Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными параметрами.
Пакет ответа имеет следующую структуру:
`[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, описывающая ошибку в человекочитаемом виде.
<!--TODO: стартовый SID-->