为什么不能保证std :: hash具有确定性?


28

此后,我们使用N4140(C ++ 14标准)。


根据第17.6.3.4节哈希要求

返回的值应仅取决于k 程序持续时间内的参数。

[注意:因此,对于给定的程序执行,h(k)具有相同值的表达式的所有求值都会 k产生相同的结果。—尾注]

§12年9月20日类模板哈希

...

实例hash<Key>应:

(1.1)-满足哈希要求(17.6.3.4)...

(1.2)-...


这意味着,如果重新启动程序,则哈希值value(即hash<decltype(value)>(value))可能采用不同的值。

但为什么?此限制不在C ++ 11标准中,而是在C ++ 14,C ++ 17和C ++ 20标准中。作为用户(不是STL开发人员),如果std::hash具有确定性,那将非常有用。实现确定性哈希函数有任何数学困难吗?但是我们日常使用的哈希函数(例如,不建议使用md5sum或更安全的函数sha256)都是确定性的。有效率问题吗?


7
“ ...散列函数只需要在程序的一次执行中为相同的输入产生相同的结果即可;这允许盐化的散列防止冲突拒绝服务攻击。” 来源:en.cppreference.com/w/cpp/utility/hash
Richard Critten

5
它允许确定性算法接受非确定性输入。例如,指针值。不变的数据结构可以对内部数据的地址进行哈希处理,这比对内容进行哈希处理要快得多。
John Kugelman

4
这个答案有一些很好的链接,说明了为什么您不想要确定性。
NathanOliver

3
不要以限制为威胁,但是要使标准约束变得不那么严格。
Marek R

4
这是充分解释了为什么限制已被放宽的原因
Marek R

Answers:


17

不需要在运行之间确定哈希函数,但是您仍然可以提供自己的哈希,例如,如果您依赖的是无序容器,则可以提供哈希。

至于为什么,cppreference说:

散列函数仅需要在程序的一次执行中为相同的输入产生相同的结果即可;这允许使用盐腌的哈希值来防止冲突拒绝服务攻击。

如果Hash需求告诉它是确定性的,那么您将无法在不违反需求的情况下提供加盐的哈希。

这是实际的原因


7

@NathanOliver建议的答案(及其链接)最终会有所帮助。让我引用重要的部分。

对于非密码散列函数,可以预先计算具有相同散列值的大量输入,以通过算法降低无序容器的速度,并导致拒绝服务攻击。

(来自问题2291。std :: hash容易受到碰撞DoS攻击

因此,语言设计人员正在迁移到随机哈希。在随机哈希中,字符串“ a”的哈希值可以在每次运行程序时更改。现在,随机哈希是Python(从3.3版开始),Ruby(从1.9版开始)和Perl(从5.18版开始)的默认设置。

(从中您是否意识到您正在使用随机哈希?

移至“就绪”,而不是“立即”,因为即使在反射器讨论中,许可也引起了争议

(来自问题2291。std :: hash容易受到碰撞DoS攻击

据我所知,实际上,没有实现会std::hash实现随机哈希,但是您可以编写自己的my::secure_hash

(根据此答案


聚苯乙烯

我只是用Google搜索“哈希表dos”,然后找到了一个信息页:您意识到世界上每台服务器都容易受到攻击的那一刻

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.