Как я делаю файловое хранилище поверх gocryptfs — 1: Рождение идеи

Так получилось, что последние несколько лет я живу в Армении. Очень хорошо помню свой самый первый день тут — бельевые веревки, горячее солнце и запах свежего хлеба. Ереван только начинал просыпаться. Пекарни встречали первых покупателей, овощные лавки выставляли на тротуар ящики с ранними абрикосами. Немногочисленные прохожие неторопливо брели по своим делам.
Самый волнительный момент в новом месте — первый выход за едой. Для первого раза я решил ограничиться яйцами, сыром и кофе. Но банковская карта работать отказалась. Неловкая ситуация, если учесть, что наличных у меня не было.
И продавщица, которая видела меня впервые, просто отдала продукты. Сказала, что я могу занести деньги потом. Надеюсь, не потому, что я выглядел голодным.
Первый вечер тоже получился довольно странным — мы пили кофе на улице с каким-то арабом и на ломаном английском обсуждали недостатки PHP и сельское хозяйство ближневосточного региона.
Вообще говоря, вечера в Ереване располагают к неторопливым беседам за чашкой кофе. Или просто к размышлениям о чем-нибудь отвлеченном. В новой стране довольно быстро появляется странная привычка размышлять о вещах, на которые раньше не обращал внимания.
И вот одним из таких вечеров я размышлял о противоположностях. Взять, к примеру, принтер. Что будет его противоположностью? Можно предположить, что шредер. Он уничтожает то, что до этого напечатал принтер.
Или вот возьмем резервное копирование. Копируется оно себе куда-то в облако. А его противоположностью будет… хм. А что будет его противоположностью? Если рассуждать совсем прямолинейно, то напрашивается ответ: что-то, что уничтожает данные локально. Такой себе электронный шредер. Мысль показалась мне интересной и я продолжил размышлять в ту сторону.
Хорошо, допустим, резервное копирование я могу делать с помощью rsync. А чем тогда можно сделать противоположное? Чем локально уничтожить данные? На ум пришла только утилита shred. Параллель получилась забавная.
Окей, для резервного копирования существует целый мир: облачные хранилища, дата-центры, просто серверы. А что с противоположной стороны? Ничего. По крайней мере, на тот момент я ничего не нашел.
И тогда я стал думать, что это могло бы быть и как это могло бы работать.
2. По ту сторону резервного копирования
Предположим, что противоположность резервному копированию имеет право на существование. Значит, у нее тоже должно быть какое-то воплощение. Но какое?
Сервис, который безвозвратно уничтожает файлы? Получается корзина с автоматической очисткой. Нет, это слишком просто. Возможно, противоположность резервному копированию вообще не обязана ничего уничтожать.
Тогда сервис, который хранит файлы и не отдает их обратно? Звучит странно. Но, похоже, именно так.
│
Резервное │ Локальное
копирование │ неотдавание?
│
А зачем вообще может понадобиться такая черная дыра для файлов? Скорее всего, незачем. Если извлечь их невозможно, то чем это принципиально отличается от обычного удаления?
Значит, способ вернуть файлы все-таки должен существовать. Но он не должен быть простым.
А что вообще значит «не должно быть простым»? И зачем файлы должны там находиться? И почему их нельзя просто вернуть обратно? Кажется, мысленный эксперимент перестал быть мысленным экспериментом. Я уже пытался решить какую-то задачу. Оставалось только понять, какую.
3. От рассуждений к требованиям
Хорошо. Допустим, задача состоит не в том, чтобы уничтожить файлы, а в том, чтобы сделать их недоступными. Как тогда должна выглядеть такая система?
По всей видимости, речь идет о файловом хранилище. Но смысл такого хранилища должен определяться не тем, что оно хранит файлы. А тем, что никто, кроме владельца, не может получить их обратно. Из этого сразу следовали два вывода.
Во-первых, такое хранилище должно быть локальным. Иначе оно перестанет быть противоположностью резервного копирования, с которого все началось. Никаких облаков, серверов и, по большому счету, даже интернет не должен быть обязательным.
Во-вторых, локальности самой по себе недостаточно. Если всё хранилище попадет в чужие руки, его содержимое должно стать бесполезным набором байтов. Для этого как раз была придумана криптография.
Стоп. Кажется, в своих рассуждениях я пришел к чему-то знакомому. Я открыл поисковик.
4. Всё уже придумано до нас
Разумеется, у этого уже было название — NAS. Всё сходилось. Локальное файловое хранилище. Никаких обязательных облаков. Возможность включить шифрование. Отлично. Я закрыл поисковик.
Подождите. Кажется, я упустил одну очень важную разницу. Для большинства систем защита — это одна из функций хранения. Я же в своих рассуждениях пришел с противоположной стороны. Для меня хранение оказалось функцией защиты. Отличалась сама отправная точка.
Я снова открыл поисковик. Но теперь искал уже совсем другое.
Если моя догадка была верной, значит нужно искать устройства или сервисы, построенные по той же логике. Не просто файловые хранилища с возможностью шифрования, а системы хранения, для которых защита файлов была бы единственным смыслом существования.
Но мне показалось, что рынок разделился на две крайности. С одной стороны — обычные файловые хранилища, для которых защита была лишь одной из функций. С другой — специализированные устройства, построенные вокруг безопасности, но совершенно для других задач. Между ними словно оставалось пустое место.
Меня удивило, насколько странным оказался мой запрос. Я не хотел ничего революционного. Мне всего лишь нужно было, чтобы файловое хранилище вело себя как аппаратно защищенный накопитель. Мне не нужна была флешка. Мне не нужен был жесткий диск. Я хотел файловое хранилище.
Думаю, подобные штуки существовали. Но в тот момент это уже не имело никакого значения. Я больше не искал готовое решение. Теперь я точно знал, что должен сделать это сам.
5. Вначале была модель угроз
Поскольку отправной точкой в моих рассуждениях было не хранение, а защита, то и начинать следовало с модели угроз.
В качестве модели угроз я сразу выбрал самый неприятный сценарий: файловое хранилище оказывается в чужих руках. Как именно это произошло не имеет никакого значения. И основная проблема даже не в том, что это произошло. А в том, что это произошло внезапно.
Владелец больше не может выключить устройство, если оно было включено, или выполнить какую-то аварийную процедуру. С этого момента хранилище должно защитить себя само.
6. Защитить любой ценой или уничтожить навсегда
Если хранилище должно защищать себя самостоятельно, значит, должно существовать нечто, без чего оно просто перестает работать. В идеале — это сам владелец. Но определить, находится ли он рядом и все ли у него хорошо, хранилище не может. А вот определить наличие ключа — запросто.
Но ключ — это еще не владелец. Ключ можно скопировать, потерять или просто забрать силой. Одного фактора недостаточно.
Значит, должно существовать не только то, чем владелец обладает, но и то, что только он знает. То есть пароль.
Возможное решение самое стандартное: ключ должен быть зашифрован паролем, который знает только владелец. Тогда зашифрованный ключ не страшно терять, ломать и копировать:
┏━━━━━━━━━━━━━━━━━━┓
┃ Master password ┃
┃ ┌──────────────┐ ┃
┃ │ Secret key │ ┃
┃ └──────────────┘ ┃
┗━━━━━━━━━━━━━━━━━━┛
Encrypted secret key
Такая схема работы выглядела довольно просто: владелец подключает ключ и вводит пароль. После этого хранилище открывается, а его содержимое становится доступным.
Оставалась одна большая проблема. Что произойдет, если хранилище окажется в чужих руках после того, как было открыто? Пароль уже введен. Ключ уже расшифрован. Хранилище уже открыто.
Значит, хранилище должно уметь не только открываться для владельца, но и закрываться (или даже очищаться) при первых признаках опасности. Но что именно должно стать таким сигналом?
Ответа у меня не было. Было ясно, что потребуется реализовать Dead Man's Switch, но каким он станет и по каким признакам будет определять проблемы у владельца, предстояло разобраться позже.
7. Атака по правилам и без
Теперь можно было мысленно прогнать теоретическую модель угроз через реальные сценарии атаки и рассмотреть варианты защиты:
Атакующий украл закрытое хранилище без ключа. Самый простой сценарий. Для атакующего хранилище представляет собой тыкву. У владельца остается и ключ, и пароль, и резервная копия зашифрованных данных.
Атакующий украл закрытое хранилище с ключом. Принципиальной разницы с предыдущим сценарием нет. Без пароля это по-прежнему тыква для атакующего. У владельца остается резервная копия зашифрованного ключа и резервная копия зашифрованных данных.
Атакующий силой забрал закрытое хранилище без ключа и требует, чтобы владелец его открыл. Владелец уверяет, что ключ он потерял, а пароль забыл. В крайнем случае владелец может пожертвовать чем-то одним из перечисленного.
Атакующий силой забрал закрытое хранилище вместе с ключом и требует, чтобы владелец сообщил пароль. Из двух линий защиты остается только одна, но и ее достаточно до тех пор, пока у владельца остается возможность не вспомнить пароль.
Атакующий силой забрал открытое хранилище или заставил владельца открыть его. Это самый скверный сценарий. Атакующий прошел через базовые линии защиты. Тут должен сработать
Dead Man's Switch, который самостоятельно закроет хранилище или безвозвратно уничтожит его содержимое. И реализация этого механизма определенно будет интересной задачей.
8. Конец первой части
В следующей части мы посмотрим на свои реальные возможности и выберем первые технологии, на которых будет построено хранилище.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.