166 lines
16 KiB
Markdown
166 lines
16 KiB
Markdown
# Спецификация протокола Stadium v1.0
|
||
|
||
Протокол Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх любого поддерживаемого транспорта. Данная спецификация описывает лишь базу, поверх которой может быть реализованы расширения (SPX - Stadium Protocol eXtension) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon, спецификация расширения которого находится в папке `Marafon SPX`.
|
||
|
||
_Здесь описана спецификация базового протокола; документация касательно версии протокола используемой в мессенджере размещена в другом репозитории._
|
||
|
||
Основной фокус при работе над сим проектом идёт на:
|
||
|
||
- Снижение оверхэдов, по сравнению с классическими решениями (Matrix, Discord, WhatsApp, пр. (Reject HTML+JSON, return to binary.)).
|
||
- Устойчивость к цензуре.
|
||
- Федеративность.
|
||
- Поддержка сквозного шифрования.
|
||
- Совместимость со всеми мажорными оверлейными сетями (Tor, I2P и yggdrasil).
|
||
- Расширяемость.
|
||
|
||
В сей спецификации вы иногда сможете встретить примеры кода и упоминание типов данных языка C++, так как без них обойтись моментами сложно.
|
||
|
||
<!-- TODO: какое шифрование, какие алгоритмы, etc. -->
|
||
|
||
|
||
|
||
## Поведение сервера и клиента
|
||
|
||
Сервер **обязан**:
|
||
|
||
1. Оповещать клиент о всех ошибках, возникших во время его запроса, кроме связанных с безопасностью.
|
||
2. Оповещать сервер в федерации о всех ошибках, возникших во время его запроса, кроме:
|
||
- Связанных с безопасностью
|
||
- Связанных с внутренними неполадками
|
||
3. По умолчанию отклонять все события, содержащие ложную подпись.
|
||
4. Отдавать предпочтение данным других серверов, нежели клиентов.
|
||
5. Отдавать предпочтение сетевым настройкам входящих соединений, нежели локальным (не считая лимиты).
|
||
|
||
Клиент **обязан**:
|
||
|
||
1. Не сообщать серверу ни о каких ошибках на своей (клиентской) стороне.
|
||
2. По умолчанию блокировать до решения юзера все события, содержащие ложную подпись.
|
||
2. Явно уведомлять юзера при возникновении проблем с безопасностью, как минимум по умолчанию.
|
||
|
||
|
||
|
||
## События, пакеты и их структура
|
||
|
||
Существует три уровня категорий событий:
|
||
|
||
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`.
|
||
|
||
### Аутентификация
|
||
|
||
Описываемый протокол предполагает наличие базовых механизмов аутентификации. Все они сводятся к проверке как цели, так и запрашивающего на предмет релевантного доступа.
|
||
|
||
<!-- TODO -->
|
||
|
||
### Сессии и подпись
|
||
|
||
Пример работы подписи; при отправке сообщения клиентом другому клиенту, оно проходит следующую цепочку:
|
||
|
||
1. Клиент-отправитель посылает пакет с подписанной полезной нагрузкой (далее - ППН) и подписанными основными данными (как часть содержания ППН), на свой хоумсервер (далее - ХС; место, где клиент аутентифицирован).
|
||
2. ХС проверяет подпись ППН на валидность. Допустим, что подпись верна.
|
||
3. ХС совершает релевантные действия, исходя из содержания и типа события.
|
||
4. ХС переподписывает пакет с использованием свой подписи.
|
||
5. ХС отправляет переподписанный пакет целевому серверу (далее - ЦС).
|
||
6. ЦС проверяет подпись ППН на валидность. Допустим, что подпись верна.
|
||
7. ЦС совершает релевантные действия, исходя из содержания и типа пакета.
|
||
8. ЦС переподписывает пакет с использованием своей подписи.
|
||
9. ЦС отправляет переподписанный пакет целевому клиенту (далее - ЦК).
|
||
10. ЦК проверяет подпись ППН на валидность. Допустим, что подпись верна.
|
||
11. ЦК проверяет подпись основных данных, на предмет соответствия подписи клиента-отправителя и совершает релевантные действия.
|
||
|
||
Каждый принятый сервером пакет, содержащий хэш полезной нагрузки, должен проверяться на соответствие подписи, путём расшифровки этого хэша открытом ключом подписи и последующего сравнения с реальным хэшем полезной нагрузки. Если сервер обнаруживает, что подпись неверна - сервер отвечает ошибкой, добавляет запись в журнал об инциденте, а обрабатываемый пакет игнорируется.
|
||
|
||
Каждый принятый клиентом пакет, содержащий хэш полезной нагрузки, должен быть проверен на соответствие подписи. Если клиент обнаруживает, что подпись неверна - он уведомляет об этом пользователя, а обрабатываемый пакет игнорируется.
|
||
|
||
<!-- TODO: решить: как и нужно-ли, чтобы сервер являлся средой нулевого доверия в плане передачи подписей пользователей (скорее всего "Да.") -->
|
||
|
||
Если при проверке ID серверной сессии обнаруживается несоответствие - сервер отвечает ошибкой, соединение разрывается.
|
||
|
||
|
||
|
||
## Система идентификаторов
|
||
|
||
Практически каждый объект в Stadium имеет свой уникальный идентификатор, по которому к нему (объекту) следует обращаться. Идентификаторы делятся на два типа: локальные и федеративные.
|
||
|
||
Первый тип является восьмибайтным числом без знака (`uint64_t`). Валидный объект не может иметь ID равный нулю.
|
||
|
||
Второй тип является структурой из двух восьмибайтных чисел без знака, кои являют из себя ID объекта и ID федерируемого сервера соответственно.
|
||
|
||
ID федерируемого сервера определяется сервером при первой попытке коммуникации и ассоциировано с его подписью, списком доменов и IP-адресов.
|
||
|
||
Сервер должен проверять идентификатор на валидность и отвергать его, если он не валиден в текущем контексте.
|
||
|
||
|
||
|
||
## Список ToDo (To Document)
|
||
|
||
- Механизм пользовательских сессий, клиентские подписи и базовая аутентификация
|
||
- Механизм синхронизации ключей для сквозного шифрования между юзерами
|
||
- Манипуляции с файлами (скачивание/загрузка)
|
||
- Стриминг аудио и видео |