为了账号安全,请及时绑定邮箱和手机立即绑定

BigInteger 异或的大小

BigInteger 异或的大小

心有法竹 2021-09-12 15:32:26
我的程序生成两个随机 BigInteger,bitLength 为 255。然后它生成这两个 BigInteger 的异或。问题是:由于大整数的大小是最小的,如果第一个位是 0,这个异或的大小可以小于 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........110111000111111011001100111.................01110011010那么 finalXor 将是:0000000011001010................10101111001高 8 位全为空,因此最终异或长度仅为 255-8 = 247 位长。当我制作 byte[] 键时,它将是 31 字节而不是 32。我需要它是 32 字节。并且仍然是好的异或。这就是为什么我说我认为我应该做一个填充,其中所有“缺少的高位”都是 0,但我不知道该怎么做。
查看完整描述

2 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

ISTM是避免BigInteger和异或直接在字节数组可以同时解决几个你的问题。在必要的地方有填充,你总是得到一个 32 字节的数组。


如果您确保顶部字节(由于大端字节序在索引 0 处)不相同,您将始终拥有 248-255 位值。


如果需要小端字节序,则索引 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

那可能同样好,更简单。


查看完整回答
反对 回复 2021-09-12
?
狐的传说

TA贡献1804条经验 获得超3个赞

填充 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 填充高位。


查看完整回答
反对 回复 2021-09-12
  • 2 回答
  • 0 关注
  • 147 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信