我在尝试计算字符串的md5哈希值时遇到了一些非常奇怪的行为。如果我传递的是串联结果,则返回的哈希值总是错误的(且与众不同)。获得真正的哈希的唯一方法是传递创建后未进行任何修改的字符串。
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import hashlib >>> m = hashlib.md5() >>> a1 = "stack" >>> a2 = "overflow" >>> a3 = a1 + a2 >>> a4 = str(a1 + a2) >>> m.update("stackoverflow") >>> m.hexdigest() '73868cb1848a216984dca1b6b0ee37bc' //actuall hash >>> m.update(a1 + a2) >>> m.hexdigest() '458b7358b9e0c3f561957b96e543c5a8' >>> m.update(a3) >>> m.hexdigest() '65b0e62d4ff2d91e111ecc8f27f0e8f5' >>> m.update(a4) >>> m.hexdigest() '60c3ae3dd9a2095340b2e024194bad3c' >>> m.update(a1 + a2) >>> m.hexdigest() 'acd4e14145d34dcb10af785badf8e73e' >>> m.update(a1 + a2) >>> m.hexdigest() '03c06ca09faa26166f1096db02272b11' >>> a1 + a2 == a1 + a2 True >>> a1 + a2 == a3 True >>> a3 == a4 True
我想念什么吗?
您缺少的是hash.update() 不会替换散列数据 。您将不断更新哈希对象,因此您将获得 串联字符串 的哈希值。从hashlib.hash.update()文档中:
hash.update()
hashlib.hash.update()
使用字符串 arg 更新哈希对象。 重复调用等效于将所有参数串联在一起的单个调用:m.update(a); m.update(b)等价于m.update(a+b)。
m.update(a)
m.update(b)
m.update(a+b)
大胆强调我的。
因此,您不会获取单个'stackoverflow'字符串的哈希,而是首先获取的哈希值'stackoverflow',然后获取的哈希值'stackoverflowstackoverflow',再获取'stackoverflowstackoverflowstackoverflow'等等,每次都 添加 另一个哈希值,则'stackoverflow'创建的字符串越来越长。这些较长的字符串都不与原始的较短的字符串相等,因此它们的哈希也不太可能相等。
'stackoverflow'
'stackoverflowstackoverflow'
'stackoverflowstackoverflowstackoverflow'
为新字符串创建一个 新 对象,而不是:
>>> import hashlib >>> m = hashlib.md5() >>> m.update('stack' + 'overflow') >>> m.hexdigest() '73868cb1848a216984dca1b6b0ee37bc' >>> m = hashlib.md5() # **new** hash object >>> m.update('stackoverflow') >>> m.hexdigest() '73868cb1848a216984dca1b6b0ee37bc' >>> m = hashlib.md5() # new object again >>> m.update('stack') # add the string in pieces, part 1 >>> m.update('overflow') # and part 2 >>> m.hexdigest() '73868cb1848a216984dca1b6b0ee37bc'
您可以通过发送串联数据轻松产生“错误”哈希:
>>> m = hashlib.md5() >>> m.update('stackoverflowstackoverflow') >>> m.hexdigest() '458b7358b9e0c3f561957b96e543c5a8' >>> m = hashlib.md5() >>> m.update('stackoverflowstackoverflowstackoverflow') >>> m.hexdigest() '65b0e62d4ff2d91e111ecc8f27f0e8f5' >>> m = hashlib.md5() >>> m.update('stackoverflow' * 4) >>> m.hexdigest() '60c3ae3dd9a2095340b2e024194bad3c'
请注意,您还可以将第一个字符串传递给md5()函数:
md5()
>>> hashlib.md5('stackoverflow').hexdigest() '73868cb1848a216984dca1b6b0ee37bc'
通常,hash.update()仅当您正在分块处理数据时才使用该方法(例如逐行读取文件或从套接字读取数据块),并且不想一次将所有数据都保存在内存中。