Java 以整数作为键和值的HashMap花费的时间太长,无法完成工作
我正在为2DES的中间相遇攻击工作。我已经实现了DES加密/解密,它正在工作。我试图实现这一点的方法是,在for循环中,将中间密码存储为HashMap的键,将可能的键存储为HashMap的值。两者都是整数-以字节[]开始,但发现键不能是数组。然而,在这个for循环中,我还想确保可能的键是唯一的,即我有一个while循环,它确保HashMap的大小是2^20,只有DES键的20位是有效的。之后,我尝试通过使用foreach迭代HashMap来查找具有匹配中间密文的密钥,并将加密中的每个中间密文与解密中的中间密文进行比较 但是,我找不到比赛,因为比赛需要很长时间才能完成。我已经等了20分钟,没有结果Java 以整数作为键和值的HashMap花费的时间太长,无法完成工作,java,hashmap,Java,Hashmap,我正在为2DES的中间相遇攻击工作。我已经实现了DES加密/解密,它正在工作。我试图实现这一点的方法是,在for循环中,将中间密码存储为HashMap的键,将可能的键存储为HashMap的值。两者都是整数-以字节[]开始,但发现键不能是数组。然而,在这个for循环中,我还想确保可能的键是唯一的,即我有一个while循环,它确保HashMap的大小是2^20,只有DES键的20位是有效的。之后,我尝试通过使用foreach迭代HashMap来查找具有匹配中间密文的密钥,并将加密中的每个中间密文与解
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);
}
}
}
中间码是我的HashMap
明文是8字节的字节[],cipherText2是明文上2DES的加密结果,GeneratedSkey是生成64位的方法,其中跳过奇偶校验位以确保20位有效,并将位转换为字节[]由于DES要求以下是一些您可以尝试缩短运行时间的方法
首先,从HashMap切换到TreeMap。当HashMap变得太大时,如2^20,最坏情况下的搜索将从O1转到On,因为哈希表中的所有插槽都充满了大量条目。然而,树映射搜索总是在Olg n中运行 其次,从地图切换到地图。您只需要将映射键转换为整数;您可以将值保留为字节数组,从而大大减少字节[]->ByteBuffer->int转换
Map<Integer, byte[]> intermediateCipher = new TreeMap<>();
及
在阅读了您的代码之后,我有几个建议来优化它: 最重要的是:如果您只能访问一次,请不要浪费时间访问地图两次:而不是: 在第二个循环中,可以进行类似的转换 正如@Thilo在一篇评论中所建议的,根据预期的最大尺寸预先调整地图的尺寸始终是一种好的做法。应该是这样的: Map intermediateCipher=new HashMapint1.7d*expectedSize; 循环,而intermediateCipher.size
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);
}
}
}
if (intermediateCipher.containsKey(temp)) {
byte[] k1 = intermediateCipher.get(temp);
...
}
byte[] k1 = intermediateCipher.get(temp);
if (k1!=null) {
...
}
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);
}