JAVA——对于IdentityHashMap的理解
场景
在实现中间相遇攻击的时候,需要对使用map存放k1加密明文得到的中间密文,中间密文作为key值,k1作为value值,然后用k2解密密文得到的中间密文去map中碰撞。 但是不同k1产生的中间密文有可能不同,所以需要解决可能出现的key值重复问题。 我目前的思路:
使用辅助list去存放重复的中间密文和k1。使用MultiMap使用IdentityHashMap(出现问题)
本文主要讨论我在这个场景下使用IdentityHashMap出现的问题,以及对于IdentityHashMap的理解。
IdentityHashMap允许key值重复的原理
简单来说,常规的Map实现类实现Map接口时,判断key值相等的方法是equals()。 而IdentityHashMap判断key值相等的方法是==。
实例1
IdentityHashMap
<String, Object> map
= new IdentityHashMap<String, Object>();
map
.put("abc",1);
map
.put("abc",2);
System
.out
.println(map
);
map
.clear();
String s1
= "abc";
String s2
= "abc";
map
.put(s1
, 1);
map
.put(s2
, 2);
System
.out
.println(map
);
地址值一样,IdentityHashMap会认为是相同的key,所以{“abc”,2}将{“abc”,1}覆盖了。
实例2
map
.put(new String("abc"), 1);
map
.put(new String("abc"), 2);
System
.out
.println(map
);
地址值不一样,IdentityHashMap会认为是不同的key,所以{“abc”,1}和{“abc”,2}都被存入map。
使用IdentityHashMap实现中间相遇攻击
public static ArrayList
<K> attack(String m
, String c
) {
IdentityHashMap
<String, String> tmpMap
= new IdentityHashMap<>();
ArrayList
<K> list
= new ArrayList<>();
for(int i
= 0; i
< 65536; i
++) {
String k1
= DECtoBIN(i
);
String mid
= DES(m
, k1
);
tmpMap
.put(mid
, k1
);
}
for(int i
= 0; i
< 65536; i
++) {
String k2
= DECtoBIN(i
);
String mid
= reDES(c
, k2
);
if(tmpMap
.containsKey(mid
)) {
for(Map
.Entry
<String, String> entry
: tmpMap
.entrySet()) {
if(entry
.getKey().equals(mid
)) {
list
.add(new K(entry
.getValue(), k2
));
}
}
}
}
return list
;
}
出现的问题以及对问题的分析
问题
碰撞的时候出现问题
if(tmpMap
.containsKey(mid
))
问题分析
上文提到,IdentityHashMap判断key值是否相等的方法是==,对于对象而言也就是判断地址值是否相等。
碰撞的时候使用的中间状态对象是个新对象,地址值不同,所以碰撞会失败。
想要解决问题,我的思路是要找到原来的地址值,但是现在还没有办法实现。
对于IdentityHashMap的理解
很多资料说IdentityHashMap可以存放相同的key,我个人觉得这样的说法比较具有误导性。
IdentityHashMap在实现Map接口时,罕见地违反了常规,没有使用equals(),而是使用==去判断两个key值是否相等。
所以虽然有时候看起来IdentityHashMap可以存放“相同的key”,但对IdentityHashMap而言,这对看起来相同的key本质上还是不同的key。
在大部分需要碰撞key值的场景中,需要的都是对象相等,使用equals()来判断key值是否相等显然比用==来判断key值是否相等合理。
综上所述,我认为IdentityHashMap仅适用于一些需要引用相等的特殊场景。