Давай по новой (c)
This commit is contained in:
parent
75630f92cf
commit
acae23fe35
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Data types/DATA TYPES.md
|
||||||
|
SPX/
|
||||||
|
_something.md
|
||||||
|
Sessions.md
|
||||||
|
LBM.md
|
||||||
|
Reserved LBM keys.md
|
||||||
|
Reserved events/
|
24
Common behavior.md
Normal file
24
Common behavior.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Общие принципы поведения узлов
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Обязанности узла
|
||||||
|
|
||||||
|
1. Оповещать об ошибке, возникшей во время обработки _события_ другого _узла_, но только если ошибка связана с его некорректной формой.
|
||||||
|
2. По умолчанию отклонять все _события_ с ложной подписью в _подписанном соединении_.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Обязанности сервера
|
||||||
|
|
||||||
|
1. Оповещать _узел_ (будь то _клиент_ или _сервер_ в федерации) о всех ошибках, возникших во время обработки его _события_, кроме связанных с безопасностью. <!--TODO: сформулировать точнее-->
|
||||||
|
2. Отдавать предпочтение данным других _серверов_ в федерации, нежели _клиентов_.
|
||||||
|
3. Отдавать предпочтение сетевым настройкам входящих соединений, нежели локальным (не считая лимиты).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Обязанности клиента
|
||||||
|
|
||||||
|
1. Не сообщать _серверу_ ни о каких ошибках на своей стороне.
|
||||||
|
2. По умолчанию блокировать до решения юзера обработку любых _событий_, содержащих ложную подпись. <!--TODO: это скорее про фронтенд-->
|
||||||
|
3. Явно уведомлять юзера при возникновении проблем с безопасностью, как минимум по умолчанию.
|
122
DATA TYPES.md
122
DATA TYPES.md
@ -1,122 +0,0 @@
|
|||||||
# Типы данных
|
|
||||||
|
|
||||||
Сия спецификация, помимо всего прочего, также определяет некоторые необходимые типы и структуры данных. В данном файле вы найдёте их описание и декларации.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### CryptoAlgoType
|
|
||||||
|
|
||||||
Перечисление всех допустимых к использованию в базовом протоколе алгоритмов вычисления хэшей, контрольных сумм, симметричного и ассиметричного шифрования.
|
|
||||||
|
|
||||||
```C++
|
|
||||||
enum CryptoAlgoType: uint8_t {
|
|
||||||
Reserved = 0,
|
|
||||||
// Checksums
|
|
||||||
CRC_16 = 11,
|
|
||||||
CRC_32,
|
|
||||||
CRC_64,
|
|
||||||
fletcher_8,
|
|
||||||
fletcher_16,
|
|
||||||
fletcher_32,
|
|
||||||
Adler_32,
|
|
||||||
// Non-crypto hashes
|
|
||||||
Murmur64A = 31,
|
|
||||||
Murmur3_32,
|
|
||||||
Murmur3_128,
|
|
||||||
Spooky_128,
|
|
||||||
// Cryptographic hashes
|
|
||||||
BLAKE2b = 61,
|
|
||||||
BLAKE3,
|
|
||||||
GOST,
|
|
||||||
HAS160,
|
|
||||||
HAVAL,
|
|
||||||
MD2,
|
|
||||||
MD5,
|
|
||||||
RIPEMD,
|
|
||||||
SHA1,
|
|
||||||
SHA2,
|
|
||||||
SHAKE128,
|
|
||||||
SHAKE256,
|
|
||||||
Skein,
|
|
||||||
Snefru,
|
|
||||||
Streebog,
|
|
||||||
Tiger,
|
|
||||||
Whirlpool,
|
|
||||||
// Symmetric key block ciphers
|
|
||||||
Blowfish = 131,
|
|
||||||
Twofish,
|
|
||||||
TripleDES_CBC,
|
|
||||||
AES_GCM, // AKA Rijndael
|
|
||||||
AES_CBC,
|
|
||||||
AES_CTR,
|
|
||||||
Camellia,
|
|
||||||
Salsa20,
|
|
||||||
CAST5,
|
|
||||||
CAST6,
|
|
||||||
Kuznyechik,
|
|
||||||
MESH,
|
|
||||||
Akelarre,
|
|
||||||
RC6,
|
|
||||||
// TODO
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- TODO: RSA, YAK, Cramer–Shoup system, Paillier cryptosystem, curves (25519 & 448), ElGamal, etc. -->
|
|
||||||
|
|
||||||
#### CryptoAlgo
|
|
||||||
|
|
||||||
Структура, определяющая криптографический алгоритм и размерность. Для шифров это размер ключа, а для хэшей - размер выходных данных (если применимо). Для хэш-функций и симметричных шифров размер ключа вычисляется по формуле `Size << 4`, а для ассиметричных по формуле `Size << 8`. Размерность опускается для контрольных сумм и не-криптографических функций.
|
|
||||||
|
|
||||||
```C++
|
|
||||||
struct CryptoAlgo {
|
|
||||||
CryptoAlgoType Type;
|
|
||||||
uint8_t Size;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### ServerDescriptor
|
|
||||||
|
|
||||||
Дескриптор сервера, представляющий из себя хэш открытого ключа серверной подписи и использующийся алгоритм. Длинна хэша может варьироваться, но всегда не более 512 бит.
|
|
||||||
|
|
||||||
```C++
|
|
||||||
struct ServerDescriptor {
|
|
||||||
char[64] Hash;
|
|
||||||
CryptoAlgo Type;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### LocID
|
|
||||||
|
|
||||||
Идентификатор локального для конкретного сервера объекта.
|
|
||||||
|
|
||||||
```C++
|
|
||||||
typedef uint64_t LocID;
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### GlobID
|
|
||||||
|
|
||||||
Идентификатор глобального объекта.
|
|
||||||
|
|
||||||
```C++
|
|
||||||
struct GlobID {
|
|
||||||
uint64_t Object;
|
|
||||||
ServerDescriptor Server;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Power
|
|
||||||
|
|
||||||
Права доступа к какому-либо объекту. Представляет из себя набор следующих флагов:
|
|
||||||
|
|
||||||
- `0b00000000000000000000000000000001`: чтение
|
|
||||||
- `0b00000000000000000000000000000010`: запись
|
|
||||||
- `0b00000000000000000000000000000100`: удаление
|
|
||||||
- `0b10000000000000000000000000000000`: изменение прав доступа
|
|
||||||
- `0b01111111111111111111111111111000`: нераспределено
|
|
||||||
|
|
||||||
Нераспределённые флаги могут быть использованы в расширениях протокола.
|
|
||||||
|
|
||||||
```C++
|
|
||||||
typedef uint32_t Power;
|
|
||||||
```
|
|
39
Events.md
Normal file
39
Events.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# События
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Категории и типы
|
||||||
|
|
||||||
|
Существует три уровня категорий _событий_:
|
||||||
|
|
||||||
|
**Надкатегория** описывает типы взаимодействующих _узлов_. Не указывается и зависит от контекста. Варианты: _Client2Server_ (_событие_ сгенерированное _клиентом_ для _сервера_), _Server2Client_ (_событие_ сгенерированное _сервером_ для _клиента_), _Peer2Peer_ (_событие_ сгенерированное _узлом_ для другого _узла_ того-же ранга, в том числе это касается _серверов_ в федерации).
|
||||||
|
|
||||||
|
**Категория** описывает _события_ одного класса. Является однобайтовым числом без знака. Всегда больше нуля. Например: _Authentication_, _Object_, т.п.
|
||||||
|
|
||||||
|
**Подкатегория** описывает конкретное _событие_ из класса, соответствующего категории. Является однобайтовым числом без знака. Всегда больше нуля. Например: _Login_, _GetContents_, т.п.
|
||||||
|
|
||||||
|
Все категории вместе - являются типом _события_. Информацию про зарезервированные типы вы можете найти в [Reserved events.md](Reserved%20events.md).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Содержание и структура
|
||||||
|
|
||||||
|
_События_ всех типов содержат хэш полезной нагрузки размером равно или более 16 байт, зашифрованный с помощью закрытого ключа подписи отправляющего. Этот подписанный хэш гарантирует достоверность полезной нагрузки на уровне прямого подключения между двумя _узлами_. Используемый алгоритм хэширования определяется на этапе рукопожатия.
|
||||||
|
|
||||||
|
Идентификатор серверной сессии является четырёхбайтным целым числом без знака. Подробнее про сессии - в [Sessions.md](Sessions.md).
|
||||||
|
|
||||||
|
Идентификатор _события_ является двухбайтным целым числом без знака и предназначен для определения отношения запросов к ответам при асинхронном обмене _событиями_.
|
||||||
|
|
||||||
|
Данная версия протокола не накладывает ограничений на формат полезной нагрузки, за исключением базовых событий, которые представлены данными в формате _LBM_. Описание всех предопределённых в базовом протоколе ключей ячеек _LBM_ доступно в [Reserved LBM keys.md](Reserved%20LBM%20keys.md). Неизвестные ключи при обработке полезной нагрузки игнорируются. Если полезная нагрузка отсутствует, то она заменяется на один нулевой байт.
|
||||||
|
|
||||||
|
<!--TODO: разные виды сериализации, в зависимости от транспорта?-->
|
||||||
|
|
||||||
|
Исходя из всего вышеописанного, минимальный размер сериализованного в бинарный вид _события_ составляет 25 байт, а его итоговая структура выглядит следующим образом:
|
||||||
|
|
||||||
|
`[category: 1B][subcategory: 1B][session id: 4B][event async id: 2B][payload hash: >16B][payload: >0B]`
|
||||||
|
|
||||||
|
Максимальный размер _события_ не нормирован и ответственность за его менеджмент остаётся на транспортном уровне. Максимальный размер полезной нагрузки _события_ определяется на этапе рукопожатия.
|
||||||
|
|
||||||
|
### Событие в шифрованном соединении
|
||||||
|
|
||||||
|
В _шифрованном соединении_ _события_ сериализуются в бинарное представление и зашифровываются с помощью утверждённого симметричного ключа сессии.
|
103
HANDSHAKE.md
103
HANDSHAKE.md
@ -1,103 +0,0 @@
|
|||||||
# Handshake
|
|
||||||
|
|
||||||
## Protocol-level handshake
|
|
||||||
|
|
||||||
После успешной установки соединения происходит обмен характеристиками обоих сторон, AKA "рукопожатие протокольного уровня". Запрашивающий соединение отправляет пакет следующего формата:
|
|
||||||
|
|
||||||
<!--`[magic number: 8B][protocol version: 4B][sizes: 1B][crypto params: 6B][reconnection flags: 4B]`-->
|
|
||||||
`[magic number: 8B][protocol version: 4B][crypto params: 8B][reconnection flags: 4B]`
|
|
||||||
|
|
||||||
- Магическое число
|
|
||||||
- _Тип:_ `uint64_t`
|
|
||||||
- Магическое число протокола, по которому определяется совместимость цели с протоколом Stadium. См. раздел "Магическое число" для справки.
|
|
||||||
- Версия протокола
|
|
||||||
- _Тип:_ `uint32_t`
|
|
||||||
- Поддерживаемая запрашивающим версия протокола.
|
|
||||||
<!--- Размерности частей пакета
|
|
||||||
- _Тип:_ `uint8_t`
|
|
||||||
- Описывает некоторые параметры пакетов.
|
|
||||||
- Маска `0b11000000`: выделено под размерности типа событий
|
|
||||||
- `0b00`: резерв
|
|
||||||
- `0b01`: категория и подкатегория это `uint8_t` (каждая)
|
|
||||||
- `0b10`: категория - `uint8_t`, подкатегория - `uint16_t`
|
|
||||||
- `0b11`: категория и подкатегория это `int16_t` (каждая)
|
|
||||||
- Маска `0b00110000`: выделено под размерность ключа в ячейке полезной нагрузки
|
|
||||||
- `0b00`: резерв
|
|
||||||
- `0b01`: ключ это `uint8_t`
|
|
||||||
- `0b10`: ключ это `uint16_t`
|
|
||||||
- `0b11`: ключ это `int32_t`
|
|
||||||
- Маска `0b00001100`: выделено под размерность данных в ячейке
|
|
||||||
- `0b00`: резерв
|
|
||||||
- `0b01`: размер данных это `uint8_t`
|
|
||||||
- `0b10`: размер данных это `uint16_t`
|
|
||||||
- `0b11`: размер данных это `uint64_t`
|
|
||||||
- Маска `0b00000011`: резерв-->
|
|
||||||
- Параметры криптографии
|
|
||||||
- _Тип:_ `CryptoAlgo[4]`
|
|
||||||
- Описывает используемые криптографические алгоритмы на уровне прямого подключения (т.е. "сервер-сервер" или "сервер-клиент"). Первый элемент выделен под хэш-функцию; второй для ассиметричной функции подписи; третий для ассиметричной функции шифрования; четвёртый для симметричной функции.
|
|
||||||
- Если равно нулю, то используются опции данной версии протокола по умолчанию (SHA256, RSA-2048, AES-192).
|
|
||||||
- Флаги переподключения
|
|
||||||
- _Тип:_ `uint32_t`
|
|
||||||
- Описывает параметры нового подключения:
|
|
||||||
- `0b00000000000000000000000000000000`: оставить текущее подключение
|
|
||||||
- `0b00000000000000000000000000000001`: переподключиться к тому-же порту
|
|
||||||
- `0b00000000000000000000000000000010`: запросить новый порт для подключения
|
|
||||||
- `0b00000000000000000000000000000100`: использовать TCP
|
|
||||||
- `0b00000000000000000000000000010000`: использовать TLS
|
|
||||||
- `0b00001111111111111111111111101000`: резерв под расширение
|
|
||||||
- `0b11110000000000000000000000000000`: резерв под под нужды сторонних реализаций
|
|
||||||
|
|
||||||
На что целевой сервер отвечает пакетом либо с согласием, либо ошибкой.
|
|
||||||
|
|
||||||
Пакет с согласием имеет следующий формат:
|
|
||||||
|
|
||||||
`[magic number: 8B][0x00][reconnection port: 2B][event payload max size: 2B]`
|
|
||||||
|
|
||||||
- Магическое число
|
|
||||||
- _Тип:_ `uint64_t`
|
|
||||||
- См. выше.
|
|
||||||
- `0x00`
|
|
||||||
- _Тип:_ `uint8_t`
|
|
||||||
- Байт с фиксированным нулевым значением, свидетельствующий об успешном подключении и принятии целевым сервером обозначенных условий.
|
|
||||||
- Порт для переподключения
|
|
||||||
- _Тип:_ `uint16_t`
|
|
||||||
- К указанному порту целевой сервер предлагает подключиться запрашиваемому, если тот запросил его. Значение должно быть нулём, если порт не был запрошен.
|
|
||||||
- Максимальный размер полезной нагрузки
|
|
||||||
- _Тип:_ `uint16_t`
|
|
||||||
- Всегда больше нуля. Запрашивающий должен соблюдать размерность полезной нагрузки в событии и она всегда должна быть равна или меньше этого значения.
|
|
||||||
|
|
||||||
Пакет с ошибкой имеет следующий формат:
|
|
||||||
|
|
||||||
`[magic number: 8B][error code: 1B][error description: ~B, zero-terminated]`
|
|
||||||
|
|
||||||
- Магическое число
|
|
||||||
- _Тип:_ `uint64_t`
|
|
||||||
- См. выше.
|
|
||||||
- Код ошибки
|
|
||||||
- _Тип:_ `uint8_t`
|
|
||||||
- Код, описывающий ошибку конкретнее.
|
|
||||||
- 0x01: магическое число ложно.
|
|
||||||
- 0x02: неподдерживаемая версия протокола.
|
|
||||||
- 0x03: невозможно выделить новый порт для подключения.
|
|
||||||
- 0x04: указанный транспортный протокол не поддерживается.
|
|
||||||
- 0x05: указанная конфигурация размерностей не поддерживается.
|
|
||||||
- 0x06: недопустимые параметры криптографии.
|
|
||||||
- 0x07: один из указанных криптографических алгоритмов отключён на сервере.
|
|
||||||
- Описание ошибки
|
|
||||||
- _Тип:_ `uint8_t`
|
|
||||||
- Текстовое описание ошибки. Является строкой в кодировке ASCII, оканчивающейся нулевым байтом.
|
|
||||||
|
|
||||||
Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными значениями.
|
|
||||||
|
|
||||||
Если при хэндшейке запрашивающим был указан новый способ подключения и получен валидный ответ с согласием от сервера - то они обязаны разорвать текущее соединение, затем, спустя случайное количество времени, от 10 мс до 500 мс, создать новое.
|
|
||||||
|
|
||||||
## Магическое число
|
|
||||||
|
|
||||||
Магическим числом протокола является следующая последовательность байт:
|
|
||||||
|
|
||||||
```
|
|
||||||
HEX: 0x53 0x74 0x61 0x64 0x69 0x75 0x6d 0x50
|
|
||||||
DEC: 83 116 97 100 105 117 109 80
|
|
||||||
```
|
|
||||||
|
|
||||||
Что соответствует строке "StadiumP" в кодировке ASCII.
|
|
125
Handshakes.md
Normal file
125
Handshakes.md
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# Рукопожатие
|
||||||
|
|
||||||
|
<!--TODO: переделать-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Протокольного уровня
|
||||||
|
|
||||||
|
После успешного подключения к целевому _узлу_ через избранный транспорт - происходит обмен параметрами обоих сторон, AKA "рукопожатие протокольного уровня". Инициирующий соединение _узел_ отправляет пакет следующего формата:
|
||||||
|
|
||||||
|
`[magic number: 8B][protocol version: 4B][crypto params: 8B][noise params: 1B][reconnection flags: 4B]`
|
||||||
|
|
||||||
|
|
||||||
|
- Магическое число
|
||||||
|
- _Тип:_ `uint64_t`
|
||||||
|
- Магическое число протокола, по которому определяется совместимость цели с протоколом Stadium. См. раздел "Магическое число" для справки.
|
||||||
|
|
||||||
|
- Версия протокола
|
||||||
|
- _Тип:_ `uint32_t`
|
||||||
|
- Поддерживаемая запрашивающим версия протокола.
|
||||||
|
|
||||||
|
- Параметры криптографии
|
||||||
|
- _Тип:_ `CryptoAlgo[4]`
|
||||||
|
- Описывает используемые криптографические алгоритмы на уровне прямого подключения (т.е. "узел-узел"). Первый элемент выделен под хэш-функцию; второй для ассиметричной функции подписи; третий для ассиметричной функции шифрования; четвёртый для симметричной функции.
|
||||||
|
- Если равно нулю, то используются опции данной версии протокола по умолчанию (SHA-384, RSA-3072, AES-256).
|
||||||
|
|
||||||
|
- Параметры генерации шума в соединении
|
||||||
|
- _Тип:_ `uint8_t`
|
||||||
|
- Описывает прочие параметры соединения:
|
||||||
|
- `0b11100000`: выделено под настройки количества _шумовых пакетов_
|
||||||
|
- `0b000`: отсутствие _шумовых пакетов_
|
||||||
|
- `0b001`: количество задаётся по усмотрению целевого _узла_ <!--TODO: звучит странно-->
|
||||||
|
- `0b010`: соотношение _шумовых пакетов_ к реальным - 1:8
|
||||||
|
- `0b011`: соотношение - 1:4
|
||||||
|
- `0b100`: 1:2
|
||||||
|
- `0b101`: 1:1
|
||||||
|
- `0b110`: 2:1
|
||||||
|
- `0b111`: 4:1
|
||||||
|
- `0b00011000`: выделено под настройки размера _шумовых пакетов_
|
||||||
|
- `0b00`: по усмотрению целевого _узла_ <!--TODO: звучит странно-->
|
||||||
|
- `0b01`: случайный размер, в пределах от минимального _пакета_ с нулевой полезной нагрузкой, до размера _пакета_ с полезной нагрузкой размерности, которую должен передать целевой _узел_ при одобрении рукопожатия
|
||||||
|
- `0b10`: случайный размер, в пределах от минимального, до максимального / 2
|
||||||
|
- `0b11`: случайный размер, на основе среднего размера передаваемого пакета +- 25% (но всегда меньше максимального)
|
||||||
|
- `0b00000111`: выделено под настройки размера _шумовых данных_ в обычных _пакетах_
|
||||||
|
- `0b000`: без шумовых данных
|
||||||
|
- `0b001`: заполнение шумовыми данными до лимита полезной нагрузки
|
||||||
|
- `0b010`: заполнение шумовыми данными в случайном количестве, от нуля, до лимита полезной нагрузки
|
||||||
|
- Диапазон `0b011`-`0b111`: зарезервировано <!--TODO: ещё варианты сделать-->
|
||||||
|
|
||||||
|
- Флаги переподключения <!--TODO: сделать енам с перечислением доступных транспортов и их параметров-->
|
||||||
|
- _Тип:_ `uint32_t`
|
||||||
|
- Описывает параметры нового подключения:
|
||||||
|
- `0b00000000000000000000000000000000`: оставить текущее подключение
|
||||||
|
- `0b00000000000000000000000000000001`: запросить новый транспорт для подключения
|
||||||
|
- `0b00000000000000000000000000000100`: использовать TCP
|
||||||
|
- `0b00000000000000000000000000010000`: использовать TLS
|
||||||
|
- `0b00001111111111111111111111101010`: резерв под расширение
|
||||||
|
- `0b11110000000000000000000000000000`: резерв под под нужды сторонних реализаций
|
||||||
|
|
||||||
|
|
||||||
|
На это целевой _узел_ отвечает пакетом либо с согласием, либо с ошибкой.
|
||||||
|
|
||||||
|
Пакет с согласием имеет следующий формат:
|
||||||
|
|
||||||
|
`[magic number: 8B][0x00][reconnection port: 2B][event payload max size: 2B]`
|
||||||
|
|
||||||
|
|
||||||
|
- Магическое число
|
||||||
|
- _Тип:_ `uint64_t`
|
||||||
|
- См. выше.
|
||||||
|
|
||||||
|
- `0x00`
|
||||||
|
- _Тип:_ `uint8_t`
|
||||||
|
- Байт с фиксированным нулевым значением, свидетельствующий об успешном подключении и принятии целевым _узлом_ обозначенных условий.
|
||||||
|
|
||||||
|
- Порт для переподключения
|
||||||
|
- _Тип:_ `uint16_t`
|
||||||
|
- К указанному порту целевой _узел_ предлагает подключиться запрашиваемому, если тот запросил его. Значение должно быть нулём, если порт не был запрошен.
|
||||||
|
|
||||||
|
- Максимальный размер полезной нагрузки
|
||||||
|
- _Тип:_ `uint16_t`
|
||||||
|
- Всегда больше нуля. Запрашивающий должен соблюдать размерность полезной нагрузки в событии и она всегда должна быть равна или меньше этого значения.
|
||||||
|
|
||||||
|
|
||||||
|
Пакет с ошибкой имеет следующий формат:
|
||||||
|
|
||||||
|
`[magic number: 8B][error code: 1B][error description: ~B, zero-terminated]`
|
||||||
|
|
||||||
|
|
||||||
|
- Магическое число
|
||||||
|
- _Тип:_ `uint64_t`
|
||||||
|
- См. выше.
|
||||||
|
|
||||||
|
- Код ошибки
|
||||||
|
- _Тип:_ `uint8_t`
|
||||||
|
- Код, описывающий ошибку конкретнее.
|
||||||
|
- `0x01`: магическое число ложно.
|
||||||
|
- `0x02`: неподдерживаемая версия протокола.
|
||||||
|
- `0x03`: невозможно выделить новый порт для подключения.
|
||||||
|
- `0x04`: указанный транспортный протокол не поддерживается.
|
||||||
|
- `0x05`: указанная конфигурация размерностей не поддерживается.
|
||||||
|
- `0x06`: недопустимые (несуществующие) параметры криптографии.
|
||||||
|
- `0x07`: один из указанных криптографических алгоритмов отключён на _узле_.
|
||||||
|
|
||||||
|
- Описание ошибки
|
||||||
|
- _Тип:_ `uint8_t`
|
||||||
|
- Текстовое описание ошибки. Является строкой в кодировке ASCII, оканчивающейся нулевым байтом.
|
||||||
|
|
||||||
|
|
||||||
|
Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными значениями.
|
||||||
|
|
||||||
|
Если при хэндшейке запрашивающим был указан новый способ подключения и получен валидный ответ с согласием от целевого _узла_ - то они обязаны разорвать текущее соединение, затем, спустя разумное случайное количество времени, создать новое.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Магическое число
|
||||||
|
|
||||||
|
Магическим числом протокола является следующая последовательность байт:
|
||||||
|
|
||||||
|
```
|
||||||
|
HEX: 0x53 0x74 0x61 0x64 0x69 0x75 0x6d 0x50
|
||||||
|
DEC: 83 116 97 100 105 117 109 80
|
||||||
|
```
|
||||||
|
|
||||||
|
Что соответствует строке "StadiumP" в кодировке ASCII.
|
@ -1,62 +0,0 @@
|
|||||||
# Список зарезервированных ключей ячеек
|
|
||||||
|
|
||||||
<!-- TODO: сделать папку и там разместить подробное описание некоторых ключей -->
|
|
||||||
Перечисленные здесь значения являются либо совсем базовыми, либо предназначены для использования сервером. Все данные транзитных пакетов (т.е. тех, которые предназначены для кого-то кроме сервера подключённого напрямую), для которых критична подлинность, должны передаваться в ячейке `Data` и быть подписанными с помощью ячейки `SignedDataHash`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Базовые примитивы
|
|
||||||
|
|
||||||
- Data
|
|
||||||
- _Значение:_ `0x01`
|
|
||||||
- _Тип:_ не имеет значения
|
|
||||||
- Основные передаваемые данные.
|
|
||||||
- ObjectID
|
|
||||||
- _Значение:_ `0x02`
|
|
||||||
- _Тип:_ `LocID || GlobID`
|
|
||||||
- ID объекта в локальном контексте. Например, ID канала для отправки сообщения.
|
|
||||||
- SrcEventAuthor
|
|
||||||
- _Значение:_ `0x03`
|
|
||||||
- _Тип:_ `GlobID`
|
|
||||||
- Источник (автор) оригинального события.
|
|
||||||
- PrevEvent
|
|
||||||
- _Значение:_ `0x04`
|
|
||||||
- _Тип:_ `LocID`
|
|
||||||
- Предыдущее событие, логически связанное с текущим.
|
|
||||||
- NextEvent
|
|
||||||
- _Значение:_ `0x05`
|
|
||||||
- _Тип:_ `LocID`
|
|
||||||
- Следующее событие, логически связанное с текущим.
|
|
||||||
- BatchNumber
|
|
||||||
- _Значение:_ `0x06`
|
|
||||||
- _Тип:_ `uint32_t`
|
|
||||||
- Последовательный номер события в цепочке.
|
|
||||||
- Path
|
|
||||||
- _Значение:_ `0x07`
|
|
||||||
- _Тип:_ `char[]`
|
|
||||||
- Путь к запрашиваемому/загружаемому ресурсу.
|
|
||||||
- Power
|
|
||||||
- _Значение:_ `0x08`
|
|
||||||
- _Тип:_ `Power`
|
|
||||||
- Права доступа к конкретному объекту.
|
|
||||||
<!--- ServerSession
|
|
||||||
- _Значение:_ `0x09`
|
|
||||||
- _Тип:_ `uint32_t`
|
|
||||||
- Идентификатор серверной сессии. В случае с аутентифицированным соединением, его присутствие обязательно.-->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Криптография
|
|
||||||
|
|
||||||
- CryptoAlgos
|
|
||||||
- _Значение:_ `0x11`
|
|
||||||
- _Тип:_ `CryptoAlgo[4]`
|
|
||||||
- Используемые криптографические алгоритмы. Предназначено для использования конечной целью, а не промежуточным узлом (сервером). Первый элемент выделен под хэш-функцию; второй для ассиметричной функции подписи; третий для ассиметричной функции шифрования; четвёртый для симметричной функции.
|
|
||||||
- CryptoKeyID
|
|
||||||
- _Значение:_ `0x12`
|
|
||||||
- _Тип:_ `uint32_t`
|
|
||||||
- Идентификатор используемого криптографического ключа для шифрования данных.
|
|
||||||
- SignedDataHash
|
|
||||||
- _Значение:_ `0x13`
|
|
||||||
- _Тип:_ не имеет значения
|
|
||||||
- Хэш основных передаваемых данных, зашифрованный закрытым ключом отправителя.
|
|
155
OVERVIEW.md
155
OVERVIEW.md
@ -1,155 +0,0 @@
|
|||||||
# Спецификация протокола 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` (включительно)
|
|
||||||
- Все субкатегории: для событий ошибок и предупреждений.
|
|
||||||
|
|
||||||
<!-- TODO: событие запроса всех сервисов на сервере -->
|
|
||||||
|
|
||||||
### Зарезервированные ключи ячеек
|
|
||||||
|
|
||||||
У данных в формате KLDR также существуют зарезервированные ключи:
|
|
||||||
|
|
||||||
- `0x00`
|
|
||||||
- Запрещено к использованию.
|
|
||||||
- `0x01-0x10` (включительно)
|
|
||||||
- Базовые примитивы.
|
|
||||||
- `0x11-0x1F` (включительно)
|
|
||||||
- Для нужд криптографии.
|
|
||||||
|
|
||||||
Подробное описание зарезервированных ключей есть в файле `KLDR RESERVED KEYS.md`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Соединение, аутентификация и сессии
|
|
||||||
|
|
||||||
Первичное подключение к серверу может выполнятся разными способами, в том числе подразумевающими маскировку траффика под существующие протоколы, но при использовании вне локальных сетей - должно сводиться к установке защищённого соединения. В будущем также будет реализован слой сквозного шифрования уровня "клиент-сервер", но, до этого момента, предполагается использование сторонних решений.
|
|
||||||
|
|
||||||
### Рукопожатие
|
|
||||||
|
|
||||||
См. файл `HANDSHAKE.md`.
|
|
||||||
|
|
||||||
### Аутентификация
|
|
||||||
|
|
||||||
Описываемый протокол предполагает наличие базовых механизмов аутентификации. Все они сводятся к проверке как цели, так и запрашивающего на предмет релевантного доступа.
|
|
||||||
|
|
||||||
<!-- TODO -->
|
|
||||||
|
|
||||||
### Сессии и подписи
|
|
||||||
|
|
||||||
См. `SESSIONS.md`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Система идентификаторов
|
|
||||||
|
|
||||||
Практически каждый объект в Stadium имеет свой уникальный идентификатор, по которому к нему (объекту) следует обращаться. Идентификаторы делятся на два типа: локальные и глобальные.
|
|
||||||
|
|
||||||
Первый тип является восьмибайтным числом без знака (`uint64_t`). Валидный объект не может иметь ID равный нулю.
|
|
||||||
|
|
||||||
Второй тип является структурой из одного восьмибайтного числа без знака для ID объекта, массива размером 64 байт для дескриптора сервера и двухбайтного числа (`CryptoAlgo`) для использованного алгоритма хэширования дескриптора.
|
|
||||||
|
|
||||||
Сервер должен проверять идентификатор на валидность и отвергать его, если он ложен в текущем контексте.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Серверный дескриптор
|
|
||||||
|
|
||||||
Серверный дескриптор являет из себя хэш открытого ключа серверной подписи и может быть представлен в виде base64-кодированной строки, если необходимо. Длинна хэша может варьироваться, но всегда менее или равно 512 бит. Используемый алгоритм хэширования определяется сервером-владельцем дескриптора.
|
|
||||||
|
|
||||||
Дескриптор может быть ассоциирован с несколькими доменами и/или IP/I2P/Tor-адресами, как на стороне сервера, так и на стороне клиента. Клиент может запросить у сервера список ассоциированных с дескриптором адресов, подписанных закрытым ключом сервера-владельца дескриптора и проверить их на достоверность с помощью его-же публичного ключа.
|
|
||||||
|
|
||||||
Сервер может отправить подписанное событие другому серверу, с целью добавить новый домен(-ы)/адрес(-а) в список ассоциированных с его дескриптором или удалить оттуда. Сервер-получатель события обязан не только проверить подпись, но и проверить все домены и адреса на соответствие серверу-отправителю, путём отправки события с запросом подписи сервера. Это событие должно по умолчанию иметь жёсткий рейт-лимит по критерию каждого отдельного ресурса, т.е. не более 10 проверок одного доменного имени или адреса в час.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Список ToDo (To Document)
|
|
||||||
|
|
||||||
- Механизм пользовательских сессий, клиентские подписи и базовая аутентификация
|
|
||||||
- Механизм синхронизации ключей для сквозного шифрования между юзерами
|
|
||||||
- Манипуляции с файлами (скачивание/загрузка)
|
|
||||||
- Стриминг аудио и видео
|
|
123
Overview.md
Normal file
123
Overview.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Обзор
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Терминология
|
||||||
|
|
||||||
|
Здесь перечислены используемые в данной документации термины, значение которых может быть не очевидно и/или не соответствует тому, которое подразумевается обычно.
|
||||||
|
|
||||||
|
### Узел
|
||||||
|
|
||||||
|
Любая машина, способная выполнять коммуникацию по протоколу Stadium. Обычно используется в контексте коммуникации двух машин одного ранга или когда ранг не имеет значения.
|
||||||
|
|
||||||
|
### Сервер
|
||||||
|
|
||||||
|
Выполняющий роль сервера _узел_ в многоранговой сети.
|
||||||
|
|
||||||
|
### Клиент
|
||||||
|
|
||||||
|
Выполняющий роль клиента _узел_ в многоранговой сети.
|
||||||
|
|
||||||
|
### Подписанное соединение/сессия
|
||||||
|
|
||||||
|
Соединение между двумя _узлами_, все _события_ в котором подписаны с помощью оговорённого ассиметричного алгоритма и приватного ключа отправителя.
|
||||||
|
|
||||||
|
### Шифрованное соединение/сессия
|
||||||
|
|
||||||
|
Соединение между двумя _узлами_, все _события_ в котором шифруется с помощью оговорённого симметричного алгоритма и ключа. Требует _подписанное соединение_ для установки.
|
||||||
|
|
||||||
|
### Событие
|
||||||
|
|
||||||
|
Структура данных, обладающая конкретными семантическими свойствами в зависимости от типа и содержащая дополнительные поля, требуемые для верного отображения и интерпретации самой структуры. Проще говоря - то, чем обмениваются и что обрабатывают _узлы_ во время коммуникации между собой.
|
||||||
|
|
||||||
|
### Шумовое событие
|
||||||
|
|
||||||
|
_Событие_ предопределённой категории, имеющее случайно-сгенерированные поля.
|
||||||
|
|
||||||
|
### LBM
|
||||||
|
|
||||||
|
Аббревиатура наименования способа форматирования данных, используемого для полезной нагрузки _события_, которая расшифровывается как "Linear Binary Map". Подробнее - в [LBM.md](LBM.md).
|
||||||
|
|
||||||
|
### Шумовые данные
|
||||||
|
|
||||||
|
Случайно-сгенерированные данные, помещённые в ячейку полезной нагрузки _события_.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Пример коммуникации двух узлов
|
||||||
|
|
||||||
|
Допустим, что у нас есть два неизвестных друг-другу _узла_ - `p1` и `p2`. Тогда полная коммуникация по шагам (от подключения неизвестного для `p2` _узла_ - до "правильного" уничтожения сессии и закрытия соединения) будет выглядеть так: <!--TODO: предстоит переделать, ввиду предстоящих нововведений-->
|
||||||
|
|
||||||
|
1. `p1` подключается с помощью соответствующего транспорта к `p2`
|
||||||
|
2. `p1` запрашивает рукопожатие с какими-то параметрами подключения
|
||||||
|
3. `p2` отвечает принятием со своей частью параметров подключения
|
||||||
|
4. `p1` запрашивает публичный ключ подписи у `p2`\*
|
||||||
|
5. `p2` отвечает своим публичным ключом и данными об использующемся алгоритме
|
||||||
|
6. `p1` сохраняет публичный ключ сервера в своём хранилище
|
||||||
|
7. `p1` отправляет _событие_ с запросом установки публичного ключа сессионной подписи, подписанное с помощью публичного ключа `p2`\*\*
|
||||||
|
8. `p2` принимает запрос и устанавливает полученный ключ в качестве сессионного для подключения `p1`, если подпись валидна
|
||||||
|
9. `p2` отвечает _событием_ с кодом успешности операции. С этого момента установлено _подписанное соединение_, т.е. узлы **обязаны** подписывать каждое _событие_ и отклонять любые неподписанные/с ложной подписью
|
||||||
|
10. `p1` отправляет _событие_ с запросом _шифрованного соединения_, симметричным ключом, зашифрованным с помощью публичного ключа сервера, и используемым алгоритмом шифрования\*\*\*
|
||||||
|
11. `p2` принимает запрос и устанавливает текущий симметричный ключ сессии
|
||||||
|
12. `p2` отвечает _событием_ с кодом успешности операции. С этого момента установлено _шифрованное соединение_, т.е. узлы **должны** шифровать _события_ с использованием обозначенного ключа
|
||||||
|
13. `p1` отправляет зашифрованное _событие_ с запросом какого-то объекта
|
||||||
|
14. `p2` отвечает зашифрованным _событием_, содержащее этот объект
|
||||||
|
15. `p1` отправляет _событие_ с сообщением о намерении уничтожить сессию и ждёт в течении n времени, по истечению которого может разорвать соединение "насильно"
|
||||||
|
16. `p2` принимает запрос и прекращает любой параллельный обмен данными
|
||||||
|
17. `p2` отвечает _событием_ с кодом успешности операции
|
||||||
|
18. `p2` закрывает соединение
|
||||||
|
|
||||||
|
И в виде схемы:
|
||||||
|
|
||||||
|
```
|
||||||
|
Handshake:
|
||||||
|
[p1] --------[transport connect]------> [p2]
|
||||||
|
[p1] --------[handshake request]------> [p2]
|
||||||
|
[p1] <-------[handshake accept]-------- [p2]
|
||||||
|
|
||||||
|
Get p2's public key:
|
||||||
|
[p1] ----[request public sign key]----> [p2]
|
||||||
|
[p1] <-[public key and crypto params]-- [p2]
|
||||||
|
[p1]: saves p2's public key at local storage
|
||||||
|
|
||||||
|
Make signed connection:
|
||||||
|
[p1]: sign event
|
||||||
|
[p1] --------[set session sign]-------> [p2]
|
||||||
|
[p2]: check event signature
|
||||||
|
[p2]: associates p1's public key with this connection
|
||||||
|
[p2]: sign event
|
||||||
|
[p1] <--------[status code OK]--------- [p2]
|
||||||
|
[p1]: check event signature
|
||||||
|
|
||||||
|
Make encrypted connection:
|
||||||
|
[p1]: sign event
|
||||||
|
[p1] ---[set session symmetric key]---> [p2]
|
||||||
|
[p2]: check event signature
|
||||||
|
[p2]: associates symmetric key with this connection
|
||||||
|
[p2]: sign and encrypt event
|
||||||
|
[p1] <--------[status code OK]--------- [p2]
|
||||||
|
[p1]: decrypt and check event signature
|
||||||
|
|
||||||
|
Request some object:
|
||||||
|
[p1]: sign and encrypt event
|
||||||
|
[p1] ------[request some object]------> [p2]
|
||||||
|
[p2]: decrypt and check event signature
|
||||||
|
[p2]: sign and encrypt event
|
||||||
|
[p1] <-------[some object data]-------- [p2]
|
||||||
|
[p1]: decrypt and check event signature
|
||||||
|
|
||||||
|
Close session:
|
||||||
|
[p1]: sign and encrypt event
|
||||||
|
[p1] ---------[close session]---------> [p2]
|
||||||
|
[p2]: decrypt and check event signature
|
||||||
|
[p2]: sign and encrypt event
|
||||||
|
[p1] <--------[status code OK]--------- [p2]
|
||||||
|
[p2]: close connection
|
||||||
|
[p1]: decrypt and check event signature
|
||||||
|
```
|
||||||
|
|
||||||
|
\* - _стоит уточнить, что в реальных сценариях использования этот публичный ключ должен быть уже известен <!--(см. `TODO`)-->, либо коммуникация должна производиться через транспорт, гарантирующий достоверность передаваемых данных._
|
||||||
|
|
||||||
|
\*\* - _это может быть публичный ключ подписи `p1`, а может быть и сгенерированный отдельно, в зависимости от сценария использования._
|
||||||
|
|
||||||
|
\*\*\* - _установка шифрованного соединения полностью опциональна и его отсутствие не накладывает каких-либо ограничений, в рамках этой версии протокола. Формат события в таком соединении см. в [Events.md](Events.md)._
|
17
README.md
17
README.md
@ -1,6 +1,19 @@
|
|||||||
# Stadium Protocol
|
# Спецификация протокола Stadium версии 1.0
|
||||||
|
|
||||||
|
Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх обширного перечня транспорта. Данная спецификация описывает базу, на основе которой могут быть реализованы расширения (_SPX - Stadium Protocol eXtension_) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon<!--, спецификация расширения которого находится в папке `SPX/Marafon/`-->.
|
||||||
|
|
||||||
|
Основной фокус при работе над сим проектом идёт на:
|
||||||
|
|
||||||
|
- Возможность функционирования в условиях низкой пропускной способности канала;
|
||||||
|
- Устойчивость к цензуре;
|
||||||
|
- Поддержка широкого спектра транспортных протоколов;
|
||||||
|
- Построение децентрализованных (федеративных и P2P) сетей;
|
||||||
|
- Гибкое сквозное шифрование;
|
||||||
|
- Расширяемость и возможность подстраивания под конкретные задачи.
|
||||||
|
|
||||||
|
<!--В сей спецификации вы можете встретить примеры кода и упоминание типов данных языка C++.-->
|
||||||
|
|
||||||
|
|
||||||
Спецификация протокола Stadium и его официального расширения для нашего мессенджера - Marafon SPX.
|
|
||||||
|
|
||||||
**ПРОЕКТ В АКТИВНОЙ РАЗРАБОТКЕ/PROJECT UNDER ACTIVE DEVELOPMENT**
|
**ПРОЕКТ В АКТИВНОЙ РАЗРАБОТКЕ/PROJECT UNDER ACTIVE DEVELOPMENT**
|
||||||
|
|
||||||
|
29
Reserved events.md
Normal file
29
Reserved events.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Зарезервированные типы событий
|
||||||
|
|
||||||
|
Некоторые категории _событий_ зарезервированы под нужды базового протокола или просто для _событий_ определённого класса. Второе носит рекомендательный характер; вы также можете использовать иные диапазоны для тех-же целей. Ниже приведены диапазоны зарезервированных значений в виде шестнадцатеричных чисел. Конкретный перечень всех зарезервированных событий, описание их структуры - есть в папке `Reserved events/`.
|
||||||
|
|
||||||
|
|
||||||
|
Зарезервировано для нужд протокола и запрещено к использованию в сторонних расширениях:
|
||||||
|
|
||||||
|
1. Категория и субкатегория `0x00`
|
||||||
|
- Запрещены к использованию.
|
||||||
|
|
||||||
|
2. Категория `0x01`
|
||||||
|
- Все субкатегории: выделены для базовых _событий_, связанных с менджментом сессии.
|
||||||
|
|
||||||
|
3. Категория `0x02`
|
||||||
|
- Все субкатегории: выделены для базовых _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_.
|
||||||
|
|
||||||
|
4. Категория `0x11`
|
||||||
|
- Все субкатегории: выделены для базовых кодов ответа, ошибок и предупреждений.
|
||||||
|
|
||||||
|
|
||||||
|
Рекомендуется к использованию расширениями в конкретных ситуациях:
|
||||||
|
|
||||||
|
1. Категории `0x12`-`0x1F` (включительно)
|
||||||
|
- Все субкатегории: для кодов ответа, ошибок и предупреждений сторонних реализаций.
|
||||||
|
|
||||||
|
2. Категории `0x20`-`0x2F` (включительно)
|
||||||
|
- Все субкатегории: для _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_.
|
||||||
|
|
||||||
|
<!-- TODO: событие запроса всех сервисов на сервере -->
|
61
SESSIONS.md
61
SESSIONS.md
@ -1,61 +0,0 @@
|
|||||||
# Сессии и все-все-все
|
|
||||||
|
|
||||||
## Подпись
|
|
||||||
|
|
||||||
### Серверная подпись
|
|
||||||
|
|
||||||
Сервер обязан заведомо иметь пару ключей своей подписи, прежде чем коммуницировать с кем-либо в принципе. Генерировать их желательно вручную, на этапе установки/настройки серверного ПО.
|
|
||||||
|
|
||||||
### Обмен пакетами в неаутентифицированом соединении типа клиент-сервер
|
|
||||||
|
|
||||||
До выполнения аутентификации, сервер может, но не обязан, подписывать каждый свой пакет. Клиент не должен подписывать свои пакеты и должен устанавливать хэш полезной нагрузки в нулевое значение.
|
|
||||||
|
|
||||||
Сервер должен не проверять подпись пакетов клиента. Клиент должен проверять подпись только в случае наличия у него открытого ключа сервера.
|
|
||||||
|
|
||||||
### Регистрация
|
|
||||||
|
|
||||||
Перед инициированием процедуры регистрации, клиент запрашивает открытый ключ подписи сервера и тот отвечает событием, с открытым ключом в качестве основных данных и подписанным закрытым ключом хэшем полезной нагрузки. Клиент должен проверить подпись этого события с помощью публичного ключа из него-же.
|
|
||||||
|
|
||||||
<!-- TODO: оговорка про способы регистрации? -->
|
|
||||||
|
|
||||||
В случае успешной регистрации, клиент генерирует публичный и приватный ключи подписи, после чего отправляет событие с публичным ключом в качестве основных данных и подписанным закрытым ключом хэшем полезной нагрузки на сервер. Сервер должен проверить подпись этого события с помощью публичного ключа из него-же.
|
|
||||||
|
|
||||||
<!-- TODO: оговорка про способы аутентификации? -->
|
|
||||||
|
|
||||||
### Обмен пакетами в аутентифицированном соединении
|
|
||||||
|
|
||||||
Каждый принятый сервером пакет, содержащий хэш полезной нагрузки, должен проверяться на соответствие подписи, путём расшифровки этого хэша открытом ключом подписи и последующего сравнения с реальным хэшем полезной нагрузки. Если сервер обнаруживает, что подпись неверна - сервер отвечает ошибкой, добавляет запись об инциденте в журнал, а обрабатываемый пакет игнорируется.
|
|
||||||
|
|
||||||
Каждый принятый клиентом пакет, содержащий хэш полезной нагрузки, должен быть проверен на соответствие подписи. Если клиент обнаруживает, что подпись неверна - он уведомляет об этом пользователя, а обрабатываемый пакет игнорируется.
|
|
||||||
|
|
||||||
### Наглядные примеры работы с подписями
|
|
||||||
|
|
||||||
#### Отправка подписанного пакета
|
|
||||||
|
|
||||||
При отправке сообщения клиентом A клиенту Б, оно проходит следующую цепочку:
|
|
||||||
|
|
||||||
1. Клиент А посылает пакет с подписанным хэшем полезной нагрузки (далее - ХПН) и подписанными основными данными (как часть содержания полезной нагрузки), на свой хоумсервер (место, где клиент А аутентифицирован, далее - ХС А).
|
|
||||||
2. ХС A проверяет ХПН на валидность. Допустим, что подпись верна.
|
|
||||||
3. ХС А совершает релевантные действия, исходя из содержания и типа события.
|
|
||||||
4. ХС А переподписывает ХПН с использованием свой подписи.
|
|
||||||
5. ХС А отправляет переподписанный пакет хоумсерверу клиента Б (далее - ХС Б).
|
|
||||||
6. ХС Б проверяет ХПН на валидность. Допустим, что подпись верна.
|
|
||||||
7. ХС Б совершает релевантные действия, исходя из содержания и типа пакета.
|
|
||||||
8. ХС Б переподписывает пакет с использованием своей подписи.
|
|
||||||
9. ХС Б отправляет переподписанный пакет клиенту Б.
|
|
||||||
10. Клиент Б проверяет ХПН на валидность. Допустим, что подпись верна.
|
|
||||||
11. Клиент Б проверяет подпись основных данных, на предмет соответствия подписи клиента А и совершает релевантные действия.
|
|
||||||
|
|
||||||
<!-- TODO: решить: как и нужно-ли, чтобы сервер являлся средой нулевого доверия в плане передачи подписей пользователей (скорее всего "Да.") -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Серверные сессии и их идентификаторы
|
|
||||||
|
|
||||||
При подключении клиента к серверу, сервер генерирует и отправляет клиенту уникальный идентификатор серверной сессии, который также ассоциирует с параметрами подключения, установленных на этапе рукопожатия. Клиент и сервер обязаны прилагать назначенный ID серверной сессии к каждому пакету.
|
|
||||||
|
|
||||||
Если при проверке ID серверной сессии в пакете обнаруживается её отсутствие среди пулла серверных сессий - сервер отвечает ошибкой, соединение разрывается.
|
|
||||||
|
|
||||||
Идентификатор серверной сессии всегда уникален, по отношению к другим активным сессиям, и никогда не равен нулю.
|
|
||||||
|
|
||||||
Если у клиента есть несколько подключений, то все они должны быть снабжены единым серверным идентификатором.
|
|
@ -1 +0,0 @@
|
|||||||
У всех событий из этой категории, ячейка базового примитива `Data` обязана содержать подробное описание ошибки.
|
|
@ -1,43 +0,0 @@
|
|||||||
# Категория.Субкатегория
|
|
||||||
|
|
||||||
**Значение типа: 0xBA98**
|
|
||||||
|
|
||||||
**Требует аутентификации: нет**
|
|
||||||
|
|
||||||
## Client2Server
|
|
||||||
|
|
||||||
Какое-то описание метода. На данный момент, "официально" поддерживается два формата, в которых могут быть представлены данные: KLDR (расположенные последовательно "ключ-длина-значение") и фиксированная схема. Тут представлен пример в формате KLDR.
|
|
||||||
|
|
||||||
**Ячейки:**
|
|
||||||
|
|
||||||
- Код кредитки
|
|
||||||
- _Ключ:_ 0x01
|
|
||||||
- _Тип:_ `uint16_t`
|
|
||||||
- CVV-код от кредитной карты разработчика. Может быть представлен 12-ю битами, но мир несправедлив и поэтому данные выровнены по сетке в 8 бит.
|
|
||||||
- ФИ
|
|
||||||
- _Ключ:_ 0x02
|
|
||||||
- _Тип:_ `char[]`
|
|
||||||
- Имя и фамилия разработчика. Так как он предпочитает никнеймы вписывающиеся в кодировку ASCII - может быть представлено в виде обычного однобайтового массива.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Server2Client
|
|
||||||
|
|
||||||
Какие-то пояснении об отличии этого метода от C2S-шной версии. Тут представлен пример в формате фиксированной схемы.
|
|
||||||
|
|
||||||
**Фиксированная схема:**
|
|
||||||
|
|
||||||
- Место жительства разработчика
|
|
||||||
- _Размер:_ 7 байт
|
|
||||||
- _Тип:_ `char[]`
|
|
||||||
- Название региона, в котором проживает разработчик. Пишется латиницей, в кодировке ASCII.
|
|
||||||
- Возраст Жака Фреско
|
|
||||||
- _Размер:_ 1 байт
|
|
||||||
- _Тип:_ `uint8_t`
|
|
||||||
- Возраст разработчика.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Server2Server
|
|
||||||
|
|
||||||
_См. Client2Server._
|
|
Loading…
Reference in New Issue
Block a user