summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-01-21 19:43:45 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-01-21 19:43:45 +0700
commite881ee06950d623a7678cda637ebd39dd33658fa (patch)
tree63d04a0b3229b35db606e736506943cb55170b51
parentBMA-118 (diff)
downloadBouncyCastle.NET-ed25519-e881ee06950d623a7678cda637ebd39dd33658fa.tar.xz
Stop using DerUnknownTag (throw exceptions during parsing instead)
-rw-r--r--crypto/src/asn1/ASN1StreamParser.cs5
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs626
-rw-r--r--crypto/src/asn1/util/Asn1Dump.cs289
-rw-r--r--crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs1
4 files changed, 457 insertions, 464 deletions
diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs
index a5e6e3164..0c6b4413a 100644
--- a/crypto/src/asn1/ASN1StreamParser.cs
+++ b/crypto/src/asn1/ASN1StreamParser.cs
@@ -187,9 +187,8 @@ namespace Org.BouncyCastle.Asn1
 						case Asn1Tags.External:
 							return new DerExternalParser(new Asn1StreamParser(defIn));
 						default:
-							// TODO Add DerUnknownTagParser class?
-							return new DerUnknownTag(true, tagNo, defIn.ToArray());
-					}
+                            throw new IOException("unknown tag " + tagNo + " encountered");
+                    }
 				}
 
 				// Some primitive encodings can be handled by parsers too...
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 5d5590655..18d13c32d 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -7,290 +7,290 @@ using Org.BouncyCastle.Utilities.IO;
 
 namespace Org.BouncyCastle.Asn1
 {
-	/**
-	 * a general purpose ASN.1 decoder - note: this class differs from the
-	 * others in that it returns null after it has read the last object in
-	 * the stream. If an ASN.1 Null is encountered a Der/BER Null object is
-	 * returned.
-	 */
-	public class Asn1InputStream
-		: FilterStream
-	{
-		private readonly int limit;
+    /**
+     * a general purpose ASN.1 decoder - note: this class differs from the
+     * others in that it returns null after it has read the last object in
+     * the stream. If an ASN.1 Null is encountered a Der/BER Null object is
+     * returned.
+     */
+    public class Asn1InputStream
+        : FilterStream
+    {
+        private readonly int limit;
 
         private readonly byte[][] tmpBuffers;
 
         internal static int FindLimit(Stream input)
-		{
-			if (input is LimitedInputStream)
-			{
-				return ((LimitedInputStream)input).GetRemaining();
-			}
-			else if (input is MemoryStream)
-			{
-				MemoryStream mem = (MemoryStream)input;
-				return (int)(mem.Length - mem.Position);
-			}
-
-			return int.MaxValue;
-		}
-
-		public Asn1InputStream(
-			Stream inputStream)
-			: this(inputStream, FindLimit(inputStream))
-		{
-		}
-
-		/**
-		 * Create an ASN1InputStream where no DER object will be longer than limit.
-		 *
-		 * @param input stream containing ASN.1 encoded data.
-		 * @param limit maximum size of a DER encoded object.
-		 */
-		public Asn1InputStream(
-			Stream	inputStream,
-			int		limit)
-			: base(inputStream)
-		{
-			this.limit = limit;
+        {
+            if (input is LimitedInputStream)
+            {
+                return ((LimitedInputStream)input).GetRemaining();
+            }
+            else if (input is MemoryStream)
+            {
+                MemoryStream mem = (MemoryStream)input;
+                return (int)(mem.Length - mem.Position);
+            }
+
+            return int.MaxValue;
+        }
+
+        public Asn1InputStream(
+            Stream inputStream)
+            : this(inputStream, FindLimit(inputStream))
+        {
+        }
+
+        /**
+         * Create an ASN1InputStream where no DER object will be longer than limit.
+         *
+         * @param input stream containing ASN.1 encoded data.
+         * @param limit maximum size of a DER encoded object.
+         */
+        public Asn1InputStream(
+            Stream	inputStream,
+            int		limit)
+            : base(inputStream)
+        {
+            this.limit = limit;
             this.tmpBuffers = new byte[16][];
         }
 
-		/**
-		 * Create an ASN1InputStream based on the input byte array. The length of DER objects in
-		 * the stream is automatically limited to the length of the input array.
-		 *
-		 * @param input array containing ASN.1 encoded data.
-		 */
-		public Asn1InputStream(
-			byte[] input)
-			: this(new MemoryStream(input, false), input.Length)
-		{
-		}
-
-		/**
-		* build an object given its tag and the number of bytes to construct it from.
-		*/
-		private Asn1Object BuildObject(
-			int	tag,
-			int	tagNo,
-			int	length)
-		{
-			bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
-
-			DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length);
-
-			if ((tag & Asn1Tags.Application) != 0)
-			{
-				return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
-			}
-
-			if ((tag & Asn1Tags.Tagged) != 0)
-			{
-				return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo);
-			}
-
-			if (isConstructed)
-			{
-				// TODO There are other tags that may be constructed (e.g. BitString)
-				switch (tagNo)
-				{
-					case Asn1Tags.OctetString:
-						//
-						// yes, people actually do this...
-						//
-						return new BerOctetString(BuildDerEncodableVector(defIn));
-					case Asn1Tags.Sequence:
-						return CreateDerSequence(defIn);
-					case Asn1Tags.Set:
-						return CreateDerSet(defIn);
-					case Asn1Tags.External:
-						return new DerExternal(BuildDerEncodableVector(defIn));                
-					default:
-						return new DerUnknownTag(true, tagNo, defIn.ToArray());
-				}
-			}
+        /**
+         * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+         * the stream is automatically limited to the length of the input array.
+         *
+         * @param input array containing ASN.1 encoded data.
+         */
+        public Asn1InputStream(
+            byte[] input)
+            : this(new MemoryStream(input, false), input.Length)
+        {
+        }
+
+        /**
+        * build an object given its tag and the number of bytes to construct it from.
+        */
+        private Asn1Object BuildObject(
+            int	tag,
+            int	tagNo,
+            int	length)
+        {
+            bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+            DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length);
+
+            if ((tag & Asn1Tags.Application) != 0)
+            {
+                return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
+            }
+
+            if ((tag & Asn1Tags.Tagged) != 0)
+            {
+                return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo);
+            }
+
+            if (isConstructed)
+            {
+                // TODO There are other tags that may be constructed (e.g. BitString)
+                switch (tagNo)
+                {
+                    case Asn1Tags.OctetString:
+                        //
+                        // yes, people actually do this...
+                        //
+                        return new BerOctetString(BuildDerEncodableVector(defIn));
+                    case Asn1Tags.Sequence:
+                        return CreateDerSequence(defIn);
+                    case Asn1Tags.Set:
+                        return CreateDerSet(defIn);
+                    case Asn1Tags.External:
+                        return new DerExternal(BuildDerEncodableVector(defIn));                
+                    default:
+                        throw new IOException("unknown tag " + tagNo + " encountered");
+                }
+            }
 
             return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers);
-		}
+        }
 
         internal Asn1EncodableVector BuildEncodableVector()
-		{
-			Asn1EncodableVector v = new Asn1EncodableVector();
-
-			Asn1Object o;
-			while ((o = ReadObject()) != null)
-			{
-				v.Add(o);
-			}
-
-			return v;
-		}
-
-		internal virtual Asn1EncodableVector BuildDerEncodableVector(
-			DefiniteLengthInputStream dIn)
-		{
-			return new Asn1InputStream(dIn).BuildEncodableVector();
-		}
-
-		internal virtual DerSequence CreateDerSequence(
-			DefiniteLengthInputStream dIn)
-		{
-			return DerSequence.FromVector(BuildDerEncodableVector(dIn));
-		}
-
-		internal virtual DerSet CreateDerSet(
-			DefiniteLengthInputStream dIn)
-		{
-			return DerSet.FromVector(BuildDerEncodableVector(dIn), false);
-		}
-
-		public Asn1Object ReadObject()
-		{
-			int tag = ReadByte();
-			if (tag <= 0)
-			{
-				if (tag == 0)
-					throw new IOException("unexpected end-of-contents marker");
-
-				return null;
-			}
-
-			//
-			// calculate tag number
-			//
-			int tagNo = ReadTagNumber(this.s, tag);
-
-			bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
-
-			//
-			// calculate length
-			//
-			int length = ReadLength(this.s, limit);
-
-			if (length < 0) // indefinite length method
-			{
-				if (!isConstructed)
-					throw new IOException("indefinite length primitive encoding encountered");
-
-				IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit);
-            	Asn1StreamParser sp = new Asn1StreamParser(indIn, limit);
-
-				if ((tag & Asn1Tags.Application) != 0)
-				{
-					return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object();
-				}
-
-				if ((tag & Asn1Tags.Tagged) != 0)
-				{
-					return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object();
-				}
-
-				// TODO There are other tags that may be constructed (e.g. BitString)
-				switch (tagNo)
-				{
-					case Asn1Tags.OctetString:
-						return new BerOctetStringParser(sp).ToAsn1Object();
-					case Asn1Tags.Sequence:
-						return new BerSequenceParser(sp).ToAsn1Object();
-					case Asn1Tags.Set:
-						return new BerSetParser(sp).ToAsn1Object();
-					case Asn1Tags.External:
-						return new DerExternalParser(sp).ToAsn1Object();
-					default:
-						throw new IOException("unknown BER object encountered");
-				}
-			}
-			else
-			{
-				try
-				{
-					return BuildObject(tag, tagNo, length);
-				}
-				catch (ArgumentException e)
-				{
-					throw new Asn1Exception("corrupted stream detected", e);
-				}
-			}
-		}
-
-		internal static int ReadTagNumber(
-			Stream	s,
-			int		tag)
-		{
-			int tagNo = tag & 0x1f;
-
-			//
-			// with tagged object tag number is bottom 5 bits, or stored at the start of the content
-			//
-			if (tagNo == 0x1f)
-			{
-				tagNo = 0;
-
-				int b = s.ReadByte();
-
-				// X.690-0207 8.1.2.4.2
-				// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
-				if ((b & 0x7f) == 0) // Note: -1 will pass
-				{
-					throw new IOException("Corrupted stream - invalid high tag number found");
-				}
-
-				while ((b >= 0) && ((b & 0x80) != 0))
-				{
-					tagNo |= (b & 0x7f);
-					tagNo <<= 7;
-					b = s.ReadByte();
-				}
-
-				if (b < 0)
-					throw new EndOfStreamException("EOF found inside tag value.");
-
-				tagNo |= (b & 0x7f);
-			}
-
-			return tagNo;
-		}
-
-		internal static int ReadLength(
-			Stream	s,
-			int		limit)
-		{
-			int length = s.ReadByte();
-			if (length < 0)
-				throw new EndOfStreamException("EOF found when length expected");
-
-			if (length == 0x80)
-				return -1;      // indefinite-length encoding
-
-			if (length > 127)
-			{
-				int size = length & 0x7f;
-
-				// Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
-				if (size > 4)
-					throw new IOException("DER length more than 4 bytes: " + size);
-
-				length = 0;
-				for (int i = 0; i < size; i++)
-				{
-					int next = s.ReadByte();
-
-					if (next < 0)
-						throw new EndOfStreamException("EOF found reading length");
-
-					length = (length << 8) + next;
-				}
-
-				if (length < 0)
-					throw new IOException("Corrupted stream - negative length found");
-
-				if (length >= limit)   // after all we must have read at least 1 byte
-					throw new IOException("Corrupted stream - out of bounds length found");
-			}
-
-			return length;
-		}
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            Asn1Object o;
+            while ((o = ReadObject()) != null)
+            {
+                v.Add(o);
+            }
+
+            return v;
+        }
+
+        internal virtual Asn1EncodableVector BuildDerEncodableVector(
+            DefiniteLengthInputStream dIn)
+        {
+            return new Asn1InputStream(dIn).BuildEncodableVector();
+        }
+
+        internal virtual DerSequence CreateDerSequence(
+            DefiniteLengthInputStream dIn)
+        {
+            return DerSequence.FromVector(BuildDerEncodableVector(dIn));
+        }
+
+        internal virtual DerSet CreateDerSet(
+            DefiniteLengthInputStream dIn)
+        {
+            return DerSet.FromVector(BuildDerEncodableVector(dIn), false);
+        }
+
+        public Asn1Object ReadObject()
+        {
+            int tag = ReadByte();
+            if (tag <= 0)
+            {
+                if (tag == 0)
+                    throw new IOException("unexpected end-of-contents marker");
+
+                return null;
+            }
+
+            //
+            // calculate tag number
+            //
+            int tagNo = ReadTagNumber(this.s, tag);
+
+            bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+            //
+            // calculate length
+            //
+            int length = ReadLength(this.s, limit);
+
+            if (length < 0) // indefinite length method
+            {
+                if (!isConstructed)
+                    throw new IOException("indefinite length primitive encoding encountered");
+
+                IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit);
+                Asn1StreamParser sp = new Asn1StreamParser(indIn, limit);
+
+                if ((tag & Asn1Tags.Application) != 0)
+                {
+                    return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object();
+                }
+
+                if ((tag & Asn1Tags.Tagged) != 0)
+                {
+                    return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object();
+                }
+
+                // TODO There are other tags that may be constructed (e.g. BitString)
+                switch (tagNo)
+                {
+                    case Asn1Tags.OctetString:
+                        return new BerOctetStringParser(sp).ToAsn1Object();
+                    case Asn1Tags.Sequence:
+                        return new BerSequenceParser(sp).ToAsn1Object();
+                    case Asn1Tags.Set:
+                        return new BerSetParser(sp).ToAsn1Object();
+                    case Asn1Tags.External:
+                        return new DerExternalParser(sp).ToAsn1Object();
+                    default:
+                        throw new IOException("unknown BER object encountered");
+                }
+            }
+            else
+            {
+                try
+                {
+                    return BuildObject(tag, tagNo, length);
+                }
+                catch (ArgumentException e)
+                {
+                    throw new Asn1Exception("corrupted stream detected", e);
+                }
+            }
+        }
+
+        internal static int ReadTagNumber(
+            Stream	s,
+            int		tag)
+        {
+            int tagNo = tag & 0x1f;
+
+            //
+            // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+            //
+            if (tagNo == 0x1f)
+            {
+                tagNo = 0;
+
+                int b = s.ReadByte();
+
+                // X.690-0207 8.1.2.4.2
+                // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+                if ((b & 0x7f) == 0) // Note: -1 will pass
+                {
+                    throw new IOException("Corrupted stream - invalid high tag number found");
+                }
+
+                while ((b >= 0) && ((b & 0x80) != 0))
+                {
+                    tagNo |= (b & 0x7f);
+                    tagNo <<= 7;
+                    b = s.ReadByte();
+                }
+
+                if (b < 0)
+                    throw new EndOfStreamException("EOF found inside tag value.");
+
+                tagNo |= (b & 0x7f);
+            }
+
+            return tagNo;
+        }
+
+        internal static int ReadLength(
+            Stream	s,
+            int		limit)
+        {
+            int length = s.ReadByte();
+            if (length < 0)
+                throw new EndOfStreamException("EOF found when length expected");
+
+            if (length == 0x80)
+                return -1;      // indefinite-length encoding
+
+            if (length > 127)
+            {
+                int size = length & 0x7f;
+
+                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+                if (size > 4)
+                    throw new IOException("DER length more than 4 bytes: " + size);
+
+                length = 0;
+                for (int i = 0; i < size; i++)
+                {
+                    int next = s.ReadByte();
+
+                    if (next < 0)
+                        throw new EndOfStreamException("EOF found reading length");
+
+                    length = (length << 8) + next;
+                }
+
+                if (length < 0)
+                    throw new IOException("Corrupted stream - negative length found");
+
+                if (length >= limit)   // after all we must have read at least 1 byte
+                    throw new IOException("Corrupted stream - out of bounds length found");
+            }
+
+            return length;
+        }
 
         internal static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
         {
@@ -311,11 +311,11 @@ namespace Org.BouncyCastle.Asn1
             return buf;
         }
 
-		internal static Asn1Object CreatePrimitiveDerObject(
-			int                         tagNo,
-			DefiniteLengthInputStream   defIn,
+        internal static Asn1Object CreatePrimitiveDerObject(
+            int                         tagNo,
+            DefiniteLengthInputStream   defIn,
             byte[][]                    tmpBuffers)
-		{
+        {
             switch (tagNo)
             {
                 case Asn1Tags.Boolean:
@@ -329,40 +329,40 @@ namespace Org.BouncyCastle.Asn1
             byte[] bytes = defIn.ToArray();
 
             switch (tagNo)
-			{
-				case Asn1Tags.BitString:
-					return DerBitString.FromAsn1Octets(bytes);
-				case Asn1Tags.BmpString:
-					return new DerBmpString(bytes);
-				case Asn1Tags.GeneralizedTime:
-					return new DerGeneralizedTime(bytes);
-				case Asn1Tags.GeneralString:
-					return new DerGeneralString(bytes);
-				case Asn1Tags.IA5String:
-					return new DerIA5String(bytes);
-				case Asn1Tags.Integer:
-					return new DerInteger(bytes);
-				case Asn1Tags.Null:
-					return DerNull.Instance;   // actual content is ignored (enforce 0 length?)
-				case Asn1Tags.NumericString:
-					return new DerNumericString(bytes);
-				case Asn1Tags.OctetString:
-					return new DerOctetString(bytes);
-				case Asn1Tags.PrintableString:
-					return new DerPrintableString(bytes);
-				case Asn1Tags.T61String:
-					return new DerT61String(bytes);
-				case Asn1Tags.UniversalString:
-					return new DerUniversalString(bytes);
-				case Asn1Tags.UtcTime:
-					return new DerUtcTime(bytes);
-				case Asn1Tags.Utf8String:
-					return new DerUtf8String(bytes);
-				case Asn1Tags.VisibleString:
-					return new DerVisibleString(bytes);
-				default:
-					return new DerUnknownTag(false, tagNo, bytes);
-			}
-		}
-	}
+            {
+                case Asn1Tags.BitString:
+                    return DerBitString.FromAsn1Octets(bytes);
+                case Asn1Tags.BmpString:
+                    return new DerBmpString(bytes);
+                case Asn1Tags.GeneralizedTime:
+                    return new DerGeneralizedTime(bytes);
+                case Asn1Tags.GeneralString:
+                    return new DerGeneralString(bytes);
+                case Asn1Tags.IA5String:
+                    return new DerIA5String(bytes);
+                case Asn1Tags.Integer:
+                    return new DerInteger(bytes);
+                case Asn1Tags.Null:
+                    return DerNull.Instance;   // actual content is ignored (enforce 0 length?)
+                case Asn1Tags.NumericString:
+                    return new DerNumericString(bytes);
+                case Asn1Tags.OctetString:
+                    return new DerOctetString(bytes);
+                case Asn1Tags.PrintableString:
+                    return new DerPrintableString(bytes);
+                case Asn1Tags.T61String:
+                    return new DerT61String(bytes);
+                case Asn1Tags.UniversalString:
+                    return new DerUniversalString(bytes);
+                case Asn1Tags.UtcTime:
+                    return new DerUtcTime(bytes);
+                case Asn1Tags.Utf8String:
+                    return new DerUtf8String(bytes);
+                case Asn1Tags.VisibleString:
+                    return new DerVisibleString(bytes);
+                default:
+                    throw new IOException("unknown tag " + tagNo + " encountered");
+            }
+        }
+    }
 }
diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs
index 43d485500..36b17c8fd 100644
--- a/crypto/src/asn1/util/Asn1Dump.cs
+++ b/crypto/src/asn1/util/Asn1Dump.cs
@@ -10,9 +10,9 @@ namespace Org.BouncyCastle.Asn1.Utilities
 {
     public sealed class Asn1Dump
     {
-		private static readonly string NewLine = Platform.NewLine;
+        private static readonly string NewLine = Platform.NewLine;
 
-		private Asn1Dump()
+        private Asn1Dump()
         {
         }
 
@@ -28,12 +28,12 @@ namespace Org.BouncyCastle.Asn1.Utilities
             string			indent,
             bool			verbose,
             Asn1Object		obj,
-			StringBuilder	buf)
+            StringBuilder	buf)
         {
             if (obj is Asn1Sequence)
             {
-				string tab = indent + Tab;
-				buf.Append(indent);
+                string tab = indent + Tab;
+                buf.Append(indent);
                 if (obj is BerSequence)
                 {
                     buf.Append("BER Sequence");
@@ -49,8 +49,8 @@ namespace Org.BouncyCastle.Asn1.Utilities
 
                 buf.Append(NewLine);
 
-				foreach (Asn1Encodable o in ((Asn1Sequence)obj))
-				{
+                foreach (Asn1Encodable o in ((Asn1Sequence)obj))
+                {
                     if (o == null || o is Asn1Null)
                     {
                         buf.Append(tab);
@@ -66,7 +66,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
             else if (obj is DerTaggedObject)
             {
                 string tab = indent + Tab;
-				buf.Append(indent);
+                buf.Append(indent);
                 if (obj is BerTaggedObject)
                 {
                     buf.Append("BER Tagged [");
@@ -76,19 +76,19 @@ namespace Org.BouncyCastle.Asn1.Utilities
                     buf.Append("Tagged [");
                 }
 
-				DerTaggedObject o = (DerTaggedObject)obj;
+                DerTaggedObject o = (DerTaggedObject)obj;
 
-				buf.Append(((int)o.TagNo).ToString());
+                buf.Append(((int)o.TagNo).ToString());
                 buf.Append(']');
 
-				if (!o.IsExplicit())
+                if (!o.IsExplicit())
                 {
                     buf.Append(" IMPLICIT ");
                 }
 
-				buf.Append(NewLine);
+                buf.Append(NewLine);
 
-				if (o.IsEmpty())
+                if (o.IsEmpty())
                 {
                     buf.Append(tab);
                     buf.Append("EMPTY");
@@ -103,12 +103,12 @@ namespace Org.BouncyCastle.Asn1.Utilities
             {
                 string tab = indent + Tab;
 
-				buf.Append(indent);
+                buf.Append(indent);
                 buf.Append("BER Set");
                 buf.Append(NewLine);
 
-				foreach (Asn1Encodable o in ((Asn1Set)obj))
-				{
+                foreach (Asn1Encodable o in ((Asn1Set)obj))
+                {
                     if (o == null)
                     {
                         buf.Append(tab);
@@ -125,12 +125,12 @@ namespace Org.BouncyCastle.Asn1.Utilities
             {
                 string tab = indent + Tab;
 
-				buf.Append(indent);
+                buf.Append(indent);
                 buf.Append("DER Set");
                 buf.Append(NewLine);
 
-				foreach (Asn1Encodable o in ((Asn1Set)obj))
-				{
+                foreach (Asn1Encodable o in ((Asn1Set)obj))
+                {
                     if (o == null)
                     {
                         buf.Append(tab);
@@ -155,33 +155,33 @@ namespace Org.BouncyCastle.Asn1.Utilities
             {
                 buf.Append(indent + "Integer(" + ((DerInteger)obj).Value + ")" + NewLine);
             }
-			else if (obj is BerOctetString)
-			{
-				byte[] octets = ((Asn1OctetString)obj).GetOctets();
-				string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
-				buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
-			}
+            else if (obj is BerOctetString)
+            {
+                byte[] octets = ((Asn1OctetString)obj).GetOctets();
+                string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
+                buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
+            }
             else if (obj is DerOctetString)
             {
-				byte[] octets = ((Asn1OctetString)obj).GetOctets();
-				string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
-				buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
-			}
-			else if (obj is DerBitString)
-			{
-				DerBitString bt = (DerBitString)obj; 
-				byte[] bytes = bt.GetBytes();
-				string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : "";
-				buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine);
-			}
+                byte[] octets = ((Asn1OctetString)obj).GetOctets();
+                string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
+                buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
+            }
+            else if (obj is DerBitString)
+            {
+                DerBitString bt = (DerBitString)obj; 
+                byte[] bytes = bt.GetBytes();
+                string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : "";
+                buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine);
+            }
             else if (obj is DerIA5String)
             {
                 buf.Append(indent + "IA5String(" + ((DerIA5String)obj).GetString() + ") " + NewLine);
             }
-			else if (obj is DerUtf8String)
-			{
-				buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine);
-			}
+            else if (obj is DerUtf8String)
+            {
+                buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine);
+            }
             else if (obj is DerPrintableString)
             {
                 buf.Append(indent + "PrintableString(" + ((DerPrintableString)obj).GetString() + ") " + NewLine);
@@ -202,14 +202,9 @@ namespace Org.BouncyCastle.Asn1.Utilities
             {
                 buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine);
             }
-			else if (obj is DerGeneralizedTime)
-			{
-				buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine);
-			}
-            else if (obj is DerUnknownTag)
+            else if (obj is DerGeneralizedTime)
             {
-				string hex = Hex.ToHexString(((DerUnknownTag)obj).GetData());
-                buf.Append(indent + "Unknown " + ((int)((DerUnknownTag)obj).Tag).ToString("X") + " " + hex + NewLine);
+                buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine);
             }
             else if (obj is BerApplicationSpecific)
             {
@@ -219,32 +214,32 @@ namespace Org.BouncyCastle.Asn1.Utilities
             {
                 buf.Append(outputApplicationSpecific("DER", indent, verbose, (DerApplicationSpecific)obj));
             }
-			else if (obj is DerEnumerated)
-			{
-				DerEnumerated en = (DerEnumerated)obj;
-				buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine);
-			}
-			else if (obj is DerExternal)
-			{
-				DerExternal ext = (DerExternal)obj;
-				buf.Append(indent + "External " + NewLine);
+            else if (obj is DerEnumerated)
+            {
+                DerEnumerated en = (DerEnumerated)obj;
+                buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine);
+            }
+            else if (obj is DerExternal)
+            {
+                DerExternal ext = (DerExternal)obj;
+                buf.Append(indent + "External " + NewLine);
                 string tab = indent + Tab;
 
-				if (ext.DirectReference != null)
-				{
-					buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine);
-				}
-				if (ext.IndirectReference != null)
-				{
-					buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine);
-				}
-				if (ext.DataValueDescriptor != null)
-				{
-					AsString(tab, verbose, ext.DataValueDescriptor, buf);
-				}
-				buf.Append(tab + "Encoding: " + ext.Encoding + NewLine);
-				AsString(tab, verbose, ext.ExternalContent, buf);
-			}
+                if (ext.DirectReference != null)
+                {
+                    buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine);
+                }
+                if (ext.IndirectReference != null)
+                {
+                    buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine);
+                }
+                if (ext.DataValueDescriptor != null)
+                {
+                    AsString(tab, verbose, ext.DataValueDescriptor, buf);
+                }
+                buf.Append(tab + "Encoding: " + ext.Encoding + NewLine);
+                AsString(tab, verbose, ext.ExternalContent, buf);
+            }
             else
             {
                 buf.Append(indent + obj.ToString() + NewLine);
@@ -267,7 +262,7 @@ namespace Org.BouncyCastle.Asn1.Utilities
                     buf.Append(indent + type + " ApplicationSpecific[" + app.ApplicationTag + "]" + NewLine);
                     foreach (Asn1Encodable ae in s)
                     {
-                    	AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf);
+                        AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf);
                     }
                 }
                 catch (IOException e)
@@ -281,98 +276,98 @@ namespace Org.BouncyCastle.Asn1.Utilities
                 + Hex.ToHexString(app.GetContents()) + ")" + NewLine;
         }
 
-		[Obsolete("Use version accepting Asn1Encodable")]
-		public static string DumpAsString(
+        [Obsolete("Use version accepting Asn1Encodable")]
+        public static string DumpAsString(
             object   obj)
         {
             if (obj is Asn1Encodable)
             {
-				StringBuilder buf = new StringBuilder();
+                StringBuilder buf = new StringBuilder();
                 AsString("", false, ((Asn1Encodable)obj).ToAsn1Object(), buf);
-				return buf.ToString();
+                return buf.ToString();
             }
 
             return "unknown object type " + obj.ToString();
         }
 
-		/**
-		 * dump out a DER object as a formatted string, in non-verbose mode
-		 *
-		 * @param obj the Asn1Encodable to be dumped out.
-		 * @return  the resulting string.
-		 */
-		public static string DumpAsString(
-			Asn1Encodable obj)
-		{
-			return DumpAsString(obj, false);
-		}
+        /**
+         * dump out a DER object as a formatted string, in non-verbose mode
+         *
+         * @param obj the Asn1Encodable to be dumped out.
+         * @return  the resulting string.
+         */
+        public static string DumpAsString(
+            Asn1Encodable obj)
+        {
+            return DumpAsString(obj, false);
+        }
 
-		/**
-		 * Dump out the object as a string
-		 *
-		 * @param obj the Asn1Encodable to be dumped out.
-		 * @param verbose  if true, dump out the contents of octet and bit strings.
-		 * @return  the resulting string.
-		 */
-		public static string DumpAsString(
-			Asn1Encodable	obj,
-			bool			verbose)
-		{
-			StringBuilder buf = new StringBuilder();
-			AsString("", verbose, obj.ToAsn1Object(), buf);
-			return buf.ToString();
-		}
+        /**
+         * Dump out the object as a string
+         *
+         * @param obj the Asn1Encodable to be dumped out.
+         * @param verbose  if true, dump out the contents of octet and bit strings.
+         * @return  the resulting string.
+         */
+        public static string DumpAsString(
+            Asn1Encodable	obj,
+            bool			verbose)
+        {
+            StringBuilder buf = new StringBuilder();
+            AsString("", verbose, obj.ToAsn1Object(), buf);
+            return buf.ToString();
+        }
 
-		private static string dumpBinaryDataAsString(string indent, byte[] bytes)
-		{
-			indent += Tab;
+        private static string dumpBinaryDataAsString(string indent, byte[] bytes)
+        {
+            indent += Tab;
 
-			StringBuilder buf = new StringBuilder(NewLine);
+            StringBuilder buf = new StringBuilder(NewLine);
 
-			for (int i = 0; i < bytes.Length; i += SampleSize)
-			{
-				if (bytes.Length - i > SampleSize)
-				{
-					buf.Append(indent);
-					buf.Append(Hex.ToHexString(bytes, i, SampleSize));
-					buf.Append(Tab);
-					buf.Append(calculateAscString(bytes, i, SampleSize));
-					buf.Append(NewLine);
-				}
-				else
-				{
-					buf.Append(indent);
-					buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i));
-					for (int j = bytes.Length - i; j != SampleSize; j++)
-					{
-						buf.Append("  ");
-					}
-					buf.Append(Tab);
-					buf.Append(calculateAscString(bytes, i, bytes.Length - i));
-					buf.Append(NewLine);
-				}
-			}
+            for (int i = 0; i < bytes.Length; i += SampleSize)
+            {
+                if (bytes.Length - i > SampleSize)
+                {
+                    buf.Append(indent);
+                    buf.Append(Hex.ToHexString(bytes, i, SampleSize));
+                    buf.Append(Tab);
+                    buf.Append(calculateAscString(bytes, i, SampleSize));
+                    buf.Append(NewLine);
+                }
+                else
+                {
+                    buf.Append(indent);
+                    buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i));
+                    for (int j = bytes.Length - i; j != SampleSize; j++)
+                    {
+                        buf.Append("  ");
+                    }
+                    buf.Append(Tab);
+                    buf.Append(calculateAscString(bytes, i, bytes.Length - i));
+                    buf.Append(NewLine);
+                }
+            }
 
-			return buf.ToString();
-		}
+            return buf.ToString();
+        }
 
-		private static string calculateAscString(
-			byte[]	bytes,
-			int		off,
-			int		len)
-		{
-			StringBuilder buf = new StringBuilder();
+        private static string calculateAscString(
+            byte[]	bytes,
+            int		off,
+            int		len)
+        {
+            StringBuilder buf = new StringBuilder();
 
-			for (int i = off; i != off + len; i++)
-			{
-				char c = (char)bytes[i]; 
-				if (c >= ' ' && c <= '~')
-				{
-					buf.Append(c);
-				}
-			}
+            for (int i = off; i != off + len; i++)
+            {
+                char c = (char)bytes[i]; 
+                if (c >= ' ' && c <= '~')
+                {
+                    buf.Append(c);
+                }
+            }
 
-			return buf.ToString();
-		}
+            return buf.ToString();
+        }
     }
 }
diff --git a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
index 21172f816..7e0695341 100644
--- a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
+++ b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
@@ -41,7 +41,6 @@ namespace Org.BouncyCastle.Asn1.Tests
                 new DerT61String("hello world"),
                 new DerTaggedObject(0, new DerPrintableString("hello world")),
                 new DerUniversalString(data),
-                new DerUnknownTag(true, 500, data),
                 new DerUtcTime(new DateTime()),
                 new DerUtf8String("hello world"),
                 new DerVisibleString("hello world")