В этой статье я хочу рассказать, как я придумал идею web-сервиса защищенных социальных сетей. Как ее реализовывал и на каких технологиях. Поделюсь технологическими решениями проблем во время разработки сервиса.
Идея этого проекта у меня появилась после ознакомления с современным положением дел в области шифрования. Я столкнулся в двумя проблемами.
С одной стороны, это полная незащищенность пользователей от утечек информации из социальных сетей, мессенджеров и тд. Например Skype или Telegram хранит все переписки у себя на серверах и по требованию правительства предоставляют любые данных из этих переписок. Еще вспоминается, недавний взлом сайта знакомств для супружеских измен Эшли Мэдисон, где уплыли данные пользователей.
С другой стороны всем известно, что чем выше уровень защиты, тем менее приятнее пользоваться таким продуктом. Например, что бы подписать и зашифровать емайлы при помощи PGP, требует специальный софт и умение. Используя Telegram, ты обязан устанавливать их мессенджер и светить свою симку и к тому же режим секретного чата, только с одним пользователем, группового режима нет. Также сменив устройство, вы уже не посмотрите, о чем вы чатились ранее в секретом чате.
В интернете я встретил сервис, который позволяет шифровать текстовые заметки и хранить их в облаках. Доступ осуществлялся через обычный браузер и нужно было знать пароль от своих заметок. Фишка была в том, что сам сервис гарантировал, что он не может подсмотреть что у вас в заметках, так как шифрование происходило у вас в браузере по вашему паролю. А на сервере все передается уже в зашифрованном виде. Использовался алгоритм симметричного шифрования. Другими словами если кто-то получит доступ к вашим заметкам, то толку от этого нет, так как они зашифрованы.
Я взял эти две концепции на вооружение. Храним у себя на серверах данные пользователей уже зашифрованные. Процесс шифрования и расшифрования идет на стороне браузера пользователя по его паролю. Моя задача усложнилась тем, что мне надо сообщение от одного пользователя передать другому. Не будут же они одним и тем же паролем шифровать. Для этого я использовал алгоритм асимметричного шифрования. Для этого каждый пользователь должен иметь публичный и приватный ключ.
Когда один пользователь посылает сообщение другому, он должен брать публичный ключ второго пользователя и шифровать им сообщение. Второй пользователь получая сообщение использует свой приватный ключ для расшифровки. Вот тут как раз и пригодился подход симметричного шифрования по паролю. Публичные ключи их можно раздавать открыто, но заставлять пользователя таскать на флешке или хранить на винте его приватный ключ не удобно. Для этого я сделал, что бы публичный и приватный ключ генерировались в браузере пользователя и передавались на сервер. Публичный в открытом виде, а приватный закрытый паролем, который задает пользователь.
Дальше мне нужно было как-то понимать что посылаемое сообщение или запрашиваемый список сообщений приходит действительно от такого-то пользователя. Для этого все запросы от пользователя подписываются его приватным ключом, а у меня на серверах храниться его публичный ключ в открытом виде с помощью которого я и проверяю этот запрос или сообщение правда ли оно от этого пользователя или нет.
Когда встал вопрос о выборе технологий, я долго думал, сделать ли все быстро и на старых проверенных вещах. А может попробовать, то что новое и за чем стоит будущее. В итоге я написал серверную часть на Scala под управлением Play Framework на базе данных Cassandra. Клиентскую часть на CoffeeScript под управлением AngularJS. Дизайн взят от Bootstrap. Шифрование делал при помощи Forge библиотеки на JavaScript. К сожаление в HTML5 нет встроенных механизмов шифрования.
Архитектурно это выглядит как JavaScript-клиент, которых ходит по Rest на сервер. Также используется WebSocket для получения нотификаций о новых сообщений с сервера. Каждое WebSocket-соединение порождает Actor-a, который подписывается на шину событий Akka и если событие связано с его пользователем, то пересылает его в браузер.
Отдельно хочу отметить опыт использования базы данных Cassandra. Это несколько не привычно. Когда работаешь с обычной базой, то накидываешь таблицы, поля и пускаешь по ним любые запросы. Если тормозит, то добавляешь индексы. У Cassandra наоборот. Каждая таблица это по сути один главный запрос который быстро идет по заданным ключам в таблице. Те если вы решили как-то по иному с другими условиями выборки выдрать из нее данные, то вам придется делать еще одну таблицу и другие к ней ключи и по-сути дублировать данные. Этот подход мешает для быстрой разработки, так как тебя заставляет сразу все оптимально продумывать. Зато на продакшен вы тормозную какашку не выкатите:)
С исходными кодами проекта можно ознакомиться тут: github.com/evgenyigumnov/protectednet
Сам сервис в рабочем режиме доступен по ссылке: protectednet.io/?lang=ru
Идея этого проекта у меня появилась после ознакомления с современным положением дел в области шифрования. Я столкнулся в двумя проблемами.
С одной стороны, это полная незащищенность пользователей от утечек информации из социальных сетей, мессенджеров и тд. Например Skype или Telegram хранит все переписки у себя на серверах и по требованию правительства предоставляют любые данных из этих переписок. Еще вспоминается, недавний взлом сайта знакомств для супружеских измен Эшли Мэдисон, где уплыли данные пользователей.
С другой стороны всем известно, что чем выше уровень защиты, тем менее приятнее пользоваться таким продуктом. Например, что бы подписать и зашифровать емайлы при помощи PGP, требует специальный софт и умение. Используя Telegram, ты обязан устанавливать их мессенджер и светить свою симку и к тому же режим секретного чата, только с одним пользователем, группового режима нет. Также сменив устройство, вы уже не посмотрите, о чем вы чатились ранее в секретом чате.
В интернете я встретил сервис, который позволяет шифровать текстовые заметки и хранить их в облаках. Доступ осуществлялся через обычный браузер и нужно было знать пароль от своих заметок. Фишка была в том, что сам сервис гарантировал, что он не может подсмотреть что у вас в заметках, так как шифрование происходило у вас в браузере по вашему паролю. А на сервере все передается уже в зашифрованном виде. Использовался алгоритм симметричного шифрования. Другими словами если кто-то получит доступ к вашим заметкам, то толку от этого нет, так как они зашифрованы.
Я взял эти две концепции на вооружение. Храним у себя на серверах данные пользователей уже зашифрованные. Процесс шифрования и расшифрования идет на стороне браузера пользователя по его паролю. Моя задача усложнилась тем, что мне надо сообщение от одного пользователя передать другому. Не будут же они одним и тем же паролем шифровать. Для этого я использовал алгоритм асимметричного шифрования. Для этого каждый пользователь должен иметь публичный и приватный ключ.
Когда один пользователь посылает сообщение другому, он должен брать публичный ключ второго пользователя и шифровать им сообщение. Второй пользователь получая сообщение использует свой приватный ключ для расшифровки. Вот тут как раз и пригодился подход симметричного шифрования по паролю. Публичные ключи их можно раздавать открыто, но заставлять пользователя таскать на флешке или хранить на винте его приватный ключ не удобно. Для этого я сделал, что бы публичный и приватный ключ генерировались в браузере пользователя и передавались на сервер. Публичный в открытом виде, а приватный закрытый паролем, который задает пользователь.
Дальше мне нужно было как-то понимать что посылаемое сообщение или запрашиваемый список сообщений приходит действительно от такого-то пользователя. Для этого все запросы от пользователя подписываются его приватным ключом, а у меня на серверах храниться его публичный ключ в открытом виде с помощью которого я и проверяю этот запрос или сообщение правда ли оно от этого пользователя или нет.
Когда встал вопрос о выборе технологий, я долго думал, сделать ли все быстро и на старых проверенных вещах. А может попробовать, то что новое и за чем стоит будущее. В итоге я написал серверную часть на Scala под управлением Play Framework на базе данных Cassandra. Клиентскую часть на CoffeeScript под управлением AngularJS. Дизайн взят от Bootstrap. Шифрование делал при помощи Forge библиотеки на JavaScript. К сожаление в HTML5 нет встроенных механизмов шифрования.
Архитектурно это выглядит как JavaScript-клиент, которых ходит по Rest на сервер. Также используется WebSocket для получения нотификаций о новых сообщений с сервера. Каждое WebSocket-соединение порождает Actor-a, который подписывается на шину событий Akka и если событие связано с его пользователем, то пересылает его в браузер.
Отдельно хочу отметить опыт использования базы данных Cassandra. Это несколько не привычно. Когда работаешь с обычной базой, то накидываешь таблицы, поля и пускаешь по ним любые запросы. Если тормозит, то добавляешь индексы. У Cassandra наоборот. Каждая таблица это по сути один главный запрос который быстро идет по заданным ключам в таблице. Те если вы решили как-то по иному с другими условиями выборки выдрать из нее данные, то вам придется делать еще одну таблицу и другие к ней ключи и по-сути дублировать данные. Этот подход мешает для быстрой разработки, так как тебя заставляет сразу все оптимально продумывать. Зато на продакшен вы тормозную какашку не выкатите:)
С исходными кодами проекта можно ознакомиться тут: github.com/evgenyigumnov/protectednet
Сам сервис в рабочем режиме доступен по ссылке: protectednet.io/?lang=ru