2016-06-26 2 views
3

У меня есть следующие две строки:Создание уникальных хэш-код на основе строки

var string1 = "MHH2016-05-20MASTECH HOLDINGS, INC. Financialshttp://finance.yahoo.com/q/is?s=mhhEDGAR Online FinancialsHeadlines"; 

var string2 = "CVEO2016-06-22Civeo upgraded by Scotia Howard Weilhttp://finance.yahoo.com/q/ud?s=CVEOBriefing.comHeadlines"; 

На первый взгляд эти две строки различны, однако их хэш-код такой же, используя GetHashCode method.

 var hash = 0; 
     var total = 0; 
     foreach (var x in string1) //string2 
     { 
      //hash = x * 7; 
      hash = x.GetHashCode(); 
      Console.WriteLine("Char: " + x + " hash: " + hash + " hashed: " + (int) x); 
      total += hash; 
     } 

Итого в конце концов составляет 620438779 для обеих строк. Есть ли другой метод, который вернет более уникальный хеш-код? Мне нужно, чтобы хэш-код был уникальным на основе символов в строке. Хотя обе строки отличаются друг от друга, и код работает правильно, эти две строки так кажутся одинаковыми. Как я могу улучшить этот код, чтобы сделать его более уникальным?

+2

Вы понимаете, не правда ли, что вы не можете гарантировать уникальный хэш-код для всех возможных строк? Хэш-код - 32 бит, что означает, что существует 4 миллиарда (и изменение) возможных значений. Каждая из двух строк имеет длину более 120 символов. Количество возможных 120-символьных строк, использующих 96 печатных символов ASCII, намного больше.Столкновения неизбежны. * В общем случае нет такого уникального хеш-кода *. Если сделать хэш-код больше, это уменьшит вероятность столкновения, но не устранит его. –

+2

Ваш вопрос подразумевает, что вы пытаетесь использовать хэш-коды как уникальные идентификаторы. Это невероятно плохая идея и обречена на провал. Ответ @AlexD объясняет, почему. –

+0

@JimMischel да, я знаю об этом сейчас, но спасибо –

ответ

12

string.GetHashCode действительно подходит для реального хеширования:

Предупреждение

Хэш-код предназначен для эффективного ввода и поиска в коллекции, которые основаны на хэш-таблице. Хеш-код не является постоянным значением. По этой причине:

  • Не сериализуйте значения хэш-кода или храните их в базах данных.
  • Не используйте хеш-код в качестве ключа для извлечения объекта из коллекции с ключом.
  • Не используйте хеш-код вместо значения, возвращаемого функцией криптографического хэширования. Для криптографических хэшей используйте класс, полученный из класса System.Security.Cryptography.HashAlgorithm или System.Security.Cryptography.KeyedHashAlgorithm.
  • Не проверяйте равенство хеш-кодов, чтобы определить, равны ли два объекта. (Неравные объекты могут иметь одинаковые хэш-коды.) Чтобы проверить равенство, вызовите метод ReferenceEquals или Equals.

и имеет высокую вероятность duplicates.

Рассмотрите HashAlgorithm.ComputeHash. Образец слегка изменен, чтобы использовать SHA256 вместо MD5, так как @zaph предложил:

static string GetSha256Hash(SHA256 shaHash, string input) 
{ 
    // Convert the input string to a byte array and compute the hash. 
    byte[] data = shaHash.ComputeHash(Encoding.UTF8.GetBytes(input)); 

    // Create a new Stringbuilder to collect the bytes 
    // and create a string. 
    StringBuilder sBuilder = new StringBuilder(); 

    // Loop through each byte of the hashed data 
    // and format each one as a hexadecimal string. 
    for (int i = 0; i < data.Length; i++) 
    { 
     sBuilder.Append(data[i].ToString("x2")); 
    } 

    // Return the hexadecimal string. 
    return sBuilder.ToString(); 
} 
+0

для полного примера см. Https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5(v=vs.110).aspx – lexx9999

+0

@ lexx9999 Я думаю, что ссылка в сообщении указывает на тот же алгоритм уже. – AlexD

+0

Поскольку я читал его, он не включал GetMd5Hash/VerifyMd5Hash – lexx9999

1
using System.Security.Cryptography; 
string data="test"; 
byte[] hash; 
using (MD5 md5 = MD5.Create()) 
{ 
    md5.Initialize(); 
    md5.ComputeHash(Encoding.UTF8.GetBytes(data)); 
    hash = md5.Hash; 
} 

хеш-массив из 16 байт, который, в свою очередь, можно в какой-то тайному шестнадцатеричных строки или base64 закодированного строка для хранения.

EDIT:

Какова цель этого хэш-кода?

От хэша (х)! = Хэш (у) вы можете получить х! = У, но

из хэша (х) == хэш (у) вы НЕ может получить х == у в целом !

+0

Это приведет к замедлению производительности, хеширование безопасности не будет использоваться для предотвращения столкновения. –

+0

@ lexx9999 Цель хеш-кода состоит в том, чтобы отличать от дубликатов. Строки возвращаются из веб-скребка. Я попробовал ваш предложенный код для двух строк, которые я использовал в качестве примера в моем вопросе, который возвращает уникальные хэш-коды, но когда я пытаюсь это сделать в своей общей программе, я все равно получаю дубликаты. –

+1

@somerandomdude. Как и в любой хэш-функции, вам придется сравнивать исходные данные, если вы хотите быть абсолютно уверенными. Вы можете попробовать другие алгоритмы хеширования, но вы всегда должны ожидать столкновения. Вот что: 'from hash (x) == hash (y) вы НЕ можете получить x == y вообще!'. – lexx9999

Смежные вопросы