2012-11-28 14 views
7

Używałem MySQL jako bazy danych i planowałem przenieść się do postgresql. Używałem funkcji aes_encrypt i aes_decrypt w MySQL w całej mojej aplikacji. Tak więc, gdy szyfrowanie/decrytion zawiedzie, MySQL automatycznie zwraca "null".Obsługa błędów pgp_sym_encrypt/pgp_sym_decrypt

Nie jestem pewien, jak sobie z tym poradzić w postgresql. Próbowano za pomocą funkcji pgp_sym_encrypt/pgp_sym_decrypt. Jeśli klucz szyfrowania jest nieprawidłowy, zgłasza błąd "Wrong key/corruptured data". Próbowałem wyszukać niektóre funkcje, które mogłyby przechwycić ten błąd i zwrócić 'null' jak w MySQL, więc nie muszę modyfikować mojego kodu. Szukałem, ale nie mogłem go znaleźć.

Czy ktoś użył dowolnego mechanizmu obsługi błędów dla poszczególnych zapytań? Odkryłem, że obsługa błędów może być wykonana dla procedur. Ale musiałem całkowicie przepisać całą aplikację.

Jeśli możesz podzielić się niektórymi szczegółami, będzie to bardzo pomocne. Dzięki.

Odpowiedz

4

Jeśli chcesz uniknąć modyfikacji kodu i funkcje zwracają NULL w przypadku błędu, możesz to zrobić, owijając je w funkcję PL/PgSQL, która używa bloku BEGIN ... EXCEPTION, aby uwięzić błąd.

Aby to zrobić, należy najpierw uzyskać SQLSTATE błędu:

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 

mogę użyć tego bezpośrednio w module obsługi błędów, ale wolę używać nazwy symboliczne, więc patrzę nazwę błędzie związane z 39000 w Appendix A - Error codes, ustalając, że jest to ogólny błąd wywołania funkcji external_routine_invocation_exception. Nie tak szczegółowe, jak byśmy sobie życzyli, ale zrobi to.

Teraz potrzebna jest funkcja opakowania. Coś takiego musi być zdefiniowane, z jedną funkcją dla każdego przeciążonego podpisu pgp_sym_decrypt, którą chcesz wspierać. Dla postaci (bytea,text) zwracającej text, na przykład:

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; 

wybrałem preseve oryginalny błąd w wiadomości DEBUG poziomu. Oto porównanie oryginału i opakowania, z pełną szczegółowością komunikatu i wyjściem z poziomu debugowania.

Włącz wyjście debugowania, aby wyświetlić RAISE. Zauważ, że pokazuje również * oryginalny tekst zapytania połączenia pgp_decrypt_sym, w tym parametry.

regress=# SET client_min_messages = DEBUG; 

New owinięty funkcja nadal zgłasza błąd, jeśli szczegółowe rejestrowanie jest włączone, ale zwraca 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) 

porównaniu do oryginału, który kończy się niepowodzeniem:

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 

Zauważ, że zarówno formularze wyświetlają parametry, z którymi wywołano funkcję, gdy nie powiodło się. Parametry nie będą wyświetlane, jeśli zostały użyte parametry powiązania ("przygotowane instrukcje"), ale nadal należy uważać dzienniki za krytyczne z punktu widzenia bezpieczeństwa, jeśli używasz szyfrowania w bazie danych.

Osobiście uważam, że lepiej jest zrobić crypto w aplikacji, aby baza danych nigdy nie miała dostępu do kluczy.

+0

dziękuję za odpowiedź.Postanowiłem pójść na realizację takiej funkcji w ostateczności. Rzeczywiście bardzo przydatne. Próbuję uzyskać maksimum z wbudowanych funkcji pgsql. Pozwól mi zobaczyć, jak najlepiej pomaga. Dziękuję również za sugestię, aby wykonać całą kryptografię w aplikacji. Tak, tak już planowałem zmienić kilka ważnych funkcji w aplikacji. Później zmienię wszystko. –

+0

@ user1365983 Dobrze - Nie sądzę, że to bardzo dobry pomysł, więc cieszę się, że nie planujesz tego zrobić. Zaakceptuj odpowiedź, jeśli była pomocna, za pomocą zaznaczenia pod wynikiem odpowiedzi w lewym górnym rogu. –