2010-05-04 79 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位散列左右,但它的更好的處理你做得到的衝突,而不是希望的情況下你永遠不會。

相關問題