\df *cryptw psql ujawnia typy argumentów pgcrypto encrypti decryptfunkcji ( podobnie jak dokumenty 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
...
więc obie funkcje encrypti decryptoczekują, że klucz będzie bytea. Zgodnie z komunikatem o błędzie „może być konieczne dodanie rzutowania typu jawnego”.
Jednak działa tutaj dobrze na stronie 9.1, więc podejrzewam, że jest w tym coś więcej niż pokazałeś. Być może masz inną funkcję o nazwie również encryptz trzema argumentami?
Oto jak działa na czystym 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)
Awooga! Awooga! Ryzyko narażenia na klucz, wymagana jest szczególna ostrożność administratora!
BTW, proszę dokładnie przemyśleć, czy PgCrypto jest naprawdę właściwym wyborem. Klucze w twoich zapytaniach mogą zostać ujawnione, pg_stat_activitya system loguje się za pomocą log_statementlub za pomocą instrukcji kryptograficznych, które kończą się błędem. IMO często lepiej jest zrobić kryptografię w aplikacji .
Obserwuj tę sesję z client_min_messageswłączoną funkcją, aby zobaczyć, co pojawi się w dziennikach:
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)
Ups, klucz może być ujawniony w logach, jeśli log_min_messagesjest wystarczająco niski. Jest teraz w pamięci serwera wraz z zaszyfrowanymi danymi. Zawieść. Ten sam problem bez log_statementwystąpienia błędu powodującego zalogowanie się instrukcji lub ewentualnie auto_explainwłączenia.
pg_stat_activityMożliwa jest także ekspozycja przez . Otwórz dwie sesje i:
- 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();
Ups! Znowu idzie klucz. Może zostać odtworzony bez LOCK TABLEnieuprzywilejowanego atakującego, po prostu trudniej go odpowiednio zinterpretować. Ataku poprzez pg_stat_activitymożna uniknąć, cofając dostęp dopg_stat_activity z public, ale to tylko dowodzi, że może nie być najlepiej wysłać swój klucz do DB, chyba że wiesz aplikacja jest jedyną rzeczą kiedykolwiek dostępu do niego. Nawet wtedy nie lubię.
Jeśli to hasła, czy w ogóle je przechowujesz?
Ponadto, jeśli przechowujesz hasła, nie szyfruj ich dwukierunkowo; jeśli w ogóle możliwe hasła soli, następnie je mieszaj i zapisz wynik . Zwykle nie musisz mieć możliwości odzyskania hasła w postaci tekstu jawnego, tylko potwierdź, że przechowywany skrót jest zgodny z hasłem, które użytkownik wysyła do zalogowania, gdy jest hashowane tą samą solą.
Jeśli to auth, niech ktoś zrobi to za ciebie
Co więcej, w ogóle nie przechowuj hasła, uwierzytelnij się przy użyciu LDAP, SASL, Active Directory, dostawcy OAuth lub OpenID lub innego systemu zewnętrznego, który został już zaprojektowany i działa.
Zasoby
i wiele więcej.