Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java (BigInteger from byte array)

I'm using following code to create a BigInteger from hexadecimal string and print in to output.

package javaapplication2;

import java.math.BigInteger;
import javax.xml.bind.DatatypeConverter;

public class JavaApplication2 {
    public static void main(String[] args) {
        // Number in hexadecimal form
        String HexString = "e04fd020ea3a6910a2d808002b30309d";
        // Convertation from string to byte array
        byte[] ByteArray = toByteArray(HexString);
        // Creation of BigInteger from byte array
        BigInteger BigNumber = new BigInteger(ByteArray);
        // Print result
        System.out.print(BigNumber + "\n");
    }
    public static String toHexString(byte[] array) {
        return DatatypeConverter.printHexBinary(array);
    }

    public static byte[] toByteArray(String s) {
        return DatatypeConverter.parseHexBinary(s);
    }
}

After execution of this code I'm get a following result:

-42120883064304190395265794005525319523

But I'm expected to see this result:

298161483856634273068108813426242891933

What I'm doing wrong?

like image 906
Kechup Avatar asked Aug 28 '15 14:08

Kechup


1 Answers

You're passing in a byte array where the first byte has a top bit that is set - making it negative. From the constructor documentation:

Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger. The input array is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element.

A two's-complement binary representation with a leading set bit is negative.

To get the result you want, you can do any of:

  • Prefix the hex string with "00" so that you'll always get a top byte of 0
  • Pass the hex string straight into the BigInteger(String, int) constructor, where the sign is inferred from the presence or absence of "-" at the start of the string. (Obviously you'd pass in 16 as the base.)
  • Use the BigInteger(int, byte[]) constructor, passing 1 as the signum value

If your real context is that you've already got the byte array, and you were only parsing it from a hex string for test purposes, I'd use the third option. If you've genuinely got a hex string as input, I'd use the second option.

like image 157
Jon Skeet Avatar answered Oct 07 '22 13:10

Jon Skeet