stadium-proto/Overview.md

8.8 KiB
Raw Blame History

Обзор

Терминология

Здесь перечислены используемые в данной документации термины, значение которых может быть не очевидно и/или не соответствует тому, которое подразумевается обычно.

Узел

Любая машина, способная выполнять коммуникацию по протоколу Stadium. Обычно используется в контексте коммуникации двух машин одного ранга или когда ранг не имеет значения.

Сервер

Выполняющий роль сервера узел в многоранговой сети.

Клиент

Выполняющий роль клиента узел в многоранговой сети.

Подписанное соединение/сессия

Соединение между двумя узлами, все события в котором подписаны с помощью оговорённого ассиметричного алгоритма и приватного ключа отправителя.

Шифрованное соединение/сессия

Соединение между двумя узлами, все события в котором шифруется с помощью оговорённого симметричного алгоритма и ключа. Требует подписанное соединение для установки.

Событие

Структура данных, обладающая конкретными семантическими свойствами в зависимости от типа и содержащая дополнительные поля, требуемые для верного отображения и интерпретации самой структуры. Проще говоря - то, чем обмениваются и что обрабатывают узлы во время коммуникации между собой.

Шумовое событие

Событие предопределённой категории, имеющее случайно-сгенерированные поля.

LBM

Аббревиатура наименования способа форматирования данных, используемого для полезной нагрузки события, которая расшифровывается как "Linear Binary Map". Подробнее - в 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.