GPLVote Trust Net - приложение для работы с сетью доверия
Логика работы приложения сети доверия
Персональный идентификатор
Персональный идентификатор - это хэш от персональных данных человека, который единым образом идентифицирует его внутри сети доверия. Для его создания используется алгоритм хэширования Bcrypt.
Метод создания (псевдокод):
N=1 hash = "" цикл по salt от 0 инкрементом hash = bcrypt(cost, salt, <персональные данные>+hash) если первые Z бит в hash нулевые N-- если N == 0, выход из цикла возврат "cost_hex$N_hex$Z_hex$hash_base64"
Значение "cost_hex$N_hex$Z_hex$hash_base64" и есть персональный идентификатор. Для его генерации используется значение salt, которое выдает N-й подходящий результат. И только его. Для проверки идентификатора придется вычислять полный цикл майнинга, поэтому включение salt в идентификатор не имеет смысла.
Для нашей сети доверия мы используем значения cost=8, N=1 и Z=8. Изменяя эти параметры в приложении сети доверия, можно формировать на той-же инфраструктуре изолированные сети доверия.
URL для QR-кодов, используемых в приложении
Регистрация нового сервера сети доверия
trustnet://regserver/<host сервера>
Верификация данных основного удостоверения
trustnet://verification/<JSON с данными для верификации>
Установка уровня доверия
trustnet://trust/<JSON с данными для установки уровня доверия>
Данные по тэгу дополнительного удостоверения
trustnet://taginfo/<JSON с информацией по тэгу>
Верификация дополнительного удостоверения
trustnet://tag/<JSON с привязкой тэга дополнительного удостоверения к персональному идентификатору и дополнительным данным>
Исходная информация для отправки сообщения получателю
trustnet://message/<Публичный ключ получателя в формате Base64> trustnet://msg/<Идентификатор публичного ключа получателя>
Публичный ключ пользователя
trustnet://publickey/<JSON с псевдонимом владельца и публичным ключем>
Работа с серверами
Вариант регистрации нового сервера сети доверия
- Потенциальный админ устанавливает и настраивает сервер сети доверия
- После установки заходит в админку нового сервера и делает несколько действий:
- Генерирует транспортный ключ нового сервера
- Подписывает документ со своим персональным идентификатором, идентификатором своего ключа, с именем нового сервера и с его публичным транспортным ключем. Данный подписанный документ выдается данным сервером по запросу с определенным URL (/signature). Сервер так-же должен по определенному URL (/signature_confirm?code=<любой код>) выдавать подписанный своим транспортным ключем случайный код. Это нужно для проверки на то, что сервер является тем сервером, за который себя выдает
- Админ в админке сервера формирует анонс сервера в сети доверия, подписывает его и отправляет в сеть
- После этого он связывается с другими админами серверов и просит их подписать свой статус админа в сообществе админов сети доверия
Как следствие - все содержательные пакеты между серверами должны подписываться транспортным ключем сервера-отправителя.
Регистрация в приложении нового сервера сети доверия по QR-коду
- Пользователь выбирает соответствующий пункт для сканировния QR-кода
- Приложение получает из QR-кода путь типа "trustnet://regserver/<ip сервера>"
- Приложение проверяет работоспособность сервера отправкой ему PING запроса
- Если запрос прошел нормально, сервер добавляется в локальную базу серверов с флагом "ручная регистрация"
- На этот новый сервер отправляется запрос на получение с него списка его доверенных серверов
- Отсутствующие в локальной базе сервера из этого списка запоминаются в локальной базе с флагом "доверенные" и пометкой об отсутствии теста (понадобиться в случае если не удастся отправить пакет на один из зарегистрированных локально серверов)
- На новый сервер из QR-кода отправляется открытый ключ текущего пользователя
- На новый сервер из QR-кода отправляются все данные с локальными удостоверениями, уровнями доверия и тэгами (данные, удостоверенные текущим пользователем)
Общая логика работы серверов сети доверия
Допуск сервера к работе в сети серверов производится на основании данных из сети доверия.
- Владелец сервера или серверов размещает в сети доверия пакет с подписанным списком своих серверов;
- Владельцы других серверов подписывают "удостоверение владельца сервера сети доверия" выставляя ему уровень доверия в качестве владельца серверов (уникальный идентификатор дополнительного удостоверения UUID - "00000000-0000-0000-0000-000000000000");
- Сервера сети доверия постоянно отслеживают пакеты со списком серверов и уровнем доверия владельцу и ведут локальный рейтинг остальных серверов;
- Параметры допуска серверов в сеть доверия должны регулироваться публичными рекомендациями, за которыми должны следить администраторы серверов сети доверия и перенастраивать свои сервера в соответствии с ними (среди параметров: уровень PoW, коэффициент рейтинга локального владельца для внешнего сервера при вычислении рейтинга внешнего сервера, коэффициент рейтинга других владельцев для внешнего сервера, глубина рекурсивного анализа сети доверия админов, степень затухания при рекурсивном анализе и т.д.);
Порядок подключения нового сервера
- Администратор нового сервера настраивает его
- Администратор через админку сервера и приложение SignDoc подписывает и отправляет в сеть доверия пакет с анонсом списка своих серверов (или одного сервера). Отправка происходит через админский интерфейс сервера. В рабочем режиме внешний интерфейс для приема подписанного документа у сервера можно закрыть.
- Администратор через систему сообщений связывается с одним или несколькими админами уже работающих серверов с просьбой авторизовать его сервер
- Админ работающего сервера подписывает доверие к данному новому админу
- Работающий сервер админа периодически шлет всем доверенным серверам пакет типа "PING"
- Новый сервер, получая "PING" от внешнего сервера определяет пустой список серверов и проводит процедуру инициализации базы данных, используя IP адрес сервера из пакета "PING" для получения данных (в первую очередь сервер запрашивает пакеты с анонсами серверов, уровнями доверия админов, удостоверениями и уровни доверия персональных идентификаторов админов)
- По мере подключения новых серверов через получение "PING", процедура инициализации становится распределенной
- После окончания процедуры инициализации сервер переходит в рабочий режим
- По умолчанию в начале работы сервер должен быть настроен на отправку данных серверам на основе данных сети доверия админов (которые закачиваются в первую очередь)
Особенности работы серверов сети доверия
- При наличии новых пакетов для внешнего сервера текущий сервер отправляет на него сначала список идентификаторов имеющихся новых пакетов. При этом для отправки этого списка используется Proof of Work - подбор хэша SHA512 настроенной сложности
- Если внешний сервер НЕ удовлетворяет такой уровень сложности, он может ответить отказом в приеме списка идентификаторов с ошибкой "Низкий уровень PoW"
- Если уровень сложности PoW устраивает, внешний сервер отправляет на данный запросы о содержимом пакетов для тех идентификаторов, которые у него отсутствуют
- При отправке пакета на следующий сервер, данный вставляет в его путь свой host
Типы пакетов
Для межсерверного общения
Все межсерверное общение идет POST запросами в корень сервера (http://host/).
Исходящий запрос на внешний сервер со списком новых пакетов:
{ "host": "<host сервера-источника пакетов>", "type": "IDS", "ids": ["<id пакета 1>", "<id пакета 2>", ...], }
Запрос сервером отсутствующие у него пакеты из списка:
{ "type": "GET_BY_IDS", "ids": ["<id пакета 1>", "<id пакета 2>", ...], }
Ответ со списком запрошенных пакетов:
[ { "id": "<идентификатор пакета в виде sha512 хэша его данных в BASE64 без переноса строк>", "path": "<путь прохождения пакета по серверам в виде [домен:ip] через запятую>", "packet": <данные пакета в стандартном виде (как при взаимодействии с клиентом)> }, ... ]
Для общения с приложением
Данные в направлении от приложения к серверу (POST запрос с JSON в теле POST запроса):
{ "doc": <json данных пакета в формате для подписания через приложение Sign Doc>, "sign": "<подпись данных>", "sign_pub_key_id": "<идентификатор ключа, подписавшего данные>", "sign_personal_id": "<персональный идентификатор подписавшего данный документ - дублируется из первого поля данных подписываемого удостоверения>", "pow_nonce": "<для некоторых типов пакетов содержит nonce, который совместно с данными doc формирует хэш с нулевыми стартовыми битами>" }
Данные от сервера приложению:
{ "status": <код ответа>, "error": "<сообщение об ошибке (если ошибки нет - пустая строка)>", "time": <unix time формирования пакета на сервере-источнике>, "doc": <json данных пакета> }
Возвращаемые сервером коды ответа:
- 200 - удачное завершение запроса
- 202 - такие данные уже есть на сервере
- 400 - неверные параметры запроса
- 402 - неверная подпись данных
- 404 - на сервере отсутствует запрошенные данные
- 412 - на сервере отсутствует публичный ключ по которому можно проверить подпись переданных данных
Сервисные пакеты
Пингующий серверный пакет
"doc": { "type": "PING", "source": "<ip сервера, отправляющего пинг>" }
Список адресов
Сервер, с которого запрашивается список адресов, возвращает первые 64 сервера с наивысшим рейтингом (по степени доверия, актуальности его онлайн статуса и т.д.).
"doc": { "type": "SERVERS", "list": ["<ip сервера 1>", "<ip сервера 2>", ...] }
Пакеты с данными
Анонс своего сервера
[ "<персональный идентификатор администратора>", "<текущее время в миллисекундах>", "<хост сервера (домен или IP адрес с, если необходимо, номером порта через ':')">, "<публичный ключ транспортного ключа сервера в формате BASE64 без перевода строк>" ]
Публичный ключ
Данные подписанного документа (в dec_data):
["<персональный идентификатор владельца>", "<текущее время GMT в формате UNIXTIME>", "<публичный ключ владельца в виде base64 без перевода строк>", "<публичный ключ отмены основного ключа в виде base64 без перевода строк>"]
Основное удостоверение
["<персональный идентификатор удостоверителя>", "<текущее время GMT в формате UNIXTIME>", "<заверяемый персональный идентификатор>", "<идентификатор заверяемого публичного ключа>", "<уровень верификации - от -127 до 127>"]
Уровень доверия
["<персональный идентификатор удостоверителя>", "<текущее время GMT в формате UNIXTIME>", "<персональный идентификатор>", "<уровень доверия - число от 0 до 127>"]
Дополнительное удостоверение
["<персональный идентификатор удостоверителя>", "<текущее время GMT в формате UNIXTIME>", "<идентификатор удостоверения в виде UUID закодированный в BASE64>", "<персональный идентификатор дополнительного удостоверения (персональный хэш)>", "<дополнительные удостоверяемые данные>", "<уровень верификации - от -127 до 127>"]
Идентификаторы вида "00000000-0000-0000-0000-xxxxxxxxxxxx" зарезервированы для внутреннего фиксированного использования сетью доверия.
Зарезервированные UUID дополнительных удостоверений
Список сообщений
От сервера приложению.
"doc": { "type": "LIST_MESSAGES", "list": ["<id сообщения 1>", "<id сообщения 2>", ... ], }
Сообщение
Для данного типа пакета в пакете должен присутствовать PoW (Proof of Work) в виде значения nonce, формирующего вместе с данными документа хэш bcrypt с несколькими нулевыми стартовыми битами. Это хэш подбирается аналогично алгоритму "майнинга" персонального идентификатора, но без циклической связи. Т.е. на следующем шаге НЕ используется результат предыдущего.
Идентификатор ключа отправителя берется из общего пакетного поля sign_pub_key_id.
["<текущее время GMT в формате UNIXTIME>", "<идентификатор ключа получателя>", "<зашифрованные публичным ключем получателя данные сообщения (подписывается открытое сообщение)>"]