问题
I am working with meet-in-the-middle attack on Double-DES. I have implemented the DES encryption/decryption and done the encryptions and now I would like to perform a MITM attack on the Double-DES in order to find the keys. The way I am trying to achieve this is by storing, within a for loop, the intermediate ciphers as the key of a HashMap and the possible keys as the values of the HashMap. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have an if statement, which checks whether the possible key already exists in the HashMap. If not, then it uses it to encrypt the plain text and store the cipher text and the possible key in the HashMap. Aftwards, I try to find the keys, which have matching intermediate cipher text by iterating through the HashMap with a foreach and compare each intermediate cipher text from the encryptions with the intermediate cipher text from the decryptions.
However, I am unable to find the match as it takes too long to finish. I have been waiting for like 2 hours now without any result. If I remove the if statement, which checks if the possible key is already in the HashMap it finishes in like 10 seconds.
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++;
}
}
I should mention that only 20 bits of the DES key is effective. That is why there are 2^20 possible keys. Furthermore, if I don't have the if statement, which checks if the possible key is already in the HashMap, I get 510 matches, which is too much.
UPDATE:
I have tried using a Set in order to store the keys first and then used the keys from the Set to encrypt etc. However, instead of having a for, which iterates from 0 to 2^20, I have tried with a while loop, which checks iterates as long as the Set has elements. However, I have tried running this approach for over 10 mins without any result. It never gets out of the loop.
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++;
}
}
I have read that for a set hasNext() always returns true for a non-empty collection. So, I have tried with a for each, but the size of the hashMap is never the same as the size of the set of keys, which doesn't make sense to me as I use every key in the set:
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);
}
回答1:
Map.containsValue() will have a linear time as you are iterating blindly over all the map values. As per the method javadoc:
Returns true if this map maps one or more keys to the specified value. More formally, returns true if and only if this map contains at least one mapping to a value v such that Objects.equals(value, v). This operation will probably require time linear in the map size for most implementations of the Map interface.
To take advantage of a hash lookup you should check the keys with Map.containsKey():
if (!intermediateCipher.containsKey(possibleKey)) {
...
}
回答2:
Map.containsValue()
must check every map entry. That costs O(n) in the size of the map. Supposing that the number of duplicates does not exceed a fixed fraction of all keys generated, checking containsValue()
on each iteration of your loop then costs an aggregate O(n2) in the number of keys generated. For a million keys that's awfully expensive.
Consider instead keeping an auxiliary Set
of the keys stored so far, and testing membership in that set instead of directly testing the values in the Map.
来源:https://stackoverflow.com/questions/53436072/why-does-checking-if-a-hashmap-has-a-certain-value-take-very-long-to-execute-wit