#oracle #encryption #plsql #dbms-crypto
Вопрос:
Я пытаюсь использовать DBMS_CRYPTO для шифрования, но независимо от того, как я выбираю некоторые параметры, я сталкиваюсь со значениями, для которых код выдает
ORA-01890: NLS error detected ORA-06512: at "SYS.UTL_I18N", line 72 ORA-06512: at "SYS.UTL_I18N", line 353 ORA-06512: at line 26
Вот пример
declare
-- v_value VARCHAR2 (4000) := '9Ab2Ov1Bd4'; -- works
-- v_value VARCHAR2 (4000) := '7Md4Mt7Gk0'; -- works
-- v_value VARCHAR2 (4000) := '3Vf8Fi2Pa5'; -- works
-- v_value VARCHAR2(4000) := '5Vq2Dc4Cq9'; -- works as well
v_value VARCHAR2(4000) := '2Cq0Yh3Vb2'; --this does not work?
v_result VARCHAR2 (4000);
v_raw_row RAW (2000); -- stores ec binary text
v_enc_type PLS_INTEGER
:=
DBMS_CRYPTO.ENCRYPT_AES256
DBMS_CRYPTO.CHAIN_CBC
DBMS_CRYPTO.PAD_ZERO; -- total encryption type
v_def_k VARCHAR2 (32) := 'mMbSmSMr_!_uAlns9asG5_a_AfhS4_3a';
begin
v_raw_row :=
DBMS_CRYPTO.ENCRYPT (
src => UTL_I18N.STRING_TO_RAW (v_value, 'AL32UTF8'),
typ => v_enc_type,
key => UTL_RAW.CAST_TO_RAW (v_def_k));
v_result := UTL_I18N.RAW_TO_CHAR (v_raw_row, 'AL32UTF8');
dbms_output.put_line(v_result);
end;
Изменение типа шифрования и ключа «решает» проблему для одного значения, которое не работает, но я всегда сталкиваюсь с другим значением, которое затем вызовет это точное исключение.
Я попробовал это в Oracle 12.2.0.1.0, а также в 19.0.0.0.0. Точно такое же поведение.
Я думаю, что то, что я делаю, совершенно неправильно. Любая помощь будет признательна.
Комментарии:
1. Шифрование двоичного представления строки, как правило, не приводит к двоичному значению, которое является строкой для печати. Используйте
RAXTOHEX()
илиUTL_ENCODE.BASE64_ENCODE
или что-то еще, если вы хотите напечатать произвольное двоичное значение (например, вывод шифрования).2. привет, kfinity, спасибо за ваш комментарий. На самом деле я не хочу печатать его, а скорее хранить в VARCHAR2 и расшифровывать позже. Пример в документации oracle ( docs.oracle.com/database/121/ARPLS/d_crypto.htm#ARPLS65690 ) предлагает использовать UTL_I18N.RAW_TO_CHAR. Ваш комментарий касается только печати или общего предложения вообще избежать этого исключения?
Ответ №1:
Вместо AL32UTF8 в качестве исходного набора символов, пожалуйста, попробуйте использовать WE8ISO8859P1 или null.
Из документа Oracle:
UTL_I18N.RAW_TO_CHAR-это функция, которая преобразует необработанные данные в символы, преобразование типов данных может быть реализовано, но не могут быть преобразованы различные наборы символов. Второй параметр должен указывать, какой набор символов передается исходными данными, то есть исходным набором символов.
Укажите набор символов, из которого были получены необработанные данные. Если значение src_charset равно NULL, то используется набор символов базы данных.
поэтому при использовании набора символов DB или NULL об ошибке не будет сообщено.
Комментарии:
1. Спасибо вам за ваш ответ. Я собирался сказать, что это не работает, так как кодировка моих баз данных действительно AL32UTF8, запрос такой:
select * from nls_database_parameters where parameter='NLS_CHARACTERSET';
. Но, похоже, это все еще работает, установив кодировку в НУЛЬ, я попробовал это с 1000 случайными строками, и исключение не появилось. Но я не понимаю, почему это работает и действительно ли этот способ безопасен или я просто не нажал на одну струну, которая заставит это снова умереть. У вас есть какие-либо дальнейшие соображения?2. Я принимаю этот ответ, поскольку он решил проблему, я попытался использовать 300 тысяч случайных строк, и это никогда не подводило. Хотя я совершенно не понимаю, почему это помогает.