2017-02-03 3 views
0

Während ein altes Projekt von C# Java Migration stieß ich auf diese Funktion:C# BigInteger äquivalent in 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(); 
} 

Das erste Problem ist, dass Java einen int-Array verwenden muss, da es nicht 4 Byte unterstützt .

Ich habe versucht, diese Funktion zu migrieren und das ist das Ergebnis:

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); 
} 

Der Byte-Array mit den Dummy-Daten ist die folgende:

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, } 

für beiden Programme (int [] für Java). Jetzt kommt der schwierige Teil: Die beiden console.writeLines in der C# -Version diese Werte ausdrucken:

x 9684545129450563760811299662317393444224628107338840479787476089424784627212472709829491894762094799169291328402088637379520119916743215796610009247820616

n 9763871338200074467010224713304495633710029487465175174521229296454337320893449010179832428198865193070649591972415477477112413797655820164788963534901447

Die Java-Version jedoch ausdruckt:

BigInteger: 1384487636125275878231756214272583599746580615359367670970277020749291139661692747315333543253640854017991792553366599843364101930280429076504504568047635739899488976412197760572976468791377536211931839579896955320180378597836121754579135558686349090024111181198802897769845015231252620523393484949244408744682782755518452496013632526359151451572349278849384043601027009481486942547342423606635954241049110830041192225899912691920909177042864305251984053702303477007620462086885017315368482937756361611079609304592527067945041572917438130926972982331458069293145225576550553455068231595004541872039273047261256

bigInteger2: 139953641455538603601673207838961549058379029424105795988000639924681675107890012510963526929083639 2362378727229942541859385680156220979323032655120786012653956497057790441490280149802553283148934560467004214861358910591562936643819189479913049351409549959873164398598055666211815485920029665855456844605176135634635342254062123114318883965379446208014067811273077439277906607738683244293540374300284127713297527831803091844750310847726168860685624174631286757167096065831296412508483930854847141757821223969111690911979811180162621071129937054751632338429538035407779745520240238094955254575062803261704634567

Die Verfahrensparameter sind 1 und 10000 für beide Programme (beispielsweise Java):

testclass.solveChallenge(dummyData, 1, 10000); 

Idealer BIGI nteger sollte die gleichen Werte wie x und bigInteger2 wie n haben. Wo ist mein Fehler? Ich habe 5 Stunden gesucht, konnte aber nichts falsch finden:/

Antwort

0

Ich habe endlich das Problem gefunden: Der IntBuffer von Java importiert seine Zahlen im 4-Byte-Format (logisch, weil ein int aus 4 Bytes besteht). Aus diesem Grund füllt es 3 Bytes mit Nullen und die letzte mit dem vorzeichenbehafteten Wert des gegebenen Wertes aus dem Array des int-Arrays. Dieser Befehl brachte Licht ins Dunkel:

BigInteger x = new BigInteger("9684545129450563760811299662317393444224628107338840479787476089424784627212472709829491894762094799169291328402088637379520119916743215796610009247820616") 

Da ich in der Lage war, die tatsächlichen BigInteger zu bekommen, die ich bekommen sollte. Nach dem Anwenden von x.toByteArray() habe ich gesehen, dass diese Bytes auf andere Weise ausgefüllt wurden (ohne die drei Nullbytes). Mit der doppelten Überprüfung der von C# generierten Werte fand ich heraus, dass es merkwürdigerweise immer das erste Byte von der zweiten Variablen (n in meinem Fall) nullt. Nach der Anwendung dieser Regeln konnte ich die gewünschten Werte erhalten.

Dies ist meine letzte fix:

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); 
}