Нашей команде доверяют аудит информационной безопасности. Не хочется представлять, что будет, если результаты одной из таких проверок утекут в сеть. Так что мы очень серьезно относимся к сохранности рабочих документов. А еще мы немного параноики, поэтому и решили изобрести велосипед разработать облако для безопасной совместной работы с файлами и поделиться наработками. Да, облачные хранилища делают командную работу проще, особенно когда все на удаленке. Но, как правило, ради удобства провайдеры жертвуют безопасностью. Большинство из них управляет ключами шифрования в той же среде, где находятся зашифрованные файлы. Файлы регулярно расшифровывают для индексации и обработки, чтобы обеспечить работу дополнительных функций облака: совместного доступа, обмена файлами, поиска по содержимому. В этот момент данные особенно уязвимы для хакерских атак, да и в остальное время риски довольно высоки. Если злоумышленник получает доступ к системе хранения провайдера, то лишь вопрос времени, когда он найдет файлы и соответствующие им ключи. Бывает, такие хищения совершают сами администраторы, которые знают, как работает сервис, и могут замести следы. Владельцы файлов не контролируют, как выполняется шифрование в облачных сервисах, и кто имеет доступ к ключам для расшифровки. Поэтому утечки случаются с завидной регулярностью, и от них страдают даже крупнейшие компании. Например, в октябре 2020 года с серверов Nitro Software украли 1 ТБ конфиденциальных документов, принадлежавших Google, Apple, Microsoft и Citibank. Конечно, можно шифровать данные вручную, еще перед загрузкой в облако. Такой подход подходит для хранения бекапов, но он неудобен для повседневной работы. Практически невозможно заставить рядовых сотрудников регулярно шифровать файлы перед отправкой. Попытки вручную рассылать пароли, управлять группами пользователей, открывать и закрывать доступ и делиться файлами отнимут уйму сил и неизбежно превратятся в бардак. Знаем, пробовали. Поэтому мы взялись за разработку системы, в которой сочетались бы удобство современного облачного хранилища, end-to-end шифрование и принцип on-premise — возможность развернуть все на собственной инфраструктуре. Особенность разработки криптографических систем в том, что здесь нет простора для творчества. Оно даже вредно. Нельзя просто взять и придумать новый протокол шифрования, его безопасность должна быть доказана многолетними независимыми исследованиями. И так во всем. Поэтому задача сводится к тому, чтобы отобрать стек проверенных технологий, заставить их работать вместе и делать то, что нужно. Гуру криптографии вряд-ли найдут в наших решениях нечто оригинальное. Дальше мы просто попробуем понятно объяснить, как работает обмен ключами, и с какими подводными камнями связано шифрование в браузере. Для хранения данных выбрали S3 MinIO и PostgreSQL. S3 обеспечивает свободу в выборе площадки. Можно установить сервер в офисе, а можно без проблем переехать на инфраструктуру практически любого хостера. MinIO поддерживает избыточное хранение данных и дает уверенность в том, что их можно будет восстановить после отказа нескольких жестких дисков. Чтобы использовать e2e-шифрование и в то же время реализовать удобное управление доступом к файлам, пришлось уделить много внимания криптографии. Мы использовали алгоритм AES256 GCM. С его помощью последовательно шифруется каждый файл в хранилище, шифруется каждая папка, каждый каталог с файлами. При этом ключи шифрования хранятся рядом с зашифрованными файлами. Получается иерархия из ключей, которая повторяет структуру файловой системы. На ее вершине находится так называемый rootKey, который генерируется случайным образом для каждого пользователя. Именно на его базе генерируются ключи дочерних папок и файлов первого уровня. Это необходимо, чтобы пользователь мог оперировать и делиться зашифрованными файлами так, как привык это делать в привычных облачных сервисах. Благодаря тому, что каждый файл зашифрован своим ключом, можно делиться доступом к отдельным каталогам и файлам, не расшифровывая их на сервере. Хранилище устроено так, что доступ можно отозвать в любой момент и перешифровать файлы, которые раньше были доступны другим пользователям. RootKey, который дает доступ к корневому каталогу и всему содержимому облака, хранится отдельно и зашифровывается еще раз с использованием аутентификации открытым ключем (создается «коробка» на базе 25519-xsalsa20-poly1305). Такой подход гарантирует, что никто кроме пользователя не сможет расшифровать корневой каталог, получить доступ к отдельным файлам и ключам для их расшифровки. Каждый файл шифруется перед загрузкой в BSC на компьютере пользователя при помощи свежего 256-битного симметричного ключа. Целостность данных обеспечивает Galois/Counter Mode — специальный режим работы алгоритма AES. Для передачи данных между клиентской машиной и облаком используется обычный HTTPS. Файл помещается в нужное место в каталоге и последовательно шифруется вплоть до мастер-ключа. Организовать безопасный обмен файлами с незарегистрированными, недоверенными пользователями оказалось сложнее. Пришлось использовать многослойное шифрование и вовсю жонглировать ключами.  Следите за руками. Сейчас будет сложно. Предположим, клиент должен безопасно передать нам в Бастион электронную копию договора. Мы генерируем ссылку на загрузку файла при помощи веб-интерфейса облака. К ссылке автоматически добавляется «хвост» из случайной последовательности знаков. Часть этой последовательности выступает в роли идентификатора ID, а часть используется в качестве ключа A. Приложение отсылает ID на сервер облака, а мы отправляем ссылку клиенту, например, через мессенджер. Вместе с ссылкой клиент получает доступ к клиентскому веб-приложению для загрузки файлов в облако, ID и ключ A. При помощи веб-интерфейса облака клиент генерирует симметричный ключ B и шифрует им договор. Затем, веб-интерфейс использует ID для подключения к облаку, отправляет туда зашифрованный договор и получает публичный ключ C, созданный заранее на стороне Бастион. Теперь клиентское приложение шифрует файл с ключом B при помощи ключа C. И тут же шифрует получившийся файл еще раз при помощи ключа A. На нашей стороне эта матрешка расшифровывается в обратном порядке. Сперва ключом A, переданным по независимому каналу связи, затем секретным ключом C, который не покидал компьютер. Таким образом, ни один из компонентов, необходимых для расшифровки, не попадает на файловый сервер. Причем эту схему можно отзеркалить и генерировать ссылки на безопасную загрузку файлов, которые будут расшифровываться только на компьютере клиента. Все функции облака можно было реализовать при помощи отдельного приложения, но мы хотели, чтобы оно работало без установки плагинов и дополнительного ПО. Современные браузеры поддерживают шифрование, так что в этом нет ничего невозможного. Проблема в том, что никто не рассчитывал, что с их помощью будут расшифровывать большие файлы. Браузер — прежде всего средство просмотра веб-страниц и выполнения несложной логики с ограниченным доступом к аппаратным средствам. Разработчики делают все, чтобы не давать воли троянам, поэтому браузер не имеет прямого доступа к файловому хранилищу и пишет данные напрямую на жесткий диск. А ведь нам нужно сперва скачать файл, расшифровать его и поместить куда-то расшифрованную версию. Сперва мы использовали оперативную память вкладки браузера. С маленькими файлами это работало, но мы быстро уперлись в ограничения. Если вкладка потребляет много оперативной памяти, браузер закрывает ее и перезапускает. Например, Safari ограничивает потребление вкладки примерно 4 ГБ. Это, не говоря о том, что оперативная память сама по себе сильно ограниченный ресурс. В средненьком ноутбуке установлено 8 ГБ, а необходимо обеспечить работу и с более тяжелыми файлами. Первое, что мы сделали — настроили последовательную загрузку и скачивание файлов. Вместо того, чтобы работать с зашифрованным файлом целиком, стали дробить его на небольшие фрагменты и удалять их сразу после обработки. Это помогло избавиться от проблем с загрузкой в облако, но не решало проблемы со скачиванием тяжелых файлов. Нужное решение лежало в другой плоскости. Мы проводили расшифровку файла в том же потоке, который отвечает за отрисовку страницы с веб-интерфейсом облака. Однако в браузерах используется Workers — механизм, который позволяет запускать скрипты в фоновом потоке, отдельно от страницы. Каждый Worker использует собственную память, и, как выяснилось, может использовать файл подкачки. Переложив расшифровку на Worker, мы избавились от проблемы с ограниченным объемом ОЗУ и ускорили расшифровку, задействовав несколько ядер процессора. Даже веб-интерфейс стал отзывчивее, так как Worker работает асинхронно, независимо от вкладки, и не мешает браузеру обрабатывать страницу. К следующему релизу мы хотим перенести в Worker не только расшифровку, но и процесс шифрования. Это должно ускорить отправку файлов. Впрочем, и без этого мы успешно используем BSC в повседневной работе. Возможно, облако пригодится и вам. Дистрибутив доступен для свободного скачивания. Bastion Secure Cloud можно пользоваться бесплатно, без ограничений на объем хранилища и доступные функции. Единственное условие — размер команды — до 10 зарегистрированных пользователей. Вы можете создавать публичные папки и с их помощью обмениваться файлами с незарегистрированными пользователями, так что это не такой жесткий лимит, как можно подумать. Недавно мы полностью переработали интерфейс BSC, добавили мобильную верстку, управление правами на доступ к файлам и теперь занимаемся разработкой новых функций. Планируем реализовать создание и скачивание архивов, подобно тому, как это работает в Google Drive и Яндекс.Диск и готовим клиент для windows и linux-машин. Делаем ставку на то, что компании станут внимательнее относиться к хранению данных, спрос на защищенные хранилища будет расти, и готовимся к этому Главный по блогу Бастион, научный журналист