Як використовувати aes-шифрування в PostgreSQL?


15

Я спробував aes-шифрування за допомогою наступного оператора:

SELECT encrypt('test', 'key', 'aes');

яка працювала, але я не в змозі розшифрувати значення. Я вставив його в поле bytea типу даних, але я не впевнений, чи це був правильний шлях.

SELECT decrypt(pw, 'key', 'aes') FROM table WHERE ID = 1;

дає мені помилку

ПОМИЛКА: функція дешифрування (байт, невідомо, невідомо) НЕ РОБОТА
1: ВИБІРТЕ розшифрування (pw, 'ключ', 'aes') ВІД tabelle WHERE ID = 7; ^
Підказка: жодна функція не відповідає заданому типу імені та аргументу. Можливо, вам доведеться додати явні типи типів.

Це насправді означає, що шифрування () є існуючою функцією, але не розшифровує ()? Як інакше я можу отримати значення зашифрованих AES?

Відповіді:


16

\df *cryptу psql розкриває типи аргументів pgcrypto encryptта decryptфункцій ( як це роблять документи PgCrypto ):

                                List of functions
 Schema |      Name       | Result data type |   Argument data types    |  Type  
--------+-----------------+------------------+--------------------------+--------
 ...
 public | decrypt         | bytea            | bytea, bytea, text       | normal
 public | encrypt         | bytea            | bytea, bytea, text       | normal
 ...

тому encryptі decryptфункції, і функції очікують, що ключ буде bytea. Згідно з повідомленням про помилку, "вам може знадобитися додати явні типи".

Однак він добре працює на Pg 9.1, тому я підозрюю, що в ньому є більше, ніж ви показали. Можливо, у вас є ще одна функція, також названа encryptз трьома аргументами?

Ось як це працює на чистому Pg 9.1:

regress=# create table demo(pw bytea);
CREATE TABLE
regress=# insert into demo(pw) values ( encrypt( 'data', 'key', 'aes') );
INSERT 0 1
regress=# select decrypt(pw, 'key', 'aes') FROM demo;
  decrypt   
------------
 \x64617461
(1 row)

regress=# select convert_from(decrypt(pw, 'key', 'aes'), 'utf-8') FROM demo;
 convert_from 
--------------
 data
(1 row)

Авоога! Авоога! Основний ризик впливу, необхідна надзвичайна обережність адміністратора!

BTW, будь ласка, подумайте, чи PgCrypto справді правильний вибір. Клавіші ваших запитів можуть виявлятися в pg_stat_activityсистемі, а система log_statementведе журнал через або через криптовиклади, які не вдається помилитися. IMO часто краще робити криптовалюту в додатку .

Побачте цей сеанс, client_min_messagesувімкнено, щоб ви могли бачити, що з’явиться в журналах:

regress# SET client_min_messages = 'DEBUG'; SET log_statement = 'all'; 
regress=# select decrypt(pw, 'key', 'aes') from demo;
LOG:  statement: select decrypt(pw, 'key', 'aes') from demo;
LOG:  duration: 0.710 ms
  decrypt   
------------
 \x64617461
(1 row)

Упс, ключ, можливо, виставлений у журналах, якщо log_min_messagesвін досить низький. Тепер він знаходиться на сховищі сервера, разом із зашифрованими даними. Збій. Те ж саме питання, log_statementякщо помилка спричиняє реєстрацію оператора, або, можливо, якщо auto_explainвін увімкнено.

pg_stat_activityТакож можлива експозиція через . Відкрийте два сеанси та:

  • S1: BEGIN;
  • S1: LOCK TABLE demo;
  • S2: select decrypt(pw, 'key', 'aes') from demo;
  • S1: select * from pg_stat_activity where current_query ILIKE '%decrypt%' AND procpid <> pg_backend_pid();

Ого! Знову йде ключ. Це може бути відтворено без LOCK TABLEнепривілейованого зловмисника, це важче встигнути правильно. Атака з допомогою pg_stat_activityможна уникнути, відмінивши доступ до pg_stat_activityз public, але це тільки йде , щоб показати , що вона не може бути краще , щоб відправити ваш ключ до БД , якщо ви не знаєте , ваш додаток є єдиним коли - або доступ до нього. Навіть тоді я цього не люблю.

Якщо це паролі, чи варто взагалі зберігати їх?

Крім того, якщо ви зберігаєте паролі, не кодуйте їх двосторонньо; якщо взагалі можливі паролі солі, тоді хешуйте їх і зберігайте результат . Зазвичай вам не потрібно мати можливість відновити прозорий текст пароля, лише підтвердьте, що збережений хеш відповідає паролю, який користувач надсилає вам для входу в систему, коли хешируется з тією ж сіллю.

Якщо це автор, нехай хтось інший зробить це за вас

Ще краще, взагалі не зберігайте пароль, не підтверджуйте автентифікацію проти LDAP, SASL, Active Directory, постачальника OAuth або OpenID або іншої зовнішньої системи, яка вже розроблена і працює.

Ресурси

та багато іншого.


Це не більше, ніж я показав, і я не визначив нові функції, це новий встановлений postgresql. Дуже дратує те, що ваш зразок та перша вибірка-заява, яку я опублікував, тим часом не спрацьовують, повертаючи ту ж помилку, що і вище. Десь щось пішло не так ... все одно дякую за вашу відповідь.
32bitfloat

Спробуйте скористатись нещодавно отриманою CREATEбазою даних d template0; наприклад, CREATE DATABASE testdb TEMPLATE template0тоді CREATE EXTENSION pgcrypto;і тест. Перевірте, чи є щось шаблонне в шаблоні1.
Крейг Рінгер

Просто примітка щодо двостороннього розшифрування в db. Я не думаю, що це завжди неправильний напрямок, але це додає складності, і де б ви не мали справу з цим, вам дійсно доводиться мати справу з управлінням ключами, яке може бути складнішим у справі.
Кріс Траверс

Також на 100% секунди поняття про те, що НІКОЛИ не доведеться розшифровувати паролі і що підключення до системи, що підтримується більшою кількістю людей, зазвичай є значним виграшем безпеки.
Кріс Траверс

3
lol, +1 для "Awooga! Awooga!"
Jeromy French
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.