# Спецификация протокола Stadium v1.0 Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх любого поддерживаемого транспорта. Данная спецификация описывает лишь базу, поверх которой могут быть реализованы расширения (SPX - Stadium Protocol eXtension) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon, спецификация расширения которого находится в папке `SPX/Marafon/`. Основной фокус при работе над сим проектом идёт на: - Снижение оверхэдов, по сравнению с классическими решениями (Matrix, Discord, WhatsApp, пр.); - Устойчивость к цензуре; - Федеративность; - Поддержка гибкого сквозного шифрования, т.е. возможность как клиенту так и серверу выбирать, какие криптографические алгоритмы использовать; - Совместимость со всеми мажорными оверлейными сетями (Tor, I2P и yggdrasil); - Расширяемость. В сей спецификации вы можете встретить примеры кода и упоминание типов данных языка C++. ## Поведение сервера и клиента Сервер **обязан**: 1. Оповещать клиент о всех ошибках, возникших во время его запроса, кроме связанных с безопасностью. 2. Оповещать сервер в федерации о всех ошибках, возникших во время его запроса, кроме: - Связанных с безопасностью - Связанных с внутренними неполадками 3. По умолчанию отклонять все события аутентифицированного клиента, содержащие ложную подпись. 4. По умолчанию отклонять все события сервера, содержащие ложную подпись. 5. Отдавать предпочтение данным других серверов, нежели клиентов. 6. Отдавать предпочтение сетевым настройкам входящих соединений, нежели локальным (не считая лимиты). Клиент **обязан**: 1. Не сообщать серверу ни о каких ошибках на своей (клиентской) стороне. 2. По умолчанию блокировать до решения юзера все события, содержащие ложную подпись. 2. Явно уведомлять юзера при возникновении проблем с безопасностью, как минимум по умолчанию. ## События, пакеты и их структура Существует три уровня категорий событий: 1. **Надкатегория:** Client2Server, Server2Client, Server2Server. 2. **Категория:** например "Authentication", "User", "Message", т.д. 3. **Подкатегория:** например "Login", "Create", "Delete", т.д. Надкатегория никак не указывается в пакете, зависит от контекста и при упоминании - чаще всего опускается. Она также определяет структуру некоторых событий, которая может меняться в конкретных случаях. Остальные две являются шестнадцатеричными числами размерности указанной при хэндшейке. Все категории вместе являются типом события. Значение типа - это шестнадцатеричное число, которое указывается в начале пакета. Пакеты с событиями всех категорий содержат хэш полезной нагрузки размером равно или более 16 байт, зашифрованный с помощью закрытого ключа подписи отправляющего. Этот подписанный хэш гарантирует достоверность полезной нагрузки на уровне прямого подключения ("клиент-сервер" или "сервер-сервер"). Идентификатор серверной сессии является четырёхбайтным числом без знака (`uint32_t`). Подробнее про сессии - в `SESSIONS.md`. Идентификатор события является двухбайтным числом без знака (`uint16_t`) и служит для определения отношения запросов к ответам во время асинхронного обмена пакетами. Данные (AKA "полезная нагрузка") представлены в формате KLDR ("Key-Length-Data-Repeat"), которые являются расположенными последовательно парами "ключ-значение" в неопределённом порядке относительно друг-друга. Сервер и клиент могут перемешивать ячейки перед отправкой намеренно. Конкретные используемые ключи зависит от типа события. Все неизвестные ключи при его парсинге игнорируются. Одна пара (AKA "ячейка") имеет следующий вид: `[key][data length][data]` Следовательно, полезная нагрузка в данном формате имеет вид: `[cell_1][cell_2][cell_3]...[cell_n]` Ключ и длинна данных являются шестнадцатеричными числами, размерность которых фиксирована и составляет 8 и 16 бит соответственно. Ключ не может являться нулём. Если значение конкретной пары пусто, то длинна данных должна быть нулём. Если полезная нагрузка отсутствует целиком, то она заменяется на один нулевой байт. Исходя из всего вышеописанного, минимальный размер пакета составляет 21 байт, а его итоговая структура выглядит следующим образом: `[category: 1B][subcategory: 1B][session id: 4B][event id: 2B][payload hash: >16B][payload: >0B]` Максимальный размер пакета не нормирован и ответственность за его менеджмент остаётся на транспортном уровне. Максимальный размер полезной нагрузки определяется сервером, к которому происходит подключение, на этапе рукопожатия. P.S.: _эталонная реализация 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 байт для дескриптора сервера и двухбайтного числа (`CryptoAlgo`) для использованного алгоритма хэширования дескриптора. Сервер должен проверять идентификатор на валидность и отвергать его, если он ложен в текущем контексте. ## Серверный дескриптор Серверный дескриптор являет из себя хэш открытого ключа серверной подписи и может быть представлен в виде base64-кодированной строки, если необходимо. Длинна хэша может варьироваться, но всегда менее или равно 512 бит. Используемый алгоритм хэширования определяется сервером-владельцем дескриптора. Дескриптор может быть ассоциирован с несколькими доменами и/или IP/I2P/Tor-адресами, как на стороне сервера, так и на стороне клиента. Клиент может запросить у сервера список ассоциированных с дескриптором адресов, подписанных закрытым ключом сервера-владельца дескриптора и проверить их на достоверность с помощью его-же публичного ключа. Сервер может отправить подписанное событие другому серверу, с целью добавить новый домен(-ы)/адрес(-а) в список ассоциированных с его дескриптором или удалить оттуда. Сервер-получатель события обязан не только проверить подпись, но и проверить все домены и адреса на соответствие серверу-отправителю, путём отправки события с запросом подписи сервера. Это событие должно по умолчанию иметь жёсткий рейт-лимит по критерию каждого отдельного ресурса, т.е. не более 10 проверок одного доменного имени или адреса в час. ## Список ToDo (To Document) - Механизм пользовательских сессий, клиентские подписи и базовая аутентификация - Механизм синхронизации ключей для сквозного шифрования между юзерами - Манипуляции с файлами (скачивание/загрузка) - Стриминг аудио и видео