2017-02-03 23 views
0

при переносе старого проекта с C# на Java я наткнулся на эту функцию:C# BigInteger эквивалент в Java

private static byte[] solveChallenge(byte[] data, int offset, int level){ 
     var x = new BigInteger(1, data, 00 + offset, 64); 
     var n = new BigInteger(1, data, 64 + offset, 64); 
     Console.Out.WriteLine("x " + x); 
     Console.Out.WriteLine("n " + n); 
     return x.ModPow(BigInteger.Two.Pow(level), n).ToByteArrayUnsigned(); 
} 

Первая проблема заключается в том, что Java нужно использовать целочисленный массив, так как он не поддерживает 4 байта ,

Я пытался перенести эту функцию, и это результат:

private byte[] solveChallenge(int[] dummyData, int offset, int level) { 
    int[] x = Arrays.copyOfRange(dummyData, 00 + offset, 64 + offset); 
    int[] n = Arrays.copyOfRange(dummyData, 64 + offset, 64 + offset + 64); 
    BigInteger bigInteger = this.toBigInteger(x, offset, level); 
    BigInteger bigInteger2 = this.toBigInteger(n, offset, level); 
    System.out.println("bigInteger : " + bigInteger); 
    System.out.println("bigInteger2 : " + bigInteger2); 
    return null; //only for debugging purposes since it doesn't calculate the right value 
} 

private BigInteger toBigInteger(int[] data, int offset, int length) { 
    byte[] array = new byte[data.length * 4]; 
    ByteBuffer bbuf = ByteBuffer.wrap(array); 
    bbuf.order(ByteOrder.BIG_ENDIAN); 
    IntBuffer ibuf = bbuf.asIntBuffer(); 
    ibuf.put(data); 
    int pos = bbuf.position(); 
    return new BigInteger(1, array); 
} 

Массив байтов с фиктивными данными заключается в следующем:

byte[] dummyData = { 3, 184, 233, 18, 14, 29, 29, 96, 191, 154, 42, 188, 39, 129, 28, 43, 179, 155, 17, 253, 104, 150, 211, 242, 218, 37, 111, 45, 234, 231, 159, 226, 229, 241, 118, 6, 93, 154, 216, 39, 147, 240, 235, 37, 235, 4, 162, 199, 3, 146, 219, 250, 55, 145, 187, 109, 129, 154, 21, 99, 195, 213, 24, 171, 72, 186, 108, 207, 23, 245, 227, 206, 155, 28, 83, 117, 208, 52, 146, 247, 107, 86, 250, 91, 120, 132, 103, 96, 151, 135, 239, 236, 171, 105, 148, 132, 210, 164, 24, 121, 46, 63, 26, 6, 147, 66, 0, 113, 226, 228, 96, 54, 247, 58, 216, 123, 239, 127, 35, 235, 117, 225, 156, 139, 231, 191, 23, 16, 199, 0, 0, 39, 16, 24, 148, 19, 244, 58, 27, 168, 77, 144, 41, 52, 231, 216, 63, 52, 240, 101, 221, 196, 61, 210, 132, 247, 242, 148, 127, 73, 20, 136, 213, 82, 154, 2, 118, 247, 27, 193, 213, 31, 20, 107, 184, 115, 129, 102, 95, 130, 42, 105, 70, 228, 111, 211, 108, 149, 43, 200, 239, 220, 58, 61, 35, 169, 51, 37, 140, 12, 150, 126, 170, 183, 95, 104, 102, 218, 171, 207, 57, 172, 57, 179, 147, 134, 251, 49, 168, 124, 154, 198, 102, 204, 88, 99, 110, 128, 73, 0, 0, 0, 0, } 
int[] dummyData = { 3, 184, 233, 18, 14, 29, 29, 96, 191, 154, 42, 188, 39, 129, 28, 43, 179, 155, 17, 253, 104, 150, 211, 242, 218, 37, 111, 45, 234, 231, 159, 226, 229, 241, 118, 6, 93, 154, 216, 39, 147, 240, 235, 37, 235, 4, 162, 199, 3, 146, 219, 250, 55, 145, 187, 109, 129, 154, 21, 99, 195, 213, 24, 171, 72, 186, 108, 207, 23, 245, 227, 206, 155, 28, 83, 117, 208, 52, 146, 247, 107, 86, 250, 91, 120, 132, 103, 96, 151, 135, 239, 236, 171, 105, 148, 132, 210, 164, 24, 121, 46, 63, 26, 6, 147, 66, 0, 113, 226, 228, 96, 54, 247, 58, 216, 123, 239, 127, 35, 235, 117, 225, 156, 139, 231, 191, 23, 16, 199, 0, 0, 39, 16, 24, 148, 19, 244, 58, 27, 168, 77, 144, 41, 52, 231, 216, 63, 52, 240, 101, 221, 196, 61, 210, 132, 247, 242, 148, 127, 73, 20, 136, 213, 82, 154, 2, 118, 247, 27, 193, 213, 31, 20, 107, 184, 115, 129, 102, 95, 130, 42, 105, 70, 228, 111, 211, 108, 149, 43, 200, 239, 220, 58, 61, 35, 169, 51, 37, 140, 12, 150, 126, 170, 183, 95, 104, 102, 218, 171, 207, 57, 172, 57, 179, 147, 134, 251, 49, 168, 124, 154, 198, 102, 204, 88, 99, 110, 128, 73, 0, 0, 0, 0, } 

для обеих программ (в межд [] для Java). Сейчас идет сложная часть: Два console.writeLines в # версии C распечатывать эти значения:

х 9684545129450563760811299662317393444224628107338840479787476089424784627212472709829491894762094799169291328402088637379520119916743215796610009247820616

н 9763871338200074467010224713304495633710029487465175174521229296454337320893449010179832428198865193070649591972415477477112413797655820164788963534901447

версия ява однако печатает:

BigInteger: 1384487636125275878231756214272583599746580615359367670970277020749291139661692747315333543253640854017991792553366599843364101930280429076504504568047635739899488976412197760572976468791377536211931839579896955320180378597836121754579135558686349090024111181198802897769845015231252620523393484949244408744682782755518452496013632526359151451572349278849384043601027009481486942547342423606635954241049110830041192225899912691920909177042864305251984053702303477007620462086885017315368482937756361611079609304592527067945041572917438130926972982331458069293145225576550553455068231595004541872039273047261256

bigInteger2: 139953641455538603601673207838961549058379029424105795988000639924681675107890012510963526929083639 2362378727229942541859385680156220979323032655120786012653956497057790441490280149802553283148934560467004214861358910591562936643819189479913049351409549959873164398598055666211815485920029665855456844605176135634635342254062123114318883965379446208014067811273077439277906607738683244293540374300284127713297527831803091844750310847726168860685624174631286757167096065831296412508483930854847141757821223969111690911979811180162621071129937054751632338429538035407779745520240238094955254575062803261704634567

Параметры метода являются 1 и 10000 для обеих программ (пример для Java):

testclass.solveChallenge(dummyData, 1, 10000); 

В идеале BIGI nteger должен иметь те же значения, что и x и bigInteger2, например n. Где моя ошибка? Я искал 5 часов, но не нашел ничего плохого:/

ответ

0

Я, наконец, нашел проблему: IntBuffer из Java импортирует свои номера в формате 4 байта (логически, потому что int состоит из 4 байтов). Вот почему он заполняет 3 байта нулями, а последний имеет знаковое значение данного значения из места массива int. Эта команда принесла свет в темноте:

BigInteger x = new BigInteger("9684545129450563760811299662317393444224628107338840479787476089424784627212472709829491894762094799169291328402088637379520119916743215796610009247820616") 

Так как я был в состоянии получить реальную BigInteger, что я должен был получить. После применения x.toByteArray() я видел, что эти байты были заполнены другим способом (без трех нулевых байтов). С двойной проверкой значений, сгенерированных C#, я обнаружил, что он странно всегда удаляет первый байт из второй переменной (n в моем случае). После применения этих правил мне удалось получить нужные значения.

Это мое окончательное исправление:

private byte[] solveChallenge(int[] dummyData, int offset, int level) { 
    int[] x = Arrays.copyOfRange(dummyData, 00 + offset, 65 + offset); 
    int[] n = Arrays.copyOfRange(dummyData, offset, 65 + offset + 64); 
    n[0] = 0; //null first byte in n, don't copy this line, this only works for my problem! 
    BigInteger xInt = this.toBigInteger(x, offset); 
    BigInteger nInt = this.toBigInteger(n, offset); 
    BigInteger inner = pow(BigInteger.valueOf(2), BigInteger.valueOf(level)); 
    return xInt.modPow(inner, nInt).toByteArray(); 
} 
private BigInteger pow(BigInteger base, BigInteger exponent) { 
     BigInteger result = BigInteger.ONE; 
     while (exponent.signum() > 0) { 
     if (exponent.testBit(0)) result = result.multiply(base); 
     base = base.multiply(base); 
     exponent = exponent.shiftRight(1); 
     } 
     return result; 
} 
private BigInteger toBigInteger(int[] data, int offset, int length) { 
    byte[] array = new byte[data.length * 4]; 
    ByteBuffer bbuf = ByteBuffer.wrap(array); 
    IntBuffer ibuf = bbuf.asIntBuffer(); 
    ibuf.put(data); 
    bbuf.order(ByteOrder.BIG_ENDIAN); 
    int i = 0; 
    byte[] newArr = new byte[(array.length/4)-1]; 
    //convert to Little-Endian like systems and only keep every fourth byte 
    for(int j = 0; j < array.length-1; ++j) { 
     if(j % 4 == 0 && j > 0) { 
      int pos = j - 1; 
      newArr[i] = array[pos]; 
      ++i; 
     } 
    } 
    return new BigInteger(1, newArr); 
}