Why does checking if a HashMap has a certain value take very long to execute within a for loop?
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);
}
java performance hashmap des
add a comment |
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);
}
java performance hashmap des
iftemp
isn't used, you don't need totoString
which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
– Peter Lawrey
Nov 22 at 17:55
I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55
@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57
@Bab I assumed if you removed theif
you removed theintermediateCipher.containsKey(temp)
but again, without theif
this method call doesn't do anything either.
– Peter Lawrey
Nov 22 at 17:58
1
Theif
statement he's talking about appears to beif (!intermediateCipher.containsValue(possibleKey))
, and the key is not a map key, but rather a cryptographic key stored as a map value.
– John Bollinger
Nov 22 at 18:02
add a comment |
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);
}
java performance hashmap des
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);
}
java performance hashmap des
java performance hashmap des
edited Nov 22 at 21:08
asked Nov 22 at 17:48
Bab
12910
12910
iftemp
isn't used, you don't need totoString
which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
– Peter Lawrey
Nov 22 at 17:55
I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55
@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57
@Bab I assumed if you removed theif
you removed theintermediateCipher.containsKey(temp)
but again, without theif
this method call doesn't do anything either.
– Peter Lawrey
Nov 22 at 17:58
1
Theif
statement he's talking about appears to beif (!intermediateCipher.containsValue(possibleKey))
, and the key is not a map key, but rather a cryptographic key stored as a map value.
– John Bollinger
Nov 22 at 18:02
add a comment |
iftemp
isn't used, you don't need totoString
which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.
– Peter Lawrey
Nov 22 at 17:55
I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55
@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57
@Bab I assumed if you removed theif
you removed theintermediateCipher.containsKey(temp)
but again, without theif
this method call doesn't do anything either.
– Peter Lawrey
Nov 22 at 17:58
1
Theif
statement he's talking about appears to beif (!intermediateCipher.containsValue(possibleKey))
, and the key is not a map key, but rather a cryptographic key stored as a map value.
– John Bollinger
Nov 22 at 18:02
if
temp
isn't used, you don't need to toString
which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.– Peter Lawrey
Nov 22 at 17:55
if
temp
isn't used, you don't need to toString
which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.– Peter Lawrey
Nov 22 at 17:55
I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55
I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55
@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57
@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57
@Bab I assumed if you removed the
if
you removed the intermediateCipher.containsKey(temp)
but again, without the if
this method call doesn't do anything either.– Peter Lawrey
Nov 22 at 17:58
@Bab I assumed if you removed the
if
you removed the intermediateCipher.containsKey(temp)
but again, without the if
this method call doesn't do anything either.– Peter Lawrey
Nov 22 at 17:58
1
1
The
if
statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey))
, and the key is not a map key, but rather a cryptographic key stored as a map value.– John Bollinger
Nov 22 at 18:02
The
if
statement he's talking about appears to be if (!intermediateCipher.containsValue(possibleKey))
, and the key is not a map key, but rather a cryptographic key stored as a map value.– John Bollinger
Nov 22 at 18:02
add a comment |
2 Answers
2
active
oldest
votes
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)) {
...
}
So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12
@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separateSet<possibleKey>
for just checking presence ofpossibleKey
.
– Karol Dowbecki
Nov 22 at 18:13
Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31
Have tried withwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29
Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30
|
show 7 more comments
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.
By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32
Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I runwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
– Bab
Nov 22 at 19:33
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436072%2fwhy-does-checking-if-a-hashmap-has-a-certain-value-take-very-long-to-execute-wit%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
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)) {
...
}
So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12
@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separateSet<possibleKey>
for just checking presence ofpossibleKey
.
– Karol Dowbecki
Nov 22 at 18:13
Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31
Have tried withwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29
Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30
|
show 7 more comments
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)) {
...
}
So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12
@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separateSet<possibleKey>
for just checking presence ofpossibleKey
.
– Karol Dowbecki
Nov 22 at 18:13
Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31
Have tried withwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29
Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30
|
show 7 more comments
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)) {
...
}
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)) {
...
}
answered Nov 22 at 18:08
Karol Dowbecki
16.4k82849
16.4k82849
So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12
@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separateSet<possibleKey>
for just checking presence ofpossibleKey
.
– Karol Dowbecki
Nov 22 at 18:13
Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31
Have tried withwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29
Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30
|
show 7 more comments
So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12
@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separateSet<possibleKey>
for just checking presence ofpossibleKey
.
– Karol Dowbecki
Nov 22 at 18:13
Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31
Have tried withwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29
Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30
So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12
So, I should change my HashMap to <possibleKey, intermediateCipher> as the possible key is stored as the value now?
– Bab
Nov 22 at 18:12
@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate
Set<possibleKey>
for just checking presence of possibleKey
.– Karol Dowbecki
Nov 22 at 18:13
@Bab If your lookup is the primary cost and you have enough memory to maintain the Map, yes. Or use a separate
Set<possibleKey>
for just checking presence of possibleKey
.– Karol Dowbecki
Nov 22 at 18:13
Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31
Have tried changing the HashMap, but it seems that it doesn't help. I am going for the Set as it doesn't allow duplicates. However, I would like to ask, if I choose this approach, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:31
Have tried with
while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29
Have tried with
while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
– Bab
Nov 22 at 19:29
Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30
Have been waiting for over 10 mins.
– Bab
Nov 22 at 19:30
|
show 7 more comments
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.
By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32
Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I runwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
– Bab
Nov 22 at 19:33
add a comment |
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.
By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32
Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I runwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
– Bab
Nov 22 at 19:33
add a comment |
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.
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.
answered Nov 22 at 18:10
John Bollinger
78.2k73974
78.2k73974
By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32
Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I runwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
– Bab
Nov 22 at 19:33
add a comment |
By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32
Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I runwhile (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?
– Bab
Nov 22 at 19:33
By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32
By using a Set, I need to have a for loop, which generates, in my case, 2^20 keys, right? I can afterwards use these keys as an element (key/value?) in the HashMap?
– Bab
Nov 22 at 18:32
Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run
while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?– Bab
Nov 22 at 19:33
Have tried with a set, as you suggested, where I store all the possible keys. Afterwards, I run
while (possibleKeySet.iterator().hasNext()) { intermediateCipher.put((encrypt(possibleKeySet.iterator().next(), plainText)).toString(), possibleKeySet.iterator().next()); }
but that didn't help either i.e. have been waiting for over 10 mins. Is that normal?– Bab
Nov 22 at 19:33
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436072%2fwhy-does-checking-if-a-hashmap-has-a-certain-value-take-very-long-to-execute-wit%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
if
temp
isn't used, you don't need totoString
which means you don't need to decrypt, which means you don't need to iterate the Map. In short, the JVM is pretty good at eliminating code which doesn't do anything.– Peter Lawrey
Nov 22 at 17:55
I think this is one of those naive attacks that will take approximately seven times as long as the heat death of the universe. You need something like Deep Crack for DES.
– Elliott Frisch
Nov 22 at 17:55
@PeterLawrey: What do you mean? I am using it in the next if statement or do you mean something else?
– Bab
Nov 22 at 17:57
@Bab I assumed if you removed the
if
you removed theintermediateCipher.containsKey(temp)
but again, without theif
this method call doesn't do anything either.– Peter Lawrey
Nov 22 at 17:58
1
The
if
statement he's talking about appears to beif (!intermediateCipher.containsValue(possibleKey))
, and the key is not a map key, but rather a cryptographic key stored as a map value.– John Bollinger
Nov 22 at 18:02