Вычислить хэш/контрольную сумму в Informix SQL

Я хотел бы рассчитать какое-то значение хэша или контрольной суммы для значения столбца в Informix SQL.

Эта проблема:

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

UPDATE personal_data SET name=HASH(name), employee_no=HASH(employee_no)

Мы хотим использовать хэш, а не просто фиксированное значение, потому что полезно, чтобы разные значения (обычно) отображались в разные результаты, а одни и те же значения — в один и тот же результат. Это позволяет по-прежнему выполнять сравнения тестовых данных (например, можно иметь несколько записей с одним и тем же номером сотрудника, и эту информацию полезно сохранить).

В большинстве СУБД есть какие-то функции хеширования (в PostgreSQL и MySQL есть MD5(), в Oracle — DBMS_UTILITY.GET_HASH_VALUE), но для Informix (Informix IDS 9) мне ничего не удалось найти. Это недостающая функция?


person sleske    schedule 25.09.2009    source источник
comment
Какую версию IDS вы используете?   -  person Jonathan Leffler    schedule 27.09.2009
comment
Informix IDS 9 (это в вопросе :-))   -  person sleske    schedule 28.09.2009


Ответы (4)


IDS не имеет каких-либо хеш-функций, представленных как встроенные функции, AFAICR.

Если вы используете IBM Informix Dynamic Server (IDS) версии 10.00 или более поздней (более ранние версии не поддерживаются — ну, 7.31 поддерживается до 30 сентября 2009 г., но не позднее), то можно создать UDR (пользовательский определенная процедура), которая делает работу. Это не невероятно сложно, но и не тривиально.

person Jonathan Leffler    schedule 27.09.2009
comment
Спасибо, этого я и опасался. Мне, вероятно, придется написать UDR или вспомогательную программу, чтобы выполнить эту работу :-(. - person sleske; 28.09.2009
comment
Извини за это. Могу ли я предложить вам тщательно обдумать, следует ли называть ваш UDR MD5() или лучше назвать его, скажем, app_hash(), чтобы, если/когда IDS получит MD5 (или SHA-1, или SHA-256, или .. .), вы не столкнетесь с проблемой именования? Или вы можете рискнуть тем, что IDS действительно предоставляет функцию с той же сигнатурой, что и ваш UDR, но что выходные данные будут несовместимы в будущем. - person Jonathan Leffler; 28.09.2009
comment
@ Джонатан: Хороший вопрос. Я бы, наверное, назвал его просто myHash или подобным, потому что меня не волнует алгоритм, мне просто нужен хеш. В любом случае, сделать это как внешнюю программу, вероятно, будет проще, так как я мало знаю о UDR (и мы их в настоящее время не используем). - person sleske; 28.09.2009

слеске,

Несколько лет назад я написал функцию T-SQL для вычисления хэшей SHA-1. Если это сработает для вас, возможно, вы сможете переработать мою функцию для Informix. эта ветка группы новостей имеет немного больше информации о своих ограничениях.

create function S( 
  @N int, 
  @x bigint 
) returns binary(4) as begin 
  declare @two_N bigint 
  set @two_N = power(cast(2 as bigint), @N) 
  declare @two_32_N bigint 
  set @two_32_N = power(cast(2 as bigint), 32-@N) 
  return cast(@x%@two_32_N*@two_N + @x/@two_32_N as binary(4)) 
end 
go 
create function f( 
  @t bigint, 
  @B bigint, 
  @C bigint, 
  @D bigint 
) returns bigint as begin 
  declare @2_32 bigint set @2_32 = power(cast(2 as bigint),32) 
  if @t between 0 and 19 
    return (@B & @C) | ((@2_32-@B-1) & @D) 
  if @t between 20 and 39 
    return @B ^ @C ^ @D 
  if @t between 40 and 59 
    return (@B & @C) | (@B & @D) | (@C & @D) 
  return @B ^ @C ^ @D 
end 
go 
create function SHA1 ( 
  @s varchar(55) 
) returns binary(20) as begin 
  declare @b varbinary(55) 
  set @b = cast(@s as varbinary(55)) 
  declare @zeros binary(64) 
  set @zeros = 0x 
  declare @padded binary(64) 
  set @padded = 
    @b + 0x80 + substring(@zeros,1,55-datalength(@b)) 
       + cast(8*datalength(@b) as binary(8)) 
  declare @H5 binary(20) 
  set @H5 = 0x67452301EFCDAB8998BADCFE10325476C3D2E1F0 
  declare @K4 binary(16) 
  set @K4 = 0x5A8279996ED9EBA18F1BBCDCCA62C1D6 
  declare @ABCDE binary(20) set @ABCDE = @H5 
  declare @W80   varbinary(320) set @W80 = @padded 
  declare @TEMP  binary(4) set @TEMP = 0x 
  declare @2_32 bigint set @2_32 = power(cast(2 as bigint),32) 
  declare @t int 
  set @t = 16 
  while @t < 80 begin 
    set @W80 = @W80 + 
      dbo.S(1,cast(substring(@W80,(@t-3)*4+1,4) as bigint) 
             ^cast(substring(@W80,(@t-8)*4+1,4) as bigint) 
             ^cast(substring(@W80,(@t-14)*4+1,4) as bigint) 
             ^cast(substring(@W80,(@t-16)*4+1,4) as bigint)) 
    set @t = @t + 1 
  end 
  set @t = 0 
  while @t < 80 begin 
    set @TEMP = cast((cast(dbo.S(5,substring(@ABCDE,1,4)) as bigint) 
          + dbo.f(@t,substring(@ABCDE,5,4) 
                    ,substring(@ABCDE,9,4) 
                    ,substring(@ABCDE,13,4)) 
          + cast(substring(@ABCDE,17,4) as bigint) 
          + cast(substring(@W80,4*@t+1,4) as bigint) 
          + cast(substring(@K4,4*(@t/20)+1,4) as bigint))%@2_32 as 
binary(4)) 
    set @ABCDE = @TEMP+substring(@ABCDE,1,4) 
                  +dbo.S(30,substring(@ABCDE,5,4)) 
                  +substring(@ABCDE,9,8) 
    set @t = @t + 1 
  end 
  set @H5 
  = cast((cast(substring(@H5, 1,4) as bigint) + cast(substring(@ABCDE, 1,4) 
as bigint))% @2_32 as binary(4)) 
  + cast((cast(substring(@H5, 5,4) as bigint) + cast(substring(@ABCDE, 5,4) 
as bigint))% @2_32 as binary(4)) 
  + cast((cast(substring(@H5, 9,4) as bigint) + cast(substring(@ABCDE, 9,4) 
as bigint))% @2_32 as binary(4)) 
  + cast((cast(substring(@H5,13,4) as bigint) + cast(substring(@ABCDE,13,4) 
as bigint))% @2_32 as binary(4)) 
  + cast((cast(substring(@H5,17,4) as bigint) + cast(substring(@ABCDE,17,4) 
as bigint))% @2_32 as binary(4)) 
  return @H5 
end 
person Steve Kass    schedule 25.09.2009
comment
Интересно! Потребуется много работы, чтобы перевести это в Informix — например, побитовые операции напрямую не поддерживаются. - person Jonathan Leffler; 27.09.2009
comment
Я не думаю, что мне имеет смысл заново реализовывать SHA-1. Если я не могу сделать это внутри Informix, я, вероятно, просто напишу для этого внешнюю программу :-/. - person sleske; 28.09.2009

Вы можете использовать ссылку ENCRYPT_TDES. Зашифрованная строка намного длиннее исходной, но это не должно быть проблемой — значение будет усечено. Шифрование + усечение должны дать результат, аналогичный хеш-значению. Я не совсем уверен, доступно ли шифрование в 9.40, возможно, нет. В этом случае вам нужно вычислить значение хеш-функции на клиенте.

person robsosno    schedule 10.12.2009
comment
Хорошее решение. Да, шифрование + усечение, скорее всего, сделают это. Он указан как новая функция в списке функций для IDS 10.0, поэтому, к сожалению, он, вероятно, недоступен в 9.40, где он мне и нужен :-/ . - person sleske; 11.12.2009
comment
Кстати: добро пожаловать в stackoverflow. Ваш первый ответ - хорошее начало :-). - person sleske; 11.12.2009

Если вы можете изменить структуру таблицы, вы можете использовать опцию WITH VERCOLS. См. Использование опции WITH VERCOLS. Вкратце: эта опция дает вам 2 дополнительных скрытых столбца: контрольная сумма для первоначально вставленной строки и количество изменений (обновлений) в строке.

person robsosno    schedule 10.12.2009
comment
Интересно. Но я не понимаю, как это мне поможет, так как, по-видимому, он генерирует контрольную сумму для всей строки, а не для значения в одном столбце. - person sleske; 10.12.2009