这取决于你的用例。在
如果你只担心意外碰撞,MD5和SHA-1都可以,MD5一般更快。事实上,MD4对于大多数用例来说也是足够的,而且通常更快……但是它的实现还不够广泛。(特别是,它不在hashlib.algorithms_guaranteed中,尽管在大多数Mac、Windows和Linux的普通版本中,它应该在hashlib_algorithms_available中。)
另一方面,如果你担心蓄意攻击,也就是说,有人故意编造一个与你的哈希匹配的伪造文件,你必须考虑你所保护的内容的价值。MD4几乎肯定是不够的,MD5可能还不够,但SHA-1是临界值。目前,Keccak(很快将由SHA-3推出)被认为是最好的选择,但你还是要继续关注这个问题,因为事情每年都在变化。在
Cryptographic hash function上的Wikipedia页面有一个经常更新的表。要了解表格:
与MD4产生碰撞只需要3发子弹,而MD5大约需要200万发,SHA-1需要15万亿。这已经足够让它花费几百万美元(以今天的价格)来产生碰撞。这对你来说可能不够好,但对NIST来说还不够好。在
另外,请记住,“通常更快”并不像“在我的数据和平台上测试得更快”那么重要。考虑到这一点,在Mac上的64位Python 3.3.0中,我创建了一个1MB随机bytes对象,然后执行以下操作:In [173]: md4 = hashlib.new('md4')
In [174]: md5 = hashlib.new('md5')
In [175]: sha1 = hashlib.new('sha1')
In [180]: %timeit md4.update(data)
1000 loops, best of 3: 1.54 ms per loop
In [181]: %timeit md5.update(data)
100 loops, best of 3: 2.52 ms per loop
In [182]: %timeit sha1.update(data)
100 loops, best of 3: 2.94 ms per loop
如您所见,md4明显比其他的快。在
使用hashlib.md5()代替hashlib.new('md5'),以及使用熵较少的bytes(以空格分隔的1-8string.ascii_letters)的测试没有显示出任何显著的差异。在
而且,对于我的安装附带的哈希算法,正如下面测试的,没有什么能比得上md4。在
^{pr2}$
如果速度真的很重要,那么有一个很好的技巧可以用来改进这个问题:使用一个糟糕但非常快的散列函数,比如zlib.adler32,并且只将它应用于每个文件的前256KB。(对于某些文件类型,最后一个256KB,或者最靠近中间的256KB而不经过遍历等等,可能会比第一个更好。)然后,如果发现冲突,请为每个文件对整个文件生成MD4/SHA-1/Keccak/whatever散列。在
最后,由于有人在评论中询问如何在不将整个文件读入内存的情况下散列文件:def hash_file(path, algorithm='md5', bufsize=8192):
h = hashlib.new(algorithm)
with open(path, 'rb') as f:
block = f.read(bufsize)
if not block:
break
h.update(block)
return h.digest()
如果挤出每一点性能都很重要,那么您需要在您的平台上试验bufsize的不同值(从4KB到8MB的2次幂)。您可能还想尝试使用原始文件句柄(os.open和os.read),这在某些平台上有时可能更快。在