stadium-proto/Handshake.md

10 KiB
Raw Blame History

Рукопожатие

На рукопожатие возложена задача выяснить способность узлов устанавливать соединение по описываемому протоколу и согласовать подключение с избранными параметрами каждой стороны. На выбор существует два типа хэндшейка: открытый и зашифрованный. Второй дополнительно требует знать публичный ключ целевого узла.

Запрос рукопожатия

После успешного подключения к целевому узлу через избранный транспорт происходит обмен параметрами обоих сторон. Инициирующий соединение узел отправляет пакет с магический числом, флагом шифрования и сериализованными данными в формат 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: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: зарезервировано

Ответ на рукопожатие

На запрос рукопожатия с корректным магическим числом целевой узел должен ответить пакетом либо с согласием, либо с ошибкой. Если это ответ с согласием, то данные в пакете должны быть зашифрованы с помощью переданного в запросе хэндшейка симметричного шифра и переданного приватного ключа. Если это ответ с ошибкой, то он может быть незашифрован, в случае, если ошибка связанна с инициализацией шифрования или версией протокола. Таким образом, запрашивающий узел должен быть готов обработать оба варианта развития событий, исходя из значения флага шифрования. Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными параметрами.

Пакет ответа имеет следующую структуру:

[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, описывающая ошибку в человекочитаемом виде.