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

2024-01-27

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

Example:

>>> hash("235")
-310569535015251310

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

>>> hash("235")
-1900164331622581997

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


Python 使用随机哈希种子来防止攻击者通过向您发送旨在冲突的密钥来对您的应用程序进行 tar-pit。请参阅原始漏洞披露 http://www.ocert.org/advisories/ocert-2011-003.html。通过使用随机种子(在启动时设置一次)抵消哈希值,攻击者无法再预测哪些密钥将发生冲突。

您可以通过设置固定种子或禁用该功能PYTHONHASHSEED环境变量 https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED;默认是random但您可以将其设置为固定的正整数值,使用0完全禁用该功能。

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

如果您依赖 Python 集中键的顺序,那么就不要这样做。 Python 使用哈希表来实现这些类型及其顺序取决于插入和删除历史记录 https://stackoverflow.com/questions/15479928/why-is-the-order-in-python-dictionaries-and-sets-arbitrary/15479974#15479974以及随机哈希种子。请注意,在 Python 3.5 及更早版本中,这也适用于字典。

另请参阅object.__hash__()特殊方法文档 https://docs.python.org/3/reference/datamodel.html#object.__hash__:

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

这样做的目的是为了防止由于精心选择的输入而导致拒绝服务,这些输入利用了字典插入的最坏情况性能,复杂度为 O(n^2)。看http://www.ocert.org/advisories/ocert-2011-003.html http://www.ocert.org/advisories/ocert-2011-003.html了解详情。

更改哈希值会影响字典、集合和其他映射的迭代顺序。 Python 从未对这种顺序做出保证(并且它通常在 32 位和 64 位版本之间有所不同)。

也可以看看PYTHONHASHSEED.

如果您需要稳定的哈希实现,您可能想看看hashlib module https://docs.python.org/3/library/hashlib.html;这实现了加密哈希函数。这pybloom 项目使用这种方法 https://github.com/jaybaird/python-bloomfilter/blob/master/pybloom/pybloom.py#L54-L98.

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 3.3 中的哈希函数在会话之间返回不同的结果 的相关文章

随机推荐