160位SHA1哈希的前32位是否可以替代CRC32哈希?

时间:2009-05-27 13:47:36

标签: .net hash cryptography

我正在研究.NET 3.5项目,我需要一个32位的哈希值。 .NET Cryptography类中似乎没有任何返回32位散列的方法(MD5为128位,SHA1为160位等)。我实现了CRC32类,但我发现已经存在的SHA1和MD5散列函数要快得多。

使用SHA1散列函数并断开前32位存储为哈希值会不会有任何问题(即碰撞的可能性增加)?

5 个答案:

答案 0 :(得分:7)

除非你想要CRC32的额外功能(作为线性代码),否则将输出切换为32位应该没问题。

是否削减某些加密哈希函数的输出会损害其在抗冲突方面的安全性是一个开放的研究问题(如果我没记错的话,存在“不自然的”构造示例)。但NIST(可能经过NSA批准)使用切割技术从SHA-256获取SHA-224(参见article about SHA in wikipedia)。

编辑:CRC32允许检测(并且可能是正确的)单个位错误,而加密散列函数应该具有找不到具有相同散列值的两个输入的属性。

你是否意识到“生日悖论”(再看维基百科)?使用32位校验和时,如果有大约2 ^ 16个输入,并且希望散列更多输入,则可能会发生冲突(即,具有相同散列值的两个输入)。 (重读你的评论,这对你来说可能不是问题。)

答案 1 :(得分:2)

假设散列函数在其codomain上平均分配其输入,假设它也将在其任何子集上均匀分布似乎是合乎逻辑的。 但是,使用“本机”32位散列函数可能仍然是更好的选择。也许更多的人可以为我们提供一个比我的直觉更好的理由:)

答案 2 :(得分:1)

为什么不使用string.GetHashCode()。它旨在计算32位散列值,并在给定真实数据的情况下产生很少的冲突。当然,它并不安全,但你的问题不包括这一要求。

答案 3 :(得分:0)

如果您不打算将32位用于加密目的,那么您应该没问题。否则,我不会依赖与整个哈希具有相同分布的前32位。

为什么你不能只使用更广泛的哈希?

答案 4 :(得分:0)

CRC32可能适合您的需求。这已在this question中讨论过。

在截断哈希原语方面,唯一使用频率很高的应用是SSL/TLS Pseudo Random Function (PRF),它用于生成密钥。它使用HMAC,种子和标签通过多次散列生成所需的字节数,然后截断为所需的字节数。

至于你的具体问题,你可以将哈希的输出读入Int32,然后如果你是偏执的话将它们排在一起:

static void Main()
{
    int xorCrc = GetHashedCrc(new SHA1Cng(), new byte[] {0xDE, 0xAD, 0xBE, 0xEF});
}

private static int GetHashedCrc(HashAlgorithm algorithm, byte[] bytesToHash)
{
    byte[] hash = algorithm.ComputeHash(bytesToHash);
    int totalInt32s = hash.Length/sizeof(int);
    int result = 0;
    for(int i = 0; i < totalInt32s; i++)
    {
        int currentInt = BitConverter.ToInt32(hash, sizeof(int)*i);
        result = result ^ currentInt;
    }

    return result;
}