обработка ошибок PGP sym encrypt/PGP sym decrypt

Я использовал MySQL в качестве базы данных и планировал перейти на postgresql. Я широко использовал функции aes_encrypt и aes_decrypt в MySQL во всем моем приложении. Поэтому, когда шифрование/расшифровка рядом не удается, MySQL автоматически возвращает значение null.

Я не уверен, как обрабатывать то же самое в postgresql. Пробовал использовать функции pgp_sym_encrypt/pgp_sym_decrypt. Если ключ шифрования неверен, он выдает ошибку "неправильный ключ/поврежденные данные". Я пытался найти их. функции, которые могли бы захватить эту ошибку и вернуть "null" как в MySQL, так что мне не нужно изменять мой код. Я искал, но не мог найти.

кто-нибудь использовал механизм обработки ошибок для отдельных запросов? Я обнаружил, что обработка ошибок может быть выполнена для процедур. Но для этого мне пришлось полностью переписать все приложение.

Если бы вы могли поделиться некоторыми деталями, это было бы очень полезно. Спасибо.

1 ответов


если вы хотите избежать изменения кода и функции возврат 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

я мог бы использовать это непосредственно в обработчике ошибок, но я предпочитаю использовать символическое имя, поэтому я ищу имя ошибки, связанное с 39000 в приложение A-коды ошибок, обнаружив, что это общая ошибка вызова функции external_routine_invocation_exception. Не так конкретно, как хотелось бы, но сойдет.

теперь требуется функция обертки. Что-то вроде этого должно быть определено, с одной функцией для каждой перегруженной подписи 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

отметим, что обе формы показывают параметры, которые вызывала функция с when it failed. Параметры не будут отображаться, если вы использовали параметры привязки ("подготовленные операторы"), но вы все равно должны считать свои журналы критичными для безопасности, если вы используете шифрование в базе данных.

лично я думаю, что лучше делать криптографию в приложении, поэтому БД никогда не имеет доступа к ключам.