Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

byte[] to unsigned BigInteger?

Motivation: I would like to convert hashes (MD5/SHA1 etc) into decimal integers for the purpose of making barcodes in Code128C. For simplicity, I prefer all the resulting (large) numbers to be positive.

I am able to convert byte[] to BigInteger in C#...
Sample from what I have so far:

byte[] data;
byte[] result;
BigInteger biResult;

result = shaM.ComputeHash(data);
biResult = new BigInteger(result);

But (rusty CS here) am I correct that a byte array can always be interpreted in two ways:

  • (A): as a signed number
  • (B): as an unsigned number

Is it possible to make an UNSIGNED BigInteger from a byte[] in C#?

Should I simply prepend a 0x00 (zero byte) to the front of the byte[]?

EDIT: Thank you to AakashM, Jon and Adam Robinson, appending a zero byte achieved what I needed.

EDIT2: The main thing I should have done was to read the detailed doc of the BigInteger(byte[]) constructor, then I would have seen the sections about how to restrict to positive numbers by appending the zero byte.

like image 618
Doochz Avatar asked Apr 13 '11 12:04

Doochz


People also ask

What is unsigned BigInteger?

Description. A large integer. The signed range is -9223372036854775808 to 9223372036854775807 . The unsigned range is 0 to 18446744073709551615 . If a column has been set to ZEROFILL, all values will be prepended by zeros so that the BIGINT value contains a number of M digits.

Is byte unsigned in Java?

Java doesn't have unsigned bytes (0 to 255). To make an unsigned byte, we can cast the byte into an int and mask (bitwise and) the new int with a 0xff to get the last 8 bits or prevent sign extension.

What is BigInteger C#?

The BigInteger type is an immutable type that represents an arbitrarily large integer whose value in theory has no upper or lower bounds. The members of the BigInteger type closely parallel those of other integral types (the Byte, Int16, Int32, Int64, SByte, UInt16, UInt32, and UInt64 types).

What are negative bytes?

Problems arise when integers are type casted to bytes. This is a narrowing primitive conversion, for integers it works by copying the less significant bits. In this case, the eight less significant bits from the integer are copied to the byte. If the copied value is above 127 we end up with a negative byte value.


4 Answers

The remarks for the BigInteger constructor state that you can make sure any BigInteger created from a byte[] is unsigned if you append a 00 byte to the end of the array before calling the constructor.

Note: the BigInteger constructor expects the array to be in little-endian order. Keep that in mind if you expect the resulting BigInteger to have a particular value.

like image 113
Jon Avatar answered Sep 25 '22 20:09

Jon


Examining the documentation for the relevant BigInteger constructor, we see:

The individual bytes in the value array should be in little-endian order, from lowest-order byte to highest-order byte

[...]

The constructor expects positive values in the byte array to use sign-and-magnitude representation, and negative values to use two's complement representation. In other words, if the highest-order bit of the highest-order byte in value is set, the resulting BigInteger value is negative. Depending on the source of the byte array, this may cause a positive value to be misinterpreted as a negative value.

[...]

To prevent positive values from being misinterpreted as negative values, you can add a zero-byte value to the end of the array.

like image 20
AakashM Avatar answered Sep 26 '22 20:09

AakashM


Since .NET Core 2.1, BigInteger has a constructor with an optional parameter isUnsigned:

public BigInteger (ReadOnlySpan<byte> value, bool isUnsigned = false, bool isBigEndian = false);
like image 36
Mike K. Avatar answered Sep 23 '22 20:09

Mike K.


As other answers have pointed out, you should append a 00 byte to the end of the array to ensure the resulting BigInteger is positive.

According to the the BigInteger Structure (System.Numerics) MSDN Documentation

To prevent the BigInteger(Byte[]) constructor from confusing the two's complement representation of a negative value with the sign and magnitude representation of a positive value, positive values in which the most significant bit of the last byte in the byte array would ordinarily be set should include an additional byte whose value is 0.

Here's code to do it:

byte[] byteArray;
// ...
var bigInteger = new BigInteger(byteArray.Concat(new byte[] { 0 }).ToArray());
like image 33
divieira Avatar answered Sep 26 '22 20:09

divieira