6 Символьный Алгоритм Короткого Хэша

моя цель-создать короткую хэш-строку из 6 символов (возможно, содержащую символы [A-Z][a-z][0-9]) для строки длиной 42 буквенно-цифровых символа без учета регистра. Уникальность-ключевое требование. Безопасность или производительность не так важно.

есть ли конкретный алгоритм, который даст этот результат, или я должен придерживаться усечения хэша MD5 или хэша SHA-1 (как в этом вопросе)? Если да, то какова вероятность столкновение?

3 ответов


лучше всего было бы усечь известную хэш-функцию (MD5 или SHA-family), потому что эти алгоритмы имеют статистически хорошие равномерные распределения хэш-значений (а также используют полный хэш, а не только 6 символов).

теперь некоторые расчеты вероятности столкновения

- Number of letters in English alphabet: 26
- Add capitals: 26
- Add numerics: 10
--------------

In total you get 26 + 26 + 10 = 62 characters. 

Now you have 6 places, which gives you 62^6 possible combinations.
That is 56.800.235.584 ~ 57 billion combinations. 
This is a space of possible hash values - N.
--------------
To compute collisions let's use the formula 

Pcollision = K^2 / 2N

Which is a very rough approximation of collision probability

теперь давайте посмотрим таблицу результатов для ряда элементов в таблице-K

# items     | Probability of collision
---------------------------------------
10          |  1.7 * 10^-9
100         |  1.7 * 10^-7
1K          |  1.7 * 10^-5
10K         |  1.7 * 10^-3
100K        |  0.17

эту формулу можно использовать только для малого K, но она показывает, что данный 100k записей в хэш-таблице у вас будет примерно 17% вероятность столкновения.

ссылки

вероятность столкновения


простой хэш :)

private string Hash(string str)
{
    var allowedSymbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();
    var hash = new char[6];

    for (int i = 0; i < str.Length; i++)
    {
        hash[i % 6] = (char)(hash[i % 6] ^ str[i]);
    }

    for (int i = 0; i < 6; i++)
    {
        hash[i] = allowedSymbols[hash[i] % allowedSymbols.Length];
    }

    return new string(hash);
}

лучшим решением почти наверняка является использование SHA1, преобразование в Base62 (хотя Base64 было бы намного проще, поскольку он встроен в фреймворк преобразовать.ToBase64String. Вам придется немного поискать приличную библиотеку Base62), а затем усечь вывод до 6 байт.

Я бы не использовать GetHashCode() Как это работает история проблемы столкновения. (Я не пытаюсь утверждать, что эта конкретная ошибка будет применяться к вам, только упоминая об этом в качестве доказательства это GetHashCode не были выполнены в прошлом.)

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