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。