2013-03-22 3 views
9

Я пытаюсь создать универсальный хэширующий алогритим, который хэширует строку как 64-битный int.SQL bigint хэш для соответствия C# int64 hash

Я способен правильно хэш строки: 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/с нг значения не совпадают: 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 для возможное решение. –

+0

Вместо того, чтобы генерировать собственные хэши на объектах, вы должны просто использовать ['GetHashCode'] (http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx), что намного эффективнее, чем переосмысление колесо, строки с одинаковыми символами будут выдавать один и тот же «HashCode». – Killrawr

+2

@Killrawr: GetHashCode следует использовать только для балансировки хеш-таблицы. У нас нет доказательств того, что оригинальный плакат пытается сбалансировать хэш-таблицу; это похоже на то, что они пытаются использовать криптопрочность. Очень важно очень никогда не использовать GetHashCode ** для криптографического хэша. Он имеет * none * свойств, необходимых для создания безопасного хэша. Опять же, если вы вызываете GetHashCode, и вы сейчас не пытаетесь сбалансировать хеш-таблицу, вы делаете что-то неправильно. –

ответ

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 reverseed = BitConverter.GetBytes (IPAddress.HostToNetworkOrder (longValue))' для замены байтов. –

+0

очень отличный ответ !!! –

+1

@DasKrumelmonster: Если вы используете 'BitConverter.GetBytes (IPAddress.HostToNetworkOrder (longValue))', а не Linq, он будет работать независимо от порядка байтов клиента, потому что за него отвечает HostToNetworkOrder(). –