Короткий ответ
Шифрование на уровне диска/тома защищает данные только «в покое» и полностью прозрачно для SQL-слоя — индексы и запросы работают как обычно, но не защищает от доступа через скомпрометированную учётную запись БД; column-level шифрование через pgcrypto защищает конкретное поле даже от доступа с правами на таблицу, если ключ хранится отдельно от БД, но делает обычный поиск/сравнение/сортировку по этому полю в зашифрованном виде невозможными без расшифровки.
Как это работает подробнее
pgcrypto предоставляет функции pgp_sym_encrypt/pgp_sym_decrypt, которые шифруют значение перед записью и расшифровывают при чтении с передачей ключа как параметра запроса; хранимое значение — бинарные зашифрованные байты, поэтому обычный индекс на этой колонке бесполезен для поиска по исходному значению.
Сравнение
- Компромисс. TDE/шифрование диска проще внедрить и не влияет на производительность и индексацию, но защищает от более узкого набора угроз; column-level шифрование защищает от более широкого класса угроз, но требует отказа от обычной индексации по этому полю и инфраструктуры управления ключами — критерий выбора — модель угроз, регуляторные требования и реальная потребность в поиске/сортировке по защищаемому полю.
Пример кода
-- Учебный пример (без реальных секретов и ключей): шифрование номера документа
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Запись: ключ передаётся из приложения как параметр запроса, не хранится в БД
INSERT INTO users (id, document_number_encrypted, document_hmac)
VALUES (
1,
pgp_sym_encrypt('1234567890', :encryption_key),
encode(hmac('1234567890', :hmac_key, 'sha256'), 'hex')
);
-- Поиск по точному значению через отдельный индексируемый HMAC, а не через расшифровку каждой строки
CREATE INDEX idx_users_document_hmac ON users(document_hmac);
SELECT id FROM users WHERE document_hmac = encode(hmac('1234567890', :hmac_key, 'sha256'), 'hex');Что использовать на практике
- Практика. Для полей, по которым нужен точный поиск, применяют детерминированное шифрование или дополнительно хранят отдельный HMAC/хеш от значения в отдельной индексируемой колонке; управление ключами выносят за пределы самой БД (KMS/Vault), так как хранение ключа рядом с данными снижает защиту почти до нуля при компрометации БД.
Подводные камни
- Ошибка. Шифруют колонку и одновременно ожидают от неё эффективного LIKE/диапазонного поиска — это невозможно без расшифровки каждой строки; хранят ключ шифрования в той же БД или в конфиге рядом с connection string, что не даёт защиты сверх обычного шифрования диска.