当前位置: 首页 > 面试题库 >

奇怪的python的hashlib.md5行为,每次都有不同的哈希

司徒嘉祥
2023-03-14
问题内容

我在尝试计算字符串的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()文档中:

使用字符串 arg 更新哈希对象。 重复调用等效于将所有参数串联在一起的单个调用m.update(a);
m.update(b)等价于m.update(a+b)

大胆强调我的。

因此,您不会获取单个'stackoverflow'字符串的哈希,而是首先获取的哈希值'stackoverflow',然后获取的哈希值'stackoverflowstackoverflow',再获取'stackoverflowstackoverflowstackoverflow'等等,每次都
添加
另一个哈希值,则'stackoverflow'创建的字符串越来越长。这些较长的字符串都不与原始的较短的字符串相等,因此它们的哈希也不太可能相等。

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

>>> 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()仅当您正在分块处理数据时才使用该方法(例如逐行读取文件或从套接字读取数据块),并且不想一次将所有数据都保存在内存中。



 类似资料:
  • 我有以下代码来解析一个JSON文件: 要处理以下JSON文件: 如果我执行此代码,我将收到以下错误: 所以我开始一步一步地调试应用程序,看看part processing()中的哪个代码部分抛出了这个异常。令人惊讶的是,那里的所有代码都正常执行:没有抛出异常,也没有返回结果I except。 更让我惊讶的是,当我稍微改变第一种方法的代码时,它可以在不产生异常的情况下工作。 我不知道println方

  • 问题内容: 我有以下简单代码: 正如我的python知识所期望的那样,输出为3-整个列表将包含的最后一个值。但是,这在内部如何运作? AFAIK,python变量只是对对象的引用,因此第一个闭包必须包含对象的第一个引用-并且此对象肯定是1,而不是3 O_O。python闭包如何将变量本身而不是对象作为变量引用的对象?它是否将变量名另存为纯文本,一些“对变量的引用”或什么? 问题答案: 闭包不是指

  • 问题内容: 我不了解python中列表的行为: 为什么一个元素的分配影响另一个元素?感谢您的回答! 问题答案: 当您将一个列表相乘时,它会复制对该列表的引用,但不会创建该列表的副本。由于列表是可变的,因此在更改列表时,所有对其引用的引用都会更改。 用ASCII术语来说: 您可以清楚地看到更改list3将同时影响两个位置。 如果要创建可变长列表而不复制引用,则应执行以下操作: 在这里,我们使用列表理

  • 问题内容: 我在GregorianCalendar类中遇到一个奇怪的行为,我想知道我是否真的做得不好。 仅当初始化日期的月份的实际Maximum大于我将日历设置为的月份时,才追加此值。 这是示例代码: 我知道问题是由于日历初始化日期是31天(可能是5月),与设置为2月(28天)的月份混淆了。修复很容易(只需在设置年和月之前将day_of_month设置为1),但是我想知道这确实是想要的行为。有什么

  • 问题内容: 我正在为一个问题而苦苦挣扎,我不明白为什么它不起作用。如何通过将变量传递并转换为? 为什么在顶部代码段中不起作用,但在行下方的底部代码段中起作用? 唯一的区别似乎是添加了一个额外的变量,该变量也被键入为? 问题答案: 该是一种原始类型,同时是一个普通的Java类。您不能在原始类型上调用方法。但是该方法在上可用,如javadoc中所示 有关这些原始类型的更多信息,请参见此处

  • 问题内容: 为什么的到哪里去了? 问题答案: 删除任何字符,并从字符串的开头和结尾。