从CPython 3.3开始,默认情况下启用哈希随机化。在以前的版本中,可以通过指定-R
command-line option或将PYTHONHASHSEED
environment variable设置为random
来启用它。
默认情况下,str,bytes和datetime的
__hash__()
值 对象被“腌制”,具有不可预测的随机值。虽然他们 在单个Python进程中保持不变,它们不是 可以在Python的重复调用之间预测。
这是否意味着生成的值将加密强大?
答案 0 :(得分:6)
在Python 3.3中,散列种子不具有加密强度;它是在启动时使用以下伪随机生成器生成的:
/* Fill buffer with pseudo-random bytes generated by a linear congruent
generator (LCG):
x(n+1) = (x(n) * 214013 + 2531011) % 2^32
Use bits 23..16 of x(n) to generate a byte. */
static void
lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
{
size_t index;
unsigned int x;
x = x0;
for (index=0; index < size; index++) {
x *= 214013;
x += 2531011;
/* modulo 2 ^ (8 * sizeof(int)) */
buffer[index] = (x >> 16) & 0xff;
}
}
还有other problems with the hash seeding仍然可以强制发生碰撞。
Python 3.4 addressed these issues默认情况下引入more secure hashing algorithm,并使其可插入。
如果您的计划中需要加密强大的随机数,请改用random.SystemRandom()
或os.urandom()
。
答案 1 :(得分:1)
在3.4之前,Python使用了FNV的变体,它不具有加密安全性。不幸的是,简单地将一个随机值添加到像Python这样的弱哈希函数中并没有提供任何真正的安全性。由于底层哈希算法的弱点,即使存在随机化,也很容易生成具有相同FNV哈希的字符串。
请注意,即使种子完全随机且未泄露给客户,也是如此。
要考虑原因,想象一个非常弱的哈希函数 - 只需添加字符串中的所有字符。在这种情况下,如果向开头添加随机值,则任何单个字符串的散列都将是随机的。但是,如果两个字符串的字符总和为相同的值,那么无论随机种子是什么,它们都将散列为相同的值。因此,随机种子不提供任何抗碰撞性。 Python实际上做的并不是那么糟糕,但它也不是更好。
在3.4中,Python将默认算法切换为SipHash,这是通过加密安全抵御碰撞DOS攻击而获得的。不幸的是,使用2.x的任何人都完全没有运气。