Столкновения MD5 и SHA-2 в Python

Я пишу простой каталог MP3, чтобы отслеживать, какие MP3 находятся на моих различных устройствах. Я планировал использовать ключи MD5 или SHA2 для идентификации соответствующих файлов, даже если они были переименованы/перемещены и т. д. Я не пытаюсь сопоставить MP3, которые логически эквивалентны (т. е.: одна и та же песня, но закодирована по-разному). У меня около 8000 MP3. Только около 6700 из них сгенерировали уникальные ключи.

моя проблема в том, что я сталкиваюсь с коллизиями независимо от алгоритма хэширования I выбирать. В одном случае у меня есть два файла, которые являются треками #1 и #2 на одном альбоме, они имеют разные размеры файлов, но производят одинаковые хэш-ключи, использую ли я MD5, SHA2-256, SHA2-512 и т. д...

это первый раз, когда я действительно использую хэш-ключи для файлов, и это неожиданный результат. Я чувствую, что здесь происходит что-то подозрительное из того немногого, что я знаю об этих алгоритмах хэширования. Может ли это быть проблемой, связанной с реализацией MP3 или Python?

здесь фрагмент кода, который я использую:

    data = open(path, 'r').read()

    m = hashlib.md5(data)

    m.update(data)

    md5String = m.hexdigest()

любые ответы или идеи о том, почему это происходит, будут высоко оценены. Спасибо заранее.

-- UPDATE--:

Я попытался выполнить этот код в linux (с Python 2.6), и он не вызвал столкновения. Как показал вызов stat, файлы не совпадают. Я также загрузил WinMD5, и это не вызвало столкновения(8d327ef3937437e0e5abbf6485c24bb3 и 9b2c66781cbe8c1be7d6a1447994430c). Это ошибка с Python hashlib в Windows? Я пробовал то же самое в Python 2.7.1 и 2.6.6, и оба дают тот же результат.

import hashlib
import os

def createMD5( path):

    fh = open(path, 'r')
    data = fh.read()
    m = hashlib.md5(data)
    md5String = m.hexdigest()
    fh.close()
    return md5String

print os.stat(path1)
print os.stat(path2)
print createMD5(path1)
print createMD5(path2)

>>> nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=6617216L, st_atime=1303808346L, st_mtime=1167098073L, st_ctime=1290222341L)
>>> nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=4921346L, st_atime=1303808348L, st_mtime=1167098076L, st_ctime=1290222341L)   
>>> a7a10146b241cddff031eb03bd572d96
>>> a7a10146b241cddff031eb03bd572d96

4 ответов


У меня такое чувство, что Вы читаете кусок данных, который меньше ожидаемого, и этот кусок оказывается одинаковым для обоих файлов. Я не знаю, почему, но попробуйте открыть файл в двоичном с "РБ". read () должен читать до конца файла, но windows ведет себя по-другому. Из документов

в Windows, 'b' добавлен в режим открывает файл в двоичном режиме, так есть также такие режимы, как "rb", "wb", и 'r+b'. Python в Windows делает различие между текстовыми и двоичными файлы; символы конца строки в текстовые файлы автоматически изменяются немного, когда данные читаются или записываются. Эта закулисная модификация данные файла хороши для текста ASCII файлы, но это повредит двоичные данные например, в JPEG или EXE-файлах. Быть очень осторожно использовать двоичный режим, когда чтение и запись таких файлов. На Unix, не помешает добавить "b" в режим, чтобы вы могли его использовать независимо от платформы для бинарных файлы.


файлы, с которыми у вас возникли проблемы, почти наверняка идентичны, если несколько разных алгоритмов хэширования возвращают одинаковые результаты хэша на них, или есть ошибка в вашей реализации.

в качестве теста на здравомыслие напишите свой собственный "хэш", который просто возвращает содержимое файла полностью, и посмотрите, генерирует ли он те же"хэши".


Как заявили другие, одно хэш-столкновение маловероятно, а несколько почти невозможно, если файлы не идентичны. Я бы рекомендовал генерировать суммы с внешней утилитой как что-то вроде проверки здравомыслия. Например, в Ubuntu (и всех других дистрибутивов):

blair@blair-eeepc:~$ md5sum Bandwagon.mp3
b87cbc2c17cd46789cb3a3c51a350557  Bandwagon.mp3
blair@blair-eeepc:~$ sha256sum Bandwagon.mp3 
b909b027271b4c3a918ec19fc85602233a4c5f418e8456648c426403526e7bc0  Bandwagon.mp3

быстрый поиск Google показывает, что есть аналогичные утилиты, доступные для машин Windows. Если вы видите коллизии с внешними утилитами, то файлы идентичны. Если нет никаких столкновений, вы делаете что-то неправильно. Я сомневаюсь, что реализация Python неверна, так как я получаю те же результаты при выполнении хэша в Python:

>>> import hashlib
>>> hashlib.md5(open('Bandwagon.mp3', 'r').read()).hexdigest()
'b87cbc2c17cd46789cb3a3c51a350557'
>>> hashlib.sha256(open('Bandwagon.mp3', 'r').read()).hexdigest()
'b909b027271b4c3a918ec19fc85602233a4c5f418e8456648c426403526e7bc0'

кроме того, если вы чувствуете, что у вас недостаточно ключей, вы можете использовать два (или даже больше) алгоритмов хэширования одновременно: используя MD5, например, у вас есть 2**128 или 340282366920938463463374607431768211456 ключи. Используя SHA-1, у вас есть 2**160 или 1461501637330902918203684832716283019655932542976 ключи. Объединив их, вы получите 2**128 * 2**160, или 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056.

(но если вы спросите меня, MD5 более чем достаточно для ваших нужд.)