将每个 SHA224 2 字节减半到 1 字节以将哈希长度减半是否会带来更高的冲突风险?

Does halving every SHA224 2 bytes to 1 byte to halve the hash length introduce a higher collision risk?

假设我有不需要可逆的字符串,假设我使用 SHA224 对其进行哈希处理。

hello world的散列为2f05477fc24bb4faefd86517156dafdecec45b8ad3cf2522a563582b,其长度为56字节。

如果我将每两个字符转换为它的数字表示并从中生成一个字节会怎么样?

在 Python 我会做这样的事情:

shalist = list("2f05477fc24bb4faefd86517156dafdecec45b8ad3cf2522a563582b")
for first_byte,next_byte in zip(shalist[0::2],shalist[1::2]):
    chr(ord(first_byte)+ord(next_byte))

结果将是 \x98ek\x9d\x95\x96\x96\xc7\xcb\x9ckhf\x9a\xc7\xc9\xc8\x97\x97\x99\x97\xc9gd\x96im\x94。 28 个字节。有效减半输入。

现在,这样做会不会有更高的散列冲突风险?

简单的答案非常明显:是的,它会增加碰撞的机会,增加的数量与丢失的比特数一样多。对于减半为 28 字节的 56 字节,碰撞的机会增加了 2^(28*8)。这仍然在 1:2^(28*8).

留下碰撞的机会

您对该截断的使用仍然完全合法,具体取决于它是什么。 Git 例如,仅显示提交哈希的前几个字节,对于大多数实际用途,短字节可以正常工作。

如果截断

A​​ "perfect" 哈希,则应保留一定比例的 "effective" 位。例如,32 位 SHA256 结果应该与 32 位 CRC 具有相同的 "strength",尽管 CRC 可能有一些特殊属性使其更适合某些用途,而截断的 SHA 可能更适合其他用途。

如果你用它来做任何类型的安全,那么证明你的系统将很困难,你可能最好使用更短但完整的散列。

让我们缩小大小以使其有意义,并使用 2 个字节的哈希值而不是 56 个字节。原始哈希值将有 65536 个可能的值,因此如果您对超过那么多的字符串进行哈希值,您肯定会发生冲突。将其减半为 1 个字节,在最多 256 个字符串散列后,您将遇到冲突,无论您采用第一个字节还是第二个字节。所以你发生碰撞的机会大 256 (2^(1byte*8bits)) 并且是 1:256.

长哈希值的使用使得暴力破解它们变得不切实际,即使经过多年的密码分析也是如此。当 MD5 在 1991 年被引入时,它被认为足够安全,可以用于证书签名,在 2008 年它被认为 "broken" 并且不适合与安全相关的用途。可以开发各种密码分析技术来降低散列和加密算法的 "effective" 强度,因此备用位越多(在其他强大的算法中),应保留越有效的位以确保散列在所有实际用途中的安全.