我们有一个文件存储,存储根据附加到 crc32 的大小唯一标识文件。
我想知道这个校验和 (crc32 + size) 是否足以识别文件,或者我们是否应该考虑其他一些哈希技术,如 MD5/SHA1?
CRC 比起严肃的散列函数,更像是一种错误检测方法。它有助于识别损坏的文件,而不是唯一地识别它们。 所以你的选择应该在 MD5 和 SHA1 之间。
如果你没有很强的安全需求,你可以选择更快的MD5。 (请记住,MD5 容易受到碰撞攻击)。 如果您需要更高的安全性,最好使用 SHA1 甚至 SHA2。
CRC-32 不够好;建立冲突是微不足道的,即两个具有相同 CRC-32 的文件(如果您愿意,长度相同)。即使没有恶意攻击者,一旦您拥有大约 65000 个长度相同的不同文件,冲突也会随机发生。
哈希函数旨在避免冲突。使用 MD5 或 SHA-1,您不会遇到随机冲突。如果您的设置与安全相关(即有人在某处可能会主动尝试创建冲突),那么您需要一个 secure 哈希函数。 MD5 不再安全(创建与 MD5 的冲突很容易)并且 SHA-1 在这方面有点弱(没有计算实际的冲突,但是创建一个的方法是已知的,虽然昂贵,但比什么便宜得多它应该是)。通常的建议是使用 SHA-256 或 SHA-512(SHA-256 足以保证安全;SHA-512 在大型 64 位系统上可能会快一点,但文件读取带宽比散列速度更受限制) .
注意:使用加密哈希函数时,不需要存储和比较文件长度;哈希足以消除文件歧义。
在非安全设置中(即你只害怕随机碰撞),那么可以使用 MD4。作为加密散列函数,它已被彻底“破解”,但它仍然是一个非常好的校验和,而且速度非常快(在某些基于 ARM 的平台上,它甚至比 CRC-32 更快,以更好地抵抗随机碰撞)。基本上,你不应该使用 MD5:如果你有安全问题,那么一定不能使用 MD5(它被破坏了;使用 SHA-256);如果你这样做not有安全问题,那么 MD4 比 MD5 更快。
CRC32+ 尺寸的空间为您提供了足够的空间来容纳更大的 CRC,这将是一个更好的选择。如果您不担心恶意碰撞,那就是在这种情况下托马斯的回答适用。
您没有指定语言,但是例如在 C++ 中,您有 Boost CRC 为您提供所需大小的 CRC(或者您可以负担得起存储)。
正如其他人所说,CRC 不保证没有碰撞。但是,只需给文件递增 64 位数字即可解决您的问题。这保证永远不会发生冲突(除非您想将大量文件保存在一个目录中,这无论如何都不是一个好主意)。
老问题,但在谷歌上的排名仍然很高,所以它值得一个现代的答案:
如果你想要一个适合识别文件的非加密散列,比CRC32好但比MD5快,我真的推荐xxHash系列。
$ time cat >/dev/null test1G.bin
real 0m0.099s
user 0m0.000s
sys 0m0.099s
$ time xxh128sum >/dev/null test1G.bin
real 0m0.169s
user 0m0.113s
sys 0m0.056s
$ time crc32 >/dev/null test1G.bin
real 0m0.936s
user 0m0.828s
sys 0m0.108s
$ time md5sum >/dev/null test1G.bin
real 0m1.554s
user 0m1.502s
sys 0m0.052s
$ time sha1sum >/dev/null test1G.bin
real 0m1.717s
user 0m1.616s
sys 0m0.096s
除了命令行工具,它还有多种语言的库,包括C、Java、Python等。