【问题标题】:SQL bigint hash to match c# int64 hash [duplicate]SQL bigint hash 以匹配 c# int64 hash [重复]
【发布时间】:2013-03-12 21:02:12
【问题描述】:

我正在尝试创建一个通用散列算法,将字符串散列为 64 位整数。

我能够正确地散列字符串: sql:

select  
    convert
    (
        varchar(64),
        HASHBYTES
        (
            'SHA1',
            'google.com'
        ),
        2
    )

返回BAEA954B95731C68AE6E45BD1E252EB4560CDC45

C#

    System.Security.Cryptography.SHA1 c = System.Security.Cryptography.SHA1.Create();
    System.Text.StringBuilder sb = new StringBuilder();
    byte[] b = c.ComputeHash(Encoding.UTF8.GetBytes("google.com"));
    for (int i = 0; i < b.Length;i++ )
    {
        byte by = b[i];
        sb.Append(by.ToString("x2").ToUpper());
    }

    return sb.ToString();

返回BAEA954B95731C68AE6E45BD1E252EB4560CDC45

但是,当我转换为 bigint/long 时,值不匹配: sql:

select  
    convert
    (
        bigint,
        HASHBYTES
        (
            'SHA1',
            'google.com'
        )
    )

返回2172193747348806725

c#:

    System.Security.Cryptography.SHA1 c = System.Security.Cryptography.SHA1.Create();
    byte[] b = c.ComputeHash(Encoding.UTF8.GetBytes("google.com"));
    return BitConverter.ToInt64(b, 0);

返回7501998164347841210

关于如何使这些数字匹配的任何想法?

【问题讨论】:

  • 请参阅此处:stackoverflow.com/questions/8467072/… 以获得可能的解决方案。
  • 与其在对象上生成自己的哈希值,不如只使用GetHashCode,它比重新发明轮子更有效,相同字符的字符串将生成相同的"HashCode"
  • @Killrawr:GetHashCode 只能用于平衡哈希表。我们没有证据表明原始发布者试图平衡哈希表;看起来他们正在尝试加密强度哈希。 永远不要将 GetHashCode 用于加密哈希是非常非常重要的。它有 none 您需要进行安全哈希的属性。同样,如果您正在调用 GetHashCode 而您现在没有尝试平衡哈希表,那么您做错了。
  • @EricLippert 哦,我想我会推荐它,如果哈希被用于其他任何事情,例如使用 Equals 方法以便在对象之间创建高效的 Contract。跨度>

标签: c# sql-server hash bigint uint64


【解决方案1】:

您的 SQL bigint 占用最后 8 个字节,而 c# 实现占用前 8 个字节(并反转它们,因为它运行在 little endian 上)。

在 C# 中取适当的数组范围并将其反转。那你应该没事。

做了一些编码:

System.Security.Cryptography.SHA1 c = System.Security.Cryptography.SHA1.Create();
byte[] b = c.ComputeHash(Encoding.UTF8.GetBytes("google.com"));
long value = BitConverter.ToInt64(b, 12);
value = IPAddress.HostToNetworkOrder(value);

Debug.WriteLine(value);
// writes 2172193747348806725

【讨论】:

  • 您可以使用var reversed = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(longValue)) 交换字节。
  • 非常好的答案!!!
  • @DasKrumelmonster:如果你使用BitConverter.GetBytes(IPAddress.HostToNetworkOrder(longValue))而不是Linq,那么无论客户端的字节顺序如何,它都可以工作,因为HostToNetworkOrder()考虑了它。
  • 好主意。虽然它以长值运行,但字节序转换在位转换器之后。另外,我可以通过使用 startIndex 参数来消除 linq。
  • 如果你想让 sql 匹配 select convert ( bigint, convert ( varbinary(8), reverse ( convert ( varbinary(8), HASHBYTES ( 'SHA1', 'google.com' ) ) ) ) ) 返回 7501998164347841210
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-18
  • 2020-12-28
  • 1970-01-01
  • 1970-01-01
  • 2012-04-19
相关资源
最近更新 更多