2010-05-04 28 views
4

我得到了很多很多文件上传到服务器,我只是想避免重复的方法。根据python中的文件内容创建一个唯一的密钥

因此,从一个大字符串生成一个唯一的小键值似乎是校验和的意图,hashing seemed like the evolution of that

所以我打算使用散列md5来做到这一点。但后来我读somewhere“MD5并不是唯一的键”,我觉得这很奇怪。

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

编辑:顺便说一下,我把twosources去以下,这是我当前如何做它和它的工作只是罚款,与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() 
+2

使用“f = open(fileName,'rb')”在Windows上获得正确的结果 – DLRdave 2012-01-05 15:04:59

回答

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并使用相同的方法。如果性能不是问题,甚至可以同时使用(连接)。

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

+0

那么,我的情况实际上是关于大图像和大视频,而性能是一个相当大的问题。但是,是的,我并不期望它能够检测到同一场景中两个稍微不同的角度。 – cregox 2010-05-04 23:41:57

+0

这绝对是最好的答案。如果OP想要比SHA1更好,而不是连接,他应该只使用SHA2。 – 2010-05-04 23:43:28

+0

在哈希上添加更多数据只会改变哈希函数(例如,此答案显示“将一些其他值附加到从MD5返回的内容上以生成更长的哈希”)。有时候这是最简单的,但是你也可以首先生成一个更长的散列。唉 - 更长的哈希不是防止碰撞的预防。 – 2010-05-05 00:52:26

0

提示:想想哈希表是如何工作的。

+1

你是对的,但他不会得到它。 – 2010-05-04 22:55:48

+0

哦,亲爱的,它看起来像是另一个没有答案的问题...... – cregox 2010-05-04 22:57:00

2

MD5的问题在于它已损坏。对于大多数常见用途而言,这个问题没有什么问题,人们仍然使用MD5和SHA1,但我认为如果您需要散列函数,那么您需要强大的散列函数。就我所知,仍然没有任何标准的替代品。有许多算法“被认为”很强大,但是我们对SHA1和MD5有很多经验。也就是说,我们(认为)我们知道这两者何时破裂,而我们并不真正了解新算法何时破裂。

底线:考虑风险。如果你想额外走一英里,那么当你找到一个散列副本时,你可能会添加额外的检查,以评估性能损失的价格。

+1

在这种情况下,散列函数的强度并不重要。 MD5将绝对防止重复到虚拟的数学确定性。 – 2010-05-04 23:03:56

+0

“哈希函数的强弱并不重要”是什么意思?目前针对MD5的攻击可让您在单个CPU上发生一秒钟的冲突 - 因此不会,MD5不会阻止“重复” – intgr 2010-05-04 23:30:33

+1

如其他地方所述,MD5不会防止重复/冲突,尽管它确实使得它们不太可能。而且,MD5仅仅是“破”的,因为它的加密不安全 - 如果需要,坚定的攻击者可能会产生冲突。但对于原始问题,加密安全性并非必要,因此这不是解散MD5的合理理由。 – 2010-05-04 23:41:15

3

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

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

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

当然,你有碰撞的几率1%与2.6 * 10^18个条目的128位散列左右,但它的更好的处理你做得到的冲突,而不是希望的情况下你永远不会。

相关问题