2012-11-28 55 views
7

私はデータベースとしてMySQLを使用していて、postgresqlに移行する予定でした。私はアプリケーション全体を通してaes_encryptとaes_decrypt関数をMySQLで広範囲にわたって使用していました。したがって、暗号化/解読が失敗すると、MySQLは自動的に 'null'を返します。pgp_sym_encrypt/pgp_sym_decryptエラー処理

postgresqlで同じように扱う方法がわかりません。 pgp_sym_encrypt/pgp_sym_decrypt関数を使用して試行します。暗号化キーが間違っていると、「間違ったキー/データ破損」というエラーがスローされます。私はこのエラーをキャプチャし、MySQLでのように 'null'を返すことができるように、私のコードを変更する必要のないいくつかの関数を探しました。私は検索していたが見つけられなかった。

個々のクエリにエラー処理メカニズムを使用した人はいますか?私はエラー処理が手続きのためにできることを発見した。しかし、私はアプリケーション全体を完全に書き直さなければなりませんでした。

詳細を分かち合うことができれば、大きな助けになるでしょう。ありがとう。

答えて

4

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

、最初に私はエラーの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 

が、私はシンボリック名を使用することを好むので、私は、エラー名を検索Appendix A - Error codesの39000に関連付けられており、それが汎用関数呼び出しエラーexternal_routine_invocation_exceptionであることがわかります。私たちが気に入ったほど具体的ではありませんが、そうするでしょう。

ラッパー機能が必要です。このような何かを定義する必要があります。オーバーロードされた署名のそれぞれについて、サポートしたいpgp_sym_decryptの関数を1つ指定してください。例えば、textを返す(bytea,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; 

IはDEBUGレベルメッセージに元のエラーをpreseveすることを選択しました。ここでは、完全なメッセージの冗長性とデバッグレベルの出力を元のラッパーと比較します。

デバッグ出力を有効にして、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はキーにアクセスできません。

+0

あなたの答えに感謝します。私は最後の手段としてこの種の機能を実装することに決めました。確かに非常に便利です。私は、ビルド中のpgsql関数を最大限に活用しようとしています。それがどのように役立つのかを見てみましょう。 また、アプリ内のすべての暗号を行うことをお祈りしています。私は既に、アプリでいくつかの重要な機能を変更する予定だったのです。私は後ですべてを変える。 –

+0

@ user1365983良い - これはとても良いアイデアだとは思わないので、あなたはそれをやることを計画していないのでうれしい。それが役に立つと答えた場合は、左上のアンサースコアの下のチェックマークを使用して受け入れてください。 –