stadium-proto/Overview.md

124 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Обзор
## Терминология
Здесь перечислены используемые в данной документации термины, значение которых может быть не очевидно и/или не соответствует тому, которое подразумевается обычно.
### Узел
Любая машина, способная выполнять коммуникацию по протоколу Stadium. Обычно используется в контексте коммуникации двух машин одного ранга или когда ранг не имеет значения.
### Сервер
Выполняющий роль сервера _узел_ в многоранговой сети.
### Клиент
Выполняющий роль клиента _узел_ в многоранговой сети.
### Подписанное соединение/сессия
Соединение между двумя _узлами_, все _события_ в котором подписаны с помощью оговорённого ассиметричного алгоритма и приватного ключа отправителя.
### Шифрованное соединение/сессия
Соединение между двумя _узлами_, все _события_ в котором шифруется с помощью оговорённого симметричного алгоритма и ключа. Требует _подписанное соединение_ для установки.
### Событие
Структура данных, обладающая конкретными семантическими свойствами в зависимости от типа и содержащая дополнительные поля, требуемые для верного отображения и интерпретации самой структуры. Проще говоря - то, чем обмениваются и что обрабатывают _узлы_ во время коммуникации между собой.
### Шумовое событие
_Событие_ предопределённой категории, имеющее случайно-сгенерированные поля.
### LBM
Аббревиатура наименования способа форматирования данных, используемого для полезной нагрузки _события_, которая расшифровывается как "Linear Binary Map". Подробнее - в [LBM.md](LBM.md).
### Шумовые данные
Случайно-сгенерированные данные, помещённые в ячейку полезной нагрузки _события_.
## Пример коммуникации двух узлов
Допустим, что у нас есть два неизвестных друг-другу _узла_ - `p1` и `p2`. Тогда полная коммуникация по шагам (от подключения неизвестного для `p2` _узла_ - до "правильного" уничтожения сессии и закрытия соединения) будет выглядеть так: <!--TODO: предстоит переделать, ввиду предстоящих нововведений-->
1. `p1` подключается с помощью соответствующего транспорта к `p2`
2. `p1` запрашивает рукопожатие с какими-то параметрами подключения
3. `p2` отвечает принятием со своей частью параметров подключения
4. `p1` запрашивает публичный ключ подписи у `p2`\*
5. `p2` отвечает своим публичным ключом и данными об использующемся алгоритме
6. `p1` сохраняет публичный ключ сервера в своём хранилище
7. `p1` отправляет _событие_ с запросом установки публичного ключа сессионной подписи, подписанное с помощью публичного ключа `p2`\*\*
8. `p2` принимает запрос и устанавливает полученный ключ в качестве сессионного для подключения `p1`, если подпись валидна
9. `p2` отвечает _событием_ с кодом успешности операции. С этого момента установлено _подписанное соединение_, т.е. узлы **обязаны** подписывать каждое _событие_ и отклонять любые неподписанные/с ложной подписью
10. `p1` отправляет _событие_ с запросом _шифрованного соединения_, симметричным ключом, зашифрованным с помощью публичного ключа сервера, и используемым алгоритмом шифрования\*\*\*
11. `p2` принимает запрос и устанавливает текущий симметричный ключ сессии
12. `p2` отвечает _событием_ с кодом успешности операции. С этого момента установлено _шифрованное соединение_, т.е. узлы **должны** шифровать _события_ с использованием обозначенного ключа
13. `p1` отправляет зашифрованное _событие_ с запросом какого-то объекта
14. `p2` отвечает зашифрованным _событием_, содержащее этот объект
15. `p1` отправляет _событие_ с сообщением о намерении уничтожить сессию и ждёт в течении n времени, по истечению которого может разорвать соединение "насильно"
16. `p2` принимает запрос и прекращает любой параллельный обмен данными
17. `p2` отвечает _событием_ с кодом успешности операции
18. `p2` закрывает соединение
И в виде схемы:
```
Handshake:
[p1] --------[transport connect]------> [p2]
[p1] --------[handshake request]------> [p2]
[p1] <-------[handshake accept]-------- [p2]
Get p2's public key:
[p1] ----[request public sign key]----> [p2]
[p1] <-[public key and crypto params]-- [p2]
[p1]: saves p2's public key at local storage
Make signed connection:
[p1]: sign event
[p1] --------[set session sign]-------> [p2]
[p2]: check event signature
[p2]: associates p1's public key with this connection
[p2]: sign event
[p1] <--------[status code OK]--------- [p2]
[p1]: check event signature
Make encrypted connection:
[p1]: sign event
[p1] ---[set session symmetric key]---> [p2]
[p2]: check event signature
[p2]: associates symmetric key with this connection
[p2]: sign and encrypt event
[p1] <--------[status code OK]--------- [p2]
[p1]: decrypt and check event signature
Request some object:
[p1]: sign and encrypt event
[p1] ------[request some object]------> [p2]
[p2]: decrypt and check event signature
[p2]: sign and encrypt event
[p1] <-------[some object data]-------- [p2]
[p1]: decrypt and check event signature
Close session:
[p1]: sign and encrypt event
[p1] ---------[close session]---------> [p2]
[p2]: decrypt and check event signature
[p2]: sign and encrypt event
[p1] <--------[status code OK]--------- [p2]
[p2]: close connection
[p1]: decrypt and check event signature
```
\* - _стоит уточнить, что в реальных сценариях использования этот публичный ключ должен быть уже известен <!--(см. `TODO`)-->, либо коммуникация должна производиться через транспорт, гарантирующий достоверность передаваемых данных._
\*\* - _это может быть публичный ключ подписи `p1`, а может быть и сгенерированный отдельно, в зависимости от сценария использования._
\*\*\* - _установка шифрованного соединения полностью опциональна и его отсутствие не накладывает каких-либо ограничений, в рамках этой версии протокола. Формат события в таком соединении см. в [Events.md](Events.md)._