Перейти к основному содержимому
Шифрование данных в PostgreSQL
Последнее изменение:

Шифрование данных в PostgreSQL

Чтобы шифровать данные в PostgreSQL, можно добавить расширение 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

Хеширование пароля

  1. Создайте таблицу:

    CREATE TABLE tbl_hash_pwd(username varchar(100) PRIMARY KEY, cryptpwd text);
  2. Вставьте данные в таблицу и зашифруйте их:

    INSERT INTO tbl_hash_pwd(username, cryptpwd)
    VALUES ('username_1', crypt('Password_1', gen_salt('md5')));
  3. Проверьте, что данные зашифрованы:

    SELECT * FROM tbl_hash_pwd;
  4. Убедитесь, что в зашифрованных данных хранится текст, который вы зашифровали на шаге 2.

    SELECT username FROM tbl_hash_pwd
    WHERE cryptpwd = crypt('Password_1', cryptpwd);

PGP-шифрование с симметричным ключом

  1. Создайте таблицу:

    CREATE TABLE tbl_crypt_sym_key (id SERIAL PRIMARY KEY, data text);
  2. Вставьте в таблицу данные, которые вы хотите зашифровать:

    INSERT INTO tbl_crypt_sym_key (data) VALUES (pgp_sym_encrypt('My confidential information', 'secret_key'));

    Здесь secret_key — секретный ключ для шифрования данных. Сохраните секретный ключ в безопасном месте — он необходим для расшифровки данных.

  3. Проверьте, что данные зашифрованы:

    SELECT * FROM tbl_crypt_sym_key;
  4. Чтобы расшифровать данные, используйте функцию pgp_sym_decrypt:

    SELECT pgp_sym_decrypt(data::bytea, 'secret_key') FROM tbl_crypt_sym_key;

PGP-шифрование с открытым ключом

  1. Установите утилиту GnuPG.

  2. Откройте CLI.

  3. Создайте ключ PGP:

    gpg --full-generate-key

    Укажите:

    • тип ключа. Рекомендуемый тип ключа — DSA и Elgamal;
    • размер ключа в битах;
    • срок действия ключа;
    • имя пользователя (Real name);
    • адрес электронной почты;
    • кодовую фразу ключа.
  4. Экспортируйте ключи в файлы:

    gpg -a --export real_name > public.key && \
    gpg -a --export-secret-keys real_name > private.key

    Здесь real_name — имя пользователя, которое вы указали при создании ключа на шаге 3.

  5. Создайте таблицу:

    CREATE TABLE tbl_crypt_pub_key(ssn_id SERIAL PRIMARY KEY,
    username varchar(100), ssn bytea);
  6. Добавьте данные, которые нужно зашифровать, и зашифруйте их:

    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.

  7. Убедитесь, что данные зашифрованы:

    SELECT * FROM tbl_crypt_pub_key;
  8. Чтобы расшифровать данные, используйте функцию 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.