Вот материал к обсуждению по безопасности DCNet. Желающих проконтролировать этот важный вопрос приглашаю к обсуждению. Голова хорошо, а две — лучше. Специалистов по безопасности среди нас не оказалось, поэтому сделаем что сможем.
Если что-то непонятно, задавайте вопросы. По идее, на основе этого текста (или, по крайней мере, по этой теме) нужно будет подготовить краткий буклет и/или видеоролик, который бы смог популярно показать юзерам, как они защищены. Потому что вкладывать много усилий (а картография это много усилий) сложно, когда нет уверенности в завтрашней сохранности и доступности данных, а выкладывать личные данные (сны с именами, местами, да и просто личными переживаниями) будет сложно, если нет уверенности в том, что их никто не прочитает.
Безопасность DCNet
Основные положения
Основное хранение данных осуществляется на нодах. На каждой ноде может храниться полная либо частичная (набор каналов) реплика данных.
Данные хранятся и предоставляются нодой открыто, любой желающий может сделать свою ноду и скопировать себе полную базу данных. Поэтому защита основывается, главным образом на шифровании и электронных подписях.
Необходимо, чтобы:
Пользователь мог быть идентифицирован без хранения пароля (или хэша) на ноде.
Доступ к приватным данным пользователя (скрытые сны и т.п.) мог получить только сам пользователь (не нода).
Можно было проверить авторство данных
Для этого предлагается следующая схема (сначала для случая единственной ноды):
Каждый пользователь имеет пару ключей ассиметричного шифрования. Публичный ключ каждого юзера доступен всем, приватный — только юзеру во время сессии.
Кроме того, по паролю пользователя генерируется ключ для симметричного шифрования (пример схемы тут:
http://qnimate.com/passphrase-based-enc ... raphy-api/). То есть, ключ нигде не хранится но может быть в любой момент сгенерирован пользователем по паролю. Зашифрованные этим ключом данные могут безопасно храниться на сервере. Условно будем это называть «зашифровано паролем».
Приватный ключ шифруется паролем и хранится на ноде вместе с незашифрованным публичным ключом юзера. Юзер скачивает свой зашифрованный приватный ключ и расшифровывает его паролем, и теперь может доказывать свою идентичность.
Хранение приватного ключа на ноде позволяет не таскать его с собой в виде файла.
Проверка идентичности. Юзер может подтвердить свою идентичность (фактически обладание приватным ключом) подписав случайное сообщение, выданное нодой, или расшифровав известное ноде сообщение. Однако необходимость в такой проверке типа «вход в систему», в общем-то не нужно, т.к. «залогиненность» юзера ничего не даёт — ни доступа к новым данным (данные ноды открыты), ни дополнительных прав.
При добавлении/модификации/удалении данных (снов, данных профиля и т.п.) запрос подписывается пользователем, и нода может это проверить зная публичный ключ юзера.
На случай забытого пароля юзер может заранее сохранить себе в безопасное место свой приватный ключ. Тогда, если он забудет пароль, то с помощью этого ключа он сможет восстановить доступ к своим данным. На этот случай есть смысл пароль, зашифрованный приватным ключом, хранить на сервере как часть профиля.
Сетевые вопросы безопасности (когда более одной ноды):
Нода тоже имеет пару ключей ассиметричного шифрования. Публичный ключ доступен открыто, приватный ключ хранится на сервере в недоступном месте. Доступ к приватному ключу имеет админ ноды и серверный код.
Добавление/модификация/удаление данных подписывается нодой. Так можно идентифицировать, какая нода производила изменения в распределённой базе данных (и добавить в чёрный список злоумышленника по факту выявления).
Синхронизация данных. Нода даёт любому желающему копию своей базы (доступ на чтение). Кроме того, нода подписывается на изменения в дублируемом наборе каналов у других нод. Если какие-то изменения произошли на других нодах, то эти модификации применяются во всех нодах, на подписанных на эту ноду и канал. Каждая модификация имеет две подписи — юзера и ноды, что затрудняет подделку.
Для борьбы с возможными нодами-злоумышленниками предлагается использовать белый список проверенных нод (фактически это и есть подписка ноды на обновления в другой ноде).
Возможна атака, когда нода-злоумышленник генерирует большое количество данных от лица группы пользователей (эти пользователи тоже должны быть злоумышленниками, т.к. нужны их приватные ключи), приводящая к переполнению хранилищ на обычных нодах. Это пресекается отслеживанием размера данных нод, причём по факту обнаружения ноды-злоумышленника можно прицельно её данные убрать из базы.
Мелкая и глубокая реплика. Нода может держать копию данных двух видов — текущее состояние и история изменений. Первый вариант менее расходует дисковое пространство, а второй вариант позволяет откатывать/просматривать историю. С учётом размеров данных можно предусмотреть полную историю по текстам, но текущее состояние по мультимедиа-данным (фото, видео, аудио).
Есть ещё момент связанный с тем, что нода-злоумышленник может долгое время прикидываться добропорядочной, но при этом встроить в клиентский код кейлоггер и тырить пароли. Хорошо бы от этого как-то защититься, чтобы юзер мог даже к сомнительной ноде подключаться ничем не рискуя (или рискуя мало чем). Я не знаю, есть ли способ «подписать» скрипты и проверить их подпись на клиенте.
Есть безопасный вариант, когда юзер скачивает html-страницу клиента с официальных источников и может проверить их цифровую подпись разработчика. Но это заморочка со скачкой и обновлением.
Другой, более прагматичный но менее защищённый вариант — это полагаться на https, заходя лишь по известному адресу. Но это создаст неудобства при закрытии ноды. Юзер должен будет знать адреса нескольких резервных нод, тоже проверенных.