从CPython 3.3开始,默认启用哈希随机化。在以前的版本中,可以通过指定-R
命令行选项或将PYTHONHASHSEED
环境变量设置为random
.
引用文档:
默认情况下,
__hash__()
str、bytes 和 datetime 对象的值是用不可预测的随机值“加盐”的。尽管它们在单个 Python 进程中保持不变,但它们在 Python 的重复调用之间是不可预测的。
这是否意味着生成的值将具有加密强度?
从CPython 3.3开始,默认启用哈希随机化。在以前的版本中,可以通过指定-R
命令行选项或将PYTHONHASHSEED
环境变量设置为random
.
引用文档:
默认情况下,
__hash__()
str、bytes 和 datetime 对象的值是用不可预测的随机值“加盐”的。尽管它们在单个 Python 进程中保持不变,但它们在 Python 的重复调用之间是不可预测的。
这是否意味着生成的值将具有加密强度?
在 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;
}
}
这在密码学上并不强大。
哈希播种还有其他问题仍然可以强制冲突。
Python 3.4通过默认引入更安全的哈希算法解决了这些问题,并使其可插入。
如果您在程序中需要加密的强随机数,请使用random.SystemRandom()
或os.urandom()
代替。
在 3.4 之前,Python 使用了 FNV 的变体,它在密码学上不安全。不幸的是,简单地将随机值添加到 Python 尝试的弱散列函数并不能提供任何真正的安全性。由于底层散列算法的弱点,即使存在随机化,也很容易生成具有相同 FNV 散列的字符串。
请注意,即使种子是完全随机的并且没有泄露给客户端,这也是正确的。
考虑原因,想象一个非常弱的散列函数——简单地将字符串中的所有字符相加。在这种情况下,如果您在开头添加一个随机值,那么任何单个字符串的哈希都是随机的。但是,如果两个字符串的字符总和为相同的值,那么无论随机种子是什么,它们都会散列到相同的值。因此,随机种子不提供任何抗碰撞性。Python 实际所做的并没有那么糟糕,但也好不到哪里去。
在 3.4 中,Python 将默认算法切换为 SipHash,这被认为是通过密码安全来防止冲突 DOS 攻击。不幸的是,任何使用 2.x 的人都完全不走运。