stadium-proto/OVERVIEW.md

15 KiB
Raw Blame History

Спецификация протокола Stadium v1.0

Протокол Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх любого поддерживаемого транспорта. Данная спецификация описывает лишь базу, поверх которой может быть реализованы расширения (SPX - Stadium Protocol eXtension) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon, спецификация расширения которого находится в папке SPX/Marafon/.

Основной фокус при работе над сим проектом идёт на:

  • Снижение оверхэдов, по сравнению с классическими решениями (Matrix, Discord, WhatsApp, пр. (Reject HTML+JSON, return to binary.)).
  • Устойчивость к цензуре.
  • Федеративность.
  • Поддержка гибкого сквозного шифрования. (возможность как клиенту так и серверу выбирать, какие криптографические алгоритмы использовать)
  • Совместимость со всеми мажорными оверлейными сетями (Tor, I2P и yggdrasil).
  • Расширяемость.

В сей спецификации вы иногда сможете встретить примеры кода и упоминание типов данных языка C++, так как без них обойтись моментами сложно.

Поведение сервера и клиента

Сервер обязан:

  1. Оповещать клиент о всех ошибках, возникших во время его запроса, кроме связанных с безопасностью.
  2. Оповещать сервер в федерации о всех ошибках, возникших во время его запроса, кроме:
    • Связанных с безопасностью
    • Связанных с внутренними неполадками
  3. По умолчанию отклонять все события аутентифицированного клиента, содержащие ложную подпись.
  4. По умолчанию отклонять все события сервера, содержащие ложную подпись.
  5. Отдавать предпочтение данным других серверов, нежели клиентов.
  6. Отдавать предпочтение сетевым настройкам входящих соединений, нежели локальным (не считая лимиты).

Клиент обязан:

  1. Не сообщать серверу ни о каких ошибках на своей (клиентской) стороне.
  2. По умолчанию блокировать до решения юзера все события, содержащие ложную подпись.
  3. Явно уведомлять юзера при возникновении проблем с безопасностью, как минимум по умолчанию.

События, пакеты и их структура

Существует три уровня категорий событий:

  1. Надкатегория: Client2Server, Server2Client, Server2Server.
  2. Категория: например "Authentication", "User", "Message", т.д.
  3. Подкатегория: например "Login", "Create", "Delete", т.д.

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

Все категории вместе являются типом события. Значение типа - это шестнадцатеричное число, которое указывается в начале пакета.

Пакеты с событиями всех категорий, кроме явно оговорённых или принадлежащих к надкатегории Server2Client, содержат идентификатор серверной сессии, являющийся четырёхбайтным числом без знака (uint32_t).

Пакеты с событиями всех категорий, кроме явно оговорённых, содержат хэш полезной нагрузки, зашифрованный с помощью закрытого ключа подписи отправляющего. Этот подписанный хэш гарантирует достоверность полезной нагрузки на уровне прямого подключения ("клиент-сервер" или "сервер-сервер").

Данные (AKA "полезная нагрузка") могут быть представлены в формате фиксированной схемы или в формате KLDR ("Key-Length-Data-Repeat"), которые являются расположенными последовательно парами "ключ-значение" и могут быть расположены в произвольном порядке относительно друг-друга. Сервер и клиент могут перемешивать ячейки перед отправкой намеренно. Применяемый формат зависит от типа события, но чаще всего это KLDR. Все неизвестные ключи при его парсинге игнорируются. Одна пара (AKA "ячейка") имеет следующий вид:

[key][data length][data]

Следовательно, полезная нагрузка в данном формате имеет вид:

[cell_1][cell_2][cell_3]...[cell_n]

Ключ и длинна данных являются шестнадцатеричными числами, размерность которых задаётся на этапе хэндшейка. Полезная нагрузка не может отсутствовать полностью (кроме особо-оговорённых случаев), а ключ не может являться нулём. Если значение конкретной пары пусто, то длинна данных должна быть нулём.

Исходя из всего вышеописанного, итоговая примерная структура пакета выглядит следующим образом:

[category][subcategory][server session: 4B][payload hash: ~B][payload: >0B]

Размер пакета не нормирован и ответственность за его менеджмент остаётся на транспортном уровне. (Эталонная реализация Stadium будет использовать общий универсальный интерфейс, который, в свою очередь, заворачивать все данные в релевантный протокол транспортного уровня)

Зарезервированные события

Некоторые категории событий зарезервированы под нужды базового протокола или просто для событий определённого рода. Второе носит рекомендательный характер; вы также можете использовать иные диапазоны для тех-же целей.

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

Зарезервировано для нужд протокола и запрещено к использованию в частных реализациях (см. также файлы в директории reserved/ для конкретных примеров):

  • Категория 0x01
    • Все субкатегории: выделены для событий общей направленности.
  • Категория 0x11
    • Все субкатегории: выделены для событий ошибок и предупреждений протокольного уровня.

Рекомендуется к использованию в конкретных ситуациях:

  • Категории 0x12-0x1F (включительно)
    • Все субкатегории: для событий ошибок и предупреждений.

Зарезервированные ключи ячеек

У данных в формате KLDR также существуют зарезервированные ключи, которые аналогичным образом помещаются в минимальную размерность ключа:

  • 0x00
    • Запрещено к использованию.
  • 0x01-0x10 (включительно)
    • Базовые примитивы.
  • 0x11-0x1F (включительно)
    • Для нужд криптографии.

Подробное описание зарезервированных ключей есть в файле KLDR RESERVED KEYS.md.

Соединение, аутентификация и сессии

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

Рукопожатие

См. файл HANDSHAKE.md.

Аутентификация

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

Сессии и подписи

См. SESSIONS.md.

Система идентификаторов

Практически каждый объект в Stadium имеет свой уникальный идентификатор, по которому к нему (объекту) следует обращаться. Идентификаторы делятся на два типа: локальные и глобальные.

Первый тип является восьмибайтным числом без знака (uint64_t). Валидный объект не может иметь ID равный нулю.

Второй тип является структурой из одного восьмибайтного числа без знака для ID объекта, массива размером 64 байт для дескриптора сервера и однобайтового числа (uint8_t) для использованного алгоритма хэширования дескриптора.

Сервер должен проверять идентификатор на валидность и отвергать его, если он ложен в текущем контексте.

Серверный дескриптор

Серверный дескриптор являет из себя хэш открытого ключа серверной подписи и может быть представлен в виде base64-кодированной строки, если необходимо. Длинна хэша может варьироваться от 128 до 512 бит. Используемый алгоритм хэширования определяется сервером-владельцем дескриптора.

Дескриптор может быть ассоциирован с несколькими доменами и/или IP/I2P/Tor-адресами, как на стороне сервера, так и на стороне клиента. Клиент может запросить у сервера список ассоциированных с дескриптором адресов, подписанных закрытым ключом сервера-владельца дескриптора и проверить их на достоверность с помощью его-же публичного ключа.

Сервер может отправить подписанное событие другому серверу, с целью добавить новый домен(-ы)/адрес(-а) в список ассоциированных с его дескриптором или удалить оттуда. Сервер-получатель события обязан не только проверить подпись, но и проверить все домены и адреса на соответствие серверу-отправителю, путём отправки события с запросом подписи сервера. Это событие должно по умолчанию иметь жёсткий рейт-лимит по критерию каждого отдельного ресурса, т.е. не более 10 проверок одного доменного имени или адреса в час.

Список ToDo (To Document)

  • Механизм пользовательских сессий, клиентские подписи и базовая аутентификация
  • Механизм синхронизации ключей для сквозного шифрования между юзерами
  • Манипуляции с файлами (скачивание/загрузка)
  • Стриминг аудио и видео