diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f01705 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +Data types/DATA TYPES.md +SPX/ +_something.md +Sessions.md +LBM.md +Reserved LBM keys.md +Reserved events/ \ No newline at end of file diff --git a/Common behavior.md b/Common behavior.md new file mode 100644 index 0000000..0093977 --- /dev/null +++ b/Common behavior.md @@ -0,0 +1,24 @@ +# Общие принципы поведения узлов + + + +## Обязанности узла + +1. Оповещать об ошибке, возникшей во время обработки _события_ другого _узла_, но только если ошибка связана с его некорректной формой. +2. По умолчанию отклонять все _события_ с ложной подписью в _подписанном соединении_. + + + +## Обязанности сервера + +1. Оповещать _узел_ (будь то _клиент_ или _сервер_ в федерации) о всех ошибках, возникших во время обработки его _события_, кроме связанных с безопасностью. +2. Отдавать предпочтение данным других _серверов_ в федерации, нежели _клиентов_. +3. Отдавать предпочтение сетевым настройкам входящих соединений, нежели локальным (не считая лимиты). + + + +## Обязанности клиента + +1. Не сообщать _серверу_ ни о каких ошибках на своей стороне. +2. По умолчанию блокировать до решения юзера обработку любых _событий_, содержащих ложную подпись. +3. Явно уведомлять юзера при возникновении проблем с безопасностью, как минимум по умолчанию. diff --git a/DATA TYPES.md b/DATA TYPES.md deleted file mode 100644 index ec68bb2..0000000 --- a/DATA TYPES.md +++ /dev/null @@ -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 -}; -``` - - - -#### 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; -``` \ No newline at end of file diff --git a/Events.md b/Events.md new file mode 100644 index 0000000..ba9eba7 --- /dev/null +++ b/Events.md @@ -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). Неизвестные ключи при обработке полезной нагрузки игнорируются. Если полезная нагрузка отсутствует, то она заменяется на один нулевой байт. + + + +Исходя из всего вышеописанного, минимальный размер сериализованного в бинарный вид _события_ составляет 25 байт, а его итоговая структура выглядит следующим образом: + +`[category: 1B][subcategory: 1B][session id: 4B][event async id: 2B][payload hash: >16B][payload: >0B]` + +Максимальный размер _события_ не нормирован и ответственность за его менеджмент остаётся на транспортном уровне. Максимальный размер полезной нагрузки _события_ определяется на этапе рукопожатия. + +### Событие в шифрованном соединении + +В _шифрованном соединении_ _события_ сериализуются в бинарное представление и зашифровываются с помощью утверждённого симметричного ключа сессии. diff --git a/HANDSHAKE.md b/HANDSHAKE.md deleted file mode 100644 index e6d4d94..0000000 --- a/HANDSHAKE.md +++ /dev/null @@ -1,103 +0,0 @@ -# Handshake - -## Protocol-level handshake - -После успешной установки соединения происходит обмен характеристиками обоих сторон, AKA "рукопожатие протокольного уровня". Запрашивающий соединение отправляет пакет следующего формата: - - -`[magic number: 8B][protocol version: 4B][crypto params: 8B][reconnection flags: 4B]` - -- Магическое число - - _Тип:_ `uint64_t` - - Магическое число протокола, по которому определяется совместимость цели с протоколом Stadium. См. раздел "Магическое число" для справки. -- Версия протокола - - _Тип:_ `uint32_t` - - Поддерживаемая запрашивающим версия протокола. - -- Параметры криптографии - - _Тип:_ `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. \ No newline at end of file diff --git a/Handshakes.md b/Handshakes.md new file mode 100644 index 0000000..d759c05 --- /dev/null +++ b/Handshakes.md @@ -0,0 +1,125 @@ +# Рукопожатие + + + + + +## Протокольного уровня + +После успешного подключения к целевому _узлу_ через избранный транспорт - происходит обмен параметрами обоих сторон, 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`: количество задаётся по усмотрению целевого _узла_ + - `0b010`: соотношение _шумовых пакетов_ к реальным - 1:8 + - `0b011`: соотношение - 1:4 + - `0b100`: 1:2 + - `0b101`: 1:1 + - `0b110`: 2:1 + - `0b111`: 4:1 + - `0b00011000`: выделено под настройки размера _шумовых пакетов_ + - `0b00`: по усмотрению целевого _узла_ + - `0b01`: случайный размер, в пределах от минимального _пакета_ с нулевой полезной нагрузкой, до размера _пакета_ с полезной нагрузкой размерности, которую должен передать целевой _узел_ при одобрении рукопожатия + - `0b10`: случайный размер, в пределах от минимального, до максимального / 2 + - `0b11`: случайный размер, на основе среднего размера передаваемого пакета +- 25% (но всегда меньше максимального) + - `0b00000111`: выделено под настройки размера _шумовых данных_ в обычных _пакетах_ + - `0b000`: без шумовых данных + - `0b001`: заполнение шумовыми данными до лимита полезной нагрузки + - `0b010`: заполнение шумовыми данными в случайном количестве, от нуля, до лимита полезной нагрузки + - Диапазон `0b011`-`0b111`: зарезервировано + +- Флаги переподключения + - _Тип:_ `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. diff --git a/KLDR RESERVED KEYS.md b/KLDR RESERVED KEYS.md deleted file mode 100644 index 5de8fdd..0000000 --- a/KLDR RESERVED KEYS.md +++ /dev/null @@ -1,62 +0,0 @@ -# Список зарезервированных ключей ячеек - - -Перечисленные здесь значения являются либо совсем базовыми, либо предназначены для использования сервером. Все данные транзитных пакетов (т.е. тех, которые предназначены для кого-то кроме сервера подключённого напрямую), для которых критична подлинность, должны передаваться в ячейке `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` - - Права доступа к конкретному объекту. - - - - -## Криптография - -- CryptoAlgos - - _Значение:_ `0x11` - - _Тип:_ `CryptoAlgo[4]` - - Используемые криптографические алгоритмы. Предназначено для использования конечной целью, а не промежуточным узлом (сервером). Первый элемент выделен под хэш-функцию; второй для ассиметричной функции подписи; третий для ассиметричной функции шифрования; четвёртый для симметричной функции. -- CryptoKeyID - - _Значение:_ `0x12` - - _Тип:_ `uint32_t` - - Идентификатор используемого криптографического ключа для шифрования данных. -- SignedDataHash - - _Значение:_ `0x13` - - _Тип:_ не имеет значения - - Хэш основных передаваемых данных, зашифрованный закрытым ключом отправителя. \ No newline at end of file diff --git a/OVERVIEW.md b/OVERVIEW.md deleted file mode 100644 index 5ef2011..0000000 --- a/OVERVIEW.md +++ /dev/null @@ -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` (включительно) - - Все субкатегории: для событий ошибок и предупреждений. - - - -### Зарезервированные ключи ячеек - -У данных в формате 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) - -- Механизм пользовательских сессий, клиентские подписи и базовая аутентификация -- Механизм синхронизации ключей для сквозного шифрования между юзерами -- Манипуляции с файлами (скачивание/загрузка) -- Стриминг аудио и видео \ No newline at end of file diff --git a/Overview.md b/Overview.md new file mode 100644 index 0000000..a6aa43e --- /dev/null +++ b/Overview.md @@ -0,0 +1,123 @@ +# Обзор + + + +## Терминология + +Здесь перечислены используемые в данной документации термины, значение которых может быть не очевидно и/или не соответствует тому, которое подразумевается обычно. + +### Узел + +Любая машина, способная выполнять коммуникацию по протоколу Stadium. Обычно используется в контексте коммуникации двух машин одного ранга или когда ранг не имеет значения. + +### Сервер + +Выполняющий роль сервера _узел_ в многоранговой сети. + +### Клиент + +Выполняющий роль клиента _узел_ в многоранговой сети. + +### Подписанное соединение/сессия + +Соединение между двумя _узлами_, все _события_ в котором подписаны с помощью оговорённого ассиметричного алгоритма и приватного ключа отправителя. + +### Шифрованное соединение/сессия + +Соединение между двумя _узлами_, все _события_ в котором шифруется с помощью оговорённого симметричного алгоритма и ключа. Требует _подписанное соединение_ для установки. + +### Событие + +Структура данных, обладающая конкретными семантическими свойствами в зависимости от типа и содержащая дополнительные поля, требуемые для верного отображения и интерпретации самой структуры. Проще говоря - то, чем обмениваются и что обрабатывают _узлы_ во время коммуникации между собой. + +### Шумовое событие + +_Событие_ предопределённой категории, имеющее случайно-сгенерированные поля. + +### LBM + +Аббревиатура наименования способа форматирования данных, используемого для полезной нагрузки _события_, которая расшифровывается как "Linear Binary Map". Подробнее - в [LBM.md](LBM.md). + +### Шумовые данные + +Случайно-сгенерированные данные, помещённые в ячейку полезной нагрузки _события_. + + + +## Пример коммуникации двух узлов + +Допустим, что у нас есть два неизвестных друг-другу _узла_ - `p1` и `p2`. Тогда полная коммуникация по шагам (от подключения неизвестного для `p2` _узла_ - до "правильного" уничтожения сессии и закрытия соединения) будет выглядеть так: + +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 +``` + +\* - _стоит уточнить, что в реальных сценариях использования этот публичный ключ должен быть уже известен , либо коммуникация должна производиться через транспорт, гарантирующий достоверность передаваемых данных._ + +\*\* - _это может быть публичный ключ подписи `p1`, а может быть и сгенерированный отдельно, в зависимости от сценария использования._ + +\*\*\* - _установка шифрованного соединения полностью опциональна и его отсутствие не накладывает каких-либо ограничений, в рамках этой версии протокола. Формат события в таком соединении см. в [Events.md](Events.md)._ diff --git a/README.md b/README.md index 2f2d9e1..1c660f1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,19 @@ -# Stadium Protocol +# Спецификация протокола Stadium версии 1.0 + +Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх обширного перечня транспорта. Данная спецификация описывает базу, на основе которой могут быть реализованы расширения (_SPX - Stadium Protocol eXtension_) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon. + +Основной фокус при работе над сим проектом идёт на: + +- Возможность функционирования в условиях низкой пропускной способности канала; +- Устойчивость к цензуре; +- Поддержка широкого спектра транспортных протоколов; +- Построение децентрализованных (федеративных и P2P) сетей; +- Гибкое сквозное шифрование; +- Расширяемость и возможность подстраивания под конкретные задачи. + + + -Спецификация протокола Stadium и его официального расширения для нашего мессенджера - Marafon SPX. **ПРОЕКТ В АКТИВНОЙ РАЗРАБОТКЕ/PROJECT UNDER ACTIVE DEVELOPMENT** diff --git a/Reserved events.md b/Reserved events.md new file mode 100644 index 0000000..e5c9488 --- /dev/null +++ b/Reserved events.md @@ -0,0 +1,29 @@ +# Зарезервированные типы событий + +Некоторые категории _событий_ зарезервированы под нужды базового протокола или просто для _событий_ определённого класса. Второе носит рекомендательный характер; вы также можете использовать иные диапазоны для тех-же целей. Ниже приведены диапазоны зарезервированных значений в виде шестнадцатеричных чисел. Конкретный перечень всех зарезервированных событий, описание их структуры - есть в папке `Reserved events/`. + + +Зарезервировано для нужд протокола и запрещено к использованию в сторонних расширениях: + +1. Категория и субкатегория `0x00` + - Запрещены к использованию. + +2. Категория `0x01` + - Все субкатегории: выделены для базовых _событий_, связанных с менджментом сессии. + +3. Категория `0x02` + - Все субкатегории: выделены для базовых _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_. + +4. Категория `0x11` + - Все субкатегории: выделены для базовых кодов ответа, ошибок и предупреждений. + + +Рекомендуется к использованию расширениями в конкретных ситуациях: + +1. Категории `0x12`-`0x1F` (включительно) + - Все субкатегории: для кодов ответа, ошибок и предупреждений сторонних реализаций. + +2. Категории `0x20`-`0x2F` (включительно) + - Все субкатегории: для _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_. + + diff --git a/SESSIONS.md b/SESSIONS.md deleted file mode 100644 index 2143a40..0000000 --- a/SESSIONS.md +++ /dev/null @@ -1,61 +0,0 @@ -# Сессии и все-все-все - -## Подпись - -### Серверная подпись - -Сервер обязан заведомо иметь пару ключей своей подписи, прежде чем коммуницировать с кем-либо в принципе. Генерировать их желательно вручную, на этапе установки/настройки серверного ПО. - -### Обмен пакетами в неаутентифицированом соединении типа клиент-сервер - -До выполнения аутентификации, сервер может, но не обязан, подписывать каждый свой пакет. Клиент не должен подписывать свои пакеты и должен устанавливать хэш полезной нагрузки в нулевое значение. - -Сервер должен не проверять подпись пакетов клиента. Клиент должен проверять подпись только в случае наличия у него открытого ключа сервера. - -### Регистрация - -Перед инициированием процедуры регистрации, клиент запрашивает открытый ключ подписи сервера и тот отвечает событием, с открытым ключом в качестве основных данных и подписанным закрытым ключом хэшем полезной нагрузки. Клиент должен проверить подпись этого события с помощью публичного ключа из него-же. - - - -В случае успешной регистрации, клиент генерирует публичный и приватный ключи подписи, после чего отправляет событие с публичным ключом в качестве основных данных и подписанным закрытым ключом хэшем полезной нагрузки на сервер. Сервер должен проверить подпись этого события с помощью публичного ключа из него-же. - - - -### Обмен пакетами в аутентифицированном соединении - -Каждый принятый сервером пакет, содержащий хэш полезной нагрузки, должен проверяться на соответствие подписи, путём расшифровки этого хэша открытом ключом подписи и последующего сравнения с реальным хэшем полезной нагрузки. Если сервер обнаруживает, что подпись неверна - сервер отвечает ошибкой, добавляет запись об инциденте в журнал, а обрабатываемый пакет игнорируется. - -Каждый принятый клиентом пакет, содержащий хэш полезной нагрузки, должен быть проверен на соответствие подписи. Если клиент обнаруживает, что подпись неверна - он уведомляет об этом пользователя, а обрабатываемый пакет игнорируется. - -### Наглядные примеры работы с подписями - -#### Отправка подписанного пакета - -При отправке сообщения клиентом A клиенту Б, оно проходит следующую цепочку: - -1. Клиент А посылает пакет с подписанным хэшем полезной нагрузки (далее - ХПН) и подписанными основными данными (как часть содержания полезной нагрузки), на свой хоумсервер (место, где клиент А аутентифицирован, далее - ХС А). -2. ХС A проверяет ХПН на валидность. Допустим, что подпись верна. -3. ХС А совершает релевантные действия, исходя из содержания и типа события. -4. ХС А переподписывает ХПН с использованием свой подписи. -5. ХС А отправляет переподписанный пакет хоумсерверу клиента Б (далее - ХС Б). -6. ХС Б проверяет ХПН на валидность. Допустим, что подпись верна. -7. ХС Б совершает релевантные действия, исходя из содержания и типа пакета. -8. ХС Б переподписывает пакет с использованием своей подписи. -9. ХС Б отправляет переподписанный пакет клиенту Б. -10. Клиент Б проверяет ХПН на валидность. Допустим, что подпись верна. -11. Клиент Б проверяет подпись основных данных, на предмет соответствия подписи клиента А и совершает релевантные действия. - - - - - -## Серверные сессии и их идентификаторы - -При подключении клиента к серверу, сервер генерирует и отправляет клиенту уникальный идентификатор серверной сессии, который также ассоциирует с параметрами подключения, установленных на этапе рукопожатия. Клиент и сервер обязаны прилагать назначенный ID серверной сессии к каждому пакету. - -Если при проверке ID серверной сессии в пакете обнаруживается её отсутствие среди пулла серверных сессий - сервер отвечает ошибкой, соединение разрывается. - -Идентификатор серверной сессии всегда уникален, по отношению к другим активным сессиям, и никогда не равен нулю. - -Если у клиента есть несколько подключений, то все они должны быть снабжены единым серверным идентификатором. \ No newline at end of file diff --git a/reserved/Base/EnumerateServices.md b/reserved/Base/EnumerateServices.md deleted file mode 100644 index e69de29..0000000 diff --git a/reserved/Base/GetServerPublicSignKey.md b/reserved/Base/GetServerPublicSignKey.md deleted file mode 100644 index e69de29..0000000 diff --git a/reserved/Base/PublicSignKey.md b/reserved/Base/PublicSignKey.md deleted file mode 100644 index e69de29..0000000 diff --git a/reserved/Base/ServicesList.md b/reserved/Base/ServicesList.md deleted file mode 100644 index e69de29..0000000 diff --git a/reserved/BaseErrors/README.md b/reserved/BaseErrors/README.md deleted file mode 100644 index 7b7150d..0000000 --- a/reserved/BaseErrors/README.md +++ /dev/null @@ -1 +0,0 @@ -У всех событий из этой категории, ячейка базового примитива `Data` обязана содержать подробное описание ошибки. \ No newline at end of file diff --git a/reserved/METHOD FORMAT EXAMPLE.md b/reserved/METHOD FORMAT EXAMPLE.md deleted file mode 100644 index eeb6f49..0000000 --- a/reserved/METHOD FORMAT EXAMPLE.md +++ /dev/null @@ -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._ \ No newline at end of file