2013-03-22 19 views
9

Tôi đang cố gắng tạo một alogrithim băm chung dùng để băm một chuỗi dưới dạng int bit 64 bit.băm bigint của SQL để khớp với b # int64 hash

tôi có thể băm chuỗi một cách chính xác: sql:

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

lợi nhuận 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

Tuy nhiên khi tôi chuyển sang một bigint/lo ng các giá trị không phù hợp: sql:

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

lợi nhuận 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); 

lợi nhuận 7501998164347841210

Bất kỳ ý tưởng về cách để có được những con số này cho phù hợp?

+0

Xem ở đây: http://stackoverflow.com/questions/8467072/sql-server-varbinary-bigint-with-bitconverter-toint64-values-are-different cho một giải pháp có thể. –

+0

Thay vì tạo băm của riêng bạn trên các đối tượng, bạn chỉ nên sử dụng ['GetHashCode'] (http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx), nó hiệu quả hơn nhiều so với việc tái tạo lại bánh xe, các chuỗi có cùng ký tự sẽ tạo ra cùng một '" HashCode "'. – Killrawr

+2

@Killrawr: GetHashCode chỉ nên được sử dụng để cân bằng bảng băm. Chúng tôi không có bằng chứng cho thấy áp phích ban đầu đang cố gắng cân bằng bảng băm; có vẻ như họ đang cố gắng băm băm sức mạnh mã hóa. Nó rất, rất quan trọng để ** không bao giờ sử dụng GetHashCode ** cho một băm mật mã. Nó có * none * của các thuộc tính mà bạn cần để tạo một băm an toàn. Một lần nữa, nếu bạn đang gọi GetHashCode và bạn không phải là ngay bây giờ cố gắng để cân bằng một bảng băm, bạn đang làm một cái gì đó sai. –

Trả lời

8

SQL bigint của bạn mất 8 byte cuối cùng trong khi triển khai C# mất 8 byte đầu tiên (và đảo ngược chúng vì chạy trên ít cuối).

Lấy phạm vi phù hợp của mảng trong C# và đảo ngược nó. Sau đó, bạn nên được tốt.

Đã làm một số mã hóa:

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

Và bạn có thể sử dụng 'var reversed = BitConverter.GetBytes (IPAddress.HostToNetworkOrder (longValue))' để hoán đổi byte. –

+0

câu trả lời rất tuyệt vời !!! –

+1

@DasKrumelmonster: Nếu bạn sử dụng 'BitConverter.GetBytes (IPAddress.HostToNetworkOrder (longValue))' thay vì LINQ, nó sẽ hoạt động bất kể thứ tự byte của máy khách vì HostToNetworkOrder() chiếm nó. –