обработка ошибок 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. Параметры не будут отображаться, если вы использовали параметры привязки ("подготовленные операторы"), но вы все равно должны считать свои журналы критичными для безопасности, если вы используете шифрование в базе данных.
лично я думаю, что лучше делать криптографию в приложении, поэтому БД никогда не имеет доступа к ключам.