2013-03-22 10 views
9

Próbuję utworzyć uniwersalny hash algrithim, który miesza łańcuch jako 64-bitowy int.SQL bigint hash, aby dopasować C# int64 hash

jestem w stanie hash ciągi poprawnie: sql:

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

powraca 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

Jednakże gdy przekonwertować do bigint/lo NG wartości nie pasują: sql:

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

powraca 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); 

powraca 7501998164347841210

pomysłów, w jaki sposób uzyskać te numery, aby dopasować?

+0

Zobacz tutaj: http://stackoverflow.com/questions/8467072/sql-server-varbinary-bigint-with-bitconverter-toint64-values-are-different dla możliwe rozwiązanie. –

+0

Zamiast generować własne skróty na obiektach, powinieneś użyć ['GetHashCode'] (http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx), o wiele skuteczniej niż na nowo. koło, łańcuchy o tych samych znakach wytworzą ten sam '' HashCode "'. – Killrawr

+2

@Killrawr: GetHashCode powinien być używany tylko do równoważenia tabeli mieszania. Nie mamy dowodów na to, że oryginalny plakat próbuje zrównoważyć stół hashowy; wygląda raczej na to, że próbują hash krypto siłę. Bardzo ważne jest, aby ** nigdy nie używać GetHashCode ** dla skrótu kryptograficznego. Ma * none * właściwości, które są potrzebne do bezpiecznego mieszania. Ponownie, jeśli wywołujesz GetHashCode, a nie próbujesz teraz wyrównać tabeli hash, robisz coś nie tak. –

Odpowiedz

8

Twój SQL bigint bierze ostatnie 8 bajtów, podczas gdy implementacja C# zajmuje pierwsze 8 bajtów (i odwraca je, ponieważ działa na małym endianie).

Przenieś odpowiedni zakres tablicy w C# i odwróć go. Wtedy powinno być dobrze.

Czy jakiś Kodowanie:

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

I można użyć 'var odwróconego = BitConverter.GetBytes (IPAddress.HostToNetworkOrder (longValue)), aby zamienić bajty. –

+0

bardzo doskonała odpowiedź !!! –

+1

@DasKrumelmonster: Jeśli użyjesz 'BitConverter.GetBytes (IPAddress.HostToNetworkOrder (longValue)) zamiast Linq, zadziała to niezależnie od kolejności bajtów klienta, ponieważ HostToNetworkOrder() uwzględnia to. –