我的程序使bitLength为255的两个随机BigInteger。然后对这两个BigInteger进行异或。
问题是:由于Big Integers的大小极小,因此如果首位为0,则此xor的大小可以小于255。我需要将其为32字节,因此介于248和256位之间。
这是我的代码:
public class test {
public static void main(String[] args) throws Exception {
SecureRandom random;
BigInteger randomBigInteger1;
byte[] randomBytes;
do {
random = new SecureRandom();
randomBytes = new byte[32];
random.nextBytes(randomBytes);
randomBigInteger1 = new BigInteger(randomBytes);
}while(randomBigInteger1.bitLength() < 255);
BigInteger randomBigInteger2;
do {
random = new SecureRandom();
randomBytes = new byte[32];
random.nextBytes(randomBytes);
randomBigInteger2 = new BigInteger(randomBytes);
}while(randomBigInteger2.bitLength() < 255);
BigInteger finalXor = randomBigInteger1.xor(randomBigInteger2);
System.out.println(finalXor.bitLength());
byte[] key = finalXor.toByteArray();
System.out.println(key.length);
}
}
问题是:即使finalXor小于248位,如何确保密钥始终为32个字节? (我想我可以用0位填充,但我不知道如何。)
示例:假设我的BigIntegers是:
1111011010101101 ........ 11011100011
1111011001100111 ............. 01110011010
那么finalXor将是:
0000000011001010 ............. 10101111001
这8个高位全为空,因此finalXor长度仅为255-8 = 247位长。当我使byte []键时,它将是31bytes而不是32。 我需要它是32个字节。仍然是好人。
这就是为什么我说我认为应该在所有“缺失的较高位”都为0的情况下进行填充,但是我不知道该怎么做。
答案 0 :(得分:0)
填充为0是一种选择,我找到了一种方法:
if(key.length != 32) {
byte[] finalKey= new byte[32];
byte a = Byte.parseByte("00000000", 2);
for(int i =0; i<key.length; i++)
finalKey[i] = key[i];
for (int i = key.length ; i<32 ; i++)
finalKey[i] = a;
key = finalKey;
}
它需要一个循环和另一个字节数组,因为出于某种原因key [31]抛出ArrayOutOfBound异常,但是它可以工作...如果有人可以改进它,请随时这样做。
编辑:OldCurmudgeon的更好解决方案:
key = Arrays.copyOf(key, 32);
它将自动用0填充高位。
答案 1 :(得分:0)
ISTM,避免 BigInteger和 xoring 字节数组可以直接解决您的多个问题。必要时会有填充,您总会得到一个32字节的数组。
如果确保高位字节(由于大尾数而在索引0处)不相同,则将始终具有248-255位值。
如果需要little-endiannes,则索引31处的字节一定不能为0且必须不同。我假设使用big-endian,因为这也是BigInteger在原始代码中返回的内容。
public class test
{
public static void main(String[] args) throws Exception
{
SecureRandom random = new SecureRandom();
// make "left" operand
byte[] randomBytesLeft = new bytes[32];
random.nextBytes(randomBytesLeft);
// make "right" operand
byte[] randomBytesRight = new byte[32];
do
{
random.nextBytes(randomBytesRight);
} while (randomBytesRight[0] == randomBytesLeft[0]); // or [31] for little-endian
// "xor" both operands
byte[] key = new byte[32];
for (int i = 0; i < 32; i++)
{
key[i] = randomBytesLeft[i] ^ randomBytesRight[i];
}
// if you really need a BigInteger:
// BigInteger finalXor = new BigInteger(key);
System.out.println(key.length);
}
}
FWIW,在我看来,您可以完全省略 xoring ,然后执行以下操作:
byte[] key = new byte[32];
do
{
random.nextBytes(key);
} while (key[0] == 0); // or key[31] for little-endian
那可能既好又简单。