6

我有很多很多文件要上传到服务器,我只是想要一种避免重复的方法。

因此,从大字符串生成唯一且小的键值似乎是校验和的目的,而散列似乎是.

所以我打算使用 hash md5 来做到这一点。但后来我在某处读到“MD5 并不意味着是唯一键”,我觉得这真的很奇怪。

这样做的正确方法是什么?

编辑:顺便说一句,我采用了两个 来源来了解以下内容,这就是我目前正在做的事情,并且使用 Python 2.5 运行良好:

import hashlib

def md5_from_file (fileName, block_size=2**14):
    md5 = hashlib.md5()
    f = open(fileName)
    while True:
        data = f.read(block_size)
        if not data:
            break
        md5.update(data)
    f.close()
    return md5.hexdigest()
4

3 回答 3

7

坚持使用 MD5 是个好主意。只是为了确保我将文件长度或块数附加到您的文件哈希表中。

是的,您可能会遇到两个具有相同 MD5 哈希的文件,但这不太可能(如果您的文件大小合适)。因此,将块的数量添加到您的哈希中可能会帮助您减少这种情况,因为现在您必须找到两个大小相同且 MD5 相同的文件。

# This is the algorithm you described, but also returns the number of chunks.
new_file_hash, nchunks = hash_for_tile(new_file)
store_file(new_file, nchunks, hash)

def store_file(file, nchunks, hash):
  "" Tells you whether there is another file with the same contents already, by 
     making a table lookup ""
  # This can be a DB lookup or some way to obtain your hash map
  big_table = ObtainTable()

  # Two level lookup table might help performance
  # Will vary on the number of entries and nature of big_table
  if nchunks in big_table:
     if hash in big_table[hash]:
       raise DuplicateFileException,\
         'File is dup with %s' big_table[nchunks][lookup_hash]
  else:
    big_table[nchunks] = {}

  big_table[nchunks].update({
    hash: file.filename
  })

  file.save() # or something

为了减少这种可能性,请切换到 SHA1 并使用相同的方法。如果性能不是问题,甚至使用两者(连接)。

当然,请记住,这仅适用于二进制级别的重复文件,而不适用于“相同”但具有不同签名的图像、声音、视频。

于 2010-05-04T23:37:11.627 回答
3

散列的问题在于它从“大”数据集中生成“小”标识符。这就像一个有损压缩。虽然您不能保证唯一性,但您可以使用它来大幅限制需要比较的其他项目的数量。

考虑一下 MD5 产生一个 128 位的值(我认为就是这样,尽管确切的位数无关紧要)。如果您的输入数据集有 129 位并且您实际上全部使用了它们,则每个 MD5 值平均会出现两次。对于较长的数据集(例如,“所有文本文件正好是 1024 个可打印字符”),一旦获得足够的输入,您仍然会遇到冲突。与另一个答案所说的相反,在数学上肯定会发生碰撞。

http://en.wikipedia.org/wiki/Birthday_Paradox

诚然,在 2.6*10^18 个条目处,与 128 位散列发生冲突的几率约为 1%,但最好处理确实发生冲突的情况,而不是希望永远不会发生冲突。

于 2010-05-04T23:13:48.110 回答
2

MD5 的问题在于它已损坏。对于最常见的用途,几乎没有问题,人们仍然使用 MD5 和 SHA1,但我认为如果你需要一个散列函数,那么你需要一个强大的散列函数。据我所知,仍然没有标准的替代品。有许多算法“被认为”很强大,但我们在 SHA1 和 MD5 方面拥有最多的经验。也就是说,我们(认为)我们知道这两个何时崩溃,而我们并不真正知道新算法何时崩溃。

底线:考虑风险。如果您想多走一点,那么您可能会在发现哈希重复时添加额外的检查,以牺牲性能为代价。

于 2010-05-04T22:57:50.533 回答