哈希映射键不是随机的

时间:2015-05-13 22:11:31

标签: java security hash collections hashmap

似乎Java的HashMap 总是的实现将键放在相同的bin中(至少我用Integer键看到了)。即散列是确定性的,并且在所有运行中它产生相同的值 我听说有些语言将插入随机化,以便出于安全原因,密钥存储在哪个存储桶中是不可预测的。
为什么Java的键总是一样的?

4 个答案:

答案 0 :(得分:5)

Java 7不是这样,它为每个HashMap实例添加了一个唯一的哈希种子。有关Collections Framework Enhancements in Java SE 7页面的更多信息。

为了提高性能,已在Java 8中删除了此机制,并将其替换为将可比较的密钥(例如String)转换为平衡树以替代DoS安全问题的替代方法。有关Collections Framework Enhancements in Java SE 8页面的更多信息。

答案 1 :(得分:4)

此处感兴趣的攻击是拒绝服务(DoS)。攻击者选择一组击中同一个桶的键。这将地图操作的性能从O(1)转换为O(n)。这样做n次(构建地图说),我们从O(n)到O(n ^ 2)。还有定时攻击的可能性,但我会方便地忽略它。

通常,大多数库代码都假定不需要采取任何措施来避免DoS。但是,最近一些Java实现使用MURMUR哈希来随机化String的哈希函数以避免某些攻击。 MURMUR将每进程随机数混合到哈希码的生成中,使得该功能对于该进程是稳定的,但是从外部难以理解(但不一定是不可能的)。最近,如果存在过多的冲突并且密钥正确地实现了Comparable,那么这已被替换为回退到树结构。

如果您在发现代码的情况下担心此类攻击,可以使用其他Map实施,例如java.util.TreeMap

答案 2 :(得分:1)

在Java中,单个类负责实现默认的hashCode()方法(或继承Object类中的一个),并且复杂的安全方​​案(如击败高级DoS攻击)不是{{{{ {1}},Object

因此,大多数类使用非常简单,快速的实现,试图在常见情况下确保均匀分布。

如果您认为实施自定义哈希策略很重要,无论是因为您想避免黑客攻击,还是因为您知道您的特定用法可能会导致与默认方法发生大量冲突,可以使用Gnu Trove's Integer之类的集合,它允许您提供特定于集合实例的自定义散列策略。

答案 3 :(得分:0)

要完成其他答案,我会提到当HashMap的密钥使用内置Object.hashCode时,i。即不要重写此方法,这是一种常见的情况,Object的hashCode是使用随机数生成器计算的,这使得整个系统的行为不那么具有确定性。有关详细信息,请参阅此问题:Java Object.hashCode() - address or random()?