Python 3.2 中的 MD5 哈希比较

4 投票
4 回答
4121 浏览
提问于 2025-04-16 16:48

我正在尝试验证从服务器下载的两个文件。第一个文件包含数据,第二个文件包含MD5哈希校验和。

我创建了一个函数,可以从数据文件中返回一个十六进制的哈希值,代码如下:

def md5(fileName):
    """Compute md5 hash of the specified file"""
    try:
        fileHandle = open(fileName, "rb")
    except IOError:
        print ("Unable to open the file in readmode: [0]", fileName)
        return
    m5Hash = hashlib.md5()
    while True:
        data = fileHandle.read(8192)
        if not data:
            break
        m5Hash.update(data)
    fileHandle.close()
    return m5Hash.hexdigest()

我用以下方式比较这两个文件:

file = "/Volumes/Mac/dataFile.tbz"
fileHash = md5(file)

hashFile = "/Volumes/Mac/hashFile.tbz.md5"
fileHandle = open(hashFile, "rb")
fileHandleData = fileHandle.read()

if fileHash == fileHandleData:
    print ("Good")
else:
    print ("Bad")

但是文件比较失败了,所以我打印了 fileHashfileHandleData,结果如下:

[0] b'MD5 (hashFile.tbz) = b60d684ab4a2570253961c2c2ad7b14c\n'
[0] b60d684ab4a2570253961c2c2ad7b14c

从上面的输出来看,哈希值是完全相同的。为什么哈希比较会失败呢?我刚接触python,正在使用python 3.2。有什么建议吗?

谢谢。

4 个回答

0

哈希值是一样的,但字符串却不一样。你需要获取摘要的十六进制值,并且需要从文件中提取出哈希值。一旦你完成了这些,就可以比较它们是否相等。

1

你正在比较一个哈希值和fileHandle的内容。你需要去掉MD5 (hashFile.tbz) =这一部分,还有最后的换行符,所以可以试试:

if fileHash == fileHandleData.rsplit(' ', 1)[-1].rstrip():
    print ("Good")
else:
    print ("Bad")

要记住,在Python 3中,rsplit()rstrip()不支持缓冲区API,只能处理字符串。因此,正如Fred Nurk正确指出的,你还需要对fileHandleData/fileHash进行编码/解码(分别是字节缓冲区或(Unicode)字符串)。

1

比较失败的原因和这个不成立的道理是一样的:

a = "data"
b = b"blah (blah) - data"
print(a == b)

那个 .md5 文件的格式有点奇怪,但如果它总是保持这个格式,可以用一个简单的方法来测试:

if fileHandleData.rstrip().endswith(fileHash.encode()):

因为你有一个文件哈希值,它是一个(Unicode)字符串,所以你需要把它转换成字节才能进行比较。你可能想要指定一种编码方式,而不是使用当前默认的字符串编码。

如果总是期待这个确切的格式,使用正则表达式来提取哈希值并可能检查文件名会更稳妥。

或者,更灵活一点,你可以测试子字符串是否存在:

if fileHash.encode() in fileHandleData:

撰写回答