Files
hcs/Hcs.ClientNet/GostCryptography/Asn1/Ber/Asn1BitString.cs

455 lines
11 KiB
C#

using GostCryptography.Properties;
using System;
using System.Collections;
using System.Text;
namespace GostCryptography.Asn1.Ber
{
[Serializable]
public class Asn1BitString : Asn1Type
{
public static readonly Asn1Tag Tag = new Asn1Tag(0, 0, BitStringTypeCode);
[NonSerialized]
public byte[] Value;
[NonSerialized]
public int NumBits;
public Asn1BitString()
{
NumBits = 0;
Value = null;
}
public Asn1BitString(bool[] bitValues)
{
AllocBitArray(bitValues.Length);
var index = 0;
var num4 = 0x80;
var num = 0;
var num2 = 0;
while (num < bitValues.Length)
{
if (bitValues[num])
{
num2 |= num4;
}
num4 = num4 >> 1;
if (num4 == 0)
{
Value[index++] = (byte)num2;
num4 = 0x80;
num2 = 0;
}
num++;
}
if (num4 != 0x80)
{
Value[index] = (byte)num2;
}
}
public Asn1BitString(BitArray bitArray)
{
AllocBitArray(bitArray.Length);
var index = 0;
var num4 = 0x80;
var num = 0;
var num2 = 0;
while (num < bitArray.Length)
{
if (bitArray.Get(num))
{
num2 |= num4;
}
num4 = num4 >> 1;
if (num4 == 0)
{
Value[index++] = (byte)num2;
num4 = 0x80;
num2 = 0;
}
num++;
}
if (num4 != 0x80)
{
Value[index] = (byte)num2;
}
}
public Asn1BitString(string value)
{
var numbits = new IntHolder();
Value = Asn1Value.ParseString(value, numbits);
NumBits = numbits.Value;
}
public Asn1BitString(int numBits, byte[] data)
{
NumBits = numBits;
Value = data;
}
private void AllocBitArray(int numbits)
{
NumBits = numbits;
var num = (NumBits + 7) / 8;
if ((Value == null) || (Value.Length < num))
{
Value = new byte[num];
}
}
public virtual void Clear(int bitIndex)
{
this[bitIndex] = false;
}
public override void Decode(Asn1BerDecodeBuffer buffer, bool explicitTagging, int implicitLength)
{
var elemLength = explicitTagging ? MatchTag(buffer, Tag) : implicitLength;
var lastTag = buffer.LastTag;
if ((lastTag == null) || !lastTag.Constructed)
{
if (elemLength < 0)
{
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidLengthException);
}
if (elemLength != 0)
{
var num8 = elemLength - 1;
var num7 = buffer.Read();
if (num7 < 0)
{
throw ExceptionUtility.CryptographicException(Resources.Asn1EndOfBufferException, buffer.ByteCount);
}
if ((num7 < 0) || (num7 > 7))
{
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidFormatOfBitString, num7);
}
if ((num8 == 0) && (num7 != 0))
{
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidLengthException);
}
NumBits = (num8 * 8) - num7;
Value = new byte[num8];
buffer.Read(Value);
}
else
{
NumBits = 0;
Value = null;
}
}
else
{
var num3 = 0;
var offset = 0;
var index = -1;
var num6 = 0;
var context = new Asn1BerDecodeContext(buffer, elemLength);
while (!context.Expired())
{
var nbytes = MatchTag(buffer, Tag);
if (nbytes <= 0)
{
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidFormatOfConstructedValue, buffer.ByteCount);
}
num3 += nbytes;
if (offset == 0)
{
AllocBitArray(num3 * 8);
}
else
{
ReallocBitArray(num3 * 8);
}
index = offset;
buffer.Read(Value, offset, nbytes);
offset = num3;
}
if (index >= 0)
{
num6 = Value[index];
if (((offset - index) - 1) > 0)
{
Array.Copy(Value, index + 1, Value, index, (offset - index) - 1);
}
num3--;
}
if ((num6 < 0) || (num6 > 7))
{
throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidFormatOfBitString, num6);
}
ReallocBitArray((num3 * 8) - num6);
if (elemLength == Asn1Status.IndefiniteLength)
{
MatchTag(buffer, Asn1Tag.Eoc);
}
}
buffer.TypeCode = 3;
}
public override int Encode(Asn1BerEncodeBuffer buffer, bool explicitTagging)
{
var length = (NumBits + 7) / 8;
var num2 = NumBits % 8;
if (num2 != 0)
{
num2 = 8 - num2;
Value[length - 1] = (byte)(Value[length - 1] & ((byte)~((1 << num2) - 1)));
}
if (length != 0)
{
buffer.Copy(Value, 0, length);
}
buffer.Copy((byte)num2);
length++;
if (explicitTagging)
{
length += buffer.EncodeTagAndLength(Tag, length);
}
return length;
}
public override void Encode(Asn1BerOutputStream outs, bool explicitTagging)
{
outs.EncodeBitString(Value, NumBits, explicitTagging, Tag);
}
public override bool Equals(object value)
{
var str = value as Asn1BitString;
if (str == null)
{
return false;
}
return Equals(str.NumBits, str.Value);
}
public virtual bool Equals(int nbits, byte[] value)
{
if (nbits != NumBits)
{
return false;
}
var num = ((nbits - 1) / 8) + 1;
for (var i = 0; i < num; ++i)
{
if (value[i] != Value[i])
{
return false;
}
}
return true;
}
public virtual bool Get(int bitno)
{
var index = bitno / 8;
var num2 = 1 << (7 - (bitno % 8));
if ((Value != null) && (Value.Length >= index))
{
int num3 = Value[index];
return ((num3 & num2) != 0);
}
return false;
}
public override int GetHashCode()
{
return (Value != null) ? Value.GetHashCode() : base.GetHashCode();
}
private void ReallocBitArray(int numbits)
{
NumBits = numbits;
var num = (NumBits + 7) / 8;
if (Value.Length != num)
{
var value = Value;
Value = new byte[num];
if (value != null)
{
Array.Copy(value, 0, Value, 0, Math.Min(value.Length, num));
}
}
}
public virtual void Set(int bitIndex)
{
Set(bitIndex, true);
}
public virtual void Set(int bitIndex, bool value)
{
var index = bitIndex / 8;
var num2 = 1 << (7 - (bitIndex % 8));
var num3 = index + 1;
if (Value == null)
{
Value = new byte[num3];
}
else if (Value.Length < num3)
{
var destinationArray = new byte[num3];
Array.Copy(Value, 0, destinationArray, 0, Value.Length);
Value = destinationArray;
}
int num4 = Value[index];
num4 = value ? (num4 | num2) : (num4 & ~num2);
Value[index] = (byte)num4;
if ((bitIndex + 1) > NumBits)
{
NumBits = bitIndex + 1;
}
}
public virtual bool[] ToBoolArray()
{
var flagArray = new bool[NumBits];
var num4 = 0;
var numbits = NumBits;
foreach (var num3 in Value)
{
var num5 = 0x80;
var num = (numbits < 8) ? numbits : 8;
for (var j = 0; j < num; ++j)
{
flagArray[num4++] = (num3 & num5) != 0;
num5 = num5 >> 1;
}
numbits -= 8;
}
return flagArray;
}
public virtual string ToHexString()
{
var str = new StringBuilder("").ToString();
foreach (var b in Value)
{
str = str + Asn1Util.ToHexString(b);
}
return str;
}
public override string ToString()
{
var str = new StringBuilder("").ToString();
if (NumBits <= 0x10)
{
if (NumBits != 0)
{
var flagArray = ToBoolArray();
foreach (bool b in flagArray)
{
str = str + (b ? "1" : "0");
}
}
return str;
}
var num2 = 4;
var capacity = (NumBits + 3) / 4;
var builder = new StringBuilder(capacity);
if (Value != null)
{
var num4 = 0;
var index = 0;
while (num4 < capacity)
{
var num6 = (Value[index] >> num2) & 15;
builder.Append((char)(num6 + ((num6 >= 10) ? 0x57 : 0x30)));
num2 -= 4;
if (num2 < 0)
{
num2 = 4;
index++;
}
num4++;
}
}
return builder.ToString();
}
public virtual bool this[int bitIndex]
{
get { return Get(bitIndex); }
set { Set(bitIndex, value); }
}
public override int Length
{
get { return NumBits; }
}
}
}