这个“快速哈希”函数是否存在风险?

5

我需要一个智能的复制功能,用于可靠和快速的文件复制和链接。这些文件非常大(从几个GB到超过200GB),分布在许多文件夹中,人们可能在一天内重命名文件甚至文件夹,因此我想使用哈希来查看是否已经复制了文件,可能使用不同的名称,在这种情况下只创建链接。

我完全不了解哈希,我正在使用这个函数来进行哈希:

import hashlib

def calculate_sha256(cls, file_path, chunk_size=2 ** 10):
    '''
    Calculate the Sha256 for a given file.

    @param file_path: The file_path including the file name.
    @param chunk_size: The chunk size to allow reading of large files.
    @return Sha256 sum for the given file.
    '''
    sha256 = hashlib.sha256()
    with open(file_path, mode="rb") as f:
        for i in xrange(0,16):
            chunk = f.read(chunk_size)
            if not chunk:
                break
            sha256.update(chunk)
    return sha256.hexdigest()

这需要一分钟处理3GB的文件,所以最终对于一个16TB的硬盘来说,这个过程可能非常慢。
现在我的想法是利用有关文件内部结构的其他知识来加快速度:我知道它们包含一个小标题,然后是很多测量数据,并且我知道它们包含实时时间戳,所以我相当确定两个文件的前16MB相同的概率非常低(要发生这种情况,必须在完全相同的环境条件下恰好在同一时间创建两个文件)。因此,我的结论是只需要对每个文件的前X MB进行哈希处理就足够了。
这在我的示例数据中有效,但由于我没有经验,所以我想问问是否有我不知道的东西(隐藏的危险或更好的方法)。
非常感谢!

2
http://codereview.stackexchange.com/ - vaultah
1
你需要计算一下可能出现意外冲突的概率,或者以某种方式保证不同的文件始终有不同的头部。在后一种情况下,你可以确保只对头部进行校验和。在前一种情况下,你需要自己决定冲突的可能性是否可以接受。如果不知道你的数据,很难提供帮助。 - Dr. Jan-Philip Gehrcke
1
你可以避免重复造轮子,使用 rsync - John Kugelman
我会转换到md5,然后结合你提供的链接中的信息来改进我的代码,非常感谢。那个问题的答案中的代码看起来与我的结果非常相似,我想知道是否曾经在某个时候读过它,只是忘记了。检查头应该没问题 - 当我考虑它时,如果发生冲突,我将增加计算哈希的数据量,直到(1)哈希开始不同或(2)文件结束。这应该是解决方案 :)。 - Blutkoete
如果我没记错的话,如果我在不同的文件夹中有相同的文件,rsync 不会创建链接。 - Blutkoete
1个回答

3
你可以通过将大文件分成小的字节块来获取MD5哈希值。
此外,计算MD5哈希值明显比SHA-256更快,因此对于不依赖哈希值进行安全目的的任何应用程序,都应该优先选择MD5哈希值以提高性能。

我收集了所有的评论和答案,提供的链接,现在我正在使用md5,哈希前16MB,如果我发现两个文件具有相同的哈希值,则重新计算它们32MB,然后是64MB,直到哈希开始不同,一个文件报告EoF但另一个文件没有(将这两种情况视为“不相等”),或者两个文件都报告EoF并且哈希相同(将这些文件视为相等)。谢谢大家! - Blutkoete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接