e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
188 lines
6.5 KiB
C#
188 lines
6.5 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
|
|
namespace System.IdentityModel
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
static class Asn1IntegerConverter
|
|
{
|
|
static List<byte[]> powersOfTwo = new List<byte[]>(new byte[][] { new byte[] { 1 } });
|
|
readonly static char[] digitMap = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
|
|
|
public static string Asn1IntegerToDecimalString(byte[] asn1)
|
|
{
|
|
if (asn1 == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("asn1");
|
|
|
|
if (asn1.Length == 0)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("asn1", SR.GetString(SR.LengthOfArrayToConvertMustGreaterThanZero)));
|
|
|
|
|
|
List<byte> positiveDecimalDigits = new List<byte>((asn1.Length * 8) / 3);
|
|
int absoluteBitNumber = 0;
|
|
byte currentByte;
|
|
|
|
// Since X509Certificate.GetSerialNumber return the little-endian,
|
|
// the most significant is at the last byte.
|
|
for (int byteNumber = 0; byteNumber < asn1.Length - 1; byteNumber++)
|
|
{
|
|
currentByte = asn1[byteNumber];
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if ((currentByte & 1) == 1)
|
|
{
|
|
AddSecondDecimalToFirst(positiveDecimalDigits, TwoToThePowerOf(absoluteBitNumber));
|
|
}
|
|
absoluteBitNumber++;
|
|
currentByte >>= 1;
|
|
}
|
|
}
|
|
|
|
// Special case the most significant bit of the most significant byte as a negative value
|
|
currentByte = asn1[asn1.Length - 1];
|
|
for (int i = 0; i < 7; i++)
|
|
{
|
|
if ((currentByte & 1) == 1)
|
|
{
|
|
AddSecondDecimalToFirst(positiveDecimalDigits, TwoToThePowerOf(absoluteBitNumber));
|
|
}
|
|
absoluteBitNumber++;
|
|
currentByte >>= 1;
|
|
}
|
|
|
|
StringBuilder result = new StringBuilder(positiveDecimalDigits.Count + 1);
|
|
List<byte> resultDigits = null;
|
|
if (currentByte == 0)
|
|
{
|
|
// positive number
|
|
resultDigits = positiveDecimalDigits;
|
|
}
|
|
else
|
|
{
|
|
// negative number
|
|
List<byte> negativeDecimalDigits = new List<byte>(TwoToThePowerOf(absoluteBitNumber));
|
|
SubtractSecondDecimalFromFirst(negativeDecimalDigits, positiveDecimalDigits);
|
|
resultDigits = negativeDecimalDigits;
|
|
result.Append('-');
|
|
}
|
|
int d;
|
|
for (d = resultDigits.Count - 1; d >= 0; d--)
|
|
{
|
|
if (resultDigits[d] != 0)
|
|
break;
|
|
}
|
|
|
|
if (d < 0 && asn1.Length > 0)
|
|
{
|
|
// This is a special case where the result contains 0
|
|
result.Append(digitMap[0]);
|
|
}
|
|
else
|
|
{
|
|
while (d >= 0)
|
|
{
|
|
result.Append(digitMap[resultDigits[d--]]);
|
|
}
|
|
}
|
|
|
|
return result.ToString();
|
|
}
|
|
|
|
static byte[] TwoToThePowerOf(int n)
|
|
{
|
|
lock (powersOfTwo)
|
|
{
|
|
if (n >= powersOfTwo.Count)
|
|
{
|
|
for (int power = powersOfTwo.Count; power <= n; power++)
|
|
{
|
|
List<byte> decimalDigits = new List<byte>(powersOfTwo[power - 1]);
|
|
byte carryover = 0;
|
|
for (int i = 0; i < decimalDigits.Count; i++)
|
|
{
|
|
byte newValue = (byte)((decimalDigits[i] << 1) + carryover);
|
|
decimalDigits[i] = (byte)(newValue % 10);
|
|
carryover = (byte)(newValue / 10);
|
|
}
|
|
if (carryover > 0)
|
|
{
|
|
decimalDigits.Add(carryover);
|
|
carryover = 0;
|
|
}
|
|
powersOfTwo.Add(decimalDigits.ToArray());
|
|
}
|
|
}
|
|
return powersOfTwo[n];
|
|
}
|
|
}
|
|
|
|
static void AddSecondDecimalToFirst(List<byte> first, byte[] second)
|
|
{
|
|
byte carryover = 0;
|
|
for (int i = 0; i < second.Length || i < first.Count; i++)
|
|
{
|
|
if (i >= first.Count)
|
|
{
|
|
first.Add(0);
|
|
}
|
|
byte newValue;
|
|
if (i < second.Length)
|
|
{
|
|
newValue = (byte)(first[i] + second[i] + carryover);
|
|
}
|
|
else
|
|
{
|
|
newValue = (byte)(first[i] + carryover);
|
|
}
|
|
first[i] = (byte)(newValue % 10);
|
|
carryover = (byte)(newValue / 10);
|
|
}
|
|
if (carryover > 0)
|
|
{
|
|
first.Add(carryover);
|
|
}
|
|
}
|
|
|
|
static void SubtractSecondDecimalFromFirst(List<byte> first, List<byte> second)
|
|
{
|
|
byte borrow = 0;
|
|
for (int i = 0; i < second.Count; i++)
|
|
{
|
|
int newValue = first[i] - second[i] - borrow;
|
|
if (newValue < 0)
|
|
{
|
|
borrow = 1;
|
|
first[i] = (byte)(newValue + 10);
|
|
}
|
|
else
|
|
{
|
|
borrow = 0;
|
|
first[i] = (byte)newValue;
|
|
}
|
|
}
|
|
if (borrow > 0)
|
|
{
|
|
for (int i = second.Count; i < first.Count; i++)
|
|
{
|
|
int newValue = first[i] - borrow;
|
|
if (newValue < 0)
|
|
{
|
|
borrow = 1;
|
|
first[i] = (byte)(newValue + 10);
|
|
}
|
|
else
|
|
{
|
|
borrow = 0;
|
|
first[i] = (byte)newValue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DiagnosticUtility.DebugAssert(borrow == 0, "");
|
|
}
|
|
}
|
|
}
|