From 812465ec2edc04d7251d2b6f3d4826c344c404c0 Mon Sep 17 00:00:00 2001 From: shr3dd3r Date: Sat, 9 Dec 2023 00:19:16 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B4=D0=BE=D0=BB=D0=B6?= =?UTF-8?q?=D0=B0=D0=B5=D0=BC=20=D0=BD=D0=BE=D0=B2=D0=BE=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Data types.md | 3 + Data types/Crypto_Algorithm.md | 20 ++++ Data types/Crypto_AlgorithmID.md | 71 +++++++++++++ Data types/Crypto_AlgorithmParams.md | 13 +++ Data types/EventAsyncID.md | 9 ++ Data types/LocalObjectID.md | 9 ++ Events.md | 32 +++--- Handshake.md | 145 +++++++++++++++++++++++++++ Handshakes.md | 125 ----------------------- Overview.md | 99 ++++++------------ README.md | 8 +- Reserved events.md | 12 +-- 12 files changed, 324 insertions(+), 222 deletions(-) create mode 100644 Data types.md create mode 100644 Data types/Crypto_Algorithm.md create mode 100644 Data types/Crypto_AlgorithmID.md create mode 100644 Data types/Crypto_AlgorithmParams.md create mode 100644 Data types/EventAsyncID.md create mode 100644 Data types/LocalObjectID.md create mode 100644 Handshake.md delete mode 100644 Handshakes.md diff --git a/Data types.md b/Data types.md new file mode 100644 index 0000000..fed3b77 --- /dev/null +++ b/Data types.md @@ -0,0 +1,3 @@ +# Структуры данных + +Сия спецификация, помимо всего прочего, также упоминает и определяет некоторые необходимые типы и структуры данных. В директории `Data types/` вы найдёте их описания и примеры декларации на языке C++. diff --git a/Data types/Crypto_Algorithm.md b/Data types/Crypto_Algorithm.md new file mode 100644 index 0000000..0b930f0 --- /dev/null +++ b/Data types/Crypto_Algorithm.md @@ -0,0 +1,20 @@ +# Crypto::Algorithm + +Описывает криптографический алгоритм вместе с его базовой конфигурацией. + +## Структура + +`[AlgorithmID: 1B][AlgorithmParams: 1B]` + +## C++ + +```C++ +namespace Crypto { + +struct Algorithm { + AlgorithmID ID; + AlgorithmParams Params; +}; + +} +``` \ No newline at end of file diff --git a/Data types/Crypto_AlgorithmID.md b/Data types/Crypto_AlgorithmID.md new file mode 100644 index 0000000..309d1a6 --- /dev/null +++ b/Data types/Crypto_AlgorithmID.md @@ -0,0 +1,71 @@ +# Crypto::AlgorithmID + +Является перечислением однобайтных целых чисел без знака, соответствующих идентификаторам допустимых к использованию в базовом протоколе криптографических (и не только) алгоритмов: хэшей, контрольных сумм, симметричного и ассиметричного шифрования. + + + +## C++ + +```C++ +namespace Crypto { + +enum struct AlgorithmID : uint8_t { + None = 0, +// Checksums + CRC = 11, // 8/16/32/64/etc. + fletcher, // 8/16/32/etc. + Adler, // 32/etc. +// Non-crypto hashes + Murmur64A = 31, + Murmur3, // 32/128 + Spooky, // 128/etc. +// Cryptographic hashes + BLAKE2b = 51, + BLAKE3, + GOST, + HAS160, + HAVAL, + MD2, + MD5, + RIPEMD, + SHA1, + SHA2, + SHA3, + SHAKE, // 128/256 + Skein, + Snefru, + Streebog, + Tiger, + Whirlpool, +// Symmetric key block ciphers + Blowfish = 81, + Twofish, + Threefish, + TripleDES, + HPC, + MARS, + SAFER2PLUS, + SQUARE, + CRYPTON, + AES, // AKA Rijndael, GCM/CBC/CTR/etc. + MAGENTA, + XTEA1, + XTEA3, + KHAZAD, + Camellia, + Salsa20, + CAST5, + CAST6, + Kuznyechik, + MESH, + Akelarre, + RC6 +}; + +} +``` + + diff --git a/Data types/Crypto_AlgorithmParams.md b/Data types/Crypto_AlgorithmParams.md new file mode 100644 index 0000000..86ed49b --- /dev/null +++ b/Data types/Crypto_AlgorithmParams.md @@ -0,0 +1,13 @@ +# Crypto::AlgorithmParams + +Описывает параметры алгоритма, например размер ключа. Является двухбайтным целым без знака. + +## C++ + +```C++ +namespace Crypto { + +typedef uint16_t AlgorithmParams; + +} +``` diff --git a/Data types/EventAsyncID.md b/Data types/EventAsyncID.md new file mode 100644 index 0000000..7f4e761 --- /dev/null +++ b/Data types/EventAsyncID.md @@ -0,0 +1,9 @@ +# EventAsyncID + +Является уникальным двухбайтным целым числом без знака и предназначен для определения отношения запросов к ответам при асинхронном обмене _событиями_. + +## C++ + +```C++ +typedef uint16_t EventAsyncID; +``` diff --git a/Data types/LocalObjectID.md b/Data types/LocalObjectID.md new file mode 100644 index 0000000..43035fb --- /dev/null +++ b/Data types/LocalObjectID.md @@ -0,0 +1,9 @@ +# LocalObjectID + +Уникальный идентификатор объекта на сервере, является восьмибайтным числом без знака. + +## C++ + +```C++ +typedef uint64_t LocalObjectID; +``` diff --git a/Events.md b/Events.md index ba9eba7..50faa8a 100644 --- a/Events.md +++ b/Events.md @@ -6,11 +6,11 @@ Существует три уровня категорий _событий_: -**Надкатегория** описывает типы взаимодействующих _узлов_. Не указывается и зависит от контекста. Варианты: _Client2Server_ (_событие_ сгенерированное _клиентом_ для _сервера_), _Server2Client_ (_событие_ сгенерированное _сервером_ для _клиента_), _Peer2Peer_ (_событие_ сгенерированное _узлом_ для другого _узла_ того-же ранга, в том числе это касается _серверов_ в федерации). +**Надкатегория** описывает виды взаимодействующих _узлов_. Не указывается и зависит от контекста. Варианты: _Client2Server_ (_событие_ сгенерированное _клиентом_ для _сервера_), _Server2Client_ (_событие_ сгенерированное _сервером_ для _клиента_), _Peer2Peer_ (_событие_ сгенерированное _узлом_ для другого _узла_ того-же ранга, в том числе это касается _серверов_ в федерации). -**Категория** описывает _события_ одного класса. Является однобайтовым числом без знака. Всегда больше нуля. Например: _Authentication_, _Object_, т.п. +**Категория** описывает _события_ одного класса. Является однобайтным числом без знака. Всегда больше нуля. Например: _Authentication_, _Object_, т.п. -**Подкатегория** описывает конкретное _событие_ из класса, соответствующего категории. Является однобайтовым числом без знака. Всегда больше нуля. Например: _Login_, _GetContents_, т.п. +**Подкатегория** описывает конкретное _событие_ из класса, соответствующего категории. Является однобайтным числом без знака. Всегда больше нуля. Например: _Login_, _GetContents_, т.п. Все категории вместе - являются типом _события_. Информацию про зарезервированные типы вы можете найти в [Reserved events.md](Reserved%20events.md). @@ -18,22 +18,28 @@ ## Содержание и структура -_События_ всех типов содержат хэш полезной нагрузки размером равно или более 16 байт, зашифрованный с помощью закрытого ключа подписи отправляющего. Этот подписанный хэш гарантирует достоверность полезной нагрузки на уровне прямого подключения между двумя _узлами_. Используемый алгоритм хэширования определяется на этапе рукопожатия. +Все _события_ содержат идентификатор серверной сессии размером 4 байта. Подробнее про сессии - в [Sessions.md](Sessions.md). -Идентификатор серверной сессии является четырёхбайтным целым числом без знака. Подробнее про сессии - в [Sessions.md](Sessions.md). +_События_ в _шифрованном соединении_ содержат хэш, применённый к зашифрованному блобу (см. ниже). Этот хэш имеет размер равно или более 16 байт и подписан с помощью закрытого ключа подписи отправляющего. Он гарантирует достоверность содержания _события_ на уровне прямого подключения между двумя _узлами_. Используемые алгоритмы подписи и хэширования определяются на этапе рукопожатия. -Идентификатор _события_ является двухбайтным целым числом без знака и предназначен для определения отношения запросов к ответам при асинхронном обмене _событиями_. +Все _события_ содержат асинхронный идентификатор _события_, который является двухбайтным целым числом без знака и предназначен для определения отношения запросов к ответам при асинхронном обмене _событиями_. -Данная версия протокола не накладывает ограничений на формат полезной нагрузки, за исключением базовых событий, которые представлены данными в формате _LBM_. Описание всех предопределённых в базовом протоколе ключей ячеек _LBM_ доступно в [Reserved LBM keys.md](Reserved%20LBM%20keys.md). Неизвестные ключи при обработке полезной нагрузки игнорируются. Если полезная нагрузка отсутствует, то она заменяется на один нулевой байт. +Все _события_ содержат тип (см. выше раздел "Категории и типы"). - +_События_ могут содержать полезную нагрузку, либо один нулевой байт, свидетельствующий о её отсутствии. Данная версия протокола не накладывает ограничений на формат полезной нагрузки, за исключением базовых событий, которые представлены данными в формате _LBM_. Описание всех предопределённых в базовом протоколе ключей ячеек _LBM_ доступно в [Reserved LBM keys.md](Reserved%20LBM%20keys.md). При использовании формата _LBM_, в полезную нагрузку могут добавляться шумовые данные. Неизвестные ключи при обработке полезной нагрузки игнорируются. -Исходя из всего вышеописанного, минимальный размер сериализованного в бинарный вид _события_ составляет 25 байт, а его итоговая структура выглядит следующим образом: +_События_ в _шифрованном соединении_ содержат блоб, зашифрованный с помощью актуального ключа сессии и утверждённого алгоритма симметричного шифрования. Этот блоб содержит асинхронный идентификатор, тип события и полезную нагрузку. В нешифрованном соединении, указанные поля находятся в "сыром" виде. -`[category: 1B][subcategory: 1B][session id: 4B][event async id: 2B][payload hash: >16B][payload: >0B]` +Исходя из всего вышеописанного, минимальный размер сериализованного в бинарный вид _события_ в нешифрованном соединении составляет 9 байт, а его итоговая структура выглядит следующим образом: -Максимальный размер _события_ не нормирован и ответственность за его менеджмент остаётся на транспортном уровне. Максимальный размер полезной нагрузки _события_ определяется на этапе рукопожатия. +`[Session ID: 4B][Async ID: 2B][Event Type: 2B][Payload: >0B]` -### Событие в шифрованном соединении +В свою очередь, _события_ в _шифрованном соединении_ имеют размер не менее 25-и байт и следующую структуру: -В _шифрованном соединении_ _события_ сериализуются в бинарное представление и зашифровываются с помощью утверждённого симметричного ключа сессии. +```text +[Session ID: 4B][Signed Hash: >=16B][Encrypted Blob: >=5B] + / | \ + [Async ID: 2B][Event Type: 2B][Payload: >0B] +``` + +Максимальный размер _события_ не нормирован. Ответственность за менеджмент разделения _события_, в случае, если оно не помещается в один пакет, остаётся на транспортном уровне. Максимальный размер полезной нагрузки _события_ определяется на этапе рукопожатия. diff --git a/Handshake.md b/Handshake.md new file mode 100644 index 0000000..3400076 --- /dev/null +++ b/Handshake.md @@ -0,0 +1,145 @@ +# Рукопожатие + +На рукопожатие возложена задача выяснить способность _узлов_ устанавливать соединение по описываемому протоколу и согласовать подключение с избранными параметрами каждой стороны. На выбор существует два типа хэндшейка: открытый и зашифрованный. Второй дополнительно требует знать публичный ключ целевого _узла_. + + + +## Запрос рукопожатия + +После успешного подключения к целевому _узлу_ через избранный транспорт происходит обмен параметрами обоих сторон. Инициирующий соединение _узел_ отправляет пакет с магический числом, флагом шифрования и сериализованными данными в формат _LBM_. В случае с зашифрованным хэндшейком, сериализованные данные дополнительно зашифровываются с помощью публичного ключа целевого _узла_. + +Структура пакета с запросом рукопожатия выглядит следующим образом: + +`[magic number: 8B][encryption flag: 1B][LBM-formatted data: >0B]` + +### Магическое число + +Магическим числом является следующая последовательность байт: + +``` +HEX: 0x53 0x74 0x61 0x64 0x69 0x75 0x6d 0x50 +DEC: 83 116 97 100 105 117 109 80 +ASCII: S t a d i u m P +``` + +Если _узел_ получает пакет, который не содержит магического числа на указанной позиции, то он должен молча закрыть соединение. + +### Флаг шифрования + +Запрос шифрованного хэндшейка предполагает установку этого флага в значение `0x7a`. Все остальные значения должны интерпретироваться как запрос открытого хэндшейка. + +### Данные + +Данные в формате _LBM_ содержат следующие ячейки: + +- Версия протокола + - _Ключ:_ `0x01` + - _Тип:_ `uint8_t` + - _Обязательна:_ да + - Поддерживаемая запрашивающим _узлом_ версия протокола. + - `0b10000000`: зарезервировано + - `0b01111111`: номер версии + +- Алгоритмы хэширования полезной нагрузки + - _Ключ:_ `0x02` + - _Тип:_ `Crypto::Algorithm[]` + - _Обязательна:_ только для шифрованного ХШ + - Описывает запрашиваемые к использованию в этом соединении хэш-функции для формирования хэша полезной нагрузки. + +- Алгоритм подписи + - _Ключ:_ `0x03` + - _Тип:_ `Crypto::Algorithm` + - _Обязательна:_ только для шифрованного ХШ + - Описывает используемый запрашивающим _узлом_ алгоритм подписи. + +- Публичный ключ подписи + - _Ключ:_ `0x04` + - _Тип:_ `char[]` + - _Обязательна:_ только для шифрованного ХШ + - Публичный ключ подписи запрашивающего _узла_, который будет использован для проверки достоверности событий в соединении. + +- Алгоритмы симметричного шифрования + - _Ключ:_ `0x05` + - _Тип:_ `Crypto::Algorithm[]` + - _Обязательна:_ только для шифрованного ХШ + - Описывает запрашиваемые к использованию в этом соединении симметричные алгоритмы шифрования. + +- Приватный ключ + - _Ключ:_ `0x06` + - _Тип:_ `char[]` + - _Обязательна:_ только для шифрованного ХШ + - Используемый в этом соединении приватный ключ, размера соответствующего избранному алгоритму симметричного шифрования. + +- Параметры шума + - _Ключ:_ `0x07` + - _Тип:_ `uint8_t` + - _Обязательна:_ нет + - Описывает параметры шума в соединении: + - `0b11100000`: выделено под настройку количества _шумовых пакетов_ + - `0b000`: отсутствие _шумовых пакетов_ + - `0b001`: соотношение _шумовых пакетов_ к реальным - 1:8 + - `0b010`: соотношение - 1:4 + - `0b011`: 1:2 + - `0b100`: 1:1 + - `0b101`: 2:1 + - `0b110`: 4:1 + - `0b111`: зарезервировано + - `0b00011000`: выделено под настройку размера _шумовых пакетов_ + - `0b00`: случайный размер, в пределах от минимального _пакета_ с нулевой полезной нагрузкой, до размера _пакета_ с полезной нагрузкой размерности, которую должен передать целевой _узел_ при одобрении рукопожатия + - `0b01`: случайный размер, на основе среднего размера передаваемого пакета +- 25% (но всегда меньше максимального) + - `0b10`: случайный размер, в пределах от минимального, до максимального / 2 + - `0b11`: зарезервировано + - `0b00000110`: выделено под настройку размера _шумовых данных_ в обычных _пакетах_ + - `0b00`: без шумовых данных + - `0b01`: заполнение шумовыми данными до лимита полезной нагрузки + - `0b10`: заполнение шумовыми данными в случайном количестве, от нуля, до лимита полезной нагрузки + - `0b11`: зарезервировано + - `0b00000001`: зарезервировано + + + + + +## Ответ на рукопожатие + +На запрос рукопожатия с корректным магическим числом целевой _узел_ должен ответить пакетом либо с согласием, либо с ошибкой. Если это ответ с согласием, то данные в пакете должны быть зашифрованы с помощью переданного в запросе хэндшейка симметричного шифра и переданного приватного ключа. Если это ответ с ошибкой, то он может быть незашифрован, в случае, если ошибка связанна с инициализацией шифрования или версией протокола. Таким образом, запрашивающий _узел_ должен быть готов обработать оба варианта развития событий, исходя из значения флага шифрования. Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными параметрами. + +Пакет ответа имеет следующую структуру: + +`[magic number: 8B][encryption flag: 1B][LBM-formatted data: >0B]` + +### Данные + +Данные в формате _LBM_ содержат следующие ячейки: + +- Максимальный размер полезной нагрузки + - _Ключ:_ `0x71` + - _Тип:_ `uint16_t` + - _Обязательна:_ только для соглашения + - Всегда больше нуля. Оба _узла_ должны соблюдать размерность полезной нагрузки в событии, она всегда должна быть равна или меньше этого значения. + +- Код ошибки + - _Ключ:_ `0x72` + - _Тип:_ `uint8_t` + - _Обязательна:_ только для ошибки + - Код, описывающий тип ошибки: + - `0x01`: магическое число ложно + - `0x02`: неподдерживаемая версия протокола + - `0x03`: недопустимый алгоритм хэширования + - `0x04`: недопустимый алгоритм подписи + - `0x05`: недопустимый алгоритм симметричного шифрования + - `0x06`: некорректный приватный ключ + - `0x07`: некорректный публичный ключ подписи + - `0x08`: недопустимые параметры шума + - `0x09`: невозможно корректно расшифровать данные (ложный публичный ключ целевого _узла_) + +- Описание ошибки + - _Ключ:_ `0x73` + - _Тип:_ `char[]` + - _Обязательна:_ нет + - Строка в кодировке ASCII, описывающая ошибку в человекочитаемом виде. diff --git a/Handshakes.md b/Handshakes.md deleted file mode 100644 index d759c05..0000000 --- a/Handshakes.md +++ /dev/null @@ -1,125 +0,0 @@ -# Рукопожатие - - - - - -## Протокольного уровня - -После успешного подключения к целевому _узлу_ через избранный транспорт - происходит обмен параметрами обоих сторон, 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/Overview.md b/Overview.md index a6aa43e..af837a8 100644 --- a/Overview.md +++ b/Overview.md @@ -18,13 +18,9 @@ Выполняющий роль клиента _узел_ в многоранговой сети. -### Подписанное соединение/сессия - -Соединение между двумя _узлами_, все _события_ в котором подписаны с помощью оговорённого ассиметричного алгоритма и приватного ключа отправителя. - ### Шифрованное соединение/сессия -Соединение между двумя _узлами_, все _события_ в котором шифруется с помощью оговорённого симметричного алгоритма и ключа. Требует _подписанное соединение_ для установки. +Соединение между двумя _узлами_, все _события_ в котором шифруются с помощью оговорённого симметричного алгоритма и ключа, а также подписываются с помощью известного приватного ключа подписи отправителя. ### Событие @@ -36,88 +32,53 @@ _Событие_ предопределённой категории, имеющ ### LBM -Аббревиатура наименования способа форматирования данных, используемого для полезной нагрузки _события_, которая расшифровывается как "Linear Binary Map". Подробнее - в [LBM.md](LBM.md). +Аббревиатура наименования способа форматирования (сериализации) данных, используемого для полезной нагрузки _события_, которая расшифровывается как "Linear Binary Map". Подробнее - в [LBM.md](LBM.md). ### Шумовые данные -Случайно-сгенерированные данные, помещённые в ячейку полезной нагрузки _события_. +Случайно-сгенерированные данные, помещённые в специализированную ячейку полезной нагрузки _события_. ## Пример коммуникации двух узлов -Допустим, что у нас есть два неизвестных друг-другу _узла_ - `p1` и `p2`. Тогда полная коммуникация по шагам (от подключения неизвестного для `p2` _узла_ - до "правильного" уничтожения сессии и закрытия соединения) будет выглядеть так: +Допустим, что у нас есть два неизвестных\* друг-другу _узла_ - `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` закрывает соединение +1. `p1` запрашивает открытое (нешифрованное) рукопожатие с избранными параметрами соединения у `p2` +2. `p2` отвечает `p1` согласием со своей частью параметров +3. `p1` запрашивает публичный ключ подписи у `p2` +4. `p2` передаёт свой публичный ключ, вместе с используемым алгоритмом +5. `p1` сохраняет полученный публичный ключ и разрывает\*\* соединение и заново устанавливает его, путём отправки `p2` запроса шифрованного хэндшейка +6. `p2` отвечает согласием со своей частью параметров подключения +7. `p1` отправляет зашифрованное _событие_ с запросом какого-то объекта +8. `p2` отвечает зашифрованным _событием_, содержащее статус-код или этот объект +9. `p1` отправляет _событие_ с сообщением о намерении уничтожить сессию и ждёт в течении n времени, по истечению которого может разорвать соединение "насильно" +10. `p2` принимает запрос и прекращает любой параллельный обмен данными +11. `p2` отвечает _событием_ с кодом успешности операции +12. `p2` закрывает соединение И в виде схемы: ``` -Handshake: -[p1] --------[transport connect]------> [p2] -[p1] --------[handshake request]------> [p2] -[p1] <-------[handshake accept]-------- [p2] - -Get p2's public key: +Requesting p2's public key: +[p1] ------[raw handshake request]----> [p2] +[p1] <-----[raw handshake accept]------ [p2] [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 + +Reconnecting in encrypted way and requesting object: +[p1] ---[encrypted handshake request]-> [p2] +[p1] <--[encrypted handshake accept]--- [p2] +[p1] ------[request some object]------> [p2] +[p1] <-[some object data/status code]-- [p2] +[p1] ---------[close session]---------> [p2] +[p1] <--------[status code OK]--------- [p2] ``` -\* - _стоит уточнить, что в реальных сценариях использования этот публичный ключ должен быть уже известен , либо коммуникация должна производиться через транспорт, гарантирующий достоверность передаваемых данных._ +\* - _стоит уточнить, что в реальных сценариях использования публичный ключ целевого узла скорее всего уже известен, либо коммуникация должна производиться через транспорт, гарантирующий достоверность передаваемых данных. `p1` может узнать о существовании таковых, путём отправки события специального типа. В данном примере сей шаг опущен._ -\*\* - _это может быть публичный ключ подписи `p1`, а может быть и сгенерированный отдельно, в зависимости от сценария использования._ + -\*\*\* - _установка шифрованного соединения полностью опциональна и его отсутствие не накладывает каких-либо ограничений, в рамках этой версии протокола. Формат события в таком соединении см. в [Events.md](Events.md)._ +\*\* - _"разрыв" соединения предполагает обмен между узлами событиями с информацией о завершении сессии; в данном пункте эти шаги опущены, но упомянуты ниже._ diff --git a/README.md b/README.md index 1c660f1..0f1c380 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,18 @@ # Спецификация протокола Stadium версии 1.0 -Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх обширного перечня транспорта. Данная спецификация описывает базу, на основе которой могут быть реализованы расширения (_SPX - Stadium Protocol eXtension_) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon. +Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх обширного перечня транспорта и архитектурно не зависящий от оного. Данная спецификация описывает базу, на основе которой могут быть реализованы расширения (_SPX - Stadium Protocol eXtension_) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon. Основной фокус при работе над сим проектом идёт на: - Возможность функционирования в условиях низкой пропускной способности канала; - Устойчивость к цензуре; - Поддержка широкого спектра транспортных протоколов; -- Построение децентрализованных (федеративных и P2P) сетей; +- Построение децентрализованных меш-сетей (как одноуровневых, так и двухуровневых); - Гибкое сквозное шифрование; - Расширяемость и возможность подстраивания под конкретные задачи. - - **ПРОЕКТ В АКТИВНОЙ РАЗРАБОТКЕ/PROJECT UNDER ACTIVE DEVELOPMENT** -All text will be translated to english later. \ No newline at end of file +All text will be translated to english later. diff --git a/Reserved events.md b/Reserved events.md index e5c9488..bdb10d0 100644 --- a/Reserved events.md +++ b/Reserved events.md @@ -1,6 +1,6 @@ # Зарезервированные типы событий -Некоторые категории _событий_ зарезервированы под нужды базового протокола или просто для _событий_ определённого класса. Второе носит рекомендательный характер; вы также можете использовать иные диапазоны для тех-же целей. Ниже приведены диапазоны зарезервированных значений в виде шестнадцатеричных чисел. Конкретный перечень всех зарезервированных событий, описание их структуры - есть в папке `Reserved events/`. +Некоторые категории _событий_ зарезервированы под нужды базового протокола или просто для _событий_ определённого класса. Второе носит рекомендательный характер; вы также можете использовать иные диапазоны для тех-же целей. Ниже приведены диапазоны зарезервированных значений в виде шестнадцатеричных чисел. Конкретный перечень всех зарезервированных событий и описание их структуры - есть в папке `Reserved events/`. Зарезервировано для нужд протокола и запрещено к использованию в сторонних расширениях: @@ -11,10 +11,7 @@ 2. Категория `0x01` - Все субкатегории: выделены для базовых _событий_, связанных с менджментом сессии. -3. Категория `0x02` - - Все субкатегории: выделены для базовых _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_. - -4. Категория `0x11` +3. Категория `0x11` - Все субкатегории: выделены для базовых кодов ответа, ошибок и предупреждений. @@ -22,8 +19,3 @@ 1. Категории `0x12`-`0x1F` (включительно) - Все субкатегории: для кодов ответа, ошибок и предупреждений сторонних реализаций. - -2. Категории `0x20`-`0x2F` (включительно) - - Все субкатегории: для _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_. - -