Продолжаем новое

This commit is contained in:
Shr3dd3r 2023-12-09 00:19:16 +03:00
parent acae23fe35
commit 812465ec2e
12 changed files with 324 additions and 222 deletions

3
Data types.md Normal file
View File

@ -0,0 +1,3 @@
# Структуры данных
Сия спецификация, помимо всего прочего, также упоминает и определяет некоторые необходимые типы и структуры данных. В директории `Data types/` вы найдёте их описания и примеры декларации на языке C++.

View File

@ -0,0 +1,20 @@
# Crypto::Algorithm
Описывает криптографический алгоритм вместе с его базовой конфигурацией.
## Структура
`[AlgorithmID: 1B][AlgorithmParams: 1B]`
## C++
```C++
namespace Crypto {
struct Algorithm {
AlgorithmID ID;
AlgorithmParams Params;
};
}
```

View File

@ -0,0 +1,71 @@
# Crypto::AlgorithmID
Является перечислением однобайтных целых чисел без знака, соответствующих идентификаторам допустимых к использованию в базовом протоколе криптографических (и не только) алгоритмов: хэшей, контрольных сумм, симметричного и ассиметричного шифрования.
<!--TODO: мб всё-таки не-криптуху стоит вынести?-->
## 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
};
}
```
<!--
TODO: симметрики распилить по категориям на блоковые и поточные
TODO: ассиметрики и подписи (RSA, YAK, CramerShoup system, Paillier cryptosystem, curves (25519 & 448), ElGamal, etc.)
-->

View File

@ -0,0 +1,13 @@
# Crypto::AlgorithmParams
Описывает параметры алгоритма, например размер ключа. Является двухбайтным целым без знака.
## C++
```C++
namespace Crypto {
typedef uint16_t AlgorithmParams;
}
```

View File

@ -0,0 +1,9 @@
# EventAsyncID
Является уникальным двухбайтным целым числом без знака и предназначен для определения отношения запросов к ответам при асинхронном обмене _событиями_.
## C++
```C++
typedef uint16_t EventAsyncID;
```

View File

@ -0,0 +1,9 @@
# LocalObjectID
Уникальный идентификатор объекта на сервере, является восьмибайтным числом без знака.
## C++
```C++
typedef uint64_t LocalObjectID;
```

View File

@ -6,11 +6,11 @@
Существует три уровня категорий _событий_: Существует три уровня категорий _событий_:
**Надкатегория** описывает типы взаимодействующих _узлов_. Не указывается и зависит от контекста. Варианты: _Client2Server_ (_событие_ сгенерированное _клиентом_ для _сервера_), _Server2Client_ (_событие_ сгенерированное _сервером_ для _клиента_), _Peer2Peer_ (_событие_ сгенерированное _узлом_ для другого _узла_ того-же ранга, в том числе это касается _серверов_ в федерации). **Надкатегория** описывает виды взаимодействующих _узлов_. Не указывается и зависит от контекста. Варианты: _Client2Server_ (_событие_ сгенерированное _клиентом_ для _сервера_), _Server2Client_ (_событие_ сгенерированное _сервером_ для _клиента_), _Peer2Peer_ (_событие_ сгенерированное _узлом_ для другого _узла_ того-же ранга, в том числе это касается _серверов_ в федерации).
**Категория** описывает _события_ одного класса. Является однобайтовым числом без знака. Всегда больше нуля. Например: _Authentication_, _Object_, т.п. **Категория** описывает _события_ одного класса. Является однобайтным числом без знака. Всегда больше нуля. Например: _Authentication_, _Object_, т.п.
**Подкатегория** описывает конкретное _событие_ из класса, соответствующего категории. Является однобайтовым числом без знака. Всегда больше нуля. Например: _Login_, _GetContents_, т.п. **Подкатегория** описывает конкретное _событие_ из класса, соответствующего категории. Является однобайтным числом без знака. Всегда больше нуля. Например: _Login_, _GetContents_, т.п.
Все категории вместе - являются типом _события_. Информацию про зарезервированные типы вы можете найти в [Reserved events.md](Reserved%20events.md). Все категории вместе - являются типом _события_. Информацию про зарезервированные типы вы можете найти в [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). Неизвестные ключи при обработке полезной нагрузки игнорируются. Если полезная нагрузка отсутствует, то она заменяется на один нулевой байт. Все _события_ содержат тип (см. выше раздел "Категории и типы").
<!--TODO: разные виды сериализации, в зависимости от транспорта?--> _События_ могут содержать полезную нагрузку, либо один нулевой байт, свидетельствующий о её отсутствии. Данная версия протокола не накладывает ограничений на формат полезной нагрузки, за исключением базовых событий, которые представлены данными в формате _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]
```
Максимальный размер _события_ не нормирован. Ответственность за менеджмент разделения _события_, в случае, если оно не помещается в один пакет, остаётся на транспортном уровне. Максимальный размер полезной нагрузки _события_ определяется на этапе рукопожатия.

145
Handshake.md Normal file
View File

@ -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[]`
- _Обязательна:_ только для шифрованного ХШ
- Описывает запрашиваемые к использованию в этом соединении хэш-функции для формирования хэша полезной нагрузки. <!--TODO: упомянуть в структуре события использование нескольких алгоритмов совместно-->
- Алгоритм подписи
- _Ключ:_ `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`: зарезервировано
<!--
- Запрос транспорта (опционально)
- _Ключ:_ `0x05`
- _Тип:_ `uint8_t`
- Если существует, то интерпретируется как запрос переподключения к другому виду транспорта. TODO: Надо сделать енум.
-->
## Ответ на рукопожатие
На запрос рукопожатия с корректным магическим числом целевой _узел_ должен ответить пакетом либо с согласием, либо с ошибкой. Если это ответ с согласием, то данные в пакете должны быть зашифрованы с помощью переданного в запросе хэндшейка симметричного шифра и переданного приватного ключа. Если это ответ с ошибкой, то он может быть незашифрован, в случае, если ошибка связанна с инициализацией шифрования или версией протокола. Таким образом, запрашивающий _узел_ должен быть готов обработать оба варианта развития событий, исходя из значения флага шифрования. Если цель не поддерживает указанные при рукопожатии параметры, запрашивающий может попробовать установить соединение снова, с иными параметрами.
Пакет ответа имеет следующую структуру:
`[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, описывающая ошибку в человекочитаемом виде.

View File

@ -1,125 +0,0 @@
# Рукопожатие
<!--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.

View File

@ -18,13 +18,9 @@
Выполняющий роль клиента _узел_ в многоранговой сети. Выполняющий роль клиента _узел_ в многоранговой сети.
### Подписанное соединение/сессия
Соединение между двумя _узлами_, все _события_ в котором подписаны с помощью оговорённого ассиметричного алгоритма и приватного ключа отправителя.
### Шифрованное соединение/сессия ### Шифрованное соединение/сессия
Соединение между двумя _узлами_, все _события_ в котором шифруется с помощью оговорённого симметричного алгоритма и ключа. Требует _подписанное соединение_ для установки. Соединение между двумя _узлами_, все _события_ в котором шифруются с помощью оговорённого симметричного алгоритма и ключа, а также подписываются с помощью известного приватного ключа подписи отправителя.
### Событие ### Событие
@ -36,88 +32,53 @@ _Событие_ предопределённой категории, имеющ
### LBM ### LBM
Аббревиатура наименования способа форматирования данных, используемого для полезной нагрузки _события_, которая расшифровывается как "Linear Binary Map". Подробнее - в [LBM.md](LBM.md). Аббревиатура наименования способа форматирования (сериализации) данных, используемого для полезной нагрузки _события_, которая расшифровывается как "Linear Binary Map". Подробнее - в [LBM.md](LBM.md).
### Шумовые данные ### Шумовые данные
Случайно-сгенерированные данные, помещённые в ячейку полезной нагрузки _события_. Случайно-сгенерированные данные, помещённые в специализированную ячейку полезной нагрузки _события_.
## Пример коммуникации двух узлов ## Пример коммуникации двух узлов
Допустим, что у нас есть два неизвестных друг-другу _узла_ - `p1` и `p2`. Тогда полная коммуникация по шагам (от подключения неизвестного для `p2` _узла_ - до "правильного" уничтожения сессии и закрытия соединения) будет выглядеть так: <!--TODO: предстоит переделать, ввиду предстоящих нововведений--> Допустим, что у нас есть два неизвестных\* друг-другу _узла_ - `p1` и `p2`. Тогда полная коммуникация по шагам (от подключения неизвестного для `p2` _узла_ - до "правильного" уничтожения сессии и закрытия соединения) будет выглядеть так:
1. `p1` подключается с помощью соответствующего транспорта к `p2` 1. `p1` запрашивает открытое (нешифрованное) рукопожатие с избранными параметрами соединения у `p2`
2. `p1` запрашивает рукопожатие с какими-то параметрами подключения 2. `p2` отвечает `p1` согласием со своей частью параметров
3. `p2` отвечает принятием со своей частью параметров подключения 3. `p1` запрашивает публичный ключ подписи у `p2`
4. `p1` запрашивает публичный ключ подписи у `p2`\* 4. `p2` передаёт свой публичный ключ, вместе с используемым алгоритмом
5. `p2` отвечает своим публичным ключом и данными об использующемся алгоритме 5. `p1` сохраняет полученный публичный ключ и разрывает\*\* соединение и заново устанавливает его, путём отправки `p2` запроса шифрованного хэндшейка
6. `p1` сохраняет публичный ключ сервера в своём хранилище 6. `p2` отвечает согласием со своей частью параметров подключения
7. `p1` отправляет _событие_ с запросом установки публичного ключа сессионной подписи, подписанное с помощью публичного ключа `p2`\*\* 7. `p1` отправляет зашифрованное _событие_ с запросом какого-то объекта
8. `p2` принимает запрос и устанавливает полученный ключ в качестве сессионного для подключения `p1`, если подпись валидна 8. `p2` отвечает зашифрованным _событием_, содержащее статус-код или этот объект
9. `p2` отвечает _событием_ с кодом успешности операции. С этого момента установлено _подписанное соединение_, т.е. узлы **обязаны** подписывать каждое _событие_ и отклонять любые неподписанные/с ложной подписью 9. `p1` отправляет _событие_ с сообщением о намерении уничтожить сессию и ждёт в течении n времени, по истечению которого может разорвать соединение "насильно"
10. `p1` отправляет _событие_ с запросом _шифрованного соединения_, симметричным ключом, зашифрованным с помощью публичного ключа сервера, и используемым алгоритмом шифрования\*\*\* 10. `p2` принимает запрос и прекращает любой параллельный обмен данными
11. `p2` принимает запрос и устанавливает текущий симметричный ключ сессии 11. `p2` отвечает _событием_ с кодом успешности операции
12. `p2` отвечает _событием_ с кодом успешности операции. С этого момента установлено _шифрованное соединение_, т.е. узлы **должны** шифровать _события_ с использованием обозначенного ключа 12. `p2` закрывает соединение
13. `p1` отправляет зашифрованное _событие_ с запросом какого-то объекта
14. `p2` отвечает зашифрованным _событием_, содержащее этот объект
15. `p1` отправляет _событие_ с сообщением о намерении уничтожить сессию и ждёт в течении n времени, по истечению которого может разорвать соединение "насильно"
16. `p2` принимает запрос и прекращает любой параллельный обмен данными
17. `p2` отвечает _событием_ с кодом успешности операции
18. `p2` закрывает соединение
И в виде схемы: И в виде схемы:
``` ```
Handshake: Requesting p2's public key:
[p1] --------[transport connect]------> [p2] [p1] ------[raw handshake request]----> [p2]
[p1] --------[handshake request]------> [p2] [p1] <-----[raw handshake accept]------ [p2]
[p1] <-------[handshake accept]-------- [p2]
Get p2's public key:
[p1] ----[request public sign key]----> [p2] [p1] ----[request public sign key]----> [p2]
[p1] <-[public key and crypto params]-- [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] [p1] ---------[close session]---------> [p2]
[p2]: decrypt and check event signature
[p2]: sign and encrypt event
[p1] <--------[status code OK]--------- [p2] [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]
``` ```
\* - _стоит уточнить, что в реальных сценариях использования этот публичный ключ должен быть уже известен <!--(см. `TODO`)-->, либо коммуникация должна производиться через транспорт, гарантирующий достоверность передаваемых данных._ \* - _стоит уточнить, что в реальных сценариях использования публичный ключ целевого узла скорее всего уже известен, либо коммуникация должна производиться через транспорт, гарантирующий достоверность передаваемых данных. `p1` может узнать о существовании таковых, путём отправки события специального типа. В данном примере сей шаг опущен._
\*\* - _это может быть публичный ключ подписи `p1`, а может быть и сгенерированный отдельно, в зависимости от сценария использования._ <!--TODO: таки описать этот шаг ^^^-->
\*\*\* - _установка шифрованного соединения полностью опциональна и его отсутствие не накладывает каких-либо ограничений, в рамках этой версии протокола. Формат события в таком соединении см. в [Events.md](Events.md)._ \*\* - _"разрыв" соединения предполагает обмен между узлами событиями с информацией о завершении сессии; в данном пункте эти шаги опущены, но упомянуты ниже._

View File

@ -1,18 +1,16 @@
# Спецификация протокола Stadium версии 1.0 # Спецификация протокола Stadium версии 1.0
Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх обширного перечня транспорта. Данная спецификация описывает базу, на основе которой могут быть реализованы расширения (_SPX - Stadium Protocol eXtension_) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon<!--, спецификация расширения которого находится в папке `SPX/Marafon/`-->. Stadium это протокол для безопасной коммуникации общего назначения, работающий поверх обширного перечня транспорта и архитектурно не зависящий от оного. Данная спецификация описывает базу, на основе которой могут быть реализованы расширения (_SPX - Stadium Protocol eXtension_) для более конкретных нужд. Помимо прочего, данный протокол служит основой для полнофункционального мессенджера Marafon<!--, спецификация расширения которого находится в папке `SPX/Marafon/`-->.
Основной фокус при работе над сим проектом идёт на: Основной фокус при работе над сим проектом идёт на:
- Возможность функционирования в условиях низкой пропускной способности канала; - Возможность функционирования в условиях низкой пропускной способности канала;
- Устойчивость к цензуре; - Устойчивость к цензуре;
- Поддержка широкого спектра транспортных протоколов; - Поддержка широкого спектра транспортных протоколов;
- Построение децентрализованных (федеративных и P2P) сетей; - Построение децентрализованных меш-сетей (как одноуровневых, так и двухуровневых);
- Гибкое сквозное шифрование; - Гибкое сквозное шифрование;
- Расширяемость и возможность подстраивания под конкретные задачи. - Расширяемость и возможность подстраивания под конкретные задачи.
<!--В сей спецификации вы можете встретить примеры кода и упоминание типов данных языка C++.-->
**ПРОЕКТ В АКТИВНОЙ РАЗРАБОТКЕ/PROJECT UNDER ACTIVE DEVELOPMENT** **ПРОЕКТ В АКТИВНОЙ РАЗРАБОТКЕ/PROJECT UNDER ACTIVE DEVELOPMENT**

View File

@ -1,6 +1,6 @@
# Зарезервированные типы событий # Зарезервированные типы событий
Некоторые категории _событий_ зарезервированы под нужды базового протокола или просто для _событий_ определённого класса. Второе носит рекомендательный характер; вы также можете использовать иные диапазоны для тех-же целей. Ниже приведены диапазоны зарезервированных значений в виде шестнадцатеричных чисел. Конкретный перечень всех зарезервированных событий, описание их структуры - есть в папке `Reserved events/`. Некоторые категории _событий_ зарезервированы под нужды базового протокола или просто для _событий_ определённого класса. Второе носит рекомендательный характер; вы также можете использовать иные диапазоны для тех-же целей. Ниже приведены диапазоны зарезервированных значений в виде шестнадцатеричных чисел. Конкретный перечень всех зарезервированных событий и описание их структуры - есть в папке `Reserved events/`.
Зарезервировано для нужд протокола и запрещено к использованию в сторонних расширениях: Зарезервировано для нужд протокола и запрещено к использованию в сторонних расширениях:
@ -11,10 +11,7 @@
2. Категория `0x01` 2. Категория `0x01`
- Все субкатегории: выделены для базовых _событий_, связанных с менджментом сессии. - Все субкатегории: выделены для базовых _событий_, связанных с менджментом сессии.
3. Категория `0x02` 3. Категория `0x11`
- Все субкатегории: выделены для базовых _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_.
4. Категория `0x11`
- Все субкатегории: выделены для базовых кодов ответа, ошибок и предупреждений. - Все субкатегории: выделены для базовых кодов ответа, ошибок и предупреждений.
@ -22,8 +19,3 @@
1. Категории `0x12`-`0x1F` (включительно) 1. Категории `0x12`-`0x1F` (включительно)
- Все субкатегории: для кодов ответа, ошибок и предупреждений сторонних реализаций. - Все субкатегории: для кодов ответа, ошибок и предупреждений сторонних реализаций.
2. Категории `0x20`-`0x2F` (включительно)
- Все субкатегории: для _событий_, которые могут быть приняты _узлом_ вне _подписанного соединения_.
<!-- TODO: событие запроса всех сервисов на сервере -->