在python程序中禁用哈希随机化

问题描述 投票:29回答:2

[从Python 3.3开始,哈希算法是不确定的salted,以避免某种攻击。这对Web服务器来说很好,但是在尝试调试程序时会很痛苦:每次运行脚本时,dict的内容都会以不同的顺序进行迭代。

某些较早的python版本具有用于[[enabling散列随机化的-R标志,但是现在它是默认行为,该标志尚未被其相反的地方代替。可以通过设置环境变量PYTHONHASHSEED来禁用随机化:

PYTHONHASHSEED

如果未将此变量设置为随机变量,则使用随机值来播种str,bytes和datetime对象的哈希值。如果将PYTHONHASHSEED设置为整数值,则它将用作生成散列随机化所覆盖类型的hash()的固定种子。

陷阱是必须在启动python进程之前设置此变量。我试图用PYTHONHASHSEEDos.putenv()进行设置,但是这些似乎对哈希方法没有影响。这并不奇怪:我不希望python在每个单独的集合或字典查找之前检查环境!因此,问题仍然存在:

Python程序是否有办法禁用自己的哈希随机化?

python python-3.x hash
2个回答
16
投票
很遗憾,我怀疑这不可能。查看os.environ,将test_hash.py类及其后代添加到test_hash.py中。他们通过修改环境并通过显式设置HashRandomizationTests来启动新进程来测试哈希行为。您可以尝试复制该模式。

[我也刚刚注意到您说:“

每次运行脚本时,字典内容都会以不同的顺序进行迭代。”-我假设您知道commit that introduced this behavior,对吗?这是获得可靠的哈希迭代的正常方法。


[如果您愿意在Shell环境中设置该值,也可以将python调用包装在bash脚本中,例如]

PYTHONHASHSEED

只要您可以使用包装脚本,就可以避免操纵整个环境。

或者甚至只是在命令行上传递值:

collections.OrderedDict


0
投票
除了字典顺序,散列随机化还可能破坏直接使用collections.OrderedDict的现有代码。在这种情况下,为我解决了问题的一种解决方法是替换

#! /bin/bash export PYTHONHASHSEED=0 # call your python program here

$ PYTHONHASHSEED=0 python YOURSCRIPT.py

对于Python 3,标准字符串需要类似`mystring.encode('utf-8')的转换。 (我正在使用字节字符串。)

请注意,数字范围和是否包含负数是不同的。后面的代码提供了更大的数字范围,并且散列冲突极不可能发生。

要重现与hash()相同的64位范围,可以将十六进制数字的数量减少到16(每位4位),并将结果偏移为最小的负64位数字开始。

hash(mystring)

或者,可以占用8个字节并使用int(hashlib.sha512(mystring).hexdigest(), 16)

hash()

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