Я пытаюсь преобразовать этот алгоритм KeeLoq из C в Java, но мой метод дешифрования, похоже, использует слишком много памяти для Java BigInteger. Мне было интересно, была ли эквивалентная операция, которая будет работать с Java BigInteger.
Исходные вычисления для переменных index и bitVal прокомментированы ниже.
Исходный исходный код, который я использую в качестве примера, можно найти здесь: https://github.com/franksmicro/Arduino/blob/master/libraries/Keeloq/Keeloq.cpp
Любая помощь приветствуется.
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());
}
}
Редактировать: Я думаю, что понял! (или, по крайней мере, часть его)
Проблема, по крайней мере, частично в этой строке: (сначала ошибочная строка, извините)
int intIndex = (int) index;
Когда index
становится достаточно большим, (int) index
будет переполняться до большого отрицательного значения. Угадайте, что произойдет, когда вы передадите это в bitRead()
?
Теперь, почему это переполнение происходит в Decrypt()
а не в Encrypt()
, я не уверен... Я посмотрю позже, как только получу немного отдохнуть, но, надеюсь, это начало.
Вы можете увеличить доступное пространство памяти, запустив программу с помощью флага -Xmx. Например, для работы с максимальным объемом 4 гигабайта вы должны использовать -Xmx 4G
В Eclipse это можно сделать, щелкнув правой кнопкой мыши по файлу, выбрав "Свойства" - "Параметры запуска/отладки" → щелкните по конфигурации запуска → "Редактировать" → "Вкладки аргументов" → "Параметры VM" → введите флаг.
Если у вас закончилась нехватка памяти с классом Java BigInteger
, я не уверен, что использование любой другой библиотеки с произвольной точностью приведет вас к очень далеко, если числа на самом деле станут такими большими.
BigIntegers
становятся достаточно большими, что напечатанные расшифрованные индексы переполняются ...