Encryption: AES-256-GCM для файла базы, WAL и temp-файлов
Аналитические данные нередко чувствительны: персональные данные клиентов, финансовые показатели, коммерческая тайна. Если файл базы попадёт не в те руки — скопируют флешку, потеряют ноутбук, утечёт бэкап, — данные окажутся доступны. Шифрование решает эту проблему: без ключа файл — бессмысленный набор байт. В DuckDB 1.4 появилось встроенное шифрование базы данных, и этот урок разбирает, как оно устроено и как им пользоваться.
Шифрование — заключительная тема модуля про запись данных, и логичная: оно касается того, в каком виде данные ложатся на диск.
Что такое encryption at rest
Уточним, о каком шифровании речь. Encryption at rest — шифрование данных «в покое», то есть на диске. Цель — чтобы файл базы, физически лежащий на накопителе, без ключа невозможно было прочитать.
Это защита от конкретной угрозы: кто-то получил доступ к файлу базы — скопировал, украл носитель, добрался до бэкапа. С шифрованием at rest этот файл без ключа бесполезен.
Чего encryption at rest не делает: это не про защиту данных в оперативной памяти работающего процесса и не про сетевое шифрование канала. DuckDB — embedded-СУБД, у неё нет сетевого протокола, и угроза «перехват трафика» к ней неприменима. Encryption at rest закрывает именно сценарий «файл попал к чужому».
Алгоритм: AES с 256-битным ключом, режим GCM
DuckDB шифрует базу алгоритмом AES (Advanced Encryption Standard) — индустриальным стандартом симметричного шифрования. Ключевые параметры:
- Длина ключа — 256 бит. AES-256 — самый стойкий вариант AES, применяемый там, где нужна максимальная защита.
- Режим работы по умолчанию — GCM (Galois/Counter Mode). GCM — это authenticated encryption: он не только шифрует данные, но и обеспечивает их целостность. То есть GCM не только скрывает содержимое, но и позволяет обнаружить, что зашифрованные данные были подменены или повреждены. Шифрование без проверки целостности оставляло бы возможность незаметной модификации; GCM эту дыру закрывает.
Симметричное шифрование означает, что один и тот же ключ используется и для зашифровки, и для расшифровки. Этот ключ задаёт пользователь; без него открыть базу нельзя.
AES-256 в режиме GCM — это authenticated encryption: одновременно конфиденциальность (содержимое скрыто) и целостность (подмена или повреждение зашифрованных данных обнаруживается). Поэтому шифрование DuckDB защищает не только от чтения файла чужими, но и даёт уверенность, что данные в файле не были незаметно изменены.
Что именно покрывается шифрованием
Это критически важная деталь. Зашифровать только основной файл базы — недостаточно: данные могут «утечь» через вспомогательные файлы. Шифрование DuckDB покрывает три компонента:
- Основной файл базы данных — собственно
.dbфайл с таблицами. Очевидная цель. - WAL (write-ahead log) — журнал упреждающей записи. В нём временно оседают изменения до checkpoint. Если бы WAL был незашифрован, свежие изменения утекали бы через него.
- Temp-файлы — файлы спилла во
temp_directory. Как мы знаем из модуля про out-of-core, при нехватке памяти DuckDB сбрасывает на диск промежуточные данные: hash-таблицы, буферы сортировки. В этих temp-файлах лежат куски реальных данных. Незашифрованные temp-файлы были бы дырой в защите.
Покрытие всех трёх компонентов означает, что данные шифруются на всех путях попадания на диск: и в постоянное хранилище, и в журнал, и во временные файлы. Дыры, через которую расшифрованные данные оказались бы на накопителе, не остаётся.
Криптографическая реализация: mbedtls или OpenSSL
Криптографические примитивы DuckDB берёт из двух источников:
- mbedtls — компактная криптобиблиотека, встроенная в DuckDB. Доступна всегда, без дополнительных установок. Это реализация по умолчанию.
- OpenSSL — широко известная криптобиблиотека, подключается через расширение
httpfs. На некоторых платформах OpenSSL-реализация AES быстрее за счёт аппаратного ускорения.
Для пользователя различие в основном в производительности: базовая встроенная mbedtls работает всегда «из коробки»; при установленном httpfs доступен путь через OpenSSL. Функционально обе дают то же AES-256-GCM.
Почему вообще важно аппаратное ускорение AES. Современные процессоры (x86 с набором инструкций AES-NI, ARM с криптографическими расширениями) умеют выполнять шаги AES на уровне отдельных инструкций CPU — в разы быстрее, чем чистая программная реализация. Криптобиблиотека, собранная с поддержкой этих инструкций, шифрует и расшифровывает существенно быстрее. Именно поэтому путь через OpenSSL на части платформ оказывается быстрее: его сборки активнее используют аппаратное ускорение. На практике это означает, что overhead шифрования на современном железе с AES-NI обычно невелик — расшифровка не становится узким местом запроса.
Как пользоваться: ключ при ATTACH
Шифрование задаётся ключом при подключении базы. Ключ передаётся через механизм параметров шифрования при ATTACH.
Создание зашифрованной базы. При создании новой базы указывается ключ — база сразу создаётся зашифрованной:
-- подключить (создав) базу с ключом шифрования
ATTACH 'secret.db' AS enc (ENCRYPTION_KEY 'мой-секретный-ключ');
-- работаем как с обычной базой
CREATE TABLE enc.customers AS SELECT * FROM source_data;
Открытие зашифрованной базы. Чтобы открыть существующую зашифрованную базу, нужно передать тот же ключ:
-- открыть зашифрованную базу — ключ обязателен и должен совпадать
ATTACH 'secret.db' AS enc (ENCRYPTION_KEY 'мой-секретный-ключ');
Без ключа или с неверным ключом база не откроется — это и есть суть защиты.
Ключ шифрования не хранится внутри базы — иначе шифрование не имело бы смысла. Если ключ потерян, зашифрованная база становится невосстановимой: данные есть на диске, но расшифровать их нечем. Храните ключ отдельно и надёжно — в менеджере секретов, переменной окружения, защищённом хранилище. Потеря ключа равнозначна потере всех данных базы.
Практические следствия использования шифрования:
- Производительность. Шифрование и расшифровка стоят CPU-времени на каждой операции I/O. На современных процессорах с аппаратным ускорением AES накладные расходы обычно умеренные, но они не нулевые — за безопасность платят небольшим замедлением.
- Управление ключом — отдельная задача. Сам факт шифрования бесполезен, если ключ лежит рядом с базой в открытом виде. Безопасность сводится к безопасности хранения ключа.
- Бэкап зашифрованной базы. Копия зашифрованного файла остаётся зашифрованной — это плюс. Но логический дамп через
EXPORT DATABASEвыгрузит данные в обычные Parquet/CSV — а они уже не зашифрованы. Если дамп тоже должен быть защищён, об этом нужно позаботиться отдельно.
Когда применять шифрование
Шифрование — не бесплатное (CPU-overhead) и добавляет операционную сложность (управление ключом). Включать его стоит осознанно.
| Сценарий | Шифрование нужно? |
|---|---|
| База с персональными данными клиентов на ноутбуке/съёмном носителе | да — высокий риск физической утраты |
| Файл базы хранится в облачном/общем хранилище | да — доступ к файлу могут получить третьи лица |
| Регуляторные требования к данным (PII, финансы, медицина) | да — часто обязательно по комплаенсу |
| Локальная учебная или публичная неконфиденциальная база | нет — overhead без выгоды |
| Промежуточные данные пайплайна, не покидающие защищённую среду | обычно нет |
Принцип: шифрование оправдано там, где есть реальная угроза физического доступа к файлу или того требует регуляторика. Для неконфиденциальных данных в контролируемой среде это лишний overhead.
Попробуй сам
- Создай зашифрованную базу: в CLI выполни
ATTACH 'enc_demo.db' AS e (ENCRYPTION_KEY 'test-key-123');и создай в ней таблицу с парой строк черезCREATE TABLE e.t AS SELECT range AS id FROM range(100);. Заверши сессию. - Попробуй открыть
enc_demo.dbБЕЗ ключа — простоATTACH 'enc_demo.db' AS e;или открыв файл напрямую. Что происходит? - Открой её с ПРАВИЛЬНЫМ ключом:
ATTACH 'enc_demo.db' AS e (ENCRYPTION_KEY 'test-key-123');и проверьSELECT count(*) FROM e.t;Данные на месте? - Попробуй открыть с НЕВЕРНЫМ ключом (
'wrong-key'). Сравни поведение с шагом 2 и шагом 3. - Сделай
EXPORT DATABASEзашифрованной базы в каталог и открой получившийся Parquet-файл напрямую обычнымSELECT * FROM 'dump/t.parquet';. Зашифрован ли экспортированный Parquet? Сформулируй, почему при бэкапе зашифрованной базы через EXPORT DATABASE о защите дампа нужно думать отдельно.