Шифрование данных в PostgreSQL TimescaleDB
Чтобы шифровать данные в PostgreSQL TimescaleDB, можно добавить расширение pgcrypto. Это расширение предоставляет набор криптографических функций для защиты данных с помощью:
- стандартного хеширования данных — digest(), hmac();
- хеширования паролей — crypt(), gen_salt();
- симметричных и открытых ключей (шифруют данные по стандарту OpenPGP) — pgp_sym_encrypt(), pgp_sym_decrypt(), pgp_pub_encrypt(), pgp_pub_decrypt(), armor(), dearmor();
- шифрования низкого уровня — encrypt(), decrypt();
- получения случайных данных — gen_random_bytes(), gen_random_uuid().
При использовании расширения pgcrypto учтите ограничения безопасности.
Посмотрите примеры шифрования данных с помощью расширения pgrypto.
Подробнее о расширении pgcrypto и его функциях в статье pgcrypto — cryptographic functions документации PostgreSQL.
Ограничения безопасности расширения pgcrypto
- данные и пароли передаются между функциями pgcrypto и клиентскими приложениями открытым текстом, поэтому рекомендуем подключаться к кластеру баз данных с SSL;
- защита данных с помощью расширения pgcrypto уязвима для атак по сторонним каналам. Например, длительность расшифровки текстов одинакового размера может различаться.
Примеры шифрования данных с помощью расширения pgcrypto
Хеширование пароля
-
Создайте таблицу:
CREATE TABLE tbl_hash_pwd(username varchar(100) PRIMARY KEY, cryptpwd text);
-
Вставьте данные в таблицу и зашифруйте их:
INSERT INTO tbl_hash_pwd(username, cryptpwd)
VALUES ('username_1', crypt('Password_1', gen_salt('md5'))); -
Проверьте, что данные зашифрованы:
SELECT * FROM tbl_hash_pwd;
-
Убедитесь, что в зашифрованных данных хранится текст, который вы зашифровали на шаге 2.
SELECT username FROM tbl_hash_pwd
WHERE cryptpwd = crypt('Password_1', cryptpwd);
PGP-шифрование с симметричным ключом
-
Создайте таблицу:
CREATE TABLE tbl_crypt_sym_key (id SERIAL PRIMARY KEY, data text);
-
Вставьте в таблицу данные, которые вы хотите зашифровать:
INSERT INTO tbl_crypt_sym_key (data) VALUES (pgp_sym_encrypt('My confidential information', 'secret_key'));
Здесь
secret_key
— секретный ключ для шифрования данных. Сохраните секретный ключ в безопасном месте — он необходим для расшифровки данных. -
Проверьте, что данные зашифрованы:
SELECT * FROM tbl_crypt_sym_key;
-
Чтобы расшифровать данные, используйте функцию
pgp_sym_decrypt
:SELECT pgp_sym_decrypt(data::bytea, 'secret_key') FROM tbl_crypt_sym_key;
PGP-шифрование с открытым ключом
-
Откройте CLI.
-
Создайте ключ PGP:
gpg --full-generate-key
Укажите:
- тип ключа. Рекомендуемый тип ключа —
DSA и Elgamal
; - размер ключа в битах;
- срок действия ключа;
- имя пользователя (Real name);
- адрес электронной почты;
- кодовую фразу ключа.
- тип ключа. Рекомендуемый тип ключа —
-
Экспортируйте ключи в файлы:
gpg -a --export real_name > public.key && \
gpg -a --export-secret-keys real_name > private.keyЗдесь
real_name
— имя пользователя, которое вы указали при создании ключа на шаге 3. -
Создайте таблицу:
CREATE TABLE tbl_crypt_pub_key(ssn_id SERIAL PRIMARY KEY,
username varchar(100), ssn bytea); -
Добавьте данные, которые нужно зашифровать, и зашифруйте их:
INSERT INTO tbl_crypt_pub_key (username, ssn)
SELECT tmp.username, pgp_pub_encrypt(tmp.ssn, keys.pubkey) AS tbl
FROM (
VALUES ('username_1', '123-45-6789'), ('username_2', '123-45-67890'))
AS tmp(username, ssn)
CROSS JOIN (SELECT dearmor('public_key') AS pubkey) AS keys;Здесь
public_key
— содержимое файлаpublic.key
, который вы создали на шаге 4. -
Убедитесь, что данные зашифрованы:
SELECT * FROM tbl_crypt_pub_key;
-
Чтобы расшифровать данные, используйте функцию
pgp_pub_decrypt
:SELECT username, pgp_pub_decrypt(ssn, keys.privkey, 'passphrase')
AS decrypted_ssn FROM tbl_crypt_pub_key
CROSS JOIN (SELECT dearmor('private_key') AS privkey) AS keys;Здесь:
passphrase
— кодовая фраза ключа;private_key
— содержимое файлаprivate.key
, который вы создали на шаге 4.