2012-11-28 3 views
7

나는 데이터베이스를 MySQL로 사용하고 있었고 postgresql로 이동할 계획이었습니다. 내 응용 프로그램을 통해 MySQL에서 aes_encrypt 및 aes_decrypt 함수를 광범위하게 사용했습니다. 따라서 암호화/해독이 실패 할 때마다 MySQL은 자동으로 'null'을 반환합니다.pgp_sym_encrypt/pgp_sym_decrypt 오류 처리

postgresql에서 동일한 처리 방법을 잘 모르겠습니다. pgp_sym_encrypt/pgp_sym_decrypt 함수를 사용해 보았습니다. 암호화 키가 잘못되면 "잘못된 키/손상된 데이터"라는 오류가 발생합니다. 이 오류를 캡처하여 MySQL에서와 같이 'null'을 반환 할 수있는 일부 함수를 검색해 보았습니다. 따라서 코드를 수정할 필요가 없습니다. 나는 찾고 있었지만 찾을 수 없었다.

개별 쿼리에 대해 오류 처리 메커니즘을 사용한 사람이 있습니까? 오류 처리가 프로 시저에 대해 수행 될 수 있음을 발견했습니다. 하지만, 전체 애플리케이션을 완전히 다시 작성해야했습니다.

몇 가지 세부 정보를 공유 할 수 있다면 큰 도움이 될 것입니다. 감사.

답변

4

코드 수정을 피하고 함수가 NULL을 오류로 반환하도록하려면 BEGIN ... EXCEPTION 블록을 사용하여 오류를 트 랩핑하는 PL/PgSQL 함수에서 래핑하여이 작업을 수행 할 수 있습니다.

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 

내가 직접 오류 처리기에서 이것을 사용할 수 있습니다,하지만 난 상징적 인 이름을 사용하는 것을 선호, 그래서 오류 이름을 조회 :

은 처음에는 오류에 대한 SQLSTATE를 얻을이 작업을 수행하려면 Appendix A - Error codes에서 39000과 연결되어 일반 함수 호출 오류 external_routine_invocation_exception이라는 것을 알게되었습니다. 우리가 좋아할만큼 구체적이지는 않지만 그렇게 할 것입니다.

이제 래퍼 기능이 필요합니다. 이와 같은 것을 정의해야하며 지원하려는 오버로드 된 각 서명에 대해 하나의 함수로 pgp_sym_decrypt을 정의해야합니다. 예를 들어, 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; 

나는 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

답변 해 주셔서 감사합니다.나는 최후의 수단으로 이런 종류의 기능을 구현하기로 결정했다. 실제로 매우 유용합니다. 나는 in-build pgsql 함수를 최대한 활용하려고 노력 중이다. 그게 얼마나 도움이되는지 봅시다. 또한 앱의 모든 암호를 수행 할 것을 제안 해 주셔서 감사합니다. 내가 이미 앱에서 몇 가지 중요한 기능을 변경하려고 계획 한 방법입니다. 나중에 모든 것을 바꿀 것입니다. –

+0

@ user1365983 좋은 생각입니다. 아주 좋은 생각이라고 생각하지 않습니다. 그렇게하기를 계획하지 않았기 때문에 기쁩니다. 도움이된다면 답을 수락하십시오. 왼쪽 상단에있는 답 점수 아래의 체크를 사용하십시오. –