适合字节数组的哈希码方法

本文关键字:哈希码 方法 数组 字节数 字节 | 更新日期: 2023-09-27 18:06:57

byte数组的最佳哈希方法是什么?

数组是序列化的类对象,包含通过TCP/IP在应用程序之间传递的jpeg图像。

数组大小约为200k

适合字节数组的哈希码方法

任何内置的哈希函数都可以;根据你对碰撞的关心程度,这些是你的选择(从大多数碰撞到最少):

  • MD5
  • SHA1
  • SHA256
  • SHA384
  • SHA512

使用起来很简单:

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

奖励标记:如果你不关心安全性(我认为你不关心,因为你正在获取图像的哈希),你可能想看看杂音哈希,它是为内容哈希而不是安全哈希而设计的(因此要快得多)。但是,它不在框架中,因此您必须找到实现(并且您可能应该选择Murmur3)。

Edit:如果您正在为byte[]数组寻找HASHCODE,这完全取决于您,它通常由位移位(通过素数)和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

Jon Skeet对如何覆盖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;
    }
}

注意在Jon的回答中,他解释了为什么这比XORing单个元素的哈希值更好(并且c#中的匿名类型目前不XOR单个元素的哈希值,而是使用类似于上面的东西)。

虽然这将比来自System.Security.Cryptography名称空间的哈希算法更快(因为您正在处理较小的哈希),但缺点是您可能会有更多的冲突。

你必须对你的数据进行测试,并确定发生碰撞的频率,以及在发生碰撞的情况下需要做的工作。

基于编译器生成的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

任何加密散列的东西应该工作。速度不太确定。也许MD5 ?