BigIntegers的Xor大小

时间:2018-09-10 11:01:07

标签: java size byte biginteger xor

我的程序使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的情况下进行填充,但是我不知道该怎么做。

2 个答案:

答案 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

那可能既好又简单。