\df *crypt
In psql werden die Argumenttypen des pgcrypto encrypt
und der decrypt
Funktionen ( 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 encrypt
und decrypt
erwarten 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 encrypt
mit 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_activity
und das System protokolliert über log_statement
oder über Kryptoanweisungen, die mit einem Fehler fehlschlagen. IMO ist es häufig besser, Kryptografie in der Anwendung durchzuführen .
client_min_messages
Sehen 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_messages
niedrig genug ist. Es befindet sich jetzt zusammen mit den verschlüsselten Daten im Speicher des Servers. Scheitern. Gleiches Problem, ohne log_statement
dass ein Fehler auftritt, der dazu führt, dass die Anweisung protokolliert wird, oder möglicherweise, wenn auto_explain
aktiviert ist.
Eine Belichtung über pg_stat_activity
ist 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 TABLE
von einem nicht privilegierten Angreifer reproduziert werden , es ist nur schwieriger, es richtig zu terminieren. Der Angriff über pg_stat_activity
kann durch Zugriff Widerruf vermieden werden , um pg_stat_activity
aus 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.