<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0" />

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; } } }