diff --git a/.gitignore b/.gitignore index 997dd27..b94ca36 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ _old/* -1.2. Терминология.md +Терминология.md diff --git a/README.md b/README.md index 945543a..a26862a 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ Stadium это протокол для безопасной коммуникац Основной фокус при работе над этим проектом идёт на: -- Низкий оверхэд и возможность функционирования в условиях низкой пропускной способности канала; +- Минимизация оверхэда и возможность функционирования в условиях низкой пропускной способности канала; +- Приемлимое функционирование в условиях большого количества потерь пакетов; - Поддержка широкого спектра транспортных протоколов из коробки; - Гибкое и кастомизируемое сквозное шифрование; - Расширяемость и возможность подгонки под конкретные задачи. -**Внимание!** В данный момент проект переживает глобальные архитектурные изменения. Данная версия спецификации акцентирует внимание на закреплении общих, преимущественно фундаментальных идей и концепций, потому и является *неформальной*. +**Внимание!** В данный момент проект находится в стадии активного проектирования. Данная версия спецификации акцентирует внимание на закреплении общих, преимущественно фундаментальных идей и концепций, потому и является *неформальной*. diff --git a/Криптография.md b/Криптография.md new file mode 100644 index 0000000..d835674 --- /dev/null +++ b/Криптография.md @@ -0,0 +1,52 @@ +# Криптография + +Перед данным протоколом стоит задача обеспечить гибкое шифрование с минимальным ущербом для совместимости между реализациями. Достигается это путём широкого спектра поддерживаемых "из коробки" криптографических алгоритмов и их комбинаций, вкупе с возможностью расширения этого списка в частных случаях, а также возможностью шифрования "в несколько слоёв". Реализуемая стадиумом криптографическая система, помимо базового свойства (сокрытие передаваемых данных от третьих лиц), обеспечивает следующие несколько вещей: + +- **Достоверность данных**: передаваемые по протоколу данные подписываются с помощью ассиметричного шифрования, алгоритмом, выбранным на этапе подключения, что исключает возможность их подмены. +- **Исключение атак повторного воспроизведения**: каждый пакет снабжён уникальными идентификатором, что приводит к невозможности проведения replay-атак. +- **Forward Secrecy**: компрометация долговременного ключа или сессионных ключей не приводит к компрометации прошлых сессионных ключей. +- **Future Secrecy**: компрометация сессионных ключей не приводит к компрометации будущих сессионных ключей. +- **Исключение различных вариаций статистического анализа**: сессионные ключи регулярно проходят ротацию, в соединение подмешиваются "шумовые" пакеты, а в пакеты с реальными данными подмешиваются "шумовые данные", что размывает статистические характеристики и затрудняет анализ, предотвращая разные формы атак на основе шифротекста. + +В рамках криптографической системы стадиума существуют несколько понятий, таких как: + +- **StreamId**: идентификатор потока. В зашифрованном потоке уникален для каждого отдельного пакета, в незашифрованном - статичен на протяжении всей сессии. Используется для определения принадлежности пакета к потоку данных и, в контексте зашифрованного потока, исключения reply-атак. К одному потоку всегда привязаны ровно два идентификатора, один для использования клиентом и другой для сервера. В случае с зашифрованным потоком, обновляется с помощью KDF, в которой подаётся прошлое значение StreamId и константа. +- **Packet Authentication Code**: код аутентификации пакета. Используется для проверки целостности и достоверности пакета, создаётся путём вычисления хэша из тела события и последующей его подписи с помощью приватного SSK отправителя. Непрошедшие проверку целостности пакеты отбрасываются. +- **Private Stream Signing Key**: сессионный ключ для подписывания пакетов в шифрованном потоке. У сервера и клиента свои ключи. +- **Public Stream Signing Key**: сессионный ключ для верификации пакетов в шифрованном потоке. У сервера и клиента свои ключи. +- **Packet Encryption Key**: сессионный ключ для шифрования содержимого пакетов в шифрованном потоке с помощью симметричного алгоритма. У сервера и клиента свои ключи. В случае с зашифрованным потоком, обновляется с помощью KDF, в которой подаётся прошлое значение PEK и константа. +- **Private Identity Key**: долговременный приватный ключ. Хранится у сервера и используется для расшифровки полученных запросов рукопожатия. +- **Public Identity Key**: долговременный публичный ключ. Ассоциирован с сервером и используется для шифрования запроса рукопожатия при создании шифрованного потока. + +Значительная часть функциональности протокола, в том числе касающаяся криптографии, опциональна в том смысле, что может не использоваться в рамках отдельного потока. К примеру, в нём может быть не только настроено количество шума, но и полностью отключен. Таким-же образом, коммуникация может происходить вовсе без шифрования, что может быть полезно, например, для снижения нагрузки на железо, когда протокол транспортного уровня уже обеспечивает требуемый уровень приватности. + + +## Пример коммуникации двух узлов + +Ниже приведена схема коммуникации двух узлов (Алиса - клиент, Боб - сервер), при условии, что PEK обновляются каждый пакет (т.е. уникальны для каждого отдельного пакета). + +```text +1: Alice -- request handshake --> Bob +2: Alice <-- accept handshake -- Bob +3: Alice -- send encrypted packet --> Bob +4: Alice and Bob updates Alice's PEK and StreamId using KDFs +5: Alice <-- send encrypted packet -- Bob +6: Bob and Alice updates Bob's PEK and StreamId using KDFs +7: Alice -- update PEK KDF const --> Bob +8: Alice and Bob updates Alice's PEK using KDF with new const and StreamId +9: Alice -- update StreamId KDF const --> Bob +10: Alice and Bob updates Alice's PEK and StreamId using KDF with new const +``` + +Более детальное описание схемы: + +1. Алиса отправляет Бобу зашифрованный с помощью публичного IK запрос рукопожатия, содержащий публичный SSK Алисы; инициализационное значение и константу для KDF, отвечающей за обновление PEK Алисы; инициализационное значение и константу для KDF, генерирующего StreamId Алисы; а также прочие параметры создаваемых сессии и потока. +2. Боб принимает шифрованный запрос рукопожатия, расшифровывает с помощью своего приватного IK и отвечает Алисе своим публичным SSK; инициализационным значением и константой KDF, отвечающей за обновление PEK Боба; инициализационное значение и константу для KDF, генерирующего StreamId Боба; а также прочей своей частью параметров, зашифровав их с помощью публичного SSK Алисы. +3. Алиса шифрует пакет с помощью своего PEK, подписывает с помощью своего приватного SSK, снабжает текущим StreamId и отправляет Бобу. +4. Боб получает пакет, проверяет его с помощью публичного SSK Алисы и расшифровывает с помощью PEK Алисы. После этого Алиса и Боб обновляют PEK и StreamId Алисы с помощью двух KDF. +5. Боб шифрует пакет с помощью своего PEK, подписывает с помощью своего приватного SSK, снабжает текущим StreamId и отправляет Алисе. +6. Алиса получает пакет, проверяет его с помощью публичного SSK Боба и расшифровывает с помощью PEK Боба. После этого Боб и Алиса обновляют PEK и StreamId Боба с помощью двух KDF. +7. Алиса запрашивает обновление константы KDF, генерирующей её PEK, помещая в пакет новое значение константы, после чего повторяя шаги из пункта 3. +8. Боб получает пакет, проверяет его с помощью публичного SSK Алисы и расшифровывает с помощью PEK Алисы. Затем Алиса и Боб обновляют константу для KDF генерирующей PEK Алисы, а также сам PEK и StreamId Алисы с помощью двух KDF. +9. Алиса запрашивает обновление константы KDF, генерирующей её StreamId, помещая в пакет новое значение константы, после чего повторяя шаги из пункта 3. +10. Боб повторяет шаги из пункта 8, но вместо обновления константы KDF для генерации PEK - обновляет уже константу для генерации StreamId Алисы. diff --git a/Оглавление.txt b/Оглавление.txt index 5e1aa1d..5f94441 100644 --- a/Оглавление.txt +++ b/Оглавление.txt @@ -1,51 +1,64 @@ -ВНИМАНИЕ! В этой версии оглавления обнаружены существенные недостатки, потому оно точно изменится в дальнейшем. - 1. Введение - 1.1. Цели и мотивация - 1.2. Терминология - 1.3. Пример работы в виде схемы -2. Параметры - 2.1. Магическое число протокола - 2.2. Версия протокола - 2.3. CryptoDesc [дескриптор криптоалгоритма] - 2.3.1. HashCryptoDesc - 2.3.2. SymCiphCryptoDesc - 2.3.3. AsymCiphCryptoDesc - 2.4. CryptoPack [набор криптоалгоритмов] - 2.4.1. HashCryptoPack - 2.4.2. SymCiphCryptoPack - 2.4.3. SignCryptoPack [набор для подписи, AsymCiphCryptoDesc + HashCryptoDesc] - 2.4.4. KDCryptoPack [набор для Key Derivation, либо существующая KDF, либо SymCiphCryptoDesc + HashCryptoDesc] - 2.4.4.1. KDInitValue [значение, которым впервые инициализируется KDF] - 2.4.4.2. KDPrivConst [приватное значение, используемое в качестве второго аргумента KDF] - 2.6. Linear Binary Map -3. Рукопожатие - 3.1. Базовые параметры - 3.2. Параметры криптографии - 3.3. Запрос - 3.4. Ответ -4. Сессия -5. Поток - 5.1. Состояние - 5.2. SID, SSID, CSID - 5.3. Шифрование - 5.4. Контроль последовательности событий - 5.5. Шум + 1.1. Безопасность и модель угроз +2. Базовая терминология +3. Криптография + 3.1. Дескриптор криптоалгоритма [CryptoDs] + 3.1.1. Дескриптор хэш-функции [HashCryptoDs] + 3.1.2. Дескриптор симметричного шифра [SymCiphCryptoDs] + 3.1.3. Дескриптор асимметричного шифра [AsymCiphCryptoDs] + 3.2. Дескриптор набора криптоалгоритмов [CryptoPack] + 3.2.1. Набор для хэширования [HashCryptoPack] + 3.2.2. Набор для симметричного шифрования [SymCiphCryptoPack] + 3.2.3. Набор для подписи [SignCryptoPack; набор для подписи, т.е. AsymCiphCryptoDs + HashCryptoDs] + 3.2.4. Набор для генерации ключей [KDCryptoPack; набор для Key Derivation, т.е. существующая KDF или SymCiphCryptoDs + HashCryptoDs] + 3.2.4.1. Стартовое значение для KDF [KDInitValue; значение, которым впервые инициализируется KDF] + 3.2.4.2. Константа для KDF [KDPrivConst; приватное значение, используемое в качестве второго аргумента KDF] +4. Установка соединения + 4.1. Возможные параметры + 4.1.1. Магическое число протокола + 4.1.2. Версия протокола + 4.2. Запрос рукопожатия + 4.3. Ответ на рукопожатие +5. Сессия + 5.1. Поток + 5.1.1. Состояние + 5.1.2. Идентификатор потока [StreamId, SrvStreamId, CltStreamId] + 5.1.3. Секрет потока [StreamSecret] + 5.1.4. Криптографические параметры потока + 5.1.5. Параметры сжатия потока + 5.1.6. Контроль последовательности + 5.1.7. Шумовые пакеты + 5.2. Секрет сессии [SessionSecret] 6. Событие - 6.1. Заголовок - 6.1.1. MAC, CMAC, SMAC [проверка целостности + проверка достоверности] - 6.1.2. Асинхронный идентификатор [AID] - 6.1.3. Тип события - 6.2. Полезная нагрузка - 6.3. Структура - 6.3.1. Открытого события - 6.3.2. Шифрованного события - 6.4. Запрос и ответ -7. Безопасность и модель угроз -8. Распределение типов событий - - ... конкретные типы ... -9. Зарезервированные ячейки LBM - - ... конкретные ячейки ... -10. Расширения протокола + 6.1. Тип события + 6.2. Зарезервированные типы и диапазоны типов событий + 6.3. Содержание события + 6.3.1. Формат содержания зарезервированных событий + 6.4. Запрос и ответ [абстрактно] +7. Пакет + 7.1. Заголовок пакета + 7.1.1. Код аутентификации [Packet Authentication Code, PAC, CltPAC, SrvPAC; проверка целостности и достоверности] + 7.1.2. Флаги + 7.1.3. Идентификатор ответа [RespId] + 7.2. Полезная нагрузка + 7.2.1. Шум в полезной нагрузке пакета + 7.3. Структура и шифрование + 7.4. Пачка пакетов и разбиение полезной нагрузки +8. Транспортный адаптер + 8.1. Дескриптор транспортного адаптера [TransportDs] + 8.2. Свойства адаптеров + 8.2.1. Максимальный размер полезной нагрузки + 8.2.2. Гарантия последовательности + 8.2.3. Гарантия обнаружения недоставки [?] + 8.2.4. Гарантия целостности + 8.2.5. Наличие шифрования + 8.3. Список адаптеров [возможно, что стоит вынести в отдельную спеку] + 8.3.1. UDP-raw + 8.3.2. TCP-raw + 8.3.3. HTTP1.1-text+binary [текстовые HTTP/1.1 POST-запросы и бинарные ответы] + 8.3.4. [???] +9. Сериализация данных [Linear Binary Map (?)] + 9.1. Используемые ключи полезной нагрузки +10. Расширения протокола [SPX] 10.1. Идентификатор расширения [SPXI] 10.2. Дескриптор расширения [SPXD] diff --git a/Событие.md b/Событие.md new file mode 100644 index 0000000..0381909 --- /dev/null +++ b/Событие.md @@ -0,0 +1,5 @@ +# Событие + +Событие представляет из себя минимальную смысловую единицу, которой могут обмениваться узлы в соединении. Событиями из зарезервированного диапазона типов (см. `6.2.`) оперирует протокол для управления соединением, все остальные события могут использоваться уровнем приложения для прочих нужд. Событие содержит тип и тело. Тип описывает способ интерпретации тела, а тело содержит произвольные данные, размер которых ограничен значением, обозначенным на этапе хэндшейка. При попытке отправки приложением данных, превышающих этот лимит, на стороне клиента стадиум должна возникнуть ошибка. Сервер не должен предполагать, что получает данные валидной длинны и должен производить проверки самостоятельно. + +Тип события является двухбайтным целым числом без знака. Событие может предполагать ответ от противоположного узла или не требовать оный. Наличие необходимости ответа определяется типом, в каждом случае индивидуально. Корректный тип события никогда не равен нулю.