Создание sha1-хэша строки в Oracle

У меня возникла проблема с созданием sha1-хэша строки при выборе в базе данных Oracle. Я сделал это в MSSQL следующим образом:

SELECT *,HASHBYTES('SHA1',CAST(ID as varchar(10)+
  TextEntry1+TextEntry2+CAST(Timestamp as varchar(10)) as Hash
FROM dbo.ExampleTable
WHERE ID = [foo]

Однако я не могу найти аналогичную функцию для использования при работе с Oracle. Что касается моего поиска в Google, я предполагаю, что dbms_crypto.hash_sh1 как-то связан с этим, но я еще не смог обдумать это...

Любые указатели будут очень признательны.


person PrometheusDrake    schedule 17.11.2009    source источник


Ответы (4)


Пакет DBMS_CRYPTO является правильным пакетом для создания хэшей. По умолчанию он не предоставляется PUBLIC, вам придется предоставить его специально (GRANT EXECUTE ON SYS.DBMS_CRYPTO TO user1).

Результат этой функции имеет тип данных RAW. Вы можете сохранить его в столбце RAW или преобразовать в VARCHAR2 с помощью функций RAWTOHEX или UTL_ENCODE.BASE64_ENCODE.

Функция HASH перегружена, чтобы принимать на вход три типа данных: RAW, CLOB и BLOB. В соответствии с правилами неявного преобразования, если вы используете VARCHAR2 в качестве входных данных, Oracle попытается преобразовать его в RAW и, скорее всего, потерпит неудачу, поскольку это преобразование работает только с шестнадцатеричными строками.

Если вы используете VARCHAR2, вам нужно преобразовать ввод в двоичный тип данных или CLOB, например:

DECLARE
   x RAW(20);
BEGIN
   SELECT sys.dbms_crypto.hash(utl_raw.cast_to_raw(col1||col2||to_char(col3)), 
                               sys.dbms_crypto.hash_sh1) 
     INTO x 
     FROM t;
END;

дополнительную информацию вы найдете в документации DBMS_CRYPTO.hash.

person Vincent Malgrat    schedule 17.11.2009
comment
Спасибо за помощь. Мне пришлось использовать значение dbms_crypto.hash_sh1 (целое число 3) вместо константы, чтобы оно работало при выполнении обычного SQL. ВЫБЕРИТЕ sys.dbms_crypto.hash(utl_raw.cast_to_raw(col1),3) FROM t; - person PrometheusDrake; 18.11.2009
comment
Я не думаю, что это точно правильно для 11g R2. dbms_crypto.hash, похоже, имеет 3 перегруженные версии для raw, blob и clob. Значение varchar2 должно быть явно преобразовано в raw с помощью utl_i18n.string_to_raw или utl_raw.cast_to_raw. Или используйте clobs для символьных данных. - person user272735; 12.01.2015
comment
Что делать, если есть некоторые столбцы, которые не имеют строкового типа данных? - person ca9163d9; 04.10.2017
comment
Комментарий выше от @PrometheusDrake говорит о dbms_crypto.hash_sh1. Чтобы было ясно, это константа, определенная в пакете и переданная dbms_crypto.hash в качестве параметра typ. Это указывает на то, что следует использовать хэш-алгоритм SHA-1. - person Andrew Philips; 08.05.2020
comment
@ ca9163d9 ca9163d9 Если ваш столбец относится к другому типу, найдите соответствующую функцию пакета UTL_RAW. Например, если у вас есть столбец типа NUMBER, используйте CAST_FROM_NUMBER, чтобы преобразовать его в RAW, а затем зашифровать. Чтобы отменить, расшифруйте, а затем CAST_TO_NUMBER. - person Andrew Philips; 08.05.2020

Пакет DBMS_crypto не поддерживает varchar2. Он работает с необработанным типом, поэтому, если вам нужен varchar2, вы должны его преобразовать. Вот пример функции, показывающий, как это сделать:

declare
  p_string varchar2(2000) := 'Hello world !';
  lv_hash_value_md5    raw (100);
  lv_hash_value_sh1    raw (100);
  lv_varchar_key_md5   varchar2 (32);
  lv_varchar_key_sh1   varchar2 (40);
begin
  lv_hash_value_md5 :=
     dbms_crypto.hash (src   => utl_raw.cast_to_raw (p_string),
                       typ   => dbms_crypto.hash_md5);

  -- convert into varchar2
  select   lower (to_char (rawtohex (lv_hash_value_md5)))
    into   lv_varchar_key_md5
    from   dual;

  lv_hash_value_sh1 :=
     dbms_crypto.hash (src   => utl_raw.cast_to_raw (p_string),
                       typ   => dbms_crypto.hash_sh1);

  -- convert into varchar2
  select   lower (to_char (rawtohex (lv_hash_value_sh1)))
    into   lv_varchar_key_sh1
    from   dual;

  --
  dbms_output.put_line('String to encrypt : '||p_string);
  dbms_output.put_line('MD5 encryption : '||lv_varchar_key_md5);
  dbms_output.put_line('SHA1 encryption : '||lv_varchar_key_sh1);
end;
person Pierre-Gilles Levallois    schedule 28.02.2012
comment
В приведенном выше примере используется cast_to_raw, однако вместо этого вызывающим абонентам следует использовать UTL_I18N.STRING_TO_RAW. cast_to_raw не учитывает двоичное независимое преобразование языка. Если язык базы данных по умолчанию изменяется между шифрованием и дешифрованием, cast_to_raw и последующие cast_to_varchar2 могут завершиться ошибкой. Например, varchar2 можно преобразовать с помощью: UTL_I18N.STRING_TO_RAW (string, 'AL32UTF8') - person Andrew Philips; 08.05.2020

Вы можете определить эту функцию в своем любимом пакете, который я определил в utils_pkg.

FUNCTION SHA1(STRING_TO_ENCRIPT VARCHAR2) RETURN VARCHAR2 AS 
BEGIN 
RETURN LOWER(TO_CHAR(RAWTOHEX(SYS.DBMS_CRYPTO.HASH(UTL_RAW.CAST_TO_RAW(STRING_TO_ENCRIPT), SYS.DBMS_CRYPTO.HASH_SH1))));
END SHA1;

Теперь, чтобы назвать это

SELECT UTILS_PKG.SHA1('My Text') AS SHA1 FROM DUAL;

Ответ

SHA1
--------------------------------------------
5411d08baddc1ad09fa3329f9920814c33ea10c0

Вы можете выбрать столбец из какой-либо таблицы:

SELECT UTILS_PKG.SHA1(myTextColumn) FROM myTable;

Наслаждаться!

person Israel Rocha    schedule 18.09.2015

Просто выложу сюда, если кто-то будет искать.

В Oracle 12 вы можете использовать функцию standard_hash(<your_value>, <algorythm>). Если параметр <algorythm> не определен, будет сгенерирован хэш SHA-1 (тип выходных данных raw(20)).

person Sheyanoff    schedule 08.06.2018