我正在编写一个简单的MP3编目器来跟踪我的各种设备上的MP3。我计划使用MD5或SHA2键来识别匹配的文件,即使它们已经被重命名/移动等等。我不是想匹配逻辑上相同的MP3(即:相同的歌曲,但编码方式不同)。我有大约8000个MP3。只有大约6700个生成了唯一的密钥。
我的问题是,无论我选择何种哈希算法,我都会遇到冲突。在一个案例中,我有两个文件碰巧是同一专辑中的曲目#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)。这是Windows上的Python hashlib的错误吗?我在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
答案 0 :(得分:8)
我有点感觉你正在读一小于预期的数据,而且这两个文件的块相同。我不知道为什么,但尝试用'rb'打开二进制文件。 read()应该读取到文件末尾,但是Windows的行为方式不同。来自文档
在Windows上,“b”附加到模式 以二进制模式打开文件,所以 还有像'rb','wb'这样的模式, 和'r + b'。 Windows上的Python制作了一个 文本和二进制之间的区别 文件;中的行尾字符 文本文件会自动更改 稍微读取或写入数据时。 这种幕后修改 文件数据适用于ASCII文本 文件,但它会破坏二进制数据 像在JPEG或EXE文件中那样。是 非常小心使用二进制模式时 读写这样的文件。上 Unix,附加一个'b'也没有坏处 到模式,所以你可以使用它 平台 - 独立于所有二进制文件 文件。
答案 1 :(得分:2)
如果几个不同的哈希算法都返回相同的哈希结果,或者您的实现中存在错误,那么您遇到问题的文件几乎肯定是相同的。
作为一个完整性测试编写你自己的“哈希”,它只是完全返回文件的内容,看看这个是否产生相同的“哈希”。
答案 2 :(得分:1)
正如其他人所说的那样,单个哈希冲突是不可能的,并且几乎不可能,除非文件是相同的。我建议使用外部实用程序生成总和作为理智检查。例如,在Ubuntu(以及大多数/所有其他Linux发行版)中:
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'
答案 3 :(得分:0)
就像@Delan Azabani所说的那样,这里有一些可疑的东西;碰撞必然会发生,但不是经常发生。检查歌曲是否相同,并请更新你的帖子。
此外,如果您觉得自己没有足够的密钥,可以同时使用两个(甚至更多)哈希算法:例如,使用MD5,您可以2**128
或{{ 1}}键。通过使用SHA-1,您可以使用340282366920938463463374607431768211456
或2**160
个密钥。通过组合它们,您可以1461501637330902918203684832716283019655932542976
或2**128 * 2**160
。
(但如果你问我,MD5足以满足你的需求。)