What is the .NET System.Numerics.BigInteger Equivalent of Org.BouncyCastle.Math.BigInteger.ToByteArrayUnsigned?

3.2k views Asked by At

I am currently working with the .NET port of BouncyCastle and I am having some trouble converting a big integer into a System.Guid using the native .NET BigInteger.

For some context, I am using BouncyCastle in one ("source") application to convert a System.Guid to a Org.BouncyCastle.Math.BigInteger. This value is then saved as a string in the format 3A2B847A960F0E4A8D49BD62DDB6EB38.

Then, in another ("destination") application, I am taking this saved string value of a BigInteger and am trying to convert it back into a System.Guid.

Please note that in the destination application I do not want BouncyCastle as a reference and would like to use core .NET libraries for the conversion. However, since I am running into problems converting with core .NET classes, I am using BouncyCastle and the following code does exactly what I would like:

var data = "3A2B847A960F0E4A8D49BD62DDB6EB38";
var integer = new Org.BouncyCastle.Math.BigInteger( data, 16 );
var bytes = integer.ToByteArrayUnsigned();
var guid = new Guid( bytes ); // holds expected value: (7A842B3A-0F96-4A0E-8D49-BD62DDB6EB38)

As you can see, there is a ToByteArrayUnsigned method on the Org.BouncyCastle.Math.BigInteger that makes this work. If I use the ToByteArray on the System.Numerics.BigInteger (even when resizing the array as discussed in this question) it does not work and I get a different System.Guid than expected.

So, what is the best way to perform the equivalent to the above operation using native .NET classes?

Solution

Thanks to @John-Tasler's suggestion, it turns out this was due to endianess... darn you endianess... will your endiness ever end? :P

var parsed = System.Numerics.BigInteger.Parse( "3A2B847A960F0E4A8D49BD62DDB6EB38", NumberStyles.HexNumber ).ToByteArray(); Array.Resize( ref parsed, 16 ); var guid = new Guid( parsed.Reverse().ToArray() ); // Hoorrrrayyyy!

2

There are 2 answers

1
John Tasler On BEST ANSWER

What's the actual value of the resulting Guid when using .NET's BigIntegrer?

It could be that the two implementations are just storing the bytes differently. Endianess, etc.

To see what comes back from each implementation's array of bytes:

var sb = new StringBuilder();

foreach (var b in bytes)
{
    sb.AppendFormat("{0:X2} ", b);
} 
sb.ToString();

It'd be an interesting comparison.

0
AudioBubble On

I would avoid BigInteger here entirely. Your data bytes are already in the correct order so you can convert to byte[] directly.

var data = "3A2B847A960F0E4A8D49BD62DDB6EB38";
var bytes = new byte[16];
for (var i = 0; i < 16; i++)
  bytes[i] = byte.Parse(data.Substring(i * 2, 2), NumberStyles.HexNumber);
var guid = new Guid(bytes); // 7a842b3a-0f96-4a0e-8d49-bd62ddb6eb38