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

问题描述 投票:46回答:3

我已经在python 3.3中实现了BloomFilter,并且每次会话都得到了不同的结果。深入研究这种奇怪的行为让我进入了内部的hash()函数 - 它为每个会话返回相同字符串的不同哈希值。

例:

>>> hash("235")
-310569535015251310

-----打开一个新的python控制台-----

>>> hash("235")
-1900164331622581997

为什么会这样?为什么这有用?

python security hash python-3.3 hash-collision
3个回答
77
投票

Python使用随机散列种子来防止攻击者通过向您发送旨在发生冲突的密钥来对您的应用程序进行tar。见original vulnerability disclosure。通过使用随机种子(在启动时设置一次)来抵消哈希,攻击者无法再预测哪些密钥会发生冲突。

您可以通过设置PYTHONHASHSEED environment variable来设置固定种子或禁用该功能;默认值为random,但您可以将其设置为固定的正整数值,0将完全禁用该功能。

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

如果您依赖于Python字典或集合中的键顺序,那么请不要这样做。 Python使用哈希表来实现这些类型及其顺序depends on the insertion and deletion history以及随机哈希种子。

另见object.__hash__() special method documentation

注意:默认情况下,str,bytes和datetime对象的__hash__()值使用不可预测的随机值“加盐”。尽管它们在单个Python进程中保持不变,但在重复调用Python之间无法预测它们。 这旨在提供针对由精心选择的输入引起的拒绝服务的保护,该输入利用dict插入的最坏情况性能,O(n ^ 2)复杂度。有关详细信息,请参阅http://www.ocert.org/advisories/ocert-2011-003.html。 更改哈希值会影响dicts,集和其他映射的迭代顺序。 Python从未对此排序做出保证(通常在32位和64位版本之间有所不同)。 另见PYTHONHASHSEED

如果你需要一个稳定的哈希实现,你可能想看看hashlib module;这实现了加密哈希函数。 pybloom project uses this approach

由于偏移量由前缀和后缀(分别为起始值和最终XORed值)组成,因此不幸的是,您不能仅存储偏移量。从好的方面来说,这确实意味着攻击者也无法轻易确定定时攻击的偏移量。


5
投票

哈希随机化是turned on by default in Python 3。这是一个安全功能:

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

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

您可以通过将PYTHONHASHSEED设置为零来关闭它。


-6
投票

hash()是一个Python内置函数,用它来计算对象的哈希值,而不是字符串或num。

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

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

默认情况下,str,bytes和datetime对象的hash()值使用不可预测的随机值“加盐”。尽管它们在单个Python进程中保持不变,但在重复调用Python之间无法预测它们。

这就是为什么你在不同的控制台中为同一个字符串设置不同的哈希值。

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

如果要计算字符串哈希值,只需使用hashlib

hash()旨在获取对象哈希值,而不是字符串。

© www.soinside.com 2019 - 2024. All rights reserved.