在Informix SQL中计算哈希/校验和

时间:2009-09-25 12:18:07

标签: sql hash informix

我想为Informix SQL中的列值计算某种哈希值或校验和值。

问题:

我们需要在测试数据中匿名化个人信息,并希望通过散列相关值来实现此目的,如:

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

我们希望使用哈希值,而不仅仅是固定值,因为它可以用于(通常)映射到不同结果的不同值,以及映射到相同结果的相同值。这使得仍然可以对测试数据进行比较(例如,可能有几个记录具有相同的employee_no,并且保留该信息很有用。)

大多数DBMS都有某种散列函数(PostgreSQL和MySQL有MD5(),Oracle有DBMS_UTILITY.GET_HASH_VALUE),但我找不到任何Informix(Informix IDS 9)。这是一个缺少的功能吗?

4 个答案:

答案 0 :(得分:1)

sleske,

几年前,我编写了一个T-SQL函数来计算SHA-1哈希值。如果这对您有用,也许您可​​以为Informix重写我的功能。 This newsgroup thread有关于其局限性的更多信息。

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 

答案 1 :(得分:1)

IDS没有任何哈希函数作为内置函数公开,AFAICR。

假设您使用的是IBM Informix Dynamic Server(IDS)版本10.00或更高版本(不支持早期版本 - 嗯,直到2009-09-30支持7.31,但不支持更高版本),那么可以创建UDR (用户定义的例程)完成这项工作。这并非难以置信 - 但这也不是一件容易的事。

答案 2 :(得分:1)

您可以使用ENCRYPT_TDES。加密字符串比原始字符串长得多,但这不应该是一个问题 - 值将被截断。加密+截断应该得到类似于哈希值的结果。 我不太确定9.40中是否有加密,可能不是。 在这种情况下,您必须在客户端上计算哈希值。

答案 3 :(得分:0)

如果您可以更改表结构,则可以使用WITH VERCOLS选项。见Using the WITH VERCOLS Option。 简而言之:此选项为您提供了2个额外的隐藏列:最初插入行的校验和以及行上的更改(更新)数。