Python 3.3中的散列函数在会话之间返回不同的结果

我已经在Python 3.3中实现了一个BloomFilter,每次会话都得到不同的结果。 深入研究这个奇怪的行为使我得到了内部的hash()函数 – 它为每个会话返回同一个string的不同散列值。

例:

>>> hash("235") -310569535015251310 

—–打开一个新的python控制台—–

 >>> hash("235") -1900164331622581997 

为什么发生这种情况? 为什么这是有用的?

Python使用随机散列种子来防止攻击者通过发送devise为冲突的密钥来压缩应用程序。 查看原始漏洞披露 。 通过用随机种子偏移哈希(在启动时设置一次),攻击者不能再预测哪些密钥会发生冲突。

您可以通过设置PYTHONHASHSEED环境variables来设置固定的种子或禁用该function; 默认值是random但您可以将其设置为固定的正整数值,其中0禁用该function。

Python版本2.7和3.2默认禁用该function(使用-R开关或设置PYTHONHASHSEED=random来启用它); 它在Python 3.3及以上版本中默认启用。

如果您依赖于Python字典或集合中的键的顺序,则不要。 Python使用一个散列表来实现这些types,它们的顺序取决于插入和删除历史以及随机散列种子。

另请参阅object.__hash__()特殊方法文档 :

:默认情况下,str,bytes和datetime对象的__hash__()值是“salted”的,具有不可预知的随机值。 虽然它们在单独的Python过程中保持不变,但在重复调用Python之间却无法预测。
这是为了防止由于精心挑选的input引起的拒绝服务,这些input利用了字典插入的最坏情况performance,O(n ^ 2)复杂度。 有关详细信息,请参阅http://www.ocert.org/advisories/ocert-2011-003.html
更改散列值会影响字典,集合和其他映射的迭代顺序。 Python从来没有对这个顺序做过保证(它通常在32位和64位版本之间变化)。
另见PYTHONHASHSEED

如果你需要一个稳定的散列实现,你可能想看看hashlib模块 ; 这实现了密码散列函数。 pybloom项目使用这种方法 。

由于偏移量由一个前缀和一个后缀(分别为开始值和最终异或值)组成,因此不幸的是您不能保存偏移量。 从好的方面来说,这确实意味着攻击者不能轻易地利用定时攻击来确定偏移量。

散列随机化在Python 3中默认打开 。 这是一个安全function:

散列随机化旨在提供保护,防止由精心挑选的input引起的拒绝服务,这些input利用字典构造的最坏情况性能

在2.6.8以前的版本中,可以在命令行上使用-R或PYTHONHASHSEED环境选项打开它。

您可以通过将PYTHONHASHSEED设置PYTHONHASHSEED来closures它。

hash()是一个Python 内置函数 ,用它来计算对象的散列值,而不是string或数字。

您可以在此页面中看到详细信息: https : //docs.python.org/3.3/library/functions.html#hash 。

和hash()值来自对象的__hash__方法。 该文件说明如下:

默认情况下,str,bytes和datetime对象的hash ()值是一个不可预知的随机值。 虽然它们在单独的Python过程中保持不变,但在重复调用Python之间却无法预测。

这就是为什么你有不同的控制台相同的string散列值。

你实施的是不是一个好方法。

当你想计算一个string哈希值,只需使用hashlib

散列()的目的是获得一个对象的哈希值,而不是stirng。