HashMap with integers as key and value takes too long to finish work












0














I am working with meet-in-the-middle attack on 2DES. I have implemented the DES encryption/decryption and it is working. 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. Both as integers - Started with byte, but figured out that a key cannot be an array. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have a while loop, which makes sure that the size of the HashMap is 2^20 (only 20 bits of the DES key are effective). 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 20 mins without any result.



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();

intermediateCipher.put(ByteBuffer.wrap(encrypt(key, plainText)).getInt() , ByteBuffer.wrap(key).getInt());
}

int count = 0;
for (Entry<Integer, Integer> arr : intermediateCipher.entrySet()) {
byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();
if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();

if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}


intermediateCipher is my HashMap .



PlainText is a byte of 8 bytes, cipherText2 is the encryption result of 2DES on the plainText and generateDesKey is the method which generates 64 bits, where the parity bits are skipped in order to make sure that the 20 bits are effective, and convert the bits to a byte as DES requires that










share|improve this question


















  • 5




    Is there some course teaching this kind of thing? I saw a very similar question just the other day, and it wasn't the first...
    – Krease
    Nov 23 '18 at 23:04










  • There are several concept and understanding errors. 1. The input to 2DES is an array of 8 bytes of which only the 7ms bytes are used. 2. 20 minutes is nothing, try days++. 3. "only 20 bits of the DES key are effective" makes is wrong and makes no sense. 4. 2DES has a 112-but key but is susceptible to the birthday paradox which reduces it.
    – zaph
    Nov 23 '18 at 23:07












  • @zaph. I mean that the key is 64bits, but the effective are 20bits and the rest is added with zeros.
    – user8231110
    Nov 23 '18 at 23:14










  • Yes @flakes, it was me, but when I debugged the code I figured out that I was unable to use byte and String, so I changed to a integers for both the key and value.
    – user8231110
    Nov 23 '18 at 23:20






  • 1




    Consider adding the the question that you are arbitrarily limiting the keys to 20-bits each. DES has a 56-bit key in 8 bytes, the "parity" bit is generally ignored these days.
    – zaph
    Nov 23 '18 at 23:29


















0














I am working with meet-in-the-middle attack on 2DES. I have implemented the DES encryption/decryption and it is working. 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. Both as integers - Started with byte, but figured out that a key cannot be an array. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have a while loop, which makes sure that the size of the HashMap is 2^20 (only 20 bits of the DES key are effective). 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 20 mins without any result.



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();

intermediateCipher.put(ByteBuffer.wrap(encrypt(key, plainText)).getInt() , ByteBuffer.wrap(key).getInt());
}

int count = 0;
for (Entry<Integer, Integer> arr : intermediateCipher.entrySet()) {
byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();
if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();

if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}


intermediateCipher is my HashMap .



PlainText is a byte of 8 bytes, cipherText2 is the encryption result of 2DES on the plainText and generateDesKey is the method which generates 64 bits, where the parity bits are skipped in order to make sure that the 20 bits are effective, and convert the bits to a byte as DES requires that










share|improve this question


















  • 5




    Is there some course teaching this kind of thing? I saw a very similar question just the other day, and it wasn't the first...
    – Krease
    Nov 23 '18 at 23:04










  • There are several concept and understanding errors. 1. The input to 2DES is an array of 8 bytes of which only the 7ms bytes are used. 2. 20 minutes is nothing, try days++. 3. "only 20 bits of the DES key are effective" makes is wrong and makes no sense. 4. 2DES has a 112-but key but is susceptible to the birthday paradox which reduces it.
    – zaph
    Nov 23 '18 at 23:07












  • @zaph. I mean that the key is 64bits, but the effective are 20bits and the rest is added with zeros.
    – user8231110
    Nov 23 '18 at 23:14










  • Yes @flakes, it was me, but when I debugged the code I figured out that I was unable to use byte and String, so I changed to a integers for both the key and value.
    – user8231110
    Nov 23 '18 at 23:20






  • 1




    Consider adding the the question that you are arbitrarily limiting the keys to 20-bits each. DES has a 56-bit key in 8 bytes, the "parity" bit is generally ignored these days.
    – zaph
    Nov 23 '18 at 23:29
















0












0








0







I am working with meet-in-the-middle attack on 2DES. I have implemented the DES encryption/decryption and it is working. 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. Both as integers - Started with byte, but figured out that a key cannot be an array. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have a while loop, which makes sure that the size of the HashMap is 2^20 (only 20 bits of the DES key are effective). 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 20 mins without any result.



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();

intermediateCipher.put(ByteBuffer.wrap(encrypt(key, plainText)).getInt() , ByteBuffer.wrap(key).getInt());
}

int count = 0;
for (Entry<Integer, Integer> arr : intermediateCipher.entrySet()) {
byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();
if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();

if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}


intermediateCipher is my HashMap .



PlainText is a byte of 8 bytes, cipherText2 is the encryption result of 2DES on the plainText and generateDesKey is the method which generates 64 bits, where the parity bits are skipped in order to make sure that the 20 bits are effective, and convert the bits to a byte as DES requires that










share|improve this question













I am working with meet-in-the-middle attack on 2DES. I have implemented the DES encryption/decryption and it is working. 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. Both as integers - Started with byte, but figured out that a key cannot be an array. However, within this for loop I also want to make sure that the possible keys are unique i.e. I have a while loop, which makes sure that the size of the HashMap is 2^20 (only 20 bits of the DES key are effective). 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 20 mins without any result.



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();

intermediateCipher.put(ByteBuffer.wrap(encrypt(key, plainText)).getInt() , ByteBuffer.wrap(key).getInt());
}

int count = 0;
for (Entry<Integer, Integer> arr : intermediateCipher.entrySet()) {
byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();
if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();

if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}


intermediateCipher is my HashMap .



PlainText is a byte of 8 bytes, cipherText2 is the encryption result of 2DES on the plainText and generateDesKey is the method which generates 64 bits, where the parity bits are skipped in order to make sure that the 20 bits are effective, and convert the bits to a byte as DES requires that







java hashmap






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 23 '18 at 22:53









user8231110user8231110

486




486








  • 5




    Is there some course teaching this kind of thing? I saw a very similar question just the other day, and it wasn't the first...
    – Krease
    Nov 23 '18 at 23:04










  • There are several concept and understanding errors. 1. The input to 2DES is an array of 8 bytes of which only the 7ms bytes are used. 2. 20 minutes is nothing, try days++. 3. "only 20 bits of the DES key are effective" makes is wrong and makes no sense. 4. 2DES has a 112-but key but is susceptible to the birthday paradox which reduces it.
    – zaph
    Nov 23 '18 at 23:07












  • @zaph. I mean that the key is 64bits, but the effective are 20bits and the rest is added with zeros.
    – user8231110
    Nov 23 '18 at 23:14










  • Yes @flakes, it was me, but when I debugged the code I figured out that I was unable to use byte and String, so I changed to a integers for both the key and value.
    – user8231110
    Nov 23 '18 at 23:20






  • 1




    Consider adding the the question that you are arbitrarily limiting the keys to 20-bits each. DES has a 56-bit key in 8 bytes, the "parity" bit is generally ignored these days.
    – zaph
    Nov 23 '18 at 23:29
















  • 5




    Is there some course teaching this kind of thing? I saw a very similar question just the other day, and it wasn't the first...
    – Krease
    Nov 23 '18 at 23:04










  • There are several concept and understanding errors. 1. The input to 2DES is an array of 8 bytes of which only the 7ms bytes are used. 2. 20 minutes is nothing, try days++. 3. "only 20 bits of the DES key are effective" makes is wrong and makes no sense. 4. 2DES has a 112-but key but is susceptible to the birthday paradox which reduces it.
    – zaph
    Nov 23 '18 at 23:07












  • @zaph. I mean that the key is 64bits, but the effective are 20bits and the rest is added with zeros.
    – user8231110
    Nov 23 '18 at 23:14










  • Yes @flakes, it was me, but when I debugged the code I figured out that I was unable to use byte and String, so I changed to a integers for both the key and value.
    – user8231110
    Nov 23 '18 at 23:20






  • 1




    Consider adding the the question that you are arbitrarily limiting the keys to 20-bits each. DES has a 56-bit key in 8 bytes, the "parity" bit is generally ignored these days.
    – zaph
    Nov 23 '18 at 23:29










5




5




Is there some course teaching this kind of thing? I saw a very similar question just the other day, and it wasn't the first...
– Krease
Nov 23 '18 at 23:04




Is there some course teaching this kind of thing? I saw a very similar question just the other day, and it wasn't the first...
– Krease
Nov 23 '18 at 23:04












There are several concept and understanding errors. 1. The input to 2DES is an array of 8 bytes of which only the 7ms bytes are used. 2. 20 minutes is nothing, try days++. 3. "only 20 bits of the DES key are effective" makes is wrong and makes no sense. 4. 2DES has a 112-but key but is susceptible to the birthday paradox which reduces it.
– zaph
Nov 23 '18 at 23:07






There are several concept and understanding errors. 1. The input to 2DES is an array of 8 bytes of which only the 7ms bytes are used. 2. 20 minutes is nothing, try days++. 3. "only 20 bits of the DES key are effective" makes is wrong and makes no sense. 4. 2DES has a 112-but key but is susceptible to the birthday paradox which reduces it.
– zaph
Nov 23 '18 at 23:07














@zaph. I mean that the key is 64bits, but the effective are 20bits and the rest is added with zeros.
– user8231110
Nov 23 '18 at 23:14




@zaph. I mean that the key is 64bits, but the effective are 20bits and the rest is added with zeros.
– user8231110
Nov 23 '18 at 23:14












Yes @flakes, it was me, but when I debugged the code I figured out that I was unable to use byte and String, so I changed to a integers for both the key and value.
– user8231110
Nov 23 '18 at 23:20




Yes @flakes, it was me, but when I debugged the code I figured out that I was unable to use byte and String, so I changed to a integers for both the key and value.
– user8231110
Nov 23 '18 at 23:20




1




1




Consider adding the the question that you are arbitrarily limiting the keys to 20-bits each. DES has a 56-bit key in 8 bytes, the "parity" bit is generally ignored these days.
– zaph
Nov 23 '18 at 23:29






Consider adding the the question that you are arbitrarily limiting the keys to 20-bits each. DES has a 56-bit key in 8 bytes, the "parity" bit is generally ignored these days.
– zaph
Nov 23 '18 at 23:29














2 Answers
2






active

oldest

votes


















1














After reading your code, I have several suggestions to optimize it:




  1. Most important: Do not waste effort accessing the map twice if you can access just once: Instead of:



if (intermediateCipher.containsKey(temp)) {
byte k1 = intermediateCipher.get(temp);
...
}


... reduce it to:




byte k1 = intermediateCipher.get(temp);
if (k1!=null) {
...
}




  1. There is too much memory allocating within the loops, because it is useless to create a new ByteBuffer only for temporary operations and then discard it (too much GC overworking). If you are certain that the byte buffers used will have length 8 (or less), you can use a single buffer in the first loop:



    ByteBuffer tempBuffer=ByteBuffer.allocate(8);
    while (intermediateCipher.size() < Math.pow(2, 20)) {
    // Note: A call to rewind() must be done before each put/get operation on the buffer:
    byte key = generateDesKey();
    tempBuffer.rewind();
    tempBuffer.put(encrypt(key, plainText));
    tempBuffer.rewind();
    int mapKey=tempBuffer.getInt();
    tempBuffer.rewind();
    tempBuffer.put(key);
    tempBuffer.rewind();
    int mapValue=tempBuffer.getInt();
    intermediateCipher.put(mapKey, mapValue);
    }



In the second loop, a similar transformation could be done.




  1. As @Thilo suggested in a comment, it is always a good practice to pre-size your map in function of the expected maximum size. It shall go like this:

    Map<...> intermediateCipher=new HashMap<...>((int)(1.7d * expectedSize));


  2. Loop while (intermediateCipher.size() < Math.pow(2, 20)) shall be simplified to

    int len=Math.pow(2, 20);
    for (int i=0;i<len;i++)



Update




  1. If the call generateDesKey() returns the same on every iteration, you can set it before the loop.






share|improve this answer























  • I'm getting java.nio.BufferUnderflowException in line int mapKey = tempBuffer.put(encrypt(key, plainText)).getInt(); I did some research I found out that it means there are fewer than eight bytes remaining in this buffer, but how?
    – user8231110
    Nov 24 '18 at 16:07










  • Ups. My fault. Right: That's because the buffer must be rewinded before each write to ensure the data is written at the beginning, and yet rewinded again before each read to ensure the data is read from the beginning. See my update at points 2 and 5.
    – Little Santi
    Nov 24 '18 at 20:12










  • Since arr.getValue() and intermediateCipher.get(temp) are integers, I need to convert them into Byte? Have tried with the following: byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array(); int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt(); byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 24 '18 at 21:48










  • You need to convert them into byte, OK. And you used those formulae. And what did you get?
    – Little Santi
    Nov 25 '18 at 15:33










  • I am getting a nullpointer Exception on byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 25 '18 at 16:32



















0














Here are some things you can try to shorten running time.



First, switch from HashMap to TreeMap. When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries. However, TreeMap searching always runs in O(lg n).



Secondly, switch from Map<Integer, Integer> to Map<Integer, byte>. You only need to convert the Map keys to integers; you can leave the values as byte arrays, resulting in significantly fewer byte -> ByteBuffer -> int conversions.



Map<Integer, byte> intermediateCipher = new TreeMap<>();


and



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();
int encrypted = ByteBuffer.wrap(encrypt(key, plainText)).getInt();
intermediateCipher.put(encrypted, key);
}

int count = 0;
for (Entry<Integer, byte> arr : intermediateCipher.entrySet()) {
byte k2 = arr.getValue();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();

if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = intermediateCipher.get(temp);
if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}





share|improve this answer





















  • "When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries" Really? Wouldn't it just rehash with a larger number of buckets? (Might be a good idea to set the expected capacity up front to avoid doing too much of that).
    – Thilo
    Nov 23 '18 at 23:57












  • @Leo Aso, I have tried your suggestion and I have been waiting for approx. 20 mins without any result, unfortunately. I think it has something to do with the conversion from byte -> ByteBuffer -> int.
    – user8231110
    Nov 24 '18 at 0:15













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
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453669%2fhashmap-with-integers-as-key-and-value-takes-too-long-to-finish-work%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









1














After reading your code, I have several suggestions to optimize it:




  1. Most important: Do not waste effort accessing the map twice if you can access just once: Instead of:



if (intermediateCipher.containsKey(temp)) {
byte k1 = intermediateCipher.get(temp);
...
}


... reduce it to:




byte k1 = intermediateCipher.get(temp);
if (k1!=null) {
...
}




  1. There is too much memory allocating within the loops, because it is useless to create a new ByteBuffer only for temporary operations and then discard it (too much GC overworking). If you are certain that the byte buffers used will have length 8 (or less), you can use a single buffer in the first loop:



    ByteBuffer tempBuffer=ByteBuffer.allocate(8);
    while (intermediateCipher.size() < Math.pow(2, 20)) {
    // Note: A call to rewind() must be done before each put/get operation on the buffer:
    byte key = generateDesKey();
    tempBuffer.rewind();
    tempBuffer.put(encrypt(key, plainText));
    tempBuffer.rewind();
    int mapKey=tempBuffer.getInt();
    tempBuffer.rewind();
    tempBuffer.put(key);
    tempBuffer.rewind();
    int mapValue=tempBuffer.getInt();
    intermediateCipher.put(mapKey, mapValue);
    }



In the second loop, a similar transformation could be done.




  1. As @Thilo suggested in a comment, it is always a good practice to pre-size your map in function of the expected maximum size. It shall go like this:

    Map<...> intermediateCipher=new HashMap<...>((int)(1.7d * expectedSize));


  2. Loop while (intermediateCipher.size() < Math.pow(2, 20)) shall be simplified to

    int len=Math.pow(2, 20);
    for (int i=0;i<len;i++)



Update




  1. If the call generateDesKey() returns the same on every iteration, you can set it before the loop.






share|improve this answer























  • I'm getting java.nio.BufferUnderflowException in line int mapKey = tempBuffer.put(encrypt(key, plainText)).getInt(); I did some research I found out that it means there are fewer than eight bytes remaining in this buffer, but how?
    – user8231110
    Nov 24 '18 at 16:07










  • Ups. My fault. Right: That's because the buffer must be rewinded before each write to ensure the data is written at the beginning, and yet rewinded again before each read to ensure the data is read from the beginning. See my update at points 2 and 5.
    – Little Santi
    Nov 24 '18 at 20:12










  • Since arr.getValue() and intermediateCipher.get(temp) are integers, I need to convert them into Byte? Have tried with the following: byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array(); int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt(); byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 24 '18 at 21:48










  • You need to convert them into byte, OK. And you used those formulae. And what did you get?
    – Little Santi
    Nov 25 '18 at 15:33










  • I am getting a nullpointer Exception on byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 25 '18 at 16:32
















1














After reading your code, I have several suggestions to optimize it:




  1. Most important: Do not waste effort accessing the map twice if you can access just once: Instead of:



if (intermediateCipher.containsKey(temp)) {
byte k1 = intermediateCipher.get(temp);
...
}


... reduce it to:




byte k1 = intermediateCipher.get(temp);
if (k1!=null) {
...
}




  1. There is too much memory allocating within the loops, because it is useless to create a new ByteBuffer only for temporary operations and then discard it (too much GC overworking). If you are certain that the byte buffers used will have length 8 (or less), you can use a single buffer in the first loop:



    ByteBuffer tempBuffer=ByteBuffer.allocate(8);
    while (intermediateCipher.size() < Math.pow(2, 20)) {
    // Note: A call to rewind() must be done before each put/get operation on the buffer:
    byte key = generateDesKey();
    tempBuffer.rewind();
    tempBuffer.put(encrypt(key, plainText));
    tempBuffer.rewind();
    int mapKey=tempBuffer.getInt();
    tempBuffer.rewind();
    tempBuffer.put(key);
    tempBuffer.rewind();
    int mapValue=tempBuffer.getInt();
    intermediateCipher.put(mapKey, mapValue);
    }



In the second loop, a similar transformation could be done.




  1. As @Thilo suggested in a comment, it is always a good practice to pre-size your map in function of the expected maximum size. It shall go like this:

    Map<...> intermediateCipher=new HashMap<...>((int)(1.7d * expectedSize));


  2. Loop while (intermediateCipher.size() < Math.pow(2, 20)) shall be simplified to

    int len=Math.pow(2, 20);
    for (int i=0;i<len;i++)



Update




  1. If the call generateDesKey() returns the same on every iteration, you can set it before the loop.






share|improve this answer























  • I'm getting java.nio.BufferUnderflowException in line int mapKey = tempBuffer.put(encrypt(key, plainText)).getInt(); I did some research I found out that it means there are fewer than eight bytes remaining in this buffer, but how?
    – user8231110
    Nov 24 '18 at 16:07










  • Ups. My fault. Right: That's because the buffer must be rewinded before each write to ensure the data is written at the beginning, and yet rewinded again before each read to ensure the data is read from the beginning. See my update at points 2 and 5.
    – Little Santi
    Nov 24 '18 at 20:12










  • Since arr.getValue() and intermediateCipher.get(temp) are integers, I need to convert them into Byte? Have tried with the following: byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array(); int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt(); byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 24 '18 at 21:48










  • You need to convert them into byte, OK. And you used those formulae. And what did you get?
    – Little Santi
    Nov 25 '18 at 15:33










  • I am getting a nullpointer Exception on byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 25 '18 at 16:32














1












1








1






After reading your code, I have several suggestions to optimize it:




  1. Most important: Do not waste effort accessing the map twice if you can access just once: Instead of:



if (intermediateCipher.containsKey(temp)) {
byte k1 = intermediateCipher.get(temp);
...
}


... reduce it to:




byte k1 = intermediateCipher.get(temp);
if (k1!=null) {
...
}




  1. There is too much memory allocating within the loops, because it is useless to create a new ByteBuffer only for temporary operations and then discard it (too much GC overworking). If you are certain that the byte buffers used will have length 8 (or less), you can use a single buffer in the first loop:



    ByteBuffer tempBuffer=ByteBuffer.allocate(8);
    while (intermediateCipher.size() < Math.pow(2, 20)) {
    // Note: A call to rewind() must be done before each put/get operation on the buffer:
    byte key = generateDesKey();
    tempBuffer.rewind();
    tempBuffer.put(encrypt(key, plainText));
    tempBuffer.rewind();
    int mapKey=tempBuffer.getInt();
    tempBuffer.rewind();
    tempBuffer.put(key);
    tempBuffer.rewind();
    int mapValue=tempBuffer.getInt();
    intermediateCipher.put(mapKey, mapValue);
    }



In the second loop, a similar transformation could be done.




  1. As @Thilo suggested in a comment, it is always a good practice to pre-size your map in function of the expected maximum size. It shall go like this:

    Map<...> intermediateCipher=new HashMap<...>((int)(1.7d * expectedSize));


  2. Loop while (intermediateCipher.size() < Math.pow(2, 20)) shall be simplified to

    int len=Math.pow(2, 20);
    for (int i=0;i<len;i++)



Update




  1. If the call generateDesKey() returns the same on every iteration, you can set it before the loop.






share|improve this answer














After reading your code, I have several suggestions to optimize it:




  1. Most important: Do not waste effort accessing the map twice if you can access just once: Instead of:



if (intermediateCipher.containsKey(temp)) {
byte k1 = intermediateCipher.get(temp);
...
}


... reduce it to:




byte k1 = intermediateCipher.get(temp);
if (k1!=null) {
...
}




  1. There is too much memory allocating within the loops, because it is useless to create a new ByteBuffer only for temporary operations and then discard it (too much GC overworking). If you are certain that the byte buffers used will have length 8 (or less), you can use a single buffer in the first loop:



    ByteBuffer tempBuffer=ByteBuffer.allocate(8);
    while (intermediateCipher.size() < Math.pow(2, 20)) {
    // Note: A call to rewind() must be done before each put/get operation on the buffer:
    byte key = generateDesKey();
    tempBuffer.rewind();
    tempBuffer.put(encrypt(key, plainText));
    tempBuffer.rewind();
    int mapKey=tempBuffer.getInt();
    tempBuffer.rewind();
    tempBuffer.put(key);
    tempBuffer.rewind();
    int mapValue=tempBuffer.getInt();
    intermediateCipher.put(mapKey, mapValue);
    }



In the second loop, a similar transformation could be done.




  1. As @Thilo suggested in a comment, it is always a good practice to pre-size your map in function of the expected maximum size. It shall go like this:

    Map<...> intermediateCipher=new HashMap<...>((int)(1.7d * expectedSize));


  2. Loop while (intermediateCipher.size() < Math.pow(2, 20)) shall be simplified to

    int len=Math.pow(2, 20);
    for (int i=0;i<len;i++)



Update




  1. If the call generateDesKey() returns the same on every iteration, you can set it before the loop.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 24 '18 at 20:11

























answered Nov 24 '18 at 1:03









Little SantiLittle Santi

6,76321032




6,76321032












  • I'm getting java.nio.BufferUnderflowException in line int mapKey = tempBuffer.put(encrypt(key, plainText)).getInt(); I did some research I found out that it means there are fewer than eight bytes remaining in this buffer, but how?
    – user8231110
    Nov 24 '18 at 16:07










  • Ups. My fault. Right: That's because the buffer must be rewinded before each write to ensure the data is written at the beginning, and yet rewinded again before each read to ensure the data is read from the beginning. See my update at points 2 and 5.
    – Little Santi
    Nov 24 '18 at 20:12










  • Since arr.getValue() and intermediateCipher.get(temp) are integers, I need to convert them into Byte? Have tried with the following: byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array(); int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt(); byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 24 '18 at 21:48










  • You need to convert them into byte, OK. And you used those formulae. And what did you get?
    – Little Santi
    Nov 25 '18 at 15:33










  • I am getting a nullpointer Exception on byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 25 '18 at 16:32


















  • I'm getting java.nio.BufferUnderflowException in line int mapKey = tempBuffer.put(encrypt(key, plainText)).getInt(); I did some research I found out that it means there are fewer than eight bytes remaining in this buffer, but how?
    – user8231110
    Nov 24 '18 at 16:07










  • Ups. My fault. Right: That's because the buffer must be rewinded before each write to ensure the data is written at the beginning, and yet rewinded again before each read to ensure the data is read from the beginning. See my update at points 2 and 5.
    – Little Santi
    Nov 24 '18 at 20:12










  • Since arr.getValue() and intermediateCipher.get(temp) are integers, I need to convert them into Byte? Have tried with the following: byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array(); int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt(); byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 24 '18 at 21:48










  • You need to convert them into byte, OK. And you used those formulae. And what did you get?
    – Little Santi
    Nov 25 '18 at 15:33










  • I am getting a nullpointer Exception on byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
    – user8231110
    Nov 25 '18 at 16:32
















I'm getting java.nio.BufferUnderflowException in line int mapKey = tempBuffer.put(encrypt(key, plainText)).getInt(); I did some research I found out that it means there are fewer than eight bytes remaining in this buffer, but how?
– user8231110
Nov 24 '18 at 16:07




I'm getting java.nio.BufferUnderflowException in line int mapKey = tempBuffer.put(encrypt(key, plainText)).getInt(); I did some research I found out that it means there are fewer than eight bytes remaining in this buffer, but how?
– user8231110
Nov 24 '18 at 16:07












Ups. My fault. Right: That's because the buffer must be rewinded before each write to ensure the data is written at the beginning, and yet rewinded again before each read to ensure the data is read from the beginning. See my update at points 2 and 5.
– Little Santi
Nov 24 '18 at 20:12




Ups. My fault. Right: That's because the buffer must be rewinded before each write to ensure the data is written at the beginning, and yet rewinded again before each read to ensure the data is read from the beginning. See my update at points 2 and 5.
– Little Santi
Nov 24 '18 at 20:12












Since arr.getValue() and intermediateCipher.get(temp) are integers, I need to convert them into Byte? Have tried with the following: byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array(); int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt(); byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
– user8231110
Nov 24 '18 at 21:48




Since arr.getValue() and intermediateCipher.get(temp) are integers, I need to convert them into Byte? Have tried with the following: byte k2 = ByteBuffer.allocate(8).putInt(arr.getValue()).array(); int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt(); byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
– user8231110
Nov 24 '18 at 21:48












You need to convert them into byte, OK. And you used those formulae. And what did you get?
– Little Santi
Nov 25 '18 at 15:33




You need to convert them into byte, OK. And you used those formulae. And what did you get?
– Little Santi
Nov 25 '18 at 15:33












I am getting a nullpointer Exception on byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
– user8231110
Nov 25 '18 at 16:32




I am getting a nullpointer Exception on byte k1 = ByteBuffer.allocate(8).putInt(intermediateCipher.get(temp)).array();
– user8231110
Nov 25 '18 at 16:32













0














Here are some things you can try to shorten running time.



First, switch from HashMap to TreeMap. When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries. However, TreeMap searching always runs in O(lg n).



Secondly, switch from Map<Integer, Integer> to Map<Integer, byte>. You only need to convert the Map keys to integers; you can leave the values as byte arrays, resulting in significantly fewer byte -> ByteBuffer -> int conversions.



Map<Integer, byte> intermediateCipher = new TreeMap<>();


and



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();
int encrypted = ByteBuffer.wrap(encrypt(key, plainText)).getInt();
intermediateCipher.put(encrypted, key);
}

int count = 0;
for (Entry<Integer, byte> arr : intermediateCipher.entrySet()) {
byte k2 = arr.getValue();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();

if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = intermediateCipher.get(temp);
if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}





share|improve this answer





















  • "When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries" Really? Wouldn't it just rehash with a larger number of buckets? (Might be a good idea to set the expected capacity up front to avoid doing too much of that).
    – Thilo
    Nov 23 '18 at 23:57












  • @Leo Aso, I have tried your suggestion and I have been waiting for approx. 20 mins without any result, unfortunately. I think it has something to do with the conversion from byte -> ByteBuffer -> int.
    – user8231110
    Nov 24 '18 at 0:15


















0














Here are some things you can try to shorten running time.



First, switch from HashMap to TreeMap. When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries. However, TreeMap searching always runs in O(lg n).



Secondly, switch from Map<Integer, Integer> to Map<Integer, byte>. You only need to convert the Map keys to integers; you can leave the values as byte arrays, resulting in significantly fewer byte -> ByteBuffer -> int conversions.



Map<Integer, byte> intermediateCipher = new TreeMap<>();


and



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();
int encrypted = ByteBuffer.wrap(encrypt(key, plainText)).getInt();
intermediateCipher.put(encrypted, key);
}

int count = 0;
for (Entry<Integer, byte> arr : intermediateCipher.entrySet()) {
byte k2 = arr.getValue();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();

if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = intermediateCipher.get(temp);
if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}





share|improve this answer





















  • "When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries" Really? Wouldn't it just rehash with a larger number of buckets? (Might be a good idea to set the expected capacity up front to avoid doing too much of that).
    – Thilo
    Nov 23 '18 at 23:57












  • @Leo Aso, I have tried your suggestion and I have been waiting for approx. 20 mins without any result, unfortunately. I think it has something to do with the conversion from byte -> ByteBuffer -> int.
    – user8231110
    Nov 24 '18 at 0:15
















0












0








0






Here are some things you can try to shorten running time.



First, switch from HashMap to TreeMap. When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries. However, TreeMap searching always runs in O(lg n).



Secondly, switch from Map<Integer, Integer> to Map<Integer, byte>. You only need to convert the Map keys to integers; you can leave the values as byte arrays, resulting in significantly fewer byte -> ByteBuffer -> int conversions.



Map<Integer, byte> intermediateCipher = new TreeMap<>();


and



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();
int encrypted = ByteBuffer.wrap(encrypt(key, plainText)).getInt();
intermediateCipher.put(encrypted, key);
}

int count = 0;
for (Entry<Integer, byte> arr : intermediateCipher.entrySet()) {
byte k2 = arr.getValue();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();

if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = intermediateCipher.get(temp);
if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}





share|improve this answer












Here are some things you can try to shorten running time.



First, switch from HashMap to TreeMap. When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries. However, TreeMap searching always runs in O(lg n).



Secondly, switch from Map<Integer, Integer> to Map<Integer, byte>. You only need to convert the Map keys to integers; you can leave the values as byte arrays, resulting in significantly fewer byte -> ByteBuffer -> int conversions.



Map<Integer, byte> intermediateCipher = new TreeMap<>();


and



while (intermediateCipher.size() < Math.pow(2, 20)) {
byte key = generateDesKey();
int encrypted = ByteBuffer.wrap(encrypt(key, plainText)).getInt();
intermediateCipher.put(encrypted, key);
}

int count = 0;
for (Entry<Integer, byte> arr : intermediateCipher.entrySet()) {
byte k2 = arr.getValue();
int temp = ByteBuffer.wrap(decrypt(k2, cipherText2)).getInt();

if (intermediateCipher.containsKey(temp)) {
count++;
byte k1 = intermediateCipher.get(temp);
if (encrypt(k2, encrypt(k1, plainText)) == cipherText2) {
System.out.println("Key is " + k1 + " " + k2);
}
}
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 23 '18 at 23:51









Leo AsoLeo Aso

4,82111028




4,82111028












  • "When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries" Really? Wouldn't it just rehash with a larger number of buckets? (Might be a good idea to set the expected capacity up front to avoid doing too much of that).
    – Thilo
    Nov 23 '18 at 23:57












  • @Leo Aso, I have tried your suggestion and I have been waiting for approx. 20 mins without any result, unfortunately. I think it has something to do with the conversion from byte -> ByteBuffer -> int.
    – user8231110
    Nov 24 '18 at 0:15




















  • "When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries" Really? Wouldn't it just rehash with a larger number of buckets? (Might be a good idea to set the expected capacity up front to avoid doing too much of that).
    – Thilo
    Nov 23 '18 at 23:57












  • @Leo Aso, I have tried your suggestion and I have been waiting for approx. 20 mins without any result, unfortunately. I think it has something to do with the conversion from byte -> ByteBuffer -> int.
    – user8231110
    Nov 24 '18 at 0:15


















"When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries" Really? Wouldn't it just rehash with a larger number of buckets? (Might be a good idea to set the expected capacity up front to avoid doing too much of that).
– Thilo
Nov 23 '18 at 23:57






"When a HashMap becomes too large, like 2^20, searching in the worst case is expected to go from O(1) to O(n), because all slots in the hash table are full with a large number of entries" Really? Wouldn't it just rehash with a larger number of buckets? (Might be a good idea to set the expected capacity up front to avoid doing too much of that).
– Thilo
Nov 23 '18 at 23:57














@Leo Aso, I have tried your suggestion and I have been waiting for approx. 20 mins without any result, unfortunately. I think it has something to do with the conversion from byte -> ByteBuffer -> int.
– user8231110
Nov 24 '18 at 0:15






@Leo Aso, I have tried your suggestion and I have been waiting for approx. 20 mins without any result, unfortunately. I think it has something to do with the conversion from byte -> ByteBuffer -> int.
– user8231110
Nov 24 '18 at 0:15




















draft saved

draft discarded




















































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.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453669%2fhashmap-with-integers-as-key-and-value-takes-too-long-to-finish-work%23new-answer', 'question_page');
}
);

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







Popular posts from this blog

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

Calculate evaluation metrics using cross_val_predict sklearn

Insert data from modal to MySQL (multiple modal on website)