我有很多很多文件要上传到服务器,我只想要一种方法来避免重复。
因此,从大字符串生成唯一且小的键值似乎是校验和要执行的操作,hashing seemed like the evolution of that。
所以我打算用hash md5来做这件事。但后来我读到somewhere“MD5并不是唯一的密钥”,我觉得这很奇怪。
这样做的正确方法是什么?
编辑:顺便说一下,我带了two sources来了解以下内容,这就是我目前正在做的事情,而且工作得很好, 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()
答案 0 :(得分:5)
坚持使用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并使用相同的方法。如果性能不是问题,甚至可以使用两者(连接)。
当然,请记住,这只适用于二进制级别的重复文件,而不是“相同”但具有不同签名的图像,声音,视频。
答案 1 :(得分:3)
散列的问题在于它从“大”数据集生成“小”标识符。这就像一个有损压缩。虽然您不能保证唯一性,但您可以使用它来大幅限制您需要比较的其他项目的数量。
考虑到MD5产生128位值(我认为它就是这样,尽管确切的位数是无关紧要的)。如果您的输入数据集有129位且实际上全部使用它们,则每个MD5值将平均显示两次。对于较长的数据集(例如“具有完全1024个可打印字符的所有文本文件”),一旦获得足够的输入,您仍然会遇到冲突。与另一个答案所说的相反,数学确定性会导致碰撞。
请参阅http://en.wikipedia.org/wiki/Birthday_Paradox
当然,你有大约1%的机会在2.6 * 10 ^ 18条目下与128位哈希冲突,但是最好处理你遇到冲突的情况,而不是希望你永远不会。
答案 2 :(得分:2)
MD5的问题在于它已经坏了。对于大多数常见用途,没有什么问题,人们仍然使用MD5和SHA1,但我认为如果你需要散列函数,那么你需要一个强大的散列函数。据我所知,仍然没有标准的替代品。有许多算法被认为是强大的,但我们对SHA1和MD5有很多经验。也就是说,我们(想)我们知道这两个什么时候打破了,而当新算法破裂时我们并不知道多少。
底线:考虑风险。如果您希望加倍努力,那么当您发现哈希重复时,可能会为性能损失的价格添加额外的检查。