Подходящие методы хэш-кода для массива байтов?

каков наилучший метод хэша для массива byte?

массивы-это сериализованные объекты класса, содержащие изображение jpeg, передаваемое между приложениями по TCP / IP.

размер массива составляет около 200k.

4 ответов


любая из встроенных функций хэширования должна делать; в зависимости от того, насколько вы заботитесь о столкновениях, это ваши варианты (от большинства столкновений до наименьшего):

  • MD5 в
  • в SHA1
  • SHA256 и
  • значения sha384
  • криптография SHA512

Они так же просты в использовании как:

var hash = SHA1.Create().ComputeHash(data);

Бонусные Знаки: если вы не заботитесь о безопасности (что я не думаю, что вы делаете, учитывая, что вы получаете хэши для изображений) вы можете посмотреть в хеше Murmur, который предназначен для хэширования контента, а не для безопасного хэширования (и, таким образом, намного быстрее). Однако это не в рамках, поэтому вам придется найти реализацию (и вы, вероятно, должны пойти на Murmur3).

Edit: если вы ищете хэш-код для массива byte[] это полностью зависит от вас, он обычно состоит из битового сдвига (по простым числам) и XORing. Е. Г.

public class ByteArrayEqualityComparer : IEqualityComparer<byte[]>
{
    public static readonly ByteArrayEqualityComparer Default = new ByteArrayEqualityComparer();
    private ByteArrayEqualityComparer() { }

    public bool Equals(byte[] x, byte[] y)
    {
        if (x == null && y == null)
            return true;
        if (x == null || y == null)
            return false;
        if (x.Length != y.Length)
            return false;
        for (var i = 0; i < x.Length; i++)
            if (x[i] != y[i])
                return false;
        return true;
    }

    public int GetHashCode(byte[] obj)
    {
        if (obj == null || obj.Length == 0)
            return 0;
        var hashCode = 0;
        for (var i = 0; i < obj.Length; i++)
            // Rotate by 3 bits and XOR the new value.
            hashCode = (hashCode << 3) | (hashCode >> (29)) ^ obj[i];
        return hashCode;
    }
}
// ...
var hc = ByteArrayEqualityComparer.Default.GetHashCode(data);

EDIT: если вы хотите проверить, что значение не изменилось, вы должны использовать CRC32 в.


у Джона Скита есть хороший ответ о том, как переопределить GetHashCode, который основан на общих эффективных методах хэша, где вы начинаете с простого числа, добавьте его в хэш-коды компонентов, умноженные на другое простое число, что позволяет переполнение.

для вашего случая, вы могли бы сделать:

static int GetByteArrayHashCode(byte[] array)
{
    unchecked
    {
        int hash = 17;

        // Cycle through each element in the array.
        foreach (var value in array)
        {
            // Update the hash.
            hash = hash * 23 + value.GetHashCode();            
        }

        return hash;
    }
}

Примечание В ответе Джона он объясняет, почему это лучше, чем XORing хэшей отдельных элементов (и что анонимные типы В C# в настоящее время не XOR хэши отдельных элементов, но использовать что-то подобное выше).

В то время как это будет быстрее, чем хэш-алгоритмы из System.Security.Cryptography пространство имен (потому что вы имеете дело с меньшими хэшами), недостатком является то, что у вас может быть больше столкновений.

вам придется протестировать свои данные и определить, как часто вы получаете столкновения против работы, которая должна быть выполнена в случае столкновения.


любой из крипто-хеширования должен работать. Не уверен насчет скорости. Возможно МД5?


на основе Компилятор Сгенерировал GetHashCode ()

public static int GetHashCode(byte[] array) {
    unchecked {
        int i = 0;
        int hash = 17;
        int rounded = array.Length & ~3;

        hash = 31 * hash + array.Length;

        for (; i < rounded; i += 4) {
            hash = 31 * hash + BitConverter.ToInt32(array, i);
        }

        if (i < array.Length) {
            int val = array[i];
            i++;

            if (i < array.Length) {
                val |= array[i] << 8;
                i++;

                if (i < array.Length) {
                    val |= array[i] << 16;
                }
            }

            hash = 31 * hash + val;
        }

        return hash;
    }
}

Ах... и ссылка на C# Murmurhash http://landman-code.blogspot.com/2009/02/c-superfasthash-and-murmurhash2.html