我正在对Double-DES进行中间相遇攻击。我已经实现了DES加密/解密并完成了加密,现在我想对Double-DES进行一次MITM攻击以找到密钥。我试图实现此目的的方法是在for循环中存储中间密码(作为HashMap的密钥)和可能的密钥(作为HashMap的值)。但是,在此for循环中,我还想确保可能的键是唯一的,即我有一个if语句,该语句检查HashMap中是否已经存在可能的键。如果不是,则使用它来加密纯文本并将密文和可能的密钥存储在HashMap中。在后端,我尝试通过使用foreach遍历HashMap来找到具有匹配的中间密文的密钥,并将加密中的每个中间密文与解密中的中间密文进行比较。
但是,我找不到匹配项,因为它需要很长时间才能完成。我已经等了2个小时,没有任何结果。如果删除if语句,该语句检查HashMap中是否已经存在可能的密钥,则它将在10秒内完成。
for (int size = intermediateCipher.size(); size < Math.pow(2, 20); size++) { // intermediateCipher is my HashMap consisting of <String, byte[]>
byte[] possibleKey = generateDesKey(); // generateDesKey generates a key of 64 bits
if (!intermediateCipher.containsValue(possibleKey)) {
intermediateCipher.put((encrypt(possibleKey, plainText)).toString(), possibleKey);
}
}
int count = 0;
for (Entry<String, byte[]> arr : intermediateCipher.entrySet()) {
String temp = (decrypt(arr.getValue(), cipherText)).toString();
if (intermediateCipher.containsKey(temp)) {
count++;
}
}
我应该提到DES密钥只有20位有效。这就是为什么有2 ^ 20个可能的键的原因。此外,如果我没有if语句,该语句检查可能的键是否已经在HashMap中,那么我会得到510个匹配项,
更新:
我尝试使用Set来首先存储密钥,然后使用Set中的密钥进行加密等。但是,我尝试使用a来代替从0到2 ^ 20的for迭代。 while循环,只要Set具有元素,它就会检查迭代。但是,我尝试将这种方法运行10分钟以上,没有任何结果。它永远不会跳出循环。
for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}
System.out.println(possibleKeySet.size());
for (int i = 0; i < possibleKeySet.size(); i++) {
intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(),
possibleKeySet.iterator().next());
}
System.out.println("ss " + intermediateCipher.size());
int count = 0;
for (Entry<String, byte[]> arr : intermediateCipher.entrySet()) {
String temp = ((decrypt(arr.getValue(), cipherText)).toString());
if (intermediateCipher.containsKey(temp)) {
count++;
}
}
我已经读过,对于一个集合,hasNext()对于非空集合总是返回true。因此,我尝试为每个设置a,但是hashMap的大小永远不会与键集的大小相同,这对我来说没有意义,因为我使用了键集中的每个键:
for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}
System.out.println(possibleKeySet.size());
for (byte[] key : possibleKeySet) {
intermediateCipher.put((encrypt(key, plainText)).toString(),
key);
}
答案 0 :(得分:1)
Map.containsValue()
将具有线性时间,因为您在所有地图值上盲目迭代。按照方法javadoc:
如果此映射将一个或多个键映射到指定值,则返回true。更正式地讲,当且仅当此映射包含至少一个到值v的映射(例如Objects.equals(value,v))时,才返回true。 对于大多数Map界面的实现,此操作可能需要在地图大小中呈线性关系。
要利用哈希查找,您应该使用Map.containsKey()
检查密钥:
if (!intermediateCipher.containsKey(possibleKey)) {
...
}
答案 1 :(得分:1)
Map.containsValue()
必须检查每个地图条目。在地图大小上花费O(n)。假设重复项的数量不超过生成的所有键的固定分数,则在循环的每次迭代中检查containsValue()
,然后在键数上的总和为O(n 2 )产生。一百万个键真是太贵了。
考虑保留到目前为止存储的密钥的辅助Set
,并测试该集合中的成员资格,而不是直接测试Map中的值。