2013-03-22 146 views
9

我想創建一個通用哈希alogrithim哈希一個字符串作爲64位int。SQL bigint哈希匹配c#int64哈希

我能夠正確地散列字符串: 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(); 

retruns BAEA954B95731C68AE6E45BD1E252EB4560CDC45

然而,當我轉換爲BIGINT/LO NG的值不匹配: 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

如何得到這些數字匹配任何想法?

+0

在這裏看到:http://stackoverflow.com/questions/8467072/sql-server-varbinary-bigint-with-bitconverter-toint64-values-are-different了可能的方案。 – 2013-03-22 21:27:23

+0

而不是在對象上生成自己的哈希,您應該只使用['GetHashCode'](http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx),它比重新創建更有效輪子,具有相同字符的字符串將產生相同的「HashCode」。 – Killrawr 2013-03-22 21:37:53

+2

@Killrawr:GetHashCode只能用來平衡哈希表。我們沒有證據表明原始海報試圖平衡散列表;它看起來很像他們正在嘗試密碼強度散列。 **從不使用GetHashCode **加密哈希是非常非常重要的。它具有* none *您需要製作安全哈希的屬性。同樣,如果您調用GetHashCode,並且您現在不想平衡哈希表,那麼您做錯了什麼。 – 2013-03-22 21:46:10

回答

8

您的SQL bigint需要最後8個字節,而c#實現需要前8個字節(並且因爲它在小端上運行而反轉它們)。

在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 
+0

你可以使用'var reversed = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(longValue))'交換字節。 – 2013-03-22 21:31:46

+0

非常好的答案! – 2013-03-22 21:36:09

+1

@DasKrumelmonster:如果使用'BitConverter.GetBytes(IPAddress.HostToNetworkOrder(longValue))'而不是Linq,它將工作,不管客戶端的字節順序如何,因爲HostToNetworkOrder()對它進行了說明。 – 2013-03-22 21:41:59