简体   繁体   English

Java BigInteger内存不足,可能是由于长时间转换

[英]Java BigInteger Out of memory, possibly from long conversion

I'm trying to convert this KeeLoq algorithm from C into Java but my decryption method seems to use too much memory for Java's BigInteger. 我正在尝试将此KeeLoq算法从C转换为Java,但是我的解密方法似乎为Java的BigInteger使用了过多的内存。 I was wondering if there was an equivalent operation that would work with Java's BigInteger. 我想知道是否存在与Java的BigInteger一起使用的等效操作。

The original calculations for the index and bitVal variables are commented out below. index和bitVal变量的原始计算在下面注释。

The original source code I'm using as an example can be found here: https://github.com/franksmicro/Arduino/blob/master/libraries/Keeloq/Keeloq.cpp 我用作示例的原始源代码可以在这里找到: https : //github.com/franksmicro/Arduino/blob/master/libraries/Keeloq/Keeloq.cpp

Any help would be much appreciated. 任何帮助将非常感激。

package keeloq;

/**
 *
 * @author 
 */
import java.math.BigInteger;

public class KeeLoq {

    BigInteger _keyHigh, _keyLow, keyHigh, keyLow;
    int KeeLoq_code = 0x3A5C742E;
    BigInteger KeeLoq_NLF = new BigInteger(Integer.toString(KeeLoq_code));

    public KeeLoq() {
    }

    public KeeLoq(BigInteger keyHigh, BigInteger keyLow) {
        _keyHigh = keyHigh;
        _keyLow = keyLow;
    }

    public BigInteger bitRead(BigInteger x, int n) {
        BigInteger temp = x.shiftRight(n);
        return temp;
    }

    public BigInteger multiplyBig(BigInteger x, BigInteger n) {
        BigInteger temp = x.multiply(n);
        return temp;
    }

    public BigInteger Encrypt(BigInteger data) {
        BigInteger x = data;
        int keyBitNo;
        long index;
        long position1, position2, position3, position4, position5;
        BigInteger keyBitVal, bitVal;
        BigInteger b1, b2, b3, b4, b5;

        for (int r = 0; r < 528; r++) {
            keyBitNo = r & 63;
            if (keyBitNo < 32) {
                keyBitVal = bitRead(_keyLow, keyBitNo);
            } else {
                keyBitVal = bitRead(_keyHigh, keyBitNo - 32);
            }

            position1 = bitRead(x, 1).longValue() * 1;
            position2 = bitRead(x, 9).longValue() * 2;
            position3 = bitRead(x, 20).longValue() * 4;
            position4 = bitRead(x, 26).longValue() * 8;
            position5 = bitRead(x, 31).longValue() * 16;

            index = position1 + position2 + position3 + position4 + position5;
            System.out.println("the encrypted index is " + index);

            b1 = bitRead(x, 0);
            b2 = bitRead(x, 16);
            int intIndex = (int) index;
            b3 = bitRead(KeeLoq_NLF, intIndex);
            b4 = keyBitVal;

            bitVal = b1.xor(b2).xor(b3).xor(b4);
            BigInteger tempx = x.shiftRight(1);
            x = tempx.xor(bitVal);
                        //bitVal = bitRead(x,0) ^ bitRead(x, 16) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal;
            //x = (x>>1) ^ bitVal<<31;
        }
        return x;
    }

    BigInteger Decrypt(BigInteger data) {
        BigInteger x = data;
        int keyBitNo;
        long index;
        long position1, position2, position3, position4, position5;
        BigInteger keyBitVal, bitVal;
        BigInteger b1, b2, b3, b4, b5;

        for (int r = 0; r < 528; r++) {
            keyBitNo = (15 - r) & 63;
            if (keyBitNo < 32) {
                keyBitVal = bitRead(_keyLow, keyBitNo);
            } else {
                keyBitVal = bitRead(_keyHigh, keyBitNo - 32);
            }

            position1 = bitRead(x, 0).longValue() * 1;
            position2 = bitRead(x, 8).longValue() * 2;
            position3 = bitRead(x, 19).longValue() * 4;
            position4 = bitRead(x, 25).longValue() * 8;
            position5 = bitRead(x, 30).longValue() * 16;

            index = position1 + position2 + position3 + position4 + position5;

            System.out.println("The Decrypted index is " + index);

            b1 = bitRead(x, 31);
            b2 = bitRead(x, 15);
            int intIndex = (int) index;
            b3 = bitRead(KeeLoq_NLF, intIndex);
            b4 = keyBitVal;

            bitVal = b1.xor(b2).xor(b3).xor(b4);
            BigInteger tempx = x.shiftLeft(1);
            x = tempx.xor(bitVal);


            //index = 1 * bitRead(x,0) + 2 * bitRead(x,8) + 4 * bitRead(x,19) + 8 * bitRead(x,25) + 16 * bitRead(x,30);
            // bitVal = bitRead(x,31) ^ bitRead(x, 15) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal;
            //   x = (x<<1) ^ bitVal;


        }
        return x;
    }

    public static void main(String[] args) {
        BigInteger highKey = new BigInteger(Integer.toString(66));
        BigInteger lowKey = new BigInteger(Integer.toString(35));
        KeeLoq KeeLoq_file = new KeeLoq(highKey, lowKey);
        System.out.println("The KeeLoq Code is " + KeeLoq_file.KeeLoq_code);
        BigInteger EncryptedBigInt = KeeLoq_file.Encrypt(KeeLoq_file.KeeLoq_NLF);
        System.out.println("The Encrypted BigIntegerValue is " + EncryptedBigInt);
        System.out.println("The Encrypted integer value is " + EncryptedBigInt.intValue());
        BigInteger DecryptedBigInt = KeeLoq_file.Decrypt(EncryptedBigInt);
        System.out.println("The Decrypted BigIntegerValue is " + DecryptedBigInt);
        System.out.println("The Decrypted integer value is " + DecryptedBigInt.intValue());
    }

}

Edit: I think I got it! 编辑:我想我明白了! (or at least part of it) (或至少一部分)

The issue is at least partially in this line: (got the wrong line at first, sorry) 问题至少部分在此行中:(首先错了一行,对不起)

 int intIndex = (int) index;

When index gets large enough, (int) index will overflow to a large negative value. index足够大时, (int) index将溢出到较大的负值。 Guess what happens when you pass that into bitRead() ? 猜猜当您将其传递给bitRead()时会发生什么?

Now, why this overflow happens in Decrypt() and not in Encrypt() , I'm not sure... I'll look later once I get some more rest, but hopefully this is a start. 现在,为什么这种溢出发生在Decrypt()而不是Encrypt() ,我不确定...等更多的休息后再看,但希望这是一个开始。

You can increase the memory space available by running the program with the -Xmx flag. 您可以通过使用-Xmx标志运行程序来增加可用的内存空间。 For example, to run with max 4 gigabytes of ram you'd use -Xmx4G 例如,要以最大4 GB的内存运行,您可以使用-Xmx4G

In Eclipse, this can by set by right-clicking on the file, going to Properties --> Run/Debug Settings --> click on the launch configuration --> Edit --> Arguments tab --> VM arguments --> type in the flag. 在Eclipse中,可以通过右键单击文件进行设置,方法是转到“属性”->“运行/调试设置”->单击启动配置->“编辑”->“参数”选项卡->“ VM参数”->输入标志。

If you're running out of memory with Java's BigInteger class, I'm not certain that using any other arbitrary-precision library would get you very far if the numbers actually get that large. 如果Java的BigInteger类用尽了内存,我不确定如果数字真的那么大,那么使用任何其他任意精度库会使您走得很远。

You have a bug in the bitRead function: Here is the documentation from arduino: 您在bitRead函数中有一个错误:这是arduino的文档:

Syntax bitRead(x, n) 语法bitRead(x,n)

Parameters x: the number from which to read 参数x:要读取的数字

n: which bit to read, starting at 0 for the least-significant (rightmost) bit n:要读取的位,从最低有效(最右边)位的0开始

Returns the value of the bit (0 or 1). 返回该位的值(0或1)。

Your function returns larger values like 3824712. 您的函数将返回较大的值,例如3824712。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM