Что такое шифрование данных в базах данных и зачем оно нужно
Шифрование данных в базе данных переводит содержимое таблиц, журналов транзакций и файлов данных в нечитаемый набор байтов, который нельзя расшифровать без ключа. Ключ хранится отдельно от данных, поэтому копия каталога data, украденный снапшот тома или дамп базы без ключа бесполезны для атакующего. Расшифровка идёт в момент чтения: силами СУБД либо в приложении до попадания данных в таблицу.
Практический ответ на главный вопрос: метод выбирают по модели угроз, а не по названию технологии. Защита от кражи диска или снапшота закрывается прозрачным шифрованием (TDE). Когда администратор базы не должен видеть номера карт и паспортные данные, нужен столбцовый уровень или шифрование в приложении. Три уровня решают разные задачи, и в одной системе они часто работают вместе.
Прозрачное шифрование шифрует файлы данных и журналы целиком, приложение об изменениях не знает. Шифрование на уровне столбцов закрывает конкретные поля вызовами функций СУБД. Шифрование на стороне приложения выполняется до отправки INSERT, и СУБД ключей не видит вообще. Любой из методов закрывает один класс рисков, утечку носителя или копии данных, и не отменяет управление доступом, аудит и защиту соединений.
Цифры показывают масштаб проблемы. В отчёте Verizon DBIR 2024 на человеческий фактор приходится 68% утечек, а IBM оценила среднюю стоимость утечки в 2024 году в 4,88 млн долларов. Утечка шифрованного дампа без ключей не превращается в инцидент с уведомлением регулятора и клиентов, а восстановление репутации обходится дороже самой защиты.
Перед включением шифрования полезно навести порядок в правах: ревизия привилегий и настроек соединений разобрана в материале про аудит безопасности PostgreSQL, MySQL и MongoDB в 2026 году. Дальше: сравнительная таблица трёх уровней, пошаговые примеры для PostgreSQL, MySQL и MongoDB, управление ключами через KMS, замеры производительности и критерии выбора.
Три уровня шифрования: TDE, шифрование на уровне столбцов и на стороне приложения
Сравнение начинается с модели угроз. Если злоумышленник получает физический доступ к диску, съёмную копию снапшота или архив резервной копии, поможет любой из трёх уровней. Если открытые данные доступны администратору базы, TDE не спасает: расшифровка идёт внутри СУБД, и SELECT вернёт открытый текст. Разница между уровнями видна в таблице.
| Критерий | TDE | Шифрование столбцов | Шифрование в приложении |
|---|---|---|---|
| Что шифруется | Файлы данных, журналы, временные файлы | Отдельные поля таблиц | Данные до отправки в СУБД |
| Где хранятся ключи | Keyring СУБД, внешний KMS, HSM | Приложение или keyring, ключ передаётся в запросе | Только приложение, KMS или Vault |
| Кто видит открытый текст | Любой пользователь с правом SELECT | Любой, кто знает ключ и имеет право SELECT | Только приложение с ключом |
| Защита от недобросовестного DBA | Нет | Частично | Да |
| Индексы и поиск | Работают без изменений | Обычные индексы и LIKE недоступны | Поиск и сортировка только в приложении |
| Изменения в приложении | Не требуются | Правки запросов на чтение и запись | Переработка логики работы с полями |
| Overhead | 5-15% на дисковом вводе-выводе | 20-30% на операциях с полями | около 40% в приложении |
| PostgreSQL | Расширение pg_tde от Percona, в core нет | pgcrypto | библиотека cryptography и аналоги |
| MySQL | Enterprise TDE и Percona Server | AES_ENCRYPT и AES_DECRYPT | любая библиотека |
| MongoDB | Шифрование на уровне хранилища | CSFLE, Queryable Encryption | любая библиотека в драйвере |
Прозрачное шифрование данных (TDE): когда оно оправдано
TDE защищает данные на диске (data at rest) и не защищает от SQL-инъекций, ошибок в приложении и администратора с доступом к памяти процесса. Расшифровка идёт на уровне страниц InnoDB или файлов данных, ключи подгружаются при старте СУБД, поэтому доступность keyring критична: без него база просто не откроется.
MySQL Enterprise включает TDE с плагинами keyring_file и keyring_okv. Файловый keyring_file годится для тестового стенда, для продакшена берут Oracle Key Vault или внешний KMS. Percona Server for MySQL поддерживает TDE с плагином keyring_vault и держит мастер-ключ в HashiCorp Vault. Приложение правок не требует, планы запросов не меняются. Расплата: зашифровать отдельные столбцы нельзя, а логи и бэкапы нуждаются в отдельной настройке.
В PostgreSQL TDE в core отсутствует. Расширение pg_tde от Percona долгое время находилось в статусе беты и умеет шифровать таблицы через keyring-файл. Для продакшена без сторонних расширений остаются столбцовое шифрование или защита тома средствами операционной системы, например LUKS. Клиентские и серверные модели шифрования с гибридными схемами разобраны в руководстве про шифрование данных при передаче и хранении.
Шифрование на уровне столбцов: гибкость и компромиссы
Столбцовое шифрование закрывает конкретные поля: номер карты, СНИЛС, паспортные данные, токен доступа. Остальные колонки остаются открытыми, обычные индексы и аналитика продолжают работать. Ключ передаётся в функцию шифрования, поэтому главный вопрос звучит так: откуда приложение берёт этот ключ. Если он лежит в той же базе или в конфиге рядом с ней, защита теряет смысл.
Ограничения проявляются на этапе запросов. Зашифрованный текст нельзя поместить в B-tree индекс, сравнить операторами больше и меньше, найти через LIKE. Диапазонные отчёты по таким полям приходится строить в приложении. Детерминированное шифрование даёт одинаковый шифротекст для одинаковых значений и разрешает поиск равенством, order-preserving шифрование сохраняет порядок, но обе схемы снижают стойкость: атакующий видит частотные закономерности.
Шифрование на стороне приложения: максимальная защита
При шифровании в приложении открытый текст не покидает код сервиса. СУБД получает готовый шифротекст, ключей не знает и не может расшифровать его даже по прямому запросу администратора. Так закрывается угроза недобросовестного DBA, утечки дампа и доступа к снапшотам. Цена высокая: серверный поиск, агрегация и уникальность по зашифрованным полям ломаются, а ключи нужно выдавать приложению через KMS или Vault.
Библиотеки: cryptography и PyNaCl в Python, libsodium в C и Go, jose в JavaScript. Формат Fernet из библиотеки cryptography даёт AES-128-CBC с HMAC-SHA256 и проверкой целостности, что защищает от подмены шифротекста. Для новых проектов берут AES-256-GCM или ChaCha20-Poly1305: обе схемы аутентифицируют данные и не позволяют незаметно изменить зашифрованное значение.
Как зашифровать базу данных: пошаговые примеры для PostgreSQL, MySQL и MongoDB
Ниже рабочие команды для трёх СУБД. Перед любыми действиями снимите свежий бэкап и проверьте восстановление на отдельном стенде: включение шифрования меняет формат файлов и путь отката.
Шифрование в PostgreSQL: pgcrypto и pg_tde
Расширение pgcrypto входит в состав contrib и ставится одной командой:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
Таблица и запись зашифрованного поля:
CREATE TABLE users (
id serial PRIMARY KEY,
name text,
card bytea
);
INSERT INTO users (name, card)
VALUES ('Alice', pgp_sym_encrypt('1234567812345678', 'mysecretkey'));
SELECT name, pgp_sym_decrypt(card, 'mysecretkey')
FROM users;
Ключ уходит в тексте запроса и попадает в лог при log_statement = all. Передавайте его параметром через prepared statement либо шифруйте на стороне приложения и отправляйте в базу готовый bytea.
Для TDE применяют расширение pg_tde от Percona: оно подключается через shared_preload_libraries, создаёт keyring-файл и позволяет создавать таблицы с шифрованием страниц. Статус беты означает простую вещь: перед продакшеном нужен тест на вашей версии PostgreSQL и проверенная процедура восстановления.
Шифрование в MySQL: TDE и функции AES
TDE в Percona Server for MySQL включается через плагин keyring_vault. В my.cnf добавляются строки:
[mysqld] early-plugin-load=keyring_vault.so keyring_vault_config=/etc/mysql/vault-keyring.json
Файл vault-keyring.json содержит адрес Vault, токен и путь к секрету с мастер-ключом. После перезапуска создаётся зашифрованная таблица:
CREATE TABLE payments ( id INT PRIMARY KEY, secret VARCHAR(255) ) ENCRYPTION='Y';
Проверка статуса шифрования:
SELECT NAME, ENCRYPTION FROM information_schema.INNODB_TABLESPACES WHERE ENCRYPTION = 'Y';
Для отдельных полей подходят функции AES_ENCRYPT и AES_DECRYPT. Режим по умолчанию, ECB, небезопасен: одинаковые блоки дают одинаковый шифротекст. Переключите режим перед работой:
SET GLOBAL block_encryption_mode = 'aes-256-cbc';
INSERT INTO users (card)
VALUES (AES_ENCRYPT('1234567812345678', 'mysecretkey'));
SELECT CAST(AES_DECRYPT(card, 'mysecretkey') AS CHAR) FROM users;
Плагин keyring_file подходит для стенда, где файл ключа лежит на том же сервере. Для продакшена держите мастер-ключ в Vault или HSM, иначе копия каталога data вместе с файлом ключа обнуляет всю защиту.
Шифрование в MongoDB: CSFLE и Queryable Encryption
Client-Side Field Level Encryption (CSFLE) требует MongoDB Enterprise или MongoDB Atlas. Приложение получает ключ данных из key vault, а драйвер сам шифрует поля по schema map. Пример на Python с pymongo:
from pymongo import MongoClient
from pymongo.encryption import ClientEncryption
client = MongoClient()
client_encryption = ClientEncryption(kms_providers, key_vault_namespace, client)
data_key_id = client_encryption.create_data_key(
'aws', master_key={'region': 'us-east-1', 'key': 'arn:aws:kms:...'})
schema_map = {'db.users': {'fields': {
'ssn': {'keyId': data_key_id, 'bsonType': 'string',
'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}}
Детерминированный алгоритм даёт одинаковый шифротекст для одинаковых значений и разрешает поиск равенством. Случайный алгоритм безопаснее, но поиск по полю становится невозможен. Queryable Encryption доступна с MongoDB 7.0 в Enterprise и Atlas: поля помечаются как Indexed, и сервер выполняет запросы равенства по зашифрованным данным, не видя открытого текста. Atlas включает шифрование хранилища по умолчанию, поэтому для защиты от кражи диска отдельная настройка не нужна.
Управление ключами шифрования: как не потерять данные и сохранить доступность
Потеря ключа равна потере данных. Файлы останутся на диске, бэкапы будут на месте, но база не восстановится: ключ TDE не подбирается, а старые дампы не содержат новых транзакций. Жизненный цикл ключа включает генерацию, хранение, использование, ротацию, отзыв и уничтожение, и на каждом шаге нужны регламент и журнал действий.
Рабочая схема строится на двух уровнях ключей. Мастер-ключ (master key, он же KEK) лежит в KMS или HSM и никогда не покидает устройство. Ключи шифрования данных (data encryption key, DEK) шифруются мастер-ключом, и в базе хранится только их зашифрованная версия. Такой подход называют envelope encryption: он позволяет сменить мастер-ключ без перешифрования всех данных. Ключи не держат в каталоге data, не коммитят в git, не переносят в конфигах приложений.
Генерация идёт через криптографический источник случайности. Локально годится команда:
openssl rand -base64 32
Пароль человека в роли ключа не используется: его превращает в ключ функция вывода ключа (KDF). Соль, число итераций и выбор между PBKDF2, scrypt и Argon2 разобраны в статье про то, как пароль превращается в ключ шифрования.
Выбор KMS: HashiCorp Vault, AWS KMS и облачные решения
HashiCorp Vault подходит для on-premise и гибридных контуров: transit secrets engine выполняет шифрование и расшифровку, не отдавая ключ наружу. Базовая версия бесплатна, аудит доступа включается настройкой audit device. Минимальный набор команд для нового ключа:
vault secrets enable transit vault write -f transit/keys/my-key vault write transit/encrypt/my-key plaintext=SGVsbG8=
Облачные KMS (AWS KMS, GCP KMS, Azure Key Vault) снимают задачу обслуживания HSM, но привязывают к платформе: перенос базы в другой контур требует переноса ключей и проверки совместимости. Для развёртывания баз в облаке с шифрованием хранилища и отдельным хранилищем ключей подходит Timeweb Cloud: там доступны управляемые базы данных, объектное хранилище и Kubernetes, а политика шифрования задаётся на уровне сервиса. Включите аудит вызовов расшифровки: всплеск операций Decrypt в три часа ночи говорит о компрометации приложения.
Ротация ключей и восстановление после сбоев
Ротация делится на два вида. Смена мастер-ключа в KMS не трогает данные: DEK перешифровывается новым мастер-ключом, простой не нужен. Смена самого DEK требует перешифрования. В MySQL InnoDB ротация мастер-ключа выполняется командой:
ALTER INSTANCE ROTATE INNODB MASTER KEY;
Для столбцового шифрования перешифрование идёт пакетами: читаем строку, расшифровываем старым ключом, шифруем новым, записываем. На таблице в 10 млн строк при 1000 строк в секунду такой проход займёт около трёх часов, поэтому его запускают в часы низкой нагрузки. Плановая ротация раз в год для мастер-ключа и раз в квартал для данных держателей карт закрывает требования аудита.
При компрометации ключа порядок действий такой: сменить мастер-ключ, перешифровать DEK, проверить журналы доступа к KMS за последние недели, урезать права приложения на расшифровку. Если ключ утерян, но есть офлайн-копия в сейфе или зашифрованный бэкап ключа в KMS, база восстанавливается. Без копии ключа данные теряются необратимо: поднять TDE-файлы из бэкапа не получится.
Производительность и требования к шифрованию персональных данных
Ориентировочные цифры для планирования: TDE на процессорах с AES-NI даёт overhead 5-15% по дисковому вводу-выводу, шифрование столбцов добавляет 20-30% на операциях с зашифрованными полями, шифрование в приложении съедает около 40% времени обработки запроса. AES-NI есть в серверных процессорах Intel и AMD с 2010 года, поэтому деградация упирается в накладные расходы на вызовы функций и в рост размера зашифрованных значений, а не в сам алгоритм AES.
Как измерить влияние шифрования на производительность
Методика одинакова для любой СУБД. Сначала снимите baseline на реальной нагрузке: TPS, latency, загрузка CPU, объём записи на диск. Затем включите шифрование на копии продакшена и повторите замеры с теми же данными и темпом запросов. Разница в цифрах и есть цена защиты.
Для PostgreSQL используйте pgbench с пользовательским скриптом:
pgbench -c 10 -j 2 -T 60 -f script.sql -U postgres testdb
Для MySQL подойдёт sysbench:
sysbench oltp_read_write --db-driver=mysql --mysql-db=test --tables=10 --table-size=1000000 prepare sysbench oltp_read_write --db-driver=mysql --mysql-db=test --tables=10 --table-size=1000000 run
Для MongoDB применяют YCSB с профилем workloada. Закладывайте запас 20-30% по CPU и по диску: после включения TDE растёт нагрузка на ввод-вывод, а при столбцовом шифровании часть работы переезжает с сервера в приложение, что меняет профиль потребления.
Соответствие 152-ФЗ, GDPR и PCI DSS: что выбрать
152-ФЗ (статья 19) обязывает принимать меры защиты персональных данных, включая шифрование при хранении и передаче. Для базы в защищённом контуре с ограниченным кругом администраторов аудиторы обычно принимают TDE вместе с политикой управления ключами. GDPR (статья 32) называет шифрование надлежащей мерой безопасности, конкретный алгоритм не задаёт. PCI DSS (требование 3.4) предписывает хранить номер карты только в нечитаемом виде и отдельно требует защиту ключей.
Практический вывод: если DBA не должен видеть номера карт, одного TDE недостаточно, нужен столбцовый уровень или шифрование в приложении. Аудиторы запрашивают три документа: политику управления ключами, журнал ротации и логи доступа к KMS. Подготовьте их заранее, иначе техническая часть окажется закрыта, а формальная нет.
Критерии выбора и типичные ошибки при внедрении шифрования
Решение принимается по пяти критериям. Модель угроз отвечает на вопрос, от кого защищаемся: от кражи диска, от недобросовестного администратора, от утечки через приложение. Требования регуляторов задают минимальный уровень. Допустимое падение производительности ограничивает выбор по железу. Сложность поддержки определяет, справится ли команда с ротацией и восстановлением. Бюджет на KMS и HSM закрывает список.
Готовые связки выглядят так. Защита от кражи диска и снапшотов: TDE в MySQL Enterprise или Percona Server, LUKS для тома PostgreSQL на Linux. Защита от недобросовестного DBA: шифрование на стороне приложения с ключами в Vault. Выборочная защита полей при сохранении серверного поиска по остальным данным: pgcrypto в PostgreSQL, AES_ENCRYPT в MySQL, CSFLE или Queryable Encryption в MongoDB. Шифрование резервных копий отдельным слоем: GnuPG, age и OpenSSL, их сравнение собрано в подборке программ и утилит для шифрования данных.
Ошибки, которые обесценивают защиту:
- Ключ лежит рядом с данными, в том же каталоге, в конфиге приложения или в git. Копия сервера отдаёт атакующему и данные, и ключ.
- Нет бэкапа ключей. Один сбой keyring-плагина превращает базу в набор нечитаемых страниц.
- Слабые алгоритмы: AES-128 вместо AES-256, режим ECB, самодельные схемы на XOR и Base64.
- Шифрование без ротации: ключ живёт годами, и утечка раскрывает исторические данные целиком.
- Один ключ на все среды: данные из dev с тем же ключом открываются в prod.
- Неполное покрытие: таблицу зашифровали, журналы, временные файлы и бэкапы забыли.
- Отсутствие замеров: шифрование включают сразу в продакшене и получают деградацию в пиковые часы.
Чек-лист перед запуском шифрования:
- Определить, какие данные шифруются и от какой угрозы.
- Выбрать уровень: TDE, столбцы или приложение.
- Настроить KMS, завести мастер-ключ и политику доступа.
- Сделать и проверить бэкап данных и ключей, включая офлайн-копию.
- Протестировать на копии продакшена и замерить TPS и latency до и после.
- Составить план отката и порядок ротации ключей.
- Обучить команду и зафиксировать регламент в документации.
Начните с одного поля или одной таблицы: включите шифрование на копии продакшена, замерьте TPS, проверьте восстановление из бэкапа с ключом и только потом переносите схему на боевой контур. Права доступа к новым зашифрованным таблицам проверьте отдельно по чек-листу контроля привилегий и защиты соединений, иначе шифрование закроет кражу диска, но оставит открытой выдачу прав шире необходимого.