我见过几个博客,展示了如何在为一组值生成哈希时将结果从HashBytes转换为bigint。这在数据仓库中似乎很常见。这有利于将散列存储为整数,这对于连接非常有用并且提供良好的分区分布。
我想知道,如果这是一个好习惯。我注意到使用Sha1和HashBytes会产生16字节的结果。由于bigint是一个8字节的数据类型,这不会导致在将它转换为bigint之前必须将16字节截断8。如果是这样,这似乎会增加碰撞的可能性。
我们已经将我们的varbinary哈希转换为bigint很长一段时间并且还没有遇到碰撞,但如果上述假设是正确的话,它肯定似乎是愚蠢的运气。
为了测试这个我尝试转换一些哈希来看看我是否可以从bigint回到原始哈希,但是无法这样做可能表明问题(或者我正在进行转换)不正确地)。
你的数学大师有没有想过这个? 提前谢谢!
DECLARE @value varchar(5) = '12345'
DECLARE @hash varbinary(max) = hashbytes('SHA1', @Value)
SELECT @hash AS OriginalHash
SELECT CAST(@hash as nvarchar(max)) AS StringHash
SELECT CAST(CAST(@hash as nvarchar(max)) as varbinary(max)) AS StringBackToOriginalHash
SELECT CAST(@hash as bigint) AS BigIntHash
SELECT CAST(CAST(@hash as bigint) as varbinary(max)) AS BigIntBackToOriginalHash
根据SQL 2016的最新迹象,他们将弃用旧的哈希算法,我们最终将不得不使用Sha2_256和Sha2_512这些更长的哈希值会占用更多的空间。这也是另一个原因,如果像旧的Sha1哈希那样碰撞抗性,那么使用bigint会很棒。
答案 0 :(得分:0)
Actually I think I may have come across the answer in this article. https://blogs.msdn.microsoft.com/sqlcat/2005/09/16/using-hashing-to-obscure-sensitive-data/
的逻辑2)如果使用数百万个SSN值,则使用从截断的哈希构建的bigint可能会产生不可接受的哈希冲突风险。可以使用在给定2 ^(#bits / 2)个输入值的情况下存在50%碰撞机会的估计来计算散列冲突的可能性。对于使用7个字节计算的bigint,这意味着如果您散列2 ^ 28个不同的值(或2.68亿个不同的SSN),则有50%的机会发生冲突。因此,如果输入值的范围很大,您可能希望使用完整的哈希字符串,或将哈希的较长子字符串转换为十进制值。