Add project
Basic formatting applied. Unnecessary comments have been removed. Suspicious code is covered by TODO.
This commit is contained in:
809
Hcs.Client/GostCryptography/Asn1/Ber/BigInteger.cs
Normal file
809
Hcs.Client/GostCryptography/Asn1/Ber/BigInteger.cs
Normal file
@ -0,0 +1,809 @@
|
||||
using System;
|
||||
|
||||
using GostCryptography.Properties;
|
||||
|
||||
namespace GostCryptography.Asn1.Ber
|
||||
{
|
||||
[Serializable]
|
||||
public class BigInteger
|
||||
{
|
||||
private const int AddressBits = 3;
|
||||
private const int BitIndexMask = 7;
|
||||
private const int BitsPerUnit = 8;
|
||||
internal const int MaxBigIntLen = 100000;
|
||||
private const int UnitMask = -1;
|
||||
|
||||
[NonSerialized]
|
||||
private static readonly int[] BitsPerDigit =
|
||||
{
|
||||
0, 0, 0x400, 0x658, 0x800, 0x94a, 0xa58, 0xb3b, 0xc00, 0xcaf, 0xd4a, 0xdd7, 0xe58, 0xece, 0xf3b, 0xfa1,
|
||||
0x1000, 0x105a, 0x10af, 0x10fe, 0x114a, 0x1192, 0x11d7, 0x1219, 0x1258, 0x1294, 0x12ce, 0x1306, 0x133b, 0x136f, 0x13a1, 0x13d2,
|
||||
0x1400, 0x142e, 0x145a, 0x1485, 0x14af
|
||||
};
|
||||
|
||||
[NonSerialized]
|
||||
private static readonly int[] ByteRadix =
|
||||
{
|
||||
0, 0, 0x80, 0, 0, 0, 0, 0, 0x40, 0, 100, 0, 0, 0, 0, 0, 0x10
|
||||
};
|
||||
|
||||
[NonSerialized]
|
||||
private static readonly int[] DigitsPerByte =
|
||||
{
|
||||
0, 0, 7, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 1
|
||||
};
|
||||
|
||||
private static readonly byte[] Zero = new byte[0];
|
||||
|
||||
[NonSerialized]
|
||||
private int _sign;
|
||||
|
||||
[NonSerialized]
|
||||
private byte[] _value;
|
||||
|
||||
public BigInteger()
|
||||
{
|
||||
_value = Zero;
|
||||
_sign = 0;
|
||||
}
|
||||
|
||||
public BigInteger(long value)
|
||||
: this(value.ToString())
|
||||
{
|
||||
}
|
||||
|
||||
public BigInteger(string value)
|
||||
{
|
||||
Init(value, 10);
|
||||
}
|
||||
|
||||
public BigInteger(byte[] value, int sign)
|
||||
{
|
||||
_value = value;
|
||||
_sign = sign;
|
||||
}
|
||||
|
||||
public BigInteger(string value, int radix)
|
||||
{
|
||||
Init(value, radix);
|
||||
}
|
||||
|
||||
private static int BitsLeftOf(int x)
|
||||
{
|
||||
if (x != 0)
|
||||
{
|
||||
return (UnitMask << (BitsPerUnit - x));
|
||||
}
|
||||
|
||||
return UnitMask;
|
||||
}
|
||||
|
||||
private static void DestructiveMulAdd(byte[] x, int y, byte z)
|
||||
{
|
||||
var num = (byte)(y & 0xff);
|
||||
var num2 = z;
|
||||
var length = x.Length;
|
||||
var num5 = 0;
|
||||
|
||||
for (var i = length - 1; i >= 0; i--)
|
||||
{
|
||||
var num4 = (num * x[i]) + num5;
|
||||
x[i] = (byte)num4;
|
||||
num5 = num4 >> BitsPerUnit;
|
||||
}
|
||||
|
||||
var num7 = x[length - 1] + num2;
|
||||
x[length - 1] = (byte)num7;
|
||||
num5 = num7 >> BitsPerUnit;
|
||||
|
||||
for (var j = length - 2; j >= 0; j--)
|
||||
{
|
||||
num7 = x[j] + num5;
|
||||
x[j] = (byte)num7;
|
||||
num5 = num7 >> BitsPerUnit;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DivideByInt(ref BigInteger divident, int divisor, ref BigInteger quotient, ref int reminder)
|
||||
{
|
||||
var index = 0;
|
||||
var num3 = 4;
|
||||
var num4 = 0;
|
||||
var num5 = 0;
|
||||
|
||||
if (divisor == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
reminder = 0;
|
||||
|
||||
if (divident._sign == 0)
|
||||
{
|
||||
quotient._sign = 0;
|
||||
quotient._value = Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
quotient._value = new byte[divident._value.Length];
|
||||
|
||||
var num2 = quotient._value.Length - 1;
|
||||
quotient._sign = ((quotient._sign * divisor) > 0) ? 1 : -1;
|
||||
|
||||
var num6 = divident._value.Length * 2;
|
||||
|
||||
while (num4 < num6)
|
||||
{
|
||||
num5 = num5 << 4;
|
||||
num4++;
|
||||
num5 |= (divident._value[index] >> num3) & 15;
|
||||
|
||||
if (num3 == 0)
|
||||
{
|
||||
num3 = 4;
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
num3 = 0;
|
||||
}
|
||||
|
||||
ShiftLeft(quotient, 4);
|
||||
|
||||
if (num5 >= divisor)
|
||||
{
|
||||
quotient._value[num2] = (byte)(quotient._value[num2] | ((byte)((num5 / divisor) & 15)));
|
||||
num5 = num5 % divisor;
|
||||
}
|
||||
|
||||
reminder = num5;
|
||||
}
|
||||
|
||||
quotient._value = RemoveLeadingZeroBytes(quotient._value);
|
||||
}
|
||||
|
||||
public bool Equals(long value)
|
||||
{
|
||||
return Equals(new BigInteger(value));
|
||||
}
|
||||
|
||||
public override bool Equals(object value)
|
||||
{
|
||||
var integer = value as BigInteger;
|
||||
|
||||
if (integer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_value.Length != integer._value.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _value.Length; i++)
|
||||
{
|
||||
if (_value[i] != integer._value[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void FastCopy(ref BigInteger src, ref BigInteger dst)
|
||||
{
|
||||
dst._value = new byte[src._value.Length];
|
||||
Array.Copy(src._value, 0, dst._value, 0, src._value.Length);
|
||||
dst._sign = src._sign;
|
||||
}
|
||||
|
||||
private BigInteger GetCopy()
|
||||
{
|
||||
var integer = new BigInteger();
|
||||
|
||||
if (_value.Length > 0)
|
||||
{
|
||||
integer._value = new byte[_value.Length];
|
||||
Array.Copy(_value, 0, integer._value, 0, _value.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
integer._value = Zero;
|
||||
}
|
||||
|
||||
integer._sign = _sign;
|
||||
|
||||
return integer;
|
||||
}
|
||||
|
||||
private BigInteger GetCopyAndInverse()
|
||||
{
|
||||
var integer = new BigInteger();
|
||||
|
||||
if (_value.Length > 0)
|
||||
{
|
||||
integer._value = new byte[_value.Length];
|
||||
|
||||
if (_sign < 0)
|
||||
{
|
||||
integer._value = GetData();
|
||||
integer._sign = 1;
|
||||
return integer;
|
||||
}
|
||||
|
||||
Array.Copy(_value, 0, integer._value, 0, _value.Length);
|
||||
integer._sign = _sign;
|
||||
|
||||
return integer;
|
||||
}
|
||||
|
||||
integer._value = Zero;
|
||||
|
||||
return integer;
|
||||
}
|
||||
|
||||
public byte[] GetData()
|
||||
{
|
||||
int num2;
|
||||
var dataLen = GetDataLen();
|
||||
var index = _value.Length - 1;
|
||||
var num4 = dataLen - 1;
|
||||
|
||||
if (_sign == 0)
|
||||
{
|
||||
return Zero;
|
||||
}
|
||||
|
||||
var buffer = new byte[dataLen];
|
||||
|
||||
if (_sign >= 0)
|
||||
{
|
||||
num2 = _value.Length - 1;
|
||||
|
||||
while (((num2 >= 0) && (num4 >= 0)) && (index >= 0))
|
||||
{
|
||||
buffer[num4] = _value[index];
|
||||
num2--;
|
||||
num4--;
|
||||
index--;
|
||||
}
|
||||
|
||||
if ((dataLen - _value.Length) > 0)
|
||||
{
|
||||
buffer[num4] = 0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
num2 = _value.Length - 1;
|
||||
|
||||
while (((num2 >= 0) && (num4 >= 0)) && (index >= 0))
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
buffer[num4] = (byte)-_value[index];
|
||||
}
|
||||
|
||||
if (_value[index] != 0)
|
||||
{
|
||||
num2--;
|
||||
num4--;
|
||||
index--;
|
||||
break;
|
||||
}
|
||||
|
||||
num2--;
|
||||
num4--;
|
||||
index--;
|
||||
}
|
||||
|
||||
while (((num2 >= 0) && (num4 >= 0)) && (index >= 0))
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
buffer[num4] = (byte)~_value[index];
|
||||
}
|
||||
|
||||
num2--;
|
||||
num4--;
|
||||
index--;
|
||||
}
|
||||
|
||||
if ((dataLen - _value.Length) > 0)
|
||||
{
|
||||
buffer[num4] = 0xff;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private int GetDataLen()
|
||||
{
|
||||
if (_sign == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((_sign > 0) && ((_value[0] & 0x80) != 0))
|
||||
{
|
||||
return (_value.Length + 1);
|
||||
}
|
||||
|
||||
if (_sign < 0)
|
||||
{
|
||||
var num = _value[0];
|
||||
|
||||
if ((_value.Length == 1) || ((_value.Length > 1) && (_value[1] == 0)))
|
||||
{
|
||||
num = (byte)~(num - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
num = (byte)~num;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num & 0x80) == 0)
|
||||
{
|
||||
return (_value.Length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return _value.Length;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (_value == null)
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
if (_value.Length == 0)
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
var num = 0;
|
||||
var num2 = (_value.Length > 20) ? 20 : _value.Length;
|
||||
|
||||
for (var i = 0; i < num2; i++)
|
||||
{
|
||||
num ^= _value[i];
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
public void Init(string val, int radix)
|
||||
{
|
||||
var str = "";
|
||||
|
||||
if (val[0] == '-')
|
||||
{
|
||||
val = val.Substring(1);
|
||||
str = "-";
|
||||
}
|
||||
|
||||
if (val.StartsWith("0x"))
|
||||
{
|
||||
radix = 0x10;
|
||||
val = val.Substring(2);
|
||||
}
|
||||
else if (val.StartsWith("0b"))
|
||||
{
|
||||
radix = 2;
|
||||
val = val.Substring(2);
|
||||
}
|
||||
else if (val.StartsWith("0o"))
|
||||
{
|
||||
radix = 8;
|
||||
val = val.Substring(2);
|
||||
}
|
||||
|
||||
val = str + val;
|
||||
var startIndex = 0;
|
||||
var length = val.Length;
|
||||
|
||||
if (((radix != 2) && (radix != 0x10)) && ((radix != 10) && (radix != 8)))
|
||||
{
|
||||
throw new FormatException(Resources.Asn1InvalidFormatForBigIntegerValue);
|
||||
}
|
||||
|
||||
if (val.Length == 0)
|
||||
{
|
||||
throw new FormatException(Resources.Asn1ZeroLengthBigInteger);
|
||||
}
|
||||
|
||||
_sign = 1;
|
||||
|
||||
var index = val.IndexOf('-');
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
if (index != 0)
|
||||
{
|
||||
throw new FormatException(Resources.Asn1IllegalEmbeddedMinusSign);
|
||||
}
|
||||
|
||||
if (val.Length == 1)
|
||||
{
|
||||
throw new FormatException(Resources.Asn1ZeroLengthBigInteger);
|
||||
}
|
||||
|
||||
_sign = -1;
|
||||
|
||||
startIndex = 1;
|
||||
}
|
||||
|
||||
while ((startIndex < length) && (val[startIndex] == '0'))
|
||||
{
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
if (startIndex == length)
|
||||
{
|
||||
_sign = 0;
|
||||
_value = Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
var num2 = length - startIndex;
|
||||
var num5 = Asn1Util.UrShift(num2 * BitsPerDigit[radix], 10) + 1;
|
||||
var num1 = (num5 + 0x1f) / 0x20;
|
||||
|
||||
_value = new byte[num2];
|
||||
|
||||
var num6 = num2 % DigitsPerByte[radix];
|
||||
|
||||
if (num6 == 0)
|
||||
{
|
||||
num6 = DigitsPerByte[radix];
|
||||
}
|
||||
|
||||
var str2 = val.Substring(startIndex, num6);
|
||||
startIndex += num6;
|
||||
|
||||
_value[_value.Length - 1] = Convert.ToByte(str2, radix);
|
||||
|
||||
if (_value[_value.Length - 1] < 0)
|
||||
{
|
||||
throw new FormatException(Resources.Asn1IllegalDigit);
|
||||
}
|
||||
|
||||
var y = ByteRadix[radix];
|
||||
byte z;
|
||||
|
||||
while (startIndex < val.Length)
|
||||
{
|
||||
str2 = val.Substring(startIndex, DigitsPerByte[radix]);
|
||||
startIndex += DigitsPerByte[radix];
|
||||
z = Convert.ToByte(str2, radix);
|
||||
|
||||
if (z < 0)
|
||||
{
|
||||
throw new FormatException(Resources.Asn1IllegalDigit);
|
||||
}
|
||||
|
||||
DestructiveMulAdd(_value, y, z);
|
||||
}
|
||||
|
||||
_value = TrustedStripLeadingZeroInts(_value);
|
||||
}
|
||||
}
|
||||
|
||||
private static string IntToStr(long value, int radix)
|
||||
{
|
||||
var chArray = new char[0x22];
|
||||
var num = 0;
|
||||
var str = "";
|
||||
|
||||
if ((radix >= 2) && (radix <= 0x10))
|
||||
{
|
||||
while (num < 0x22)
|
||||
{
|
||||
chArray[num++] = (char)((ushort)(value % radix));
|
||||
|
||||
if ((value /= radix) == 0L)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (num != 0)
|
||||
{
|
||||
var ch = chArray[--num];
|
||||
|
||||
if (ch < '\n')
|
||||
{
|
||||
str = str + ((char)(ch + '0'));
|
||||
}
|
||||
else
|
||||
{
|
||||
str = str + ((char)((ch - '\n') + 0x41));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
public bool IsNegative()
|
||||
{
|
||||
return (_sign < 0);
|
||||
}
|
||||
|
||||
private char NibbleToHexChar(int b)
|
||||
{
|
||||
if ((b >= 0) && (b <= 9))
|
||||
{
|
||||
return (char)(b + 0x30);
|
||||
}
|
||||
|
||||
if ((b >= 10) && (b <= 15))
|
||||
{
|
||||
return (char)((b - 10) + 0x61);
|
||||
}
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
public static implicit operator BigInteger(long value)
|
||||
{
|
||||
return new BigInteger(value);
|
||||
}
|
||||
|
||||
private static byte[] RemoveLeadingZeroBytes(byte[] data)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
|
||||
while ((index < data.Length) && (data[index] == 0))
|
||||
{
|
||||
index++;
|
||||
}
|
||||
|
||||
var destinationArray = new byte[data.Length - index];
|
||||
Array.Copy(data, index, destinationArray, 0, data.Length - index);
|
||||
|
||||
return destinationArray;
|
||||
}
|
||||
|
||||
public void SetData(byte[] ivalue)
|
||||
{
|
||||
if (ivalue.Length > MaxBigIntLen)
|
||||
{
|
||||
throw ExceptionUtility.CryptographicException(Resources.Asn1TooBigIntegerValue, ivalue.Length);
|
||||
}
|
||||
|
||||
if ((ivalue.Length > 0) && ((ivalue[0] & 0x80) != 0))
|
||||
{
|
||||
var index = 0;
|
||||
var num = 0;
|
||||
|
||||
_sign = -1;
|
||||
|
||||
while ((num < ivalue.Length) && (ivalue[index] == 0xff))
|
||||
{
|
||||
num++;
|
||||
index++;
|
||||
}
|
||||
|
||||
var num2 = num;
|
||||
|
||||
while ((num2 < ivalue.Length) && (ivalue[index] == 0))
|
||||
{
|
||||
num2++;
|
||||
index++;
|
||||
}
|
||||
|
||||
var num3 = (num2 == ivalue.Length) ? 1 : 0;
|
||||
_value = new byte[(ivalue.Length - num) + num3];
|
||||
index = num;
|
||||
|
||||
var num4 = num;
|
||||
|
||||
while (num < ivalue.Length)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
_value[(num - num4) + num3] = (byte)~ivalue[index];
|
||||
}
|
||||
|
||||
num++;
|
||||
index++;
|
||||
}
|
||||
|
||||
for (num = _value.Length - 1; (_value[num] = (byte)(_value[num] + 1)) == 0; num--)
|
||||
{
|
||||
}
|
||||
|
||||
_value = RemoveLeadingZeroBytes(_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_value = RemoveLeadingZeroBytes(ivalue);
|
||||
_sign = (ivalue.Length == 0) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int ShiftLeft(BigInteger data, uint shift)
|
||||
{
|
||||
var value = data._value;
|
||||
var length = value.Length;
|
||||
var index = (int)(shift >> AddressBits);
|
||||
var num3 = ((int)shift) & BitIndexMask;
|
||||
var num4 = 8 - num3;
|
||||
var num5 = 0;
|
||||
var num7 = length;
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
length = length << AddressBits;
|
||||
var num6 = (int)((((length - shift) + 8L) - 1L) >> AddressBits);
|
||||
|
||||
while (num5 < (num6 - 1))
|
||||
{
|
||||
value[num5++] = (byte)((value[index] << num3) | ((num4 == 8) ? 0 : (value[index + 1] >> num4)));
|
||||
index++;
|
||||
}
|
||||
|
||||
length &= BitIndexMask;
|
||||
value[num5] = (num7 == num6) ? ((byte)((value[index] & BitsLeftOf(length)) << num3)) : ((byte)((value[index] << num3) | ((num4 == 8) ? 0 : ((value[index + 1] & BitsLeftOf(length)) >> num4))));
|
||||
|
||||
if (num6 < num7)
|
||||
{
|
||||
for (var i = num6; i < (num7 - num6); i++)
|
||||
{
|
||||
value[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(10);
|
||||
}
|
||||
|
||||
public string ToString(int radix)
|
||||
{
|
||||
if ((radix == 2) || (radix == 0x10))
|
||||
{
|
||||
int num;
|
||||
int num2;
|
||||
|
||||
if (radix == 2)
|
||||
{
|
||||
num2 = 8;
|
||||
num = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
num2 = 2;
|
||||
num = 4;
|
||||
}
|
||||
|
||||
var num3 = num2 * GetDataLen();
|
||||
var chArray = new char[num3];
|
||||
var index = num3 - 1;
|
||||
|
||||
for (var i = _value.Length - 1; i >= 0; i--)
|
||||
{
|
||||
byte num6;
|
||||
int num8;
|
||||
|
||||
if (_sign < 0)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
num6 = (byte)~_value[i];
|
||||
}
|
||||
|
||||
if ((_sign < 0) && ((num6 = (byte)(num6 + 1)) != 0))
|
||||
{
|
||||
_sign = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num6 = _value[i];
|
||||
}
|
||||
|
||||
var num7 = num8 = 0;
|
||||
|
||||
while (num7 < num2)
|
||||
{
|
||||
var b = (num6 >> num8) & ((1 << num) - 1);
|
||||
chArray[index] = NibbleToHexChar(b);
|
||||
num7++;
|
||||
index--;
|
||||
num8 += num;
|
||||
}
|
||||
}
|
||||
|
||||
while (index >= 0)
|
||||
{
|
||||
chArray[index--] = '0';
|
||||
}
|
||||
|
||||
return new string(chArray);
|
||||
}
|
||||
|
||||
var reminder = 0;
|
||||
var str = "";
|
||||
var quotient = new BigInteger();
|
||||
|
||||
var copy = (radix == 10) ? GetCopy() : GetCopyAndInverse();
|
||||
|
||||
do
|
||||
{
|
||||
DivideByInt(ref copy, ByteRadix[radix], ref quotient, ref reminder);
|
||||
var str2 = IntToStr(reminder, radix);
|
||||
var length = str2.Length;
|
||||
|
||||
str = str2 + str;
|
||||
|
||||
if ((quotient._value.Length != 0) || (radix != 10))
|
||||
{
|
||||
int num12;
|
||||
|
||||
for (num12 = length; num12 < DigitsPerByte[radix]; num12++)
|
||||
{
|
||||
str = '0' + str;
|
||||
}
|
||||
|
||||
FastCopy(ref quotient, ref copy);
|
||||
|
||||
if (((quotient._value.Length == 0) && (_sign > 0)) && ((radix != 10) && ((reminder & 0x80) != 0)))
|
||||
{
|
||||
str = '0' + str;
|
||||
}
|
||||
}
|
||||
else if ((_sign < 0) && (radix == 10))
|
||||
{
|
||||
str = '-' + str;
|
||||
}
|
||||
|
||||
}
|
||||
while ((quotient._value != null) && (quotient._value.Length != 0));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
private static byte[] TrustedStripLeadingZeroInts(byte[] val)
|
||||
{
|
||||
var index = 0;
|
||||
|
||||
while ((index < val.Length) && (val[index] == 0))
|
||||
{
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index <= 0)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
var buffer = new byte[val.Length - index];
|
||||
|
||||
for (var i = 0; i < (val.Length - index); i++)
|
||||
{
|
||||
buffer[i] = val[index + i];
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user