7

私はデータベースとしてMySQLを使用していて、postgresqlに移行することを計画していました。私は、MySQLでaes_encrypt関数とaes_decrypt関数をアプリケーション全体で広範囲に使用していました。したがって、暗号化/復号化が失敗すると、MySQLは自動的に「null」を返します。

postgresqlで同じことを処理する方法がわかりません。pgp_sym_encrypt/pgp_sym_decrypt関数を使用してみました。暗号化キーが間違っていると、「キーが間違っています/データが壊れています」というエラーがスローされます。コードを変更する必要がないように、このエラーをキャプチャしてMySQLのように「null」を返す可能性のあるいくつかの関数を検索してみました。探していましたが見つかりませんでした。

誰かが個々のクエリにエラー処理メカニズムを使用しましたか?プロシージャに対してエラー処理を実行できることがわかりました。しかし、そのためにアプリケーション全体を完全に書き直さなければなりませんでした。

あなたがいくつかの詳細を共有することができれば、それは大きな助けになるでしょう。ありがとう。

4

1 に答える 1

4

コードの変更を避け、関数がエラー時に返されるようにしたい場合は、ブロックをNULL使用してエラーをトラップするPL/PgSQL関数でそれらをラップすることでこれを行うことができます。BEGIN ... EXCEPTION

これを行うには、最初にエラーのSQLSTATEを取得します。

regress=# \set VERBOSITY verbose
regress=# SELECT pgp_sym_decrypt('fred','key');
ERROR:  39000: Wrong key or corrupt data
LOCATION:  decrypt_internal, pgp-pgsql.c:607

これはエラーハンドラーで直接使用できますが、シンボリック名を使用することを好むため、付録A-エラーコードで39000に関連付けられているエラー名を調べて、それが総称関数呼び出しエラーであることを確認しますexternal_routine_invocation_exception。私たちが望んでいたほど具体的ではありませんが、それは可能です。

ここで、ラッパー関数が必要です。このようなものを定義する必要があります。サポートするオーバーロードされた署名ごとに1つの関数を使用pgp_sym_decryptします。(bytea,text)を返すフォームの場合、たとえば、次のようになりますtext

CREATE OR REPLACE FUNCTION pgp_sym_decrypt_null_on_err(data bytea, psw text) RETURNS text AS $$
BEGIN
  RETURN pgp_sym_decrypt(data, psw);
EXCEPTION
  WHEN external_routine_invocation_exception THEN
    RAISE DEBUG USING
       MESSAGE = format('Decryption failed: SQLSTATE %s, Msg: %s',
                        SQLSTATE,SQLERRM),
       HINT = 'pgp_sym_encrypt(...) failed; check your key',
       ERRCODE = 'external_routine_invocation_exception';
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

DEBUGレベルメッセージで元のエラーを保存することを選択しました。これは、元のラッパーとラッパーの比較であり、完全なメッセージの詳細度とデバッグレベルの出力が含まれています。

デバッグ出力を有効にして、を表示しRAISEます。pgp_decrypt_symパラメータを含む、呼び出しの*元のクエリテキストも表示されることに注意してください。

regress=# SET client_min_messages = DEBUG;

詳細なロギングが有効になっている場合でも、新しいラップされた関数はエラーを報告しますが、以下を返しますNULL

regress=# SELECT pgp_sym_decrypt_null_on_err('redsdfsfdsfd','bobsdf');
LOG:  00000: statement: SELECT pgp_sym_decrypt_null_on_err('redsdfsfdsfd','bobsdf');
LOCATION:  exec_simple_query, postgres.c:860
DEBUG:  39000: Decryption failed: SQLSTATE 39000, Msg: Wrong key or corrupt data
HINT:  pgp_sym_encrypt(...) failed; check your key
LOCATION:  exec_stmt_raise, pl_exec.c:2806
 pgp_sym_decrypt_null_on_err
-----------------------------

(1 row)

失敗するオリジナルと比較して:

regress=# SELECT pgp_sym_decrypt('redsdfsfdsfd','bobsdf');
LOG:  00000: statement: SELECT pgp_sym_decrypt('redsdfsfdsfd','bobsdf');
LOCATION:  exec_simple_query, postgres.c:860
ERROR:  39000: Wrong key or corrupt data
LOCATION:  decrypt_internal, pgp-pgsql.c:607

どちらの形式も、関数が失敗したときに呼び出されたパラメーターを示していることに注意してください。バインドパラメータ(「プリペアドステートメント」)を使用した場合、パラメータは表示されませんが、データベース内暗号化を使用している場合は、ログがセキュリティ上重要であると見なす必要があります。

個人的には、アプリで暗号化を行う方が良いと思います。そのため、DBはキーにアクセスできません。

于 2012-11-28T07:00:21.323 に答える