MD5 в Oracle (DBMS_OBFUSCATION_TOOLKIT.MD5)

#oracle #plsql #md5 #oracle-xe #subtype

#Oracle #plsql #md5 #oracle-xe #подтип

Вопрос:

Я пытаюсь составить функцию для получения хэшей MD5 из битов, которые я собрал здесь и там. Я хочу получить шестнадцатеричное представление хэша в нижнем регистре. У меня пока это есть:

 CREATE OR REPLACE FUNCTION MD5 (
    CADENA IN VARCHAR2
) RETURN DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM
AS
BEGIN
    RETURN LOWER(
        RAWTOHEX(
            UTL_RAW.CAST_TO_RAW(
                DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => CADENA)
            )
        )
    );
END;
  

Я не уверен насчет возвращаемого типа функции. DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM выглядит как подходящий выбор, и, насколько я могу судить, он работает так, как ожидалось, но определение пакета для dbms_obfuscation_toolkit , отображаемое разработчиком SQL, показывает это:

 SUBTYPE varchar2_checksum IS VARCHAR2(16);
  

Выходные данные содержат 32 символа, поэтому я, должно быть, делаю что-то не так. Мои вопросы:

  • Какой правильный тип для RETURN инструкции?
  • Выполняю ли я ненужные преобразования для вычисления хэша?

Комментарии:

1. Это один из случаев, когда я хотел бы иметь возможность принять два ответа…

Ответ №1:

Вот так:

 create or replace function getMD5(
  in_string in varchar2)
return varchar2
as
  cln_md5raw raw(2000);
  out_raw raw(16);
begin
  cln_md5raw := utl_raw.cast_to_raw(in_string);
  dbms_obfuscation_toolkit.md5(input=>cln_md5raw,checksum=>out_raw);
  -- return hex version (32 length)
  return rawtohex(out_raw);
end;
  

Длина 32 объясняется тем, что это шестнадцатеричное представление необработанного значения (16). Или измените выше, чтобы вывести необработанную версию и сохранить необработанную в необработанном столбце (используется меньше места, но вы будете выполнять будущие преобразования rawtohex и hextoraw, поверьте мне).

Приветствия

Комментарии:

1. Отлично! Я, наконец, использовал вариант этого. Самое главное, это, наконец, помогло мне разобраться, как работают внутренние компоненты. MD5(INPUT_STRING => CADENA) Я использовал на самом деле возвращает строку, но она содержит 0x5F4D... байты, а не буквальное "5F4D" представление. Таким образом, мы прибегаем к RAW в качестве промежуточного формата, чтобы мы могли использовать RAWTOHEX() . (Принудительное автоматическое преобразование из RAW в VARCHAR, похоже, также работает.)

2. каким будет сценарий, когда мы захотим передать как CLOB вместо VARCHAR2

Ответ №2:

Особенностью Oracle PL / SQL является то, что параметры хранимых процедур и типы возвращаемых функций не могут быть ограничены. То есть у нас не может быть процедуры с подобной подписью:

 SQL> create or replace procedure my_proc (p1 in varchar2(30))
  2  is
  3  begin
  4      null;
  5  end;
  6  /

Warning: Procedure created with compilation errors.

SQL> show error
Errors for PROCEDURE MY_PROC:

LINE/COL ERROR
-------- -----------------------------------------------------------------
1/34     PLS-00103: Encountered the symbol "(" when expecting one of the
         following:
         := . ) , @ % default character
         The symbol ":=" was substituted for "(" to continue.

SQL> create or replace procedure my_proc (p1 in varchar2)
  2  is
  3  begin
  4      null;
  5  end;
  6  /

Procedure created.

SQL>
  

Конечно, мы можем определить параметр процедуры, используя ПОДТИП, но Oracle проигнорирует его. То же самое касается типов возвращаемых функций…

 SQL> create or replace package my_subtypes as
  2      subtype ltd_string is varchar2(30);
  3  end;
  4  /

Package created.

SQL> create or replace function my_func return my_subtypes.ltd_string
  2  is
  3  begin
  4      return lpad('a', 4000, 'a');
  5  end;
  6  /

Function created.

SQL> select length(my_func) from dual
  2  /

LENGTH(MY_FUNC)
---------------
           4000

SQL>
  

Единственный способ ограничить параметры и возвращаемые типы — объявлять переменные с использованием подтипов в хранимой процедуре. Используйте переменные внутри пакета и присваивайте их параметрам OUT (или ВОЗВРАЩАЙТЕ переменную для функций).

Это многословный способ сказать, что вы можете использовать DBMS_OBFUSCATION_TOOLKIT.VARCHAR2_CHECKSUM в своем коде, будучи уверенными, что это не помешает вашей функции возвращать 32 символа.

Однако это собьет с толку разработчиков, которые будут просматривать объявление подтипа. В худшем случае эти люди будут использовать подтип для объявления своих собственных рабочих переменных со следующим трагическим результатом:

 SQL> declare
  2      v my_subtypes.ltd_string;
  3  begin
  4      v := my_func;
  5  end;
  6  /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4


SQL>
  

Таким образом, лучше не использовать неподходящий подтип. Вместо этого объявите свой собственный.