summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-10-14 20:33:18 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-10-14 20:33:18 +0700
commit61605407b72d584c94daeafe4ea4c2b1cad3914e (patch)
treefb8d07b180f7c06dd1438e1a5796d4766df6d44a
parentFix and Obsolete BerNull (diff)
downloadBouncyCastle.NET-ed25519-61605407b72d584c94daeafe4ea4c2b1cad3914e.tar.xz
Add withID to Encode method
- refactor Asn1OutputStream utility methods
-rw-r--r--crypto/src/asn1/Asn1Object.cs4
-rw-r--r--crypto/src/asn1/Asn1OutputStream.cs130
-rw-r--r--crypto/src/asn1/BERBitString.cs6
-rw-r--r--crypto/src/asn1/BEROctetStringGenerator.cs10
-rw-r--r--crypto/src/asn1/BerOctetString.cs14
-rw-r--r--crypto/src/asn1/BerOutputStream.cs9
-rw-r--r--crypto/src/asn1/BerSequence.cs14
-rw-r--r--crypto/src/asn1/BerSet.cs12
-rw-r--r--crypto/src/asn1/BerTaggedObject.cs16
-rw-r--r--crypto/src/asn1/DERExternal.cs4
-rw-r--r--crypto/src/asn1/DerApplicationSpecific.cs8
-rw-r--r--crypto/src/asn1/DerBMPString.cs4
-rw-r--r--crypto/src/asn1/DerBitString.cs6
-rw-r--r--crypto/src/asn1/DerBoolean.cs4
-rw-r--r--crypto/src/asn1/DerEnumerated.cs4
-rw-r--r--crypto/src/asn1/DerGeneralString.cs4
-rw-r--r--crypto/src/asn1/DerGeneralizedTime.cs4
-rw-r--r--crypto/src/asn1/DerGraphicString.cs4
-rw-r--r--crypto/src/asn1/DerIA5String.cs4
-rw-r--r--crypto/src/asn1/DerInteger.cs4
-rw-r--r--crypto/src/asn1/DerNull.cs8
-rw-r--r--crypto/src/asn1/DerNumericString.cs4
-rw-r--r--crypto/src/asn1/DerObjectIdentifier.cs4
-rw-r--r--crypto/src/asn1/DerOctetString.cs8
-rw-r--r--crypto/src/asn1/DerOutputStream.cs115
-rw-r--r--crypto/src/asn1/DerPrintableString.cs4
-rw-r--r--crypto/src/asn1/DerSequence.cs6
-rw-r--r--crypto/src/asn1/DerSet.cs8
-rw-r--r--crypto/src/asn1/DerT61String.cs4
-rw-r--r--crypto/src/asn1/DerTaggedObject.cs17
-rw-r--r--crypto/src/asn1/DerUTCTime.cs4
-rw-r--r--crypto/src/asn1/DerUTF8String.cs4
-rw-r--r--crypto/src/asn1/DerUniversalString.cs4
-rw-r--r--crypto/src/asn1/DerVideotexString.cs4
-rw-r--r--crypto/src/asn1/DerVisibleString.cs4
-rw-r--r--crypto/src/asn1/LazyDERSequence.cs6
-rw-r--r--crypto/src/asn1/LazyDERSet.cs6
37 files changed, 243 insertions, 232 deletions
diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs
index d60a85348..7c7f87704 100644
--- a/crypto/src/asn1/Asn1Object.cs
+++ b/crypto/src/asn1/Asn1Object.cs
@@ -62,9 +62,9 @@ namespace Org.BouncyCastle.Asn1
             return this;
         }
 
-		internal abstract void Encode(Asn1OutputStream asn1Out);
+        internal abstract void Encode(Asn1OutputStream asn1Out, bool withID);
 
-		protected abstract bool Asn1Equals(Asn1Object asn1Object);
+        protected abstract bool Asn1Equals(Asn1Object asn1Object);
 		protected abstract int Asn1GetHashCode();
 
 		internal bool CallAsn1Equals(Asn1Object obj)
diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs
index e6eec563e..1b253419a 100644
--- a/crypto/src/asn1/Asn1OutputStream.cs
+++ b/crypto/src/asn1/Asn1OutputStream.cs
@@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Asn1
             if (null == encodable)
                 throw new IOException("null object detected");
 
-            WritePrimitive(encodable.ToAsn1Object());
+            WritePrimitive(encodable.ToAsn1Object(), true);
             FlushInternal();
         }
 
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Asn1
             if (null == primitive)
                 throw new IOException("null object detected");
 
-            WritePrimitive(primitive);
+            WritePrimitive(primitive, true);
             FlushInternal();
         }
 
@@ -52,29 +52,145 @@ namespace Org.BouncyCastle.Asn1
             // Placeholder to support future internal buffering
         }
 
-        internal override bool IsBer
+        internal virtual bool IsBer
         {
             get { return true; }
         }
 
+        internal void WriteDL(int length)
+        {
+            if (length < 128)
+            {
+                WriteByte((byte)length);
+            }
+            else
+            {
+                byte[] stack = new byte[5];
+                int pos = stack.Length;
+
+                do
+                {
+                    stack[--pos] = (byte)length;
+                    length >>= 8;
+                }
+                while (length > 0);
+
+                int count = stack.Length - pos;
+                stack[--pos] = (byte)(0x80 | count);
+
+                Write(stack, pos, count + 1);
+            }
+        }
+
         internal virtual void WriteElements(Asn1Encodable[] elements)
         {
             for (int i = 0, count = elements.Length; i < count; ++i)
             {
-                elements[i].ToAsn1Object().Encode(this);
+                elements[i].ToAsn1Object().Encode(this, true);
+            }
+        }
+
+        internal void WriteEncodingDL(bool withID, int identifier, byte contents)
+        {
+            WriteIdentifier(withID, identifier);
+            WriteDL(1);
+            WriteByte(contents);
+        }
+
+        internal void WriteEncodingDL(bool withID, int identifier, byte[] contents)
+        {
+            WriteIdentifier(withID, identifier);
+            WriteDL(contents.Length);
+            Write(contents, 0, contents.Length);
+        }
+
+        internal void WriteEncodingDL(bool withID, int identifier, byte[] contents, int contentsOff, int contentsLen)
+        {
+            WriteIdentifier(withID, identifier);
+            WriteDL(contentsLen);
+            Write(contents, contentsOff, contentsLen);
+        }
+
+        internal void WriteEncodingDL(bool withID, int identifier, byte contentsPrefix, byte[] contents,
+            int contentsOff, int contentsLen)
+        {
+            WriteIdentifier(withID, identifier);
+            WriteDL(1 + contentsLen);
+            WriteByte(contentsPrefix);
+            Write(contents, contentsOff, contentsLen);
+        }
+
+        internal void WriteEncodingDL(bool withID, int identifier, byte[] contents, int contentsOff, int contentsLen,
+            byte contentsSuffix)
+        {
+            WriteIdentifier(withID, identifier);
+            WriteDL(contentsLen + 1);
+            Write(contents, contentsOff, contentsLen);
+            WriteByte(contentsSuffix);
+        }
+
+        internal void WriteEncodingDL(bool withID, int flags, int tag, byte[] contents)
+        {
+            WriteIdentifier(withID, flags, tag);
+            WriteDL(contents.Length);
+            Write(contents, 0, contents.Length);
+        }
+
+        internal void WriteEncodingIL(bool withID, int identifier, Asn1Encodable[] elements)
+        {
+            WriteIdentifier(withID, identifier);
+            WriteByte(0x80);
+            WriteElements(elements);
+            WriteByte(0x00);
+            WriteByte(0x00);
+        }
+
+        internal void WriteIdentifier(bool withID, int identifier)
+        {
+            if (withID)
+            {
+                WriteByte((byte)identifier);
+            }
+        }
+
+        internal void WriteIdentifier(bool withID, int flags, int tag)
+        {
+            if (!withID)
+            {
+                // Don't write the identifier
+            }
+            else if (tag < 31)
+            {
+                WriteByte((byte)(flags | tag));
+            }
+            else
+            {
+                byte[] stack = new byte[6];
+                int pos = stack.Length;
+
+                stack[--pos] = (byte)(tag & 0x7F);
+                while (tag > 127)
+                {
+                    tag >>= 7;
+                    stack[--pos] = (byte)(tag & 0x7F | 0x80);
+                }
+
+                stack[--pos] = (byte)(flags | 0x1F);
+
+                Write(stack, pos, stack.Length - pos);
             }
         }
 
-        internal virtual void WritePrimitive(Asn1Object primitive)
+        internal virtual void WritePrimitive(Asn1Object primitive, bool withID)
         {
-            primitive.Encode(this);
+            primitive.Encode(this, withID);
         }
 
         internal virtual void WritePrimitives(Asn1Object[] primitives)
         {
             for (int i = 0, count = primitives.Length; i < count; ++i)
             {
-                WritePrimitive(primitives[i]);
+                WritePrimitive(primitives[i], true);
             }
         }
     }
diff --git a/crypto/src/asn1/BERBitString.cs b/crypto/src/asn1/BERBitString.cs
index 0db973a07..a738a75e6 100644
--- a/crypto/src/asn1/BERBitString.cs
+++ b/crypto/src/asn1/BERBitString.cs
@@ -27,15 +27,15 @@ namespace Org.BouncyCastle.Asn1
 		{
 		}
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             if (asn1Out.IsBer)
             {
-                asn1Out.WriteEncoded(Asn1Tags.BitString, (byte)mPadBits, mData);
+                asn1Out.WriteEncodingDL(withID, Asn1Tags.BitString, (byte)mPadBits, mData, 0, mData.Length);
             }
             else
             {
-                base.Encode(asn1Out);
+                base.Encode(asn1Out, withID);
             }
         }
     }
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index 4a7f1e8e5..37e46bea5 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -67,7 +67,7 @@ namespace Org.BouncyCastle.Asn1
 
 				if (_off == _buf.Length)
 				{
-					DerOctetString.Encode(_derOut, _buf, 0, _off);
+					DerOctetString.Encode(_derOut, true, _buf, 0, _off);
 					_off = 0;
 				}
 			}
@@ -88,13 +88,13 @@ namespace Org.BouncyCastle.Asn1
                 {
                     Array.Copy(b, off, _buf, _off, available);
                     count += available;
-                    DerOctetString.Encode(_derOut, _buf, 0, bufLen);
+                    DerOctetString.Encode(_derOut, true, _buf, 0, bufLen);
                 }
 
                 int remaining;
                 while ((remaining = len - count) >= bufLen)
                 {
-                    DerOctetString.Encode(_derOut, b, off + count, bufLen);
+                    DerOctetString.Encode(_derOut, true, b, off + count, bufLen);
                     count += bufLen;
                 }
 
@@ -109,7 +109,7 @@ namespace Org.BouncyCastle.Asn1
                 {
 				    if (_off != 0)
 				    {
-					    DerOctetString.Encode(_derOut, _buf, 0, _off);
+					    DerOctetString.Encode(_derOut, true, _buf, 0, _off);
 				    }
 
                     _derOut.FlushInternal();
@@ -123,7 +123,7 @@ namespace Org.BouncyCastle.Asn1
 			{
 				if (_off != 0)
 				{
-					DerOctetString.Encode(_derOut, _buf, 0, _off);
+					DerOctetString.Encode(_derOut, true, _buf, 0, _off);
 				}
 
                 _derOut.FlushInternal();
diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs
index 2140faef1..1a8f761a4 100644
--- a/crypto/src/asn1/BerOctetString.cs
+++ b/crypto/src/asn1/BerOctetString.cs
@@ -121,20 +121,20 @@ namespace Org.BouncyCastle.Asn1
 			return GetEnumerator();
 		}
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             if (asn1Out.IsBer)
             {
-                asn1Out.WriteByte(Asn1Tags.Constructed | Asn1Tags.OctetString);
+                if (withID)
+                {
+                    asn1Out.WriteByte(Asn1Tags.Constructed | Asn1Tags.OctetString);
+                }
 
                 asn1Out.WriteByte(0x80);
 
-                //
-                // write out the octet array
-                //
                 foreach (Asn1OctetString oct in this)
                 {
-                    oct.Encode(asn1Out);
+                    oct.Encode(asn1Out, true);
                 }
 
 				asn1Out.WriteByte(0x00);
@@ -142,7 +142,7 @@ namespace Org.BouncyCastle.Asn1
             }
             else
             {
-                base.Encode(asn1Out);
+                base.Encode(asn1Out, withID);
             }
         }
 
diff --git a/crypto/src/asn1/BerOutputStream.cs b/crypto/src/asn1/BerOutputStream.cs
index 54b72cf06..1486368e0 100644
--- a/crypto/src/asn1/BerOutputStream.cs
+++ b/crypto/src/asn1/BerOutputStream.cs
@@ -13,9 +13,14 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
-        internal override bool IsBer
+        public override void WriteObject(Asn1Encodable encodable)
         {
-            get { return true; }
+            Asn1OutputStream.Create(s).WriteObject(encodable);
+        }
+
+        public override void WriteObject(Asn1Object primitive)
+        {
+            Asn1OutputStream.Create(s).WriteObject(primitive);
         }
     }
 }
diff --git a/crypto/src/asn1/BerSequence.cs b/crypto/src/asn1/BerSequence.cs
index b8ef12dd0..341090c7a 100644
--- a/crypto/src/asn1/BerSequence.cs
+++ b/crypto/src/asn1/BerSequence.cs
@@ -39,21 +39,15 @@ namespace Org.BouncyCastle.Asn1
 		{
 		}
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
 		{
 			if (asn1Out.IsBer)
-			{
-				asn1Out.WriteByte(Asn1Tags.Sequence | Asn1Tags.Constructed);
-				asn1Out.WriteByte(0x80);
-
-                asn1Out.WriteElements(elements);
-
-				asn1Out.WriteByte(0x00);
-				asn1Out.WriteByte(0x00);
+            {
+                asn1Out.WriteEncodingIL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, elements);
 			}
 			else
 			{
-				base.Encode(asn1Out);
+				base.Encode(asn1Out, withID);
 			}
 		}
 	}
diff --git a/crypto/src/asn1/BerSet.cs b/crypto/src/asn1/BerSet.cs
index a3868dfa6..3a1163fcb 100644
--- a/crypto/src/asn1/BerSet.cs
+++ b/crypto/src/asn1/BerSet.cs
@@ -44,21 +44,15 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             if (asn1Out.IsBer)
             {
-                asn1Out.WriteByte(Asn1Tags.Set | Asn1Tags.Constructed);
-                asn1Out.WriteByte(0x80);
-
-                asn1Out.WriteElements(elements);
-
-                asn1Out.WriteByte(0x00);
-                asn1Out.WriteByte(0x00);
+                asn1Out.WriteEncodingIL(withID, Asn1Tags.Constructed | Asn1Tags.Set, elements);
             }
             else
             {
-                base.Encode(asn1Out);
+                base.Encode(asn1Out, withID);
             }
         }
     }
diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs
index 097f77610..631d34420 100644
--- a/crypto/src/asn1/BerTaggedObject.cs
+++ b/crypto/src/asn1/BerTaggedObject.cs
@@ -47,12 +47,16 @@ namespace Org.BouncyCastle.Asn1
 		{
 		}
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
 		{
 			if (asn1Out.IsBer)
 			{
-				asn1Out.WriteIdentifier(true, Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo);
-				asn1Out.WriteByte(0x80);
+                if (withID)
+                {
+                    asn1Out.WriteIdentifier(true, Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo);
+                }
+
+                asn1Out.WriteByte(0x80);
 
 				if (!IsEmpty())
 				{
@@ -86,12 +90,12 @@ namespace Org.BouncyCastle.Asn1
 
 						foreach (Asn1Encodable o in eObj)
 						{
-							asn1Out.WritePrimitive(o.ToAsn1Object());
+							asn1Out.WritePrimitive(o.ToAsn1Object(), true);
 						}
 					}
 					else
 					{
-						asn1Out.WritePrimitive(obj.ToAsn1Object());
+						asn1Out.WritePrimitive(obj.ToAsn1Object(), true);
 					}
 				}
 
@@ -100,7 +104,7 @@ namespace Org.BouncyCastle.Asn1
 			}
 			else
 			{
-				base.Encode(asn1Out);
+				base.Encode(asn1Out, withID);
 			}
 		}
 	}
diff --git a/crypto/src/asn1/DERExternal.cs b/crypto/src/asn1/DERExternal.cs
index 1e5a42f77..4f3c6ed6c 100644
--- a/crypto/src/asn1/DERExternal.cs
+++ b/crypto/src/asn1/DERExternal.cs
@@ -89,7 +89,7 @@ namespace Org.BouncyCastle.Asn1
 			ExternalContent = externalData.ToAsn1Object();
 		}
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
 		{
 			MemoryStream ms = new MemoryStream();
 			WriteEncodable(ms, directReference);
@@ -97,7 +97,7 @@ namespace Org.BouncyCastle.Asn1
 			WriteEncodable(ms, dataValueDescriptor);
 			WriteEncodable(ms, new DerTaggedObject(Asn1Tags.External, externalContent));
 
-			asn1Out.WriteEncoded(Asn1Tags.Constructed, Asn1Tags.External, ms.ToArray());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.External, ms.ToArray());
 		}
 
 		protected override int Asn1GetHashCode()
diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs
index 7bba8c5a9..0d60a3e38 100644
--- a/crypto/src/asn1/DerApplicationSpecific.cs
+++ b/crypto/src/asn1/DerApplicationSpecific.cs
@@ -163,15 +163,15 @@ namespace Org.BouncyCastle.Asn1
 			return FromByteArray(tmp);
 		}
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-			int classBits = Asn1Tags.Application;
+			int flags = Asn1Tags.Application;
 			if (isConstructed)
 			{
-				classBits |= Asn1Tags.Constructed; 
+                flags |= Asn1Tags.Constructed; 
 			}
 
-			asn1Out.WriteEncoded(classBits, tag, octets);
+            asn1Out.WriteEncodingDL(withID, flags, tag, octets);
 		}
 
 		protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs
index eb9606096..3a75604ae 100644
--- a/crypto/src/asn1/DerBMPString.cs
+++ b/crypto/src/asn1/DerBMPString.cs
@@ -111,7 +111,7 @@ namespace Org.BouncyCastle.Asn1
 			return this.str.Equals(other.str);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             char[] c = str.ToCharArray();
             byte[] b = new byte[c.Length * 2];
@@ -122,7 +122,7 @@ namespace Org.BouncyCastle.Asn1
                 b[2 * i + 1] = (byte)c[i];
             }
 
-            asn1Out.WriteEncoded(Asn1Tags.BmpString, b);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.BmpString, b);
         }
     }
 }
diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs
index 282e97929..624da6763 100644
--- a/crypto/src/asn1/DerBitString.cs
+++ b/crypto/src/asn1/DerBitString.cs
@@ -191,7 +191,7 @@ namespace Org.BouncyCastle.Asn1
 			}
 		}
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
 		{
             if (mPadBits > 0)
             {
@@ -208,12 +208,12 @@ namespace Org.BouncyCastle.Asn1
                      */
                     contents[contents.Length - 1] = (byte)(last ^ unusedBits);
 
-                    asn1Out.WriteEncoded(Asn1Tags.BitString, contents);
+                    asn1Out.WriteEncodingDL(withID, Asn1Tags.BitString, contents);
                     return;
                 }
             }
 
-            asn1Out.WriteEncoded(Asn1Tags.BitString, (byte)mPadBits, mData);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.BitString, (byte)mPadBits, mData, 0, mData.Length);
 		}
 
         protected override int Asn1GetHashCode()
diff --git a/crypto/src/asn1/DerBoolean.cs b/crypto/src/asn1/DerBoolean.cs
index 3052c6e0d..7458b18ea 100644
--- a/crypto/src/asn1/DerBoolean.cs
+++ b/crypto/src/asn1/DerBoolean.cs
@@ -81,10 +81,10 @@ namespace Org.BouncyCastle.Asn1
             get { return value != 0; }
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             // TODO Should we make sure the byte value is one of '0' or '0xff' here?
-            asn1Out.WriteEncoded(Asn1Tags.Boolean, new byte[]{ value });
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Boolean, value);
         }
 
         protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerEnumerated.cs b/crypto/src/asn1/DerEnumerated.cs
index f00eab05e..6e3a16054 100644
--- a/crypto/src/asn1/DerEnumerated.cs
+++ b/crypto/src/asn1/DerEnumerated.cs
@@ -119,9 +119,9 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.Enumerated, bytes);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Enumerated, bytes);
         }
 
         protected override bool Asn1Equals(Asn1Object asn1Object)
diff --git a/crypto/src/asn1/DerGeneralString.cs b/crypto/src/asn1/DerGeneralString.cs
index f6e800e73..f7446dc27 100644
--- a/crypto/src/asn1/DerGeneralString.cs
+++ b/crypto/src/asn1/DerGeneralString.cs
@@ -61,9 +61,9 @@ namespace Org.BouncyCastle.Asn1
             return Strings.ToAsciiByteArray(str);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.GeneralString, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.GeneralString, GetOctets());
         }
 
 		protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerGeneralizedTime.cs b/crypto/src/asn1/DerGeneralizedTime.cs
index 0b603d65d..d1505d9b0 100644
--- a/crypto/src/asn1/DerGeneralizedTime.cs
+++ b/crypto/src/asn1/DerGeneralizedTime.cs
@@ -295,9 +295,9 @@ namespace Org.BouncyCastle.Asn1
             return Strings.ToAsciiByteArray(time);
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.GeneralizedTime, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.GeneralizedTime, GetOctets());
         }
 
         protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerGraphicString.cs b/crypto/src/asn1/DerGraphicString.cs
index 879a2f658..e2901118d 100644
--- a/crypto/src/asn1/DerGraphicString.cs
+++ b/crypto/src/asn1/DerGraphicString.cs
@@ -79,9 +79,9 @@ namespace Org.BouncyCastle.Asn1
             return Arrays.Clone(mString);
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.GraphicString, mString);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.GraphicString, mString);
         }
 
         protected override int Asn1GetHashCode()
diff --git a/crypto/src/asn1/DerIA5String.cs b/crypto/src/asn1/DerIA5String.cs
index 22311fdb8..14fefa941 100644
--- a/crypto/src/asn1/DerIA5String.cs
+++ b/crypto/src/asn1/DerIA5String.cs
@@ -100,9 +100,9 @@ namespace Org.BouncyCastle.Asn1
             return Strings.ToAsciiByteArray(str);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.IA5String, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.IA5String, GetOctets());
         }
 
 		protected override int Asn1GetHashCode()
diff --git a/crypto/src/asn1/DerInteger.cs b/crypto/src/asn1/DerInteger.cs
index 43e991b36..c71f4685d 100644
--- a/crypto/src/asn1/DerInteger.cs
+++ b/crypto/src/asn1/DerInteger.cs
@@ -169,9 +169,9 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.Integer, bytes);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Integer, bytes);
         }
 
 		protected override int Asn1GetHashCode()
diff --git a/crypto/src/asn1/DerNull.cs b/crypto/src/asn1/DerNull.cs
index 60f040b40..01a2e3c72 100644
--- a/crypto/src/asn1/DerNull.cs
+++ b/crypto/src/asn1/DerNull.cs
@@ -16,12 +16,12 @@ namespace Org.BouncyCastle.Asn1
 		{
 		}
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
 		{
-			asn1Out.WriteEncoded(Asn1Tags.Null, ZeroBytes);
-		}
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Null, ZeroBytes);
+        }
 
-		protected override bool Asn1Equals(Asn1Object asn1Object)
+        protected override bool Asn1Equals(Asn1Object asn1Object)
 		{
 			return asn1Object is DerNull;
 		}
diff --git a/crypto/src/asn1/DerNumericString.cs b/crypto/src/asn1/DerNumericString.cs
index 1163d71f4..7839b04ff 100644
--- a/crypto/src/asn1/DerNumericString.cs
+++ b/crypto/src/asn1/DerNumericString.cs
@@ -100,9 +100,9 @@ namespace Org.BouncyCastle.Asn1
             return Strings.ToAsciiByteArray(str);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.NumericString, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.NumericString, GetOctets());
         }
 
 		protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs
index aa40c4c06..9a4e80ac2 100644
--- a/crypto/src/asn1/DerObjectIdentifier.cs
+++ b/crypto/src/asn1/DerObjectIdentifier.cs
@@ -197,9 +197,9 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.ObjectIdentifier, GetContents());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.ObjectIdentifier, GetContents());
         }
 
         protected override int Asn1GetHashCode()
diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs
index 4dc5bff2c..f865abff8 100644
--- a/crypto/src/asn1/DerOctetString.cs
+++ b/crypto/src/asn1/DerOctetString.cs
@@ -22,14 +22,14 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.OctetString, str);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.OctetString, str);
         }
 
-		internal static void Encode(Asn1OutputStream asn1Out, byte[] bytes, int offset, int length)
+		internal static void Encode(Asn1OutputStream asn1Out, bool withID, byte[] buf, int off, int len)
 		{
-			asn1Out.WriteEncoded(Asn1Tags.OctetString, bytes, offset, length);
+			asn1Out.WriteEncodingDL(withID, Asn1Tags.OctetString, buf, off, len);
 		}
 	}
 }
diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs
index 84d1af44b..b8cbe9ee2 100644
--- a/crypto/src/asn1/DerOutputStream.cs
+++ b/crypto/src/asn1/DerOutputStream.cs
@@ -17,119 +17,12 @@ namespace Org.BouncyCastle.Asn1
 
         public virtual void WriteObject(Asn1Encodable encodable)
         {
-            new DerOutputStreamNew(s).WriteObject(encodable);
+            Asn1OutputStream.Create(s, Asn1Encodable.Der).WriteObject(encodable);
         }
 
         public virtual void WriteObject(Asn1Object primitive)
         {
-            new DerOutputStreamNew(s).WriteObject(primitive);
-        }
-
-        internal virtual bool IsBer
-        {
-            get { return false; }
-        }
-
-		internal void WriteDL(int length)
-		{
-            if (length < 128)
-            {
-                WriteByte((byte)length);
-            }
-            else
-            {
-                byte[] stack = new byte[5];
-                int pos = stack.Length;
-
-                do
-                {
-                    stack[--pos] = (byte)length;
-                    length >>= 8;
-                }
-                while (length > 0);
-
-                int count = stack.Length - pos;
-                stack[--pos] = (byte)(0x80 | count);
-
-                Write(stack, pos, count + 1);
-            }
-        }
-
-        internal void WriteEncoded(
-			int		tag,
-			byte[]	bytes)
-		{
-			WriteByte((byte)tag);
-			WriteDL(bytes.Length);
-			Write(bytes, 0, bytes.Length);
-		}
-
-        internal void WriteEncoded(
-            int     tag,
-            byte    first,
-            byte[]  bytes)
-        {
-            WriteByte((byte)tag);
-            WriteDL(bytes.Length + 1);
-            WriteByte(first);
-            Write(bytes, 0, bytes.Length);
-        }
-
-        internal void WriteEncoded(
-			int		tag,
-			byte[]	bytes,
-			int		offset,
-			int		length)
-		{
-			WriteByte((byte)tag);
-            WriteDL(length);
-			Write(bytes, offset, length);
-		}
-
-		internal void WriteEncoded(
-			int		flags,
-			int		tagNo,
-			byte[]	bytes)
-		{
-			WriteIdentifier(true, flags, tagNo);
-            WriteDL(bytes.Length);
-			Write(bytes, 0, bytes.Length);
-		}
-
-        internal void WriteIdentifier(bool withID, int identifier)
-        {
-            if (withID)
-            {
-                WriteByte((byte)identifier);
-            }
-        }
-
-        internal void WriteIdentifier(bool withID, int flags, int tag)
-        {
-            if (!withID)
-            {
-                // Don't write the identifier
-            }
-            else if (tag < 31)
-            {
-                WriteByte((byte)(flags | tag));
-            }
-            else
-            {
-                byte[] stack = new byte[6];
-                int pos = stack.Length;
-
-                stack[--pos] = (byte)(tag & 0x7F);
-                while (tag > 127)
-                {
-                    tag >>= 7;
-                    stack[--pos] = (byte)(tag & 0x7F | 0x80);
-                }
-
-                stack[--pos] = (byte)(flags | 0x1F);
-
-                Write(stack, pos, stack.Length - pos);
-            }
+            Asn1OutputStream.Create(s, Asn1Encodable.Der).WriteObject(primitive);
         }
 	}
 
@@ -146,7 +39,7 @@ namespace Org.BouncyCastle.Asn1
             get { return false; }
         }
 
-        internal override void WritePrimitive(Asn1Object primitive)
+        internal override void WritePrimitive(Asn1Object primitive, bool withID)
         {
             Asn1Set asn1Set = primitive as Asn1Set;
             if (null != asn1Set)
@@ -158,7 +51,7 @@ namespace Org.BouncyCastle.Asn1
                 primitive = new DerSet(asn1Set.elements);
             }
 
-            primitive.Encode(this);
+            primitive.Encode(this, withID);
         }
     }
 }
diff --git a/crypto/src/asn1/DerPrintableString.cs b/crypto/src/asn1/DerPrintableString.cs
index 5198dc30c..5df1de547 100644
--- a/crypto/src/asn1/DerPrintableString.cs
+++ b/crypto/src/asn1/DerPrintableString.cs
@@ -100,9 +100,9 @@ namespace Org.BouncyCastle.Asn1
             return Strings.ToAsciiByteArray(str);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.PrintableString, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.PrintableString, GetOctets());
         }
 
 		protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerSequence.cs b/crypto/src/asn1/DerSequence.cs
index 05b6f4533..b5ab20b9e 100644
--- a/crypto/src/asn1/DerSequence.cs
+++ b/crypto/src/asn1/DerSequence.cs
@@ -53,11 +53,11 @@ namespace Org.BouncyCastle.Asn1
 		 * ASN.1 descriptions given. Rather than just outputing Sequence,
 		 * we also have to specify Constructed, and the objects length.
 		 */
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             if (Count < 1)
             {
-                asn1Out.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, Asn1OctetString.EmptyOctets);
+                asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, Asn1OctetString.EmptyOctets);
                 return;
             }
 
@@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Asn1
             int length = (int)bOut.Position;
 #endif
 
-            asn1Out.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, bytes, 0, length);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, bytes, 0, length);
 
             Platform.Dispose(dOut);
         }
diff --git a/crypto/src/asn1/DerSet.cs b/crypto/src/asn1/DerSet.cs
index 62d8873b8..517d83b5f 100644
--- a/crypto/src/asn1/DerSet.cs
+++ b/crypto/src/asn1/DerSet.cs
@@ -70,17 +70,17 @@ namespace Org.BouncyCastle.Asn1
 		 * ASN.1 descriptions given. Rather than just outputing Set,
 		 * we also have to specify Constructed, and the objects length.
 		 */
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             if (Count < 1)
             {
-                asn1Out.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, Asn1OctetString.EmptyOctets);
+                asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, Asn1OctetString.EmptyOctets);
                 return;
             }
 
             // TODO Intermediate buffer could be avoided if we could calculate expected length
             MemoryStream bOut = new MemoryStream();
-            Asn1OutputStream dOut = Asn1OutputStream.Create(bOut, Asn1Encodable.Der);
+            Asn1OutputStream dOut = Asn1OutputStream.Create(bOut, Der);
             dOut.WriteElements(elements);
             dOut.Flush();
 
@@ -92,7 +92,7 @@ namespace Org.BouncyCastle.Asn1
             int length = (int)bOut.Position;
 #endif
 
-            asn1Out.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, bytes, 0, length);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, bytes, 0, length);
 
             Platform.Dispose(dOut);
         }
diff --git a/crypto/src/asn1/DerT61String.cs b/crypto/src/asn1/DerT61String.cs
index 40906f3c1..e4f84b10a 100644
--- a/crypto/src/asn1/DerT61String.cs
+++ b/crypto/src/asn1/DerT61String.cs
@@ -77,9 +77,9 @@ namespace Org.BouncyCastle.Asn1
             return str;
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.T61String, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.T61String, GetOctets());
         }
 
         public byte[] GetOctets()
diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs
index 40776ace3..7f1541c15 100644
--- a/crypto/src/asn1/DerTaggedObject.cs
+++ b/crypto/src/asn1/DerTaggedObject.cs
@@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Asn1
 		{
 		}
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
 		{
 			if (!IsEmpty())
 			{
@@ -50,21 +50,26 @@ namespace Org.BouncyCastle.Asn1
 
 				if (explicitly)
 				{
-					asn1Out.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, bytes);
+					asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, bytes);
 				}
 				else
 				{
 					//
 					// need to mark constructed types... (preserve Constructed tag)
 					//
-					int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged;
-					asn1Out.WriteIdentifier(true, flags, tagNo);
-					asn1Out.Write(bytes, 1, bytes.Length - 1);
+                    if (withID)
+                    {
+                        int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged;
+                        asn1Out.WriteIdentifier(true, flags, tagNo);
+                    }
+
+                    asn1Out.Write(bytes, 1, bytes.Length - 1);
 				}
 			}
 			else
 			{
-				asn1Out.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, new byte[0]);
+				asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo,
+                    Asn1OctetString.EmptyOctets);
 			}
 		}
 	}
diff --git a/crypto/src/asn1/DerUTCTime.cs b/crypto/src/asn1/DerUTCTime.cs
index 7c8330874..55a1ac5c2 100644
--- a/crypto/src/asn1/DerUTCTime.cs
+++ b/crypto/src/asn1/DerUTCTime.cs
@@ -237,9 +237,9 @@ namespace Org.BouncyCastle.Asn1
             return Strings.ToAsciiByteArray(time);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.UtcTime, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.UtcTime, GetOctets());
         }
 
 		protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerUTF8String.cs b/crypto/src/asn1/DerUTF8String.cs
index 72e882afe..b9f389fce 100644
--- a/crypto/src/asn1/DerUTF8String.cs
+++ b/crypto/src/asn1/DerUTF8String.cs
@@ -89,9 +89,9 @@ namespace Org.BouncyCastle.Asn1
 			return this.str.Equals(other.str);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str));
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str));
         }
     }
 }
diff --git a/crypto/src/asn1/DerUniversalString.cs b/crypto/src/asn1/DerUniversalString.cs
index e7367dc38..29dbbce95 100644
--- a/crypto/src/asn1/DerUniversalString.cs
+++ b/crypto/src/asn1/DerUniversalString.cs
@@ -86,9 +86,9 @@ namespace Org.BouncyCastle.Asn1
             return (byte[]) str.Clone();
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.UniversalString, this.str);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.UniversalString, this.str);
         }
 
 		protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/DerVideotexString.cs b/crypto/src/asn1/DerVideotexString.cs
index c52987368..0e063b4fc 100644
--- a/crypto/src/asn1/DerVideotexString.cs
+++ b/crypto/src/asn1/DerVideotexString.cs
@@ -79,9 +79,9 @@ namespace Org.BouncyCastle.Asn1
             return Arrays.Clone(mString);
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.VideotexString, mString);
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.VideotexString, mString);
         }
 
         protected override int Asn1GetHashCode()
diff --git a/crypto/src/asn1/DerVisibleString.cs b/crypto/src/asn1/DerVisibleString.cs
index 3d25e788e..db6d7f818 100644
--- a/crypto/src/asn1/DerVisibleString.cs
+++ b/crypto/src/asn1/DerVisibleString.cs
@@ -86,9 +86,9 @@ namespace Org.BouncyCastle.Asn1
             return Strings.ToAsciiByteArray(str);
         }
 
-		internal override void Encode(Asn1OutputStream asn1Out)
+		internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
-            asn1Out.WriteEncoded(Asn1Tags.VisibleString, GetOctets());
+            asn1Out.WriteEncodingDL(withID, Asn1Tags.VisibleString, GetOctets());
         }
 
 		protected override bool Asn1Equals(
diff --git a/crypto/src/asn1/LazyDERSequence.cs b/crypto/src/asn1/LazyDERSequence.cs
index bd14b6578..83997aa98 100644
--- a/crypto/src/asn1/LazyDERSequence.cs
+++ b/crypto/src/asn1/LazyDERSequence.cs
@@ -59,17 +59,17 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             lock (this)
             {
                 if (encoded == null)
                 {
-                    base.Encode(asn1Out);
+                    base.Encode(asn1Out, withID);
                 }
                 else
                 {
-                    asn1Out.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, encoded);
+                    asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, encoded);
                 }
             }
         }
diff --git a/crypto/src/asn1/LazyDERSet.cs b/crypto/src/asn1/LazyDERSet.cs
index f8271f330..ae56f5e50 100644
--- a/crypto/src/asn1/LazyDERSet.cs
+++ b/crypto/src/asn1/LazyDERSet.cs
@@ -59,17 +59,17 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out)
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
         {
             lock (this)
             {
                 if (encoded == null)
                 {
-                    base.Encode(asn1Out);
+                    base.Encode(asn1Out, withID);
                 }
                 else
                 {
-                    asn1Out.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, encoded);
+                    asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, encoded);
                 }
             }
         }