Wie verwende ich AES-Verschlüsselung in PostgreSQL?

15

Ich habe versucht, AES-Verschlüsselung mithilfe der folgenden Anweisung:

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

das hat funktioniert, aber ich kann den wert nicht entschlüsseln. Ich habe es in ein Feld des Datentyps bytea eingefügt , bin mir aber nicht sicher, ob das der richtige Weg war.

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

gibt mir den fehler

FEHLER: Funktion entschlüsseln (bytea, unknown, unknown) existiert nicht
LINE 1: SELECT entschlüsseln (pw, 'key', 'aes') FROM tabelle WHERE ID = 7; ^
TIPP: Keine Funktion entspricht dem angegebenen Namen und den angegebenen Argumenttypen. Möglicherweise müssen Sie explizite Typumwandlungen hinzufügen.

Bedeutet das wirklich, dass encrypt () eine vorhandene Funktion ist, aber nicht decrypt ()? Wie sonst könnte ich aes-verschlüsselte Werte erhalten?

32bit flott
quelle

Antworten:

16

\df *cryptIn psql werden die Argumenttypen des pgcrypto encryptund der decryptFunktionen ( wie auch in den PgCrypto-Dokumenten ) angezeigt :

                                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
 ...

Die Funktionen encryptund decrypterwarten also, dass der Schlüssel vorhanden ist bytea. In der Fehlermeldung heißt es: "Möglicherweise müssen Sie explizite Typumwandlungen hinzufügen".

Hier auf Seite 9.1 funktioniert es jedoch einwandfrei. Ich vermute, dass mehr dahinter steckt, als Sie gezeigt haben. Vielleicht haben Sie eine andere Funktion encryptmit drei Argumenten?

So funktioniert es auf einer sauberen Seite 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)

Awooga! Awooga! Hauptexpositionsrisiko, äußerste Vorsicht des Administrators erforderlich!

Übrigens, überlegen Sie sich bitte genau, ob PgCrypto wirklich die richtige Wahl ist. Schlüssel in Ihren Abfragen können in angezeigt werden, pg_stat_activityund das System protokolliert über log_statementoder über Kryptoanweisungen, die mit einem Fehler fehlschlagen. IMO ist es häufig besser, Kryptografie in der Anwendung durchzuführen .

client_min_messagesSehen Sie sich diese Sitzung mit aktivierter Option an, damit Sie sehen können, was in den Protokollen angezeigt wird:

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)

Whoops, Schlüssel möglicherweise in den Protokollen ausgesetzt, wenn log_min_messagesniedrig genug ist. Es befindet sich jetzt zusammen mit den verschlüsselten Daten im Speicher des Servers. Scheitern. Gleiches Problem, ohne log_statementdass ein Fehler auftritt, der dazu führt, dass die Anweisung protokolliert wird, oder möglicherweise, wenn auto_explainaktiviert ist.

Eine Belichtung über pg_stat_activityist ebenfalls möglich. Öffnen Sie zwei Sitzungen und:

  • 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();

Hoppla! Da geht der Schlüssel wieder. Es kann ohne das LOCK TABLEvon einem nicht privilegierten Angreifer reproduziert werden , es ist nur schwieriger, es richtig zu terminieren. Der Angriff über pg_stat_activitykann durch Zugriff Widerruf vermieden werden , um pg_stat_activityaus public, aber es geht nur um zu zeigen , dass es nicht am besten sein könnte Ihren Schlüssel zur DB zu senden , wenn Sie Ihre Anwendung wissen , das einzige , was es überhaupt erreichbar. Auch dann mag ich nicht.

Wenn es sich um Passwörter handelt, sollten Sie diese überhaupt speichern?

Wenn Sie Kennwörter speichern, sollten Sie sie außerdem nicht in beide Richtungen verschlüsseln. wenn überhaupt möglich Salt-Passwörter, dann hashe sie und speichere das Ergebnis . Normalerweise müssen Sie nicht in der Lage sein, den Klartext des Passworts wiederherzustellen. Vergewissern Sie sich lediglich, dass der gespeicherte Hash mit dem Passwort übereinstimmt, das der Benutzer Ihnen zur Anmeldung sendet, wenn er mit demselben Salt gehasht hat.

Wenn es auth ist, lass es jemand anderes für dich tun

Außerdem sollten Sie das Kennwort nicht speichern und sich bei LDAP, SASL, Active Directory, einem OAuth- oder OpenID-Anbieter oder einem anderen externen System authentifizieren, das bereits entwickelt wurde und funktioniert.

Ressourcen

und vieles mehr.

Craig Ringer
quelle
Es ist nicht mehr als ich gezeigt habe und ich habe keine neuen Funktionen definiert, es ist ein neu installiertes postgresql. Es ist ziemlich irritierend, dass Ihr Beispiel und die erste Select-Anweisung, die ich veröffentlicht habe, in der Zwischenzeit ebenfalls nicht funktionieren und denselben Fehler wie oben zurückgeben. Irgendwo ist etwas schief gelaufen ... trotzdem danke für deine Antwort.
32bitfloat
Probieren Sie eine neue CREATEDatenbank aus template0; zB CREATE DATABASE testdb TEMPLATE template0dann CREATE EXTENSION pgcrypto;und testen. Sehen Sie nach, ob in template1 etwas zweifelhaftes ist.
Craig Ringer
Nur ein Hinweis zur bidirektionalen Entschlüsselung in der Datenbank. Ich denke nicht, dass es immer die falsche Richtung ist, aber es erhöht die Komplexität und wo immer Sie sich damit befassen, müssen Sie sich wirklich mit der Schlüsselverwaltung befassen, die in der Datenbank komplizierter sein kann.
Chris Travers
Auch 100% zweitens ist die Vorstellung, dass Sie NIEMALS Passwörter entschlüsseln sollten und dass das Einbinden in ein System, das von mehr Personen gewartet wird, in der Regel sicherheitstechnisch von erheblicher Bedeutung ist.
Chris Travers
3
lol, +1 für "Awooga! Awooga!"
Jeromy Französisch