次のステートメントを使用してaes-encryptionを試しました:
SELECT encrypt('test', 'key', 'aes');
うまくいきましたが、値を復号化できません。データ型byteaのフィールドに挿入しましたが、それが正しい方法かどうかはわかりません。
SELECT decrypt(pw, 'key', 'aes') FROM table WHERE ID = 1;
エラーが出ます
エラー:関数の復号化(bytea、不明、不明)は存在しません
行1:SELECT(pw、 'key'、 'aes')FROM tabelle WHERE ID = 7; ^
ヒント:指定された名前と引数の型に一致する関数はありません。明示的な型キャストを追加する必要がある場合があります。
それは本当に、encrypt()が既存の関数であり、decrypt()ではないということですか?他にどのようにaesで暗号化された値を取得できますか?
psqlの_\df *crypt
_は、pgcrypto encrypt
およびdecrypt
関数の引数の型を示します( PgCrypto docsと同様 ):
_ 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で正常に機能するため、表示されている以上の機能があると思います。おそらく、3つの引数を持つ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)
_
ところで、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
_による露出も可能です。2つのセッションを開いて、
BEGIN;
_LOCK TABLE demo;
_select decrypt(pw, 'key', 'aes') from demo;
select * from pg_stat_activity where current_query ILIKE '%decrypt%' AND procpid <> pg_backend_pid();
おっと!鍵が再び行きます。権限のない攻撃者は、_LOCK TABLE
_なしで再現できますが、正確にタイミングを合わせるのは困難です。 _pg_stat_activity
_を介した攻撃は、public
から_pg_stat_activity
_へのアクセスを取り消すことで回避できますが、知らない限り、DBにキーを送信するのが最善ではない可能性があることを示しています。アプリは、これにアクセスする唯一のものです。それでも、私は好きではありません。
さらに、パスワードを保存する場合は、双方向の暗号化を行わないでください。可能な限りソルトパスワードをハッシュしてハッシュし、結果を保存します。通常、パスワードのクリアテキストを復元する必要はありません。保存されているハッシュが、同じソルトでハッシュされたときにユーザーがログインするために送信するパスワードと一致することを確認するだけです。
さらに良いのは、パスワードをまったく保存せず、LDAP、SASL、Active Directory、OAuthまたはOpenIDプロバイダー、またはすでに設計され機能している他の外部システムに対して認証を行うことです。
そしてもっとたくさん。