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

Asn1InputStream

public class Asn1InputStream : FilterStream
using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; using System; using System.IO; namespace Org.BouncyCastle.Asn1 { public class Asn1InputStream : FilterStream { private readonly int limit; private readonly bool m_leaveOpen; internal byte[][] tmpBuffers; internal static int FindLimit(Stream input) { LimitedInputStream limitedInputStream = input as LimitedInputStream; if (limitedInputStream != null) return limitedInputStream.Limit; Asn1InputStream asn1InputStream = input as Asn1InputStream; if (asn1InputStream != null) return asn1InputStream.limit; MemoryStream memoryStream = input as MemoryStream; if (memoryStream != null) return Convert.ToInt32(memoryStream.Length - memoryStream.Position); return 2147483647; } public Asn1InputStream(byte[] input) : this(new MemoryStream(input, false), input.Length) { } public Asn1InputStream(Stream input) : this(input, FindLimit(input)) { } public Asn1InputStream(Stream input, int limit) : this(input, limit, false) { } public Asn1InputStream(Stream input, int limit, bool leaveOpen) : this(input, limit, leaveOpen, new byte[16][]) { } internal Asn1InputStream(Stream input, int limit, bool leaveOpen, byte[][] tmpBuffers) : base(input) { if (!input.CanRead) throw new ArgumentException("Expected stream to be readable", "input"); this.limit = limit; m_leaveOpen = leaveOpen; this.tmpBuffers = tmpBuffers; } protected override void Dispose(bool disposing) { tmpBuffers = null; if (m_leaveOpen) Detach(disposing); else base.Dispose(disposing); } private Asn1Object BuildObject(int tagHdr, int tagNo, int length) { DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(s, length, limit); if ((tagHdr & 224) == 0) return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers); int num = tagHdr & 192; if (num == 0) { switch (tagNo) { case 3: return BuildConstructedBitString(ReadVector(defIn)); case 4: return BuildConstructedOctetString(ReadVector(defIn)); case 16: return DLSequence.FromVector(ReadVector(defIn)); case 17: return DLSet.FromVector(ReadVector(defIn)); case 8: return DLSequence.FromVector(ReadVector(defIn)).ToAsn1External(); default: throw new IOException("unknown tag " + tagNo.ToString() + " encountered"); } } bool constructed = (tagHdr & 32) != 0; return ReadTaggedObjectDL(num, tagNo, constructed, defIn); } internal Asn1Object ReadTaggedObjectDL(int tagClass, int tagNo, bool constructed, DefiniteLengthInputStream defIn) { if (!constructed) { byte[] contentsOctets = defIn.ToArray(); return Asn1TaggedObject.CreatePrimitive(tagClass, tagNo, contentsOctets); } Asn1EncodableVector contentsElements = ReadVector(defIn); return Asn1TaggedObject.CreateConstructedDL(tagClass, tagNo, contentsElements); } private Asn1EncodableVector ReadVector() { Asn1Object asn1Object = ReadObject(); if (asn1Object == null) return new Asn1EncodableVector(0); Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(); do { asn1EncodableVector.Add(asn1Object); } while ((asn1Object = ReadObject()) != null); return asn1EncodableVector; } private Asn1EncodableVector ReadVector(DefiniteLengthInputStream defIn) { int remaining = defIn.Remaining; if (remaining < 1) return new Asn1EncodableVector(0); using (Asn1InputStream asn1InputStream = new Asn1InputStream(defIn, remaining, true, tmpBuffers)) return asn1InputStream.ReadVector(); } public Asn1Object ReadObject() { int num = s.ReadByte(); if (num <= 0) { if (num == 0) throw new IOException("unexpected end-of-contents marker"); return null; } int num2 = ReadTagNumber(s, num); int num3 = ReadLength(s, limit, false); if (num3 >= 0) try { return BuildObject(num, num2, num3); } catch (ArgumentException innerException) { throw new Asn1Exception("corrupted stream detected", innerException); } if ((num & 32) == 0) throw new IOException("indefinite-length primitive encoding encountered"); Asn1StreamParser asn1StreamParser = new Asn1StreamParser(new IndefiniteLengthInputStream(s, limit), limit, tmpBuffers); int num4 = num & 192; if (num4 == 0) { switch (num2) { case 3: return BerBitStringParser.Parse(asn1StreamParser); case 4: return BerOctetStringParser.Parse(asn1StreamParser); case 16: return BerSequenceParser.Parse(asn1StreamParser); case 17: return BerSetParser.Parse(asn1StreamParser); case 8: return DerExternalParser.Parse(asn1StreamParser); default: throw new IOException("unknown BER object encountered"); } } return asn1StreamParser.LoadTaggedIL(num4, num2); } private DerBitString BuildConstructedBitString(Asn1EncodableVector contentsElements) { DerBitString[] array = new DerBitString[contentsElements.Count]; for (int i = 0; i != array.Length; i++) { DerBitString derBitString = contentsElements[i] as DerBitString; if (derBitString == null) throw new Asn1Exception("unknown object encountered in constructed BIT STRING: " + Platform.GetTypeName(contentsElements[i])); array[i] = derBitString; } return new DLBitString(BerBitString.FlattenBitStrings(array), false); } private Asn1OctetString BuildConstructedOctetString(Asn1EncodableVector contentsElements) { Asn1OctetString[] array = new Asn1OctetString[contentsElements.Count]; for (int i = 0; i != array.Length; i++) { Asn1OctetString asn1OctetString = contentsElements[i] as Asn1OctetString; if (asn1OctetString == null) throw new Asn1Exception("unknown object encountered in constructed OCTET STRING: " + Platform.GetTypeName(contentsElements[i])); array[i] = asn1OctetString; } return new DerOctetString(BerOctetString.FlattenOctetStrings(array)); } internal static int ReadTagNumber(Stream s, int tagHdr) { int num = tagHdr & 31; if (num == 31) { int num2 = s.ReadByte(); if (num2 < 31) { if (num2 < 0) throw new EndOfStreamException("EOF found inside tag value."); throw new IOException("corrupted stream - high tag number < 31 found"); } num = (num2 & 127); if (num == 0) throw new IOException("corrupted stream - invalid high tag number found"); while ((num2 & 128) != 0) { if ((uint)num >> 24 != 0) throw new IOException("Tag number more than 31 bits"); num <<= 7; num2 = s.ReadByte(); if (num2 < 0) throw new EndOfStreamException("EOF found inside tag value."); num |= (num2 & 127); } } return num; } internal static int ReadLength(Stream s, int limit, bool isParsing) { int num = s.ReadByte(); if ((uint)num >> 7 == 0) return num; if (128 == num) return -1; if (num < 0) throw new EndOfStreamException("EOF found when length expected"); if (255 == num) throw new IOException("invalid long form definite-length 0xFF"); int num2 = num & 127; int num3 = 0; num = 0; do { int num4 = s.ReadByte(); if (num4 < 0) throw new EndOfStreamException("EOF found reading length"); if ((uint)num >> 23 != 0) throw new IOException("long form definite-length more than 31 bits"); num = (num << 8) + num4; } while (++num3 < num2); if (num >= limit && !isParsing) throw new IOException("corrupted stream - out of bounds length found: " + num.ToString() + " >= " + limit.ToString()); return num; } private static bool GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers, out byte[] contents) { int remaining = defIn.Remaining; if (remaining >= tmpBuffers.Length) { contents = defIn.ToArray(); return false; } byte[] array = tmpBuffers[remaining]; if (array == null) array = (tmpBuffers[remaining] = new byte[remaining]); defIn.ReadAllIntoByteArray(array); contents = array; return true; } internal static Asn1Object CreatePrimitiveDerObject(int tagNo, DefiniteLengthInputStream defIn, byte[][] tmpBuffers) { switch (tagNo) { case 30: return CreateDerBmpString(defIn); case 1: GetBuffer(defIn, tmpBuffers, out byte[] contents5); return DerBoolean.CreatePrimitive(contents5); case 10: { byte[] contents4; bool buffer3 = GetBuffer(defIn, tmpBuffers, out contents4); return DerEnumerated.CreatePrimitive(contents4, buffer3); } case 6: { DerObjectIdentifier.CheckContentsLength(defIn.Remaining); byte[] contents3; bool buffer2 = GetBuffer(defIn, tmpBuffers, out contents3); return DerObjectIdentifier.CreatePrimitive(contents3, buffer2); } case 13: { Asn1RelativeOid.CheckContentsLength(defIn.Remaining); byte[] contents2; bool buffer = GetBuffer(defIn, tmpBuffers, out contents2); return Asn1RelativeOid.CreatePrimitive(contents2, buffer); } default: { byte[] contents = defIn.ToArray(); switch (tagNo) { case 3: return DerBitString.CreatePrimitive(contents); case 24: return Asn1GeneralizedTime.CreatePrimitive(contents); case 27: return DerGeneralString.CreatePrimitive(contents); case 25: return DerGraphicString.CreatePrimitive(contents); case 22: return DerIA5String.CreatePrimitive(contents); case 2: return DerInteger.CreatePrimitive(contents); case 5: return Asn1Null.CreatePrimitive(contents); case 18: return DerNumericString.CreatePrimitive(contents); case 7: return Asn1ObjectDescriptor.CreatePrimitive(contents); case 4: return Asn1OctetString.CreatePrimitive(contents); case 19: return DerPrintableString.CreatePrimitive(contents); case 20: return DerT61String.CreatePrimitive(contents); case 28: return DerUniversalString.CreatePrimitive(contents); case 23: return Asn1UtcTime.CreatePrimitive(contents); case 12: return DerUtf8String.CreatePrimitive(contents); case 21: return DerVideotexString.CreatePrimitive(contents); case 26: return DerVisibleString.CreatePrimitive(contents); case 9: case 11: case 14: case 29: case 31: case 32: case 33: case 34: case 35: case 36: throw new IOException("unsupported tag " + tagNo.ToString() + " encountered"); default: throw new IOException("unknown tag " + tagNo.ToString() + " encountered"); } } } } private static DerBmpString CreateDerBmpString(DefiniteLengthInputStream defIn) { int num = defIn.Remaining; if ((num & 1) != 0) throw new IOException("malformed BMPString encoding encountered"); char[] array = new char[num / 2]; int num2 = 0; byte[] array2 = new byte[8]; while (num >= 8) { if (Streams.ReadFully(defIn, array2, 0, 8) != 8) throw new EndOfStreamException("EOF encountered in middle of BMPString"); array[num2] = (char)((array2[0] << 8) | (array2[1] & 255)); array[num2 + 1] = (char)((array2[2] << 8) | (array2[3] & 255)); array[num2 + 2] = (char)((array2[4] << 8) | (array2[5] & 255)); array[num2 + 3] = (char)((array2[6] << 8) | (array2[7] & 255)); num2 += 4; num -= 8; } if (num > 0) { if (Streams.ReadFully(defIn, array2, 0, num) != num) throw new EndOfStreamException("EOF encountered in middle of BMPString"); int num3 = 0; do { int num5 = array2[num3++] << 8; int num7 = array2[num3++] & 255; array[num2++] = (char)(num5 | num7); } while (num3 < num); } if (defIn.Remaining != 0 || array.Length != num2) throw new InvalidOperationException(); return DerBmpString.CreatePrimitive(array); } } }