我试图使用“在中间遇见”来打破对称加密。攻击。为此,我需要存储2 ** 32个整数 - 整数对。我将映射从4字节的密文存储到4字节密钥。
起初我尝试使用数组,但后来我意识到你不能在java中有这么大的数组(最大大小由Integer.MAX_VALUE
绑定)。
现在我正在使用HashMap,但是当地图变大时,即使用-Xmx8192M
将最大内存增加到8GB,这也会变得太慢。
什么是超大型HashMap的有效替代方案?
这是我目前用来填充我的hashmap的代码:
HashMap<Integer, Integer> map = new HashMap<>(Integer.MAX_VALUE);
// Loop until integer overflow
for (int k = 1; k != 0; k++)
map.put(encrypt_left(c, k), k);
即使让它运行了几个小时,我还没有看到这段代码完成。进度记录显示前22 ** 24值是在22秒内创建的,但随后性能会迅速下降。
答案 0 :(得分:3)
我存储从4字节密文到4字节密钥的映射。
方便地,4个字节是int
。如您所见,数组大小受Integer.MAX_VALUE
限制。这表明你可以使用一个数组 - 但这是一个小小的挂断。整数已签名,但数组只允许值> = 0。
所以你创建了两个数组:一个用于正的cyphertexts,一个用于负的cyphertexts。然后你只需要确保你已经为JVM提供了足够的堆。
那是多少堆?
4个字节* Integer.MAX_VALUE
* 2个阵列
= 17179869176字节
= ~16.0千兆字节。
答案 1 :(得分:2)
根据@MattBall的建议,我实现了自己的BigArray
,它由4个独立的数组组成一个32位长的数组。
在没有建议的JVM参数的情况下运行它将导致OutOfMemoryError。将此与建议的JVM参数一起使用但RAM太少可能会导致计算机崩溃。
/**
* Array that holds 2**32 integers, Implemented as four 30-bit arrays.
* <p>
* Requires 16 GB RAM solely for the array allocation.
* <p>
* Example JVM Arguments: <code>-Xmx22000M -Xms17000M</code>
* <p>
* This sets the max memory to 22,000 MB and the initial memory to 17,000 MB
* <p>
* WARNING: don't use these settings if your machine does not have this much RAM.
*
* @author popovitsj
*/
public class BigArray
{
private int[] a_00= new int[1 << 30];
private int[] a_01 = new int[1 << 30];
private int[] a_10 = new int[1 << 30];
private int[] a_11 = new int[1 << 30];
private static final int A_00 = 0;
private static final int A_01 = 1 << 30;
private static final int A_10 = 1 << 31;
private static final int A_11 = 3 << 30;
private static final int A_30 = A_01 - 1;
public void set(int index, int value)
{
getArray(index)[index & A_30] = value;
}
public int get(int index)
{
return getArray(index)[index & A_30];
}
private int[] getArray(int index)
{
switch (index & A_11)
{
case (A_00):
return a_00;
case (A_01):
return a_01;
case (A_10):
return a_10;
default:
return a_11;
}
}
}
答案 2 :(得分:1)
在构建彩虹表时,请考虑您要生成的数据大小。还要考虑一个事实,即没有大量的RAM就可以解决这个问题。这是通过使用文件而不是全部放入内存来完成的。通常,您构建的文件大小适合您的文件缓冲区。例如4096字节或8192字节。如果你得到一个密钥,你只需将其除以文件缓冲区的大小,加载文件并查看mod x位置。 棘手的部分是您需要铺设加密数据,而不是密钥。因此,您从虚拟文件开始,并将密钥数据写入加密数据的位置。
所以,让我们说,你的密钥是1026,加密数据是126.写入1026的flke是0.rbt,因为126 * 4字节/ 4096 = 0.位置是126 * 4字节。 当然,你需要nio类。
答案 3 :(得分:1)
这是大数据问题,在这种情况下,它更像是一个大内存问题。计算应该在内存中进行,以提高性能。使用Hazelcast分发HashMap
。它非常易于使用且性能非常高。
您可以使用2台或更多台机器来解决问题。
样本用法:
HazelcastInstance hzInstance = Hazelcast.newHazelcastInstance();
Map<Integer, Integer> map = hzInstance.getMap("map1");
map.put(x,y);
..