convert strings's byte array to big integer and perform functions in any language

Question:

I want to convert String’s byte array to BigInteger and vis-versa.

I’m able to do this for some language specifically. For example:-

in java: new BigInteger("ab".getBytes())

and in dart: _convertBytesToBigInt(Uint8List.fromList(Utf8Encoder().convert('ab')))

where _convertBytesToBigInt() method is from dartlang sdk’s github issue discussion (here and here).

I tried coping the same code from dart to java:

    BigInteger _convertBytesToBigInt(byte[] bytes) {
        BigInteger result = BigInteger.ZERO;
        for (byte z : bytes) {
// reading in big-endian, so we essentially concat the new byte to the end
            result = (result.shiftLeft(8)).or(BigInteger.valueOf(z));
        }
        return result;
    }

and this don’t work when I try to perform simple multiplication/division in java (but it works in flutter however)

// in java:

byte[] x = writeBigInt(_convertBytesToBigInt(writeBigInt(_convertBytesToBigInt("ab".getBytes()).multiply(BigInteger.TEN))).divide(BigInteger.TEN));
//returns [-25, -6] but it should return [97,98]
//in dart:

Uint8List y = _writeBigInt(_convertBytesToBigInt(_writeBigInt(
          _convertBytesToBigInt(
                  Uint8List.fromList(const Utf8Encoder().convert('ab'))) *
              BigInt.two)) ~/
      BigInt.two);

//it returns [97,98] which is expected result.

I tried copying Java’s BigInteger class and it’s toByteArray() method but again, it don’t work with dart properly.

These methods works normally if I try without multiplication/division, so only possible thing is, they both multiply/divide in different way if I’m not wrong.

Is there ANY solution for this? So that I can turn byte arr to BigInteger in ANY language (specifically popular ones like Java, Dart/flutter, Rust, Python, JS, etc).

NOTE:

Following are the methods which I used in dart and java respectively.

BigInt _convertBytesToBigInt(Uint8List bytes) {
  BigInt result = BigInt.zero;

  for (final byte in bytes) {
// reading in big-endian, so we essentially concat the new byte to the end
    result = (result << 8) | BigInt.from(byte);
  }
  return result;
}

Uint8List _writeBigInt(BigInt number) {
  // Not handling negative numbers. Decide how you want to do that.
  int bytes = (number.bitLength + 7) >> 3;
  var b256 = BigInt.from(256);
  var result = Uint8List(bytes);
  for (int i = 0; i < bytes; i++) {
    result[i] = number.remainder(b256).toInt();
    number = number >> 8;
  }
  return result;
}
BigInteger _convertBytesToBigInt(byte[] bytes) {
        BigInteger result = BigInteger.ZERO;
        for (byte z : bytes) {
// reading in big-endian, so we essentially concat the new byte to the end
            result = (result.shiftLeft(8)).or(BigInteger.valueOf(z));
        }
        return result;
    }

static byte[] writeBigInt(BigInteger number) {
        // Not handling negative numbers. Decide how you want to do that.
        int bytes = (number.bitLength() + 7) >> 3;
        BigInteger b256 = BigInteger.valueOf(256);
        byte[] result = new byte[bytes];
        for (int i = 0; i < bytes; i++) {
            result[i] = (byte) Integer.parseInt(number.remainder(b256).toString());
            number = number.shiftRight(8);
        }
        return result;
    }
Asked By: Sandip

||

Answers:

In Java a byte is a signed 8-bit value (ranges from -128 to 127). To get an unsigned value, you can bitwise AND it with 255. Try

BigInteger _convertBytesToBigInt(byte[] bytes) {
        BigInteger result = BigInteger.ZERO;
        for (byte z : bytes) {
            result = (result.shiftLeft(8)).or(BigInteger.valueOf(z & 0xff));
        }
        return result;
    }

Side note regarding writeBigInt: just use Number#byteValue() instead of toString() and parseInt().

Udate

_convertBytesToBigInt() assumes the bytes to be given in big-endian whereas writeBigInt writes little-endian. Here’s a corrected version for that, too:

byte[] writeBigInt(BigInteger number) {
    // Not handling negative numbers. Decide how you want to do that.
    int bytes = (number.bitLength() + 7) >> 3;
    BigInteger b256 = BigInteger.valueOf(256);
    byte[] result = new byte[bytes];
    for (int i = 0; i < bytes; i++) {
        result[bytes-1-i] = number.remainder(b256).byteValue();
        number = number.shiftRight(8);
    }
    return result;
}
Answered By: Mihe