DerBitString
using Org.BouncyCastle.Utilities;
using System;
using System.IO;
using System.Text;
namespace Org.BouncyCastle.Asn1
{
public class DerBitString : DerStringBase, Asn1BitStringParser, IAsn1Convertible
{
internal class Meta : Asn1UniversalType
{
internal static readonly Asn1UniversalType Instance = new Meta();
private Meta()
: base(typeof(DerBitString), 3)
{
}
internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
{
return CreatePrimitive(octetString.GetOctets());
}
internal override Asn1Object FromImplicitConstructed(Asn1Sequence sequence)
{
return sequence.ToAsn1BitString();
}
}
internal static readonly byte[] EmptyOctetsContents = new byte[1];
private static readonly char[] table = new char[16] {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'
};
internal readonly byte[] m_contents;
public virtual int PadBits => m_contents[0];
public virtual int IntValue {
get {
int num = 0;
int num2 = System.Math.Min(5, m_contents.Length - 1);
for (int i = 1; i < num2; i++) {
num |= m_contents[i] << 8 * (i - 1);
}
if (1 <= num2 && num2 < 5) {
int num3 = m_contents[0];
byte b = (byte)(m_contents[num2] & (255 << num3));
num |= b << 8 * (num2 - 1);
}
return num;
}
}
public Asn1BitStringParser Parser => this;
public static DerBitString GetInstance(object obj)
{
if (obj == null)
return null;
DerBitString derBitString = obj as DerBitString;
if (derBitString != null)
return derBitString;
IAsn1Convertible asn1Convertible = obj as IAsn1Convertible;
if (asn1Convertible != null) {
if (!(obj is Asn1Object)) {
DerBitString derBitString2 = asn1Convertible.ToAsn1Object() as DerBitString;
if (derBitString2 != null)
return derBitString2;
}
} else {
byte[] array = obj as byte[];
if (array != null)
try {
return GetInstance(Asn1Object.FromByteArray(array));
} catch (IOException ex) {
throw new ArgumentException("failed to construct BIT STRING from byte[]: " + ex.Message);
}
}
throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj));
}
public static DerBitString GetInstance(Asn1TaggedObject obj, bool isExplicit)
{
return (DerBitString)Meta.Instance.GetContextInstance(obj, isExplicit);
}
public static DerBitString GetOptional(Asn1Encodable element)
{
if (element == null)
throw new ArgumentNullException("element");
DerBitString derBitString = element as DerBitString;
if (derBitString != null)
return derBitString;
return null;
}
public static DerBitString GetTagged(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
return (DerBitString)Meta.Instance.GetTagged(taggedObject, declaredExplicit);
}
public DerBitString(byte data, int padBits)
{
if (padBits > 7 || padBits < 0)
throw new ArgumentException("pad bits cannot be greater than 7 or less than 0", "padBits");
m_contents = new byte[2] {
(byte)padBits,
data
};
}
public DerBitString(byte[] data)
: this(data, 0)
{
}
public DerBitString(byte[] data, int padBits)
{
if (data == null)
throw new ArgumentNullException("data");
if (padBits < 0 || padBits > 7)
throw new ArgumentException("must be in the range 0 to 7", "padBits");
if (data.Length == 0 && padBits != 0)
throw new ArgumentException("if 'data' is empty, 'padBits' must be 0");
m_contents = Arrays.Prepend(data, (byte)padBits);
}
public DerBitString(int namedBits)
{
if (namedBits == 0)
m_contents = EmptyOctetsContents;
else {
int num = (32 - Integers.NumberOfLeadingZeros(namedBits) + 7) / 8;
byte[] array = new byte[1 + num];
for (int i = 1; i < num; i++) {
array[i] = (byte)namedBits;
namedBits >>= 8;
}
array[num] = (byte)namedBits;
int j;
for (j = 0; (namedBits & (1 << j)) == 0; j++) {
}
array[0] = (byte)j;
m_contents = array;
}
}
public DerBitString(IAsn1Convertible obj)
: this(obj.ToAsn1Object())
{
}
public DerBitString(Asn1Encodable obj)
: this(GetDerContents(obj), false)
{
}
internal DerBitString(byte[] contents, bool check)
{
if (check) {
if (contents == null)
throw new ArgumentNullException("contents");
if (contents.Length < 1)
throw new ArgumentException("cannot be empty", "contents");
int num = contents[0];
if (num > 0) {
if (contents.Length < 2)
throw new ArgumentException("zero length data with non-zero pad bits", "contents");
if (num > 7)
throw new ArgumentException("pad bits cannot be greater than 7 or less than 0", "contents");
}
}
m_contents = contents;
}
public virtual byte[] GetOctets()
{
CheckOctetAligned();
return Arrays.CopyOfRange(m_contents, 1, m_contents.Length);
}
public virtual byte[] GetBytes()
{
if (m_contents.Length == 1)
return Asn1OctetString.EmptyOctets;
int num = m_contents[0];
byte[] array = Arrays.CopyOfRange(m_contents, 1, m_contents.Length);
array[array.Length - 1] &= (byte)(255 << num);
return array;
}
public virtual int GetBytesLength()
{
return m_contents.Length - 1;
}
public virtual bool IsOctetAligned()
{
return PadBits == 0;
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
int num = m_contents[0];
if (num != 0) {
int num2 = m_contents.Length - 1;
byte num3 = m_contents[num2];
byte b = (byte)(num3 & (255 << num));
if (num3 != b)
return new PrimitiveEncodingSuffixed(0, 3, m_contents, b);
}
return new PrimitiveEncoding(0, 3, m_contents);
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
int num = m_contents[0];
if (num != 0) {
int num2 = m_contents.Length - 1;
byte num3 = m_contents[num2];
byte b = (byte)(num3 & (255 << num));
if (num3 != b)
return new PrimitiveEncodingSuffixed(tagClass, tagNo, m_contents, b);
}
return new PrimitiveEncoding(tagClass, tagNo, m_contents);
}
internal sealed override DerEncoding GetEncodingDer()
{
int num = m_contents[0];
if (num != 0) {
int num2 = m_contents.Length - 1;
byte num3 = m_contents[num2];
byte b = (byte)(num3 & (255 << num));
if (num3 != b)
return new PrimitiveDerEncodingSuffixed(0, 3, m_contents, b);
}
return new PrimitiveDerEncoding(0, 3, m_contents);
}
internal sealed override DerEncoding GetEncodingDerImplicit(int tagClass, int tagNo)
{
int num = m_contents[0];
if (num != 0) {
int num2 = m_contents.Length - 1;
byte num3 = m_contents[num2];
byte b = (byte)(num3 & (255 << num));
if (num3 != b)
return new PrimitiveDerEncodingSuffixed(tagClass, tagNo, m_contents, b);
}
return new PrimitiveDerEncoding(tagClass, tagNo, m_contents);
}
protected override int Asn1GetHashCode()
{
if (m_contents.Length < 2)
return 1;
int num = m_contents[0];
int num2 = m_contents.Length - 1;
byte b = (byte)(m_contents[num2] & (255 << num));
return (Arrays.GetHashCode(m_contents, 0, num2) * 257) ^ b;
}
protected override bool Asn1Equals(Asn1Object asn1Object)
{
DerBitString derBitString = asn1Object as DerBitString;
if (derBitString == null)
return false;
byte[] contents = m_contents;
byte[] contents2 = derBitString.m_contents;
int num = contents.Length;
if (contents2.Length != num)
return false;
if (num == 1)
return true;
int num2 = num - 1;
for (int i = 0; i < num2; i++) {
if (contents[i] != contents2[i])
return false;
}
int num3 = contents[0];
byte num4 = (byte)(contents[num2] & (255 << num3));
byte b = (byte)(contents2[num2] & (255 << num3));
return num4 == b;
}
public Stream GetBitStream()
{
return GetMemoryStream();
}
public Stream GetOctetStream()
{
return GetOctetMemoryStream();
}
internal MemoryStream GetOctetMemoryStream()
{
CheckOctetAligned();
return GetMemoryStream();
}
private MemoryStream GetMemoryStream()
{
return new MemoryStream(m_contents, 1, m_contents.Length - 1, false);
}
public override string GetString()
{
byte[] derEncoded = GetDerEncoded();
StringBuilder stringBuilder = new StringBuilder(1 + derEncoded.Length * 2);
stringBuilder.Append('#');
for (int i = 0; i != derEncoded.Length; i++) {
uint num = derEncoded[i];
stringBuilder.Append(table[num >> 4]);
stringBuilder.Append(table[num & 15]);
}
return stringBuilder.ToString();
}
private void CheckOctetAligned()
{
if (m_contents[0] != 0)
throw new IOException("expected octet-aligned bitstring, but found padBits: " + m_contents[0].ToString());
}
internal static DerBitString CreatePrimitive(byte[] contents)
{
int num = contents.Length;
if (num < 1)
throw new ArgumentException("truncated BIT STRING detected", "contents");
int num2 = contents[0];
if (num2 > 0) {
if (num2 > 7 || num < 2)
throw new ArgumentException("invalid pad bits detected", "contents");
byte b = contents[num - 1];
if (b != (byte)(b & (255 << num2)))
return new DLBitString(contents, false);
}
return new DerBitString(contents, false);
}
private static byte[] GetDerContents(Asn1Encodable obj)
{
byte[] encoded = obj.GetEncoded("DER", 1, 0);
encoded[0] = 0;
return encoded;
}
}
}