【问题标题】:Strange python's hashlib.md5 behavior, different hash each time奇怪的python的hashlib.md5行为,每次都有不同的hash
【发布时间】:2017-04-29 15:19:59
【问题描述】:

我在尝试计算字符串的 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

我错过了什么吗?

【问题讨论】:

    标签: python hash


    【解决方案1】:

    您缺少的是hash.update() 不会替换散列数据。您不断更新散列对象,因此您将获得 串联字符串 的散列。来自hashlib.hash.update() documentation

    用字符串 arg 更新哈希对象。 重复调用等同于连接所有参数的单个调用:m.update(a)m.update(b) 等价于m.update(a+b)

    我的大胆强调。

    所以你没有得到单个 'stackoverflow' 字符串的哈希值,你得到的是 'stackoverflow' 的哈希值,然后是 'stackoverflowstackoverflow' 的哈希值,然后是 'stackoverflowstackoverflowstackoverflow' 等等,每次 附加 em> 另一个'stackoverflow' 创建一个越来越长的字符串。这些较长的字符串都不等于原始的短字符串,因此它们的哈希值也不可能相等。

    为新字符串创建一个 new 对象,而不是:

    >>> 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() 函数:

    >>> hashlib.md5('stackoverflow').hexdigest()
    '73868cb1848a216984dca1b6b0ee37bc'
    

    您通常仅在以块的形式处理数据(例如逐行读取文件或从套接字读取数据块)并且不想保留所有数据时才使用hash.update() 方法立即进入内存。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    相关资源
    最近更新 更多