Как работает DeM
Для понимания работы DeM желательно ознакомится с общей информацией по Artery Storage описанной в этой статье
На текущий момент весь обмен DeM с нодами строится на базе REST API (JSON RPC). Для проверки аутентичности и неизменности запросов все они подписываются приватным ключом отправителя и приложения (для этого JSON канонизируется, после чего вычисляется его sha256 хэш, который и обрабатывается с помощью Secp256k1 DSA и полученная цифровая подпись добавляется в тело JSON).
Инициализация
Так как весь обмен данными происходит через ноды Artery Storage, в первую очередь необходимо присоединиться к ним. Поиск и соединение может осуществляться двумя способами: с использованием централизованного адреса API компании или, если по каким то причинам адрес недоступен или не возвращает список нод, обратиться ко встроенному в приложение списку ip адресов управляющих нод.
После запуска приложения и получения соединения с первыми управляющими нодами им отправляется запрос на получение адресов нод, обслуживающих данные конкретного аккаунта (от которого запущено конкретное приложение). После получения списка и соединения с «хранящими» нодами, дальнейший обмен служебной информацией осуществляется уже с ними.
К служебной информации относятся — список нод, хранящих переписки пользователя, список контактов пользователя (в зашифрованном виде), лимиты места на хранение данных, адреса блокчейн нод, информация об аккаунтах блокчейн по их адресу и нику, настройки приложения. На этом «этап инициализации» завершен.
Выход приложения в сеть
Во-первых, приложение производит обновление временной метки последнего своего присутствия в сети, запускает таймер регулярного уведомления о нахождении «онлайн».
Во-вторых, оно связывается с нодами, хранящими переписку, и скачивает новые сообщения и контакты в локальную (расположенную на телефоне) базу, запускает таймер регулярного опроса на предмет появления новых записей (резервный механизм обновления сообщений и контактов).
Принцип обмена сообщениями (через ноды стор)
При обмене сообщениями приложение отправляет запросы на «хранящие» ноды (полученные на этапе инициализации).
Исходящие сообщения
Приложение получает из блокчейн публичный ключ пользователя-адресата, шифрует им сообщение и записывает его в публичный раздел хранящей ноды получателя сообщения. Также копия сообщения, зашифрованная публичным ключом отправителя, записывается в его собственный публичный раздел.
Входящие сообщения
Пользователь записывает зашифрованное вашим публичным ключом сообщение на вашу хранящую ноду, а ваше приложение скачивает эти сообщения, расшифровывает его с помощью приватного ключа и сохраняет в локальное хранилище.
Все операции подписываются ключом пользователя и проверяются на аутентичность (неизменность и принадлежность конкретному пользователю).
По сути, сообщение представляет из себя блок данных в формате JSON, зашифрованных аналогично блокам загружаемых в Storage файлов.
При этом JSON содержит поля, необходимые мессенджеру для правильной трактовки сообщения. А именно: кто является отправителем, получателем, локальная временная метка, содержимое сообщения, информация о вложении.
Сборка мусора
По умолчанию публичный раздел пользователя имеет размер 5ГБ, увеличить этот лимит можно, отправив соответствующую транзакцию в блокчейн. Когда это место заканчивается, в зависимости от настроек пользователя, либо новые сообщения перестают приниматься и отправляться, либо самые старые сообщения автоматически удаляются, чтобы освободить место для новых. Удалённые таким образом сообщения восстановлению не подлежат.
Отправка файлов
Схема отправки файлов в мессенджере полностью аналогична таковой при загрузке файлов в Artery Storage, с одной оговоркой — хэши загруженных блоков не добавляются в индексный блок, а прикрепляются к блоку конкретного сообщения, которому они принадлежат. Это позволяет в дальнейшем удалять файлы вместе с сообщениями во время циклической записи.
Подпись на события
Для быстрой доставки сообщений в протоколе предусмотрена подпись на события, происходящие в Storage (при записи в данных DeM). Подписка осуществляется через Websockets (используется библиотека Socket.io), и отвечают за нее хранящие ноды.
Подробнее про структуру блока и шифрование
Структура блока полностью унифицирована в рамках Artery Storage.
Любой блок имеет заголовок, хранящий следующую информацию:
- версия заголовка;
- тип блока;
- метод шифрования, используемый в блоке;
- размер блока;
- его хэш.
Кроме этого блок сообщения имеет также временную метку, которая помогает упростить обработку таких блоков.
Методы шифрования могут реализовываться конкретными приложениями, использующими Storage, и помечаться ими в заголовке. При этом для разных задач и разными разработчиками могут использоваться разные методы (DeM использует XChaCha20 и эллиптические кривые Secp256k1).
Исходное содержимое блока шифруется с помощью случайного ключа, полученного CPRNG (cryptographically secure pseudorandom number generator) и таким же образом полученного nonce. Дополнительно в каждый блок данных добавляется произвольный набор (длинной до 32) байт (соль), чтобы усложнить подбор ключа. После этого использованные ключ и nonce также дополняются солью и шифруются с использованием эллиптической кривой и публичного ключа пользователя, полученного из блокчейн ранее. Получатель сообщения, используя только ему известный приватный ключ, расшифровывает данные в обратном порядке.
Защита от спама
Для защиты от спама реализована подпись всех запросов не только ключом пользователя, но и ключом приложения. Это позволяет проверить, является ли источник сообщения доверенным системе, а также аннулировать доступ отдельных приложений в систему в процессе работы.
Для получения ключа стороннему разработчику необходимо обратиться в лидерский совет, который после согласования внесёт ключ в систему. Для тестирования и проверки библиотек вне продакшн среды планируется запуск тестнет, в котором ключ сможет получить любой желающий по запросу на e-mail компании.
Хранение данных на клиенте (кэш, шифрование)
Все данные при записи и скачивании сохраняются в локальную базу данных на устройстве для обеспечения офлайн доступа и ускорения повторной загрузки (при переходе из одного чата в другой берутся из локальной копии, а не скачиваются повторно). При этом в текущей разрабатываемой версии DeM предусмотрено шифрование этих данных ключом, построенным на основе PIN кода. Для шифрования используется библиотеки android-database-sqlcipher на Android и SQLCipher на iOS, шифрование 256 bit AES.
Отправка транзакций в Artery Blockchain из DeM
Для отправки переводов и оплаты Storage приложение формирует соответствующую транзакцию, подписывает её приватным ключом пользователя и отправляет на публичную ноду блокчейн. Формирование и подписание транзакции происходят непосредственно на устройстве пользователя, а значит его приватные данные никуда не передаются. Реализацию этого (и всего остального) функционала можно посмотреть в библиотеке dem-api на GitHub.
Централизованные функции
В мессенджере есть ряд централизованных функций, децентрализованная реализация которых либо в принципе невозможна, либо потребовала бы слишком много ресурсов от нод Artery Storage. Такие функции были реализованы с целью повышения удобства пользовательского интерфейса и построены так чтобы не влиять на изначальную идею и основную функцию DeM — децентрализованный обмен сообщениями. В итоге на текущий момент уже реализованы такие улучшения как:
- переводы сообщений (для переводов используется Google Translate, и его ответы кэшируются, чтобы не переводить типовые фразы по многу раз; все фразы для перевода отправляются обезличено и в отрыве от контекста);
- тип активности пользователя в чате (например: “печатает сообщение”);
- время последнего визита.