summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-11-09 16:08:19 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-11-09 16:08:19 +0700
commit7735c6336809bc20d10dae1c15891143d0cc54c5 (patch)
tree3f08af7faa908520ae06944744c1e86aeea395d6
parentRemove unused class (diff)
downloadBouncyCastle.NET-ed25519-7735c6336809bc20d10dae1c15891143d0cc54c5.tar.xz
Asn1Generator implements IDisposable
- now expects BerOctetStringGenerator to be disposed, not just its octets stream
-rw-r--r--crypto/src/asn1/ASN1Generator.cs37
-rw-r--r--crypto/src/asn1/BERGenerator.cs68
-rw-r--r--crypto/src/asn1/BEROctetStringGenerator.cs56
-rw-r--r--crypto/src/asn1/DERGenerator.cs88
-rw-r--r--crypto/src/asn1/DERSequenceGenerator.cs20
-rw-r--r--crypto/src/asn1/DERSetGenerator.cs20
-rw-r--r--crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs47
-rw-r--r--crypto/src/cms/CMSCompressedDataStreamGenerator.cs24
-rw-r--r--crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs39
-rw-r--r--crypto/src/cms/CMSSignedDataStreamGenerator.cs35
-rw-r--r--crypto/src/cms/CMSUtils.cs6
-rw-r--r--crypto/test/src/asn1/test/ASN1SequenceParserTest.cs285
-rw-r--r--crypto/test/src/asn1/test/OctetStringTest.cs168
13 files changed, 439 insertions, 454 deletions
diff --git a/crypto/src/asn1/ASN1Generator.cs b/crypto/src/asn1/ASN1Generator.cs
index cd2d06e72..28fffc6ab 100644
--- a/crypto/src/asn1/ASN1Generator.cs
+++ b/crypto/src/asn1/ASN1Generator.cs
@@ -1,20 +1,23 @@
+using System;
 using System.IO;
 
 namespace Org.BouncyCastle.Asn1
 {
     public abstract class Asn1Generator
+        : IDisposable
     {
-		private Stream _out;
+		private Stream m_outStream;
 
-		protected Asn1Generator(
-			Stream outStream)
+		protected Asn1Generator(Stream outStream)
         {
-            _out = outStream;
+            m_outStream = outStream ?? throw new ArgumentNullException(nameof(outStream));
         }
 
-		protected Stream Out
+        protected abstract void Finish();
+
+		protected Stream OutStream
 		{
-			get { return _out; }
+			get { return m_outStream ?? throw new InvalidOperationException(); }
 		}
 
 		public abstract void AddObject(Asn1Encodable obj);
@@ -23,6 +26,26 @@ namespace Org.BouncyCastle.Asn1
 
         public abstract Stream GetRawOutputStream();
 
-		public abstract void Close();
+        #region IDisposable
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (m_outStream != null) 
+                {
+                    Finish();
+                    m_outStream = null;
+                }
+            }
+        }
+
+        #endregion
     }
 }
diff --git a/crypto/src/asn1/BERGenerator.cs b/crypto/src/asn1/BERGenerator.cs
index e43d9f80c..073c36a30 100644
--- a/crypto/src/asn1/BERGenerator.cs
+++ b/crypto/src/asn1/BERGenerator.cs
@@ -1,3 +1,4 @@
+using System;
 using System.IO;
 
 using Org.BouncyCastle.Utilities.IO;
@@ -7,20 +8,16 @@ namespace Org.BouncyCastle.Asn1
     public abstract class BerGenerator
         : Asn1Generator
     {
-        private bool      _tagged = false;
-        private bool      _isExplicit;
-        private int          _tagNo;
+        private bool _tagged = false;
+        private bool _isExplicit;
+        private int _tagNo;
 
-        protected BerGenerator(
-            Stream outStream)
+        protected BerGenerator(Stream outStream)
             : base(outStream)
         {
         }
 
-        protected BerGenerator(
-            Stream outStream,
-            int tagNo,
-            bool isExplicit)
+        protected BerGenerator(Stream outStream, int tagNo, bool isExplicit)
             : base(outStream)
         {
             _tagged = true;
@@ -28,35 +25,33 @@ namespace Org.BouncyCastle.Asn1
             _tagNo = tagNo;
         }
 
-		public override void AddObject(Asn1Encodable obj)
+        protected override void Finish()
+        {
+            WriteBerEnd();
+        }
+
+        public override void AddObject(Asn1Encodable obj)
 		{
-            obj.EncodeTo(Out);
+            obj.EncodeTo(OutStream);
 		}
 
         public override void AddObject(Asn1Object obj)
         {
-            obj.EncodeTo(Out);
+            obj.EncodeTo(OutStream);
         }
 
         public override Stream GetRawOutputStream()
         {
-            return Out;
+            return OutStream;
         }
 
-		public override void Close()
-		{
-			WriteBerEnd();
-		}
-
-        private void WriteHdr(
-            int tag)
+        private void WriteHdr(int tag)
         {
-            Out.WriteByte((byte) tag);
-            Out.WriteByte(0x80);
+            OutStream.WriteByte((byte)tag);
+            OutStream.WriteByte(0x80);
         }
 
-        protected void WriteBerHeader(
-            int tag)
+        protected void WriteBerHeader(int tag)
         {
             if (_tagged)
             {
@@ -85,22 +80,33 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-		protected void WriteBerBody(
-            Stream contentStream)
+		protected void WriteBerBody(Stream contentStream)
         {
-			Streams.PipeAll(contentStream, Out);
+			Streams.PipeAll(contentStream, OutStream);
         }
 
 		protected void WriteBerEnd()
         {
-            Out.WriteByte(0x00);
-            Out.WriteByte(0x00);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            Span<byte> data = stackalloc byte[4]{ 0x00, 0x00, 0x00, 0x00 };
+            if (_tagged && _isExplicit)  // write extra end for tag header
+            {
+                OutStream.Write(data[..4]);
+            }
+            else
+            {
+                OutStream.Write(data[..2]);
+            }
+#else
+            OutStream.WriteByte(0x00);
+            OutStream.WriteByte(0x00);
 
             if (_tagged && _isExplicit)  // write extra end for tag header
             {
-                Out.WriteByte(0x00);
-                Out.WriteByte(0x00);
+                OutStream.WriteByte(0x00);
+                OutStream.WriteByte(0x00);
             }
+#endif
         }
     }
 }
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index b07576e7d..5472802a2 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -8,38 +8,39 @@ namespace Org.BouncyCastle.Asn1
 	public class BerOctetStringGenerator
 		: BerGenerator
 	{
-		public BerOctetStringGenerator(Stream outStream)
-			: base(outStream)
-		{
-			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
-		}
+        public BerOctetStringGenerator(Stream outStream)
+            : base(outStream)
+        {
+            WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+        }
 
-		public BerOctetStringGenerator(
-			Stream	outStream,
-			int		tagNo,
-			bool	isExplicit)
-			: base(outStream, tagNo, isExplicit)
-		{
-			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
-		}
+        public BerOctetStringGenerator(Stream outStream, int tagNo, bool isExplicit)
+            : base(outStream, tagNo, isExplicit)
+        {
+            WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+        }
 
+        /// <remarks>The caller is responsible for disposing the returned <see cref="Stream"/> before disposing
+        /// this generator.</remarks>
 		public Stream GetOctetOutputStream()
 		{
 			return GetOctetOutputStream(new byte[1000]); // limit for CER encoding.
 		}
 
-		public Stream GetOctetOutputStream(
-			int bufSize)
+        /// <remarks>The caller is responsible for disposing the returned <see cref="Stream"/> before disposing
+        /// this generator.</remarks>
+		public Stream GetOctetOutputStream(int bufSize)
 		{
-			return bufSize < 1
-				?	GetOctetOutputStream()
-				:	GetOctetOutputStream(new byte[bufSize]);
-		}
+            return bufSize < 1
+                ? GetOctetOutputStream()
+                : GetOctetOutputStream(new byte[bufSize]);
+        }
 
-		public Stream GetOctetOutputStream(
-			byte[] buf)
+        /// <remarks>The caller is responsible for disposing the returned <see cref="Stream"/> before disposing
+        /// this generator.</remarks>
+		public Stream GetOctetOutputStream(byte[] buf)
 		{
-			return new BufferedBerOctetStream(this, buf);
+			return new BufferedBerOctetStream(GetRawOutputStream(), buf);
 		}
 
 		private class BufferedBerOctetStream
@@ -47,17 +48,13 @@ namespace Org.BouncyCastle.Asn1
 		{
 			private byte[] _buf;
 			private int    _off;
-			private readonly BerOctetStringGenerator _gen;
 			private readonly Asn1OutputStream _derOut;
 
-			internal BufferedBerOctetStream(
-				BerOctetStringGenerator	gen,
-				byte[]					buf)
+			internal BufferedBerOctetStream(Stream outStream, byte[] buf)
 			{
-				_gen = gen;
 				_buf = buf;
 				_off = 0;
-				_derOut = Asn1OutputStream.Create(_gen.Out, Asn1Encodable.Der);
+				_derOut = Asn1OutputStream.Create(outStream, Asn1Encodable.Der);
 			}
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -145,11 +142,10 @@ namespace Org.BouncyCastle.Asn1
                     if (_off != 0)
                     {
                         DerOctetString.Encode(_derOut, _buf, 0, _off);
+                        _off = 0;
                     }
 
                     _derOut.FlushInternal();
-
-                    _gen.WriteBerEnd();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/asn1/DERGenerator.cs b/crypto/src/asn1/DERGenerator.cs
index 387a2c5f8..4bdc60972 100644
--- a/crypto/src/asn1/DERGenerator.cs
+++ b/crypto/src/asn1/DERGenerator.cs
@@ -11,16 +11,12 @@ namespace Org.BouncyCastle.Asn1
         private bool _isExplicit;
         private int _tagNo;
 
-		protected DerGenerator(
-            Stream outStream)
+        protected DerGenerator(Stream outStream)
             : base(outStream)
 		{
         }
 
-        protected DerGenerator(
-            Stream outStream,
-            int tagNo,
-            bool isExplicit)
+        protected DerGenerator(Stream outStream, int tagNo, bool isExplicit)
             : base(outStream)
         {
             _tagged = true;
@@ -28,80 +24,70 @@ namespace Org.BouncyCastle.Asn1
             _tagNo = tagNo;
         }
 
-		private static void WriteLength(
-            Stream	outStr,
-            int		length)
+		internal void WriteDerEncoded(int tag, byte[] bytes)
         {
-            if (length > 127)
+            if (_tagged)
             {
-                int size = 1;
-                int val = length;
+                int tagNum = _tagNo | Asn1Tags.ContextSpecific;
 
-				while ((val >>= 8) != 0)
+                if (_isExplicit)
                 {
-                    size++;
+                    int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.ContextSpecific;
+					MemoryStream bOut = new MemoryStream();
+                    WriteDerEncoded(bOut, tag, bytes);
+                    WriteDerEncoded(OutStream, newTag, bOut.ToArray());
                 }
-
-				outStr.WriteByte((byte)(size | 0x80));
-
-				for (int i = (size - 1) * 8; i >= 0; i -= 8)
+                else
                 {
-                    outStr.WriteByte((byte)(length >> i));
+					if ((tag & Asn1Tags.Constructed) != 0)
+					{
+						tagNum |= Asn1Tags.Constructed;
+					}
+
+					WriteDerEncoded(OutStream, tagNum, bytes);
                 }
             }
             else
             {
-                outStr.WriteByte((byte)length);
+                WriteDerEncoded(OutStream, tag, bytes);
             }
         }
 
-		internal static void WriteDerEncoded(
-            Stream	outStream,
-            int		tag,
-            byte[]	bytes)
+        internal static void WriteDerEncoded(Stream outStream, int tag, byte[] bytes)
         {
-            outStream.WriteByte((byte) tag);
+            outStream.WriteByte((byte)tag);
             WriteLength(outStream, bytes.Length);
             outStream.Write(bytes, 0, bytes.Length);
         }
 
-		internal void WriteDerEncoded(
-            int		tag,
-            byte[]	bytes)
+        internal static void WriteDerEncoded(Stream	outStream, int tag, Stream	inStream)
         {
-            if (_tagged)
+			WriteDerEncoded(outStream, tag, Streams.ReadAll(inStream));
+        }
+
+        private static void WriteLength(Stream outStream, int length)
+        {
+            if (length > 127)
             {
-                int tagNum = _tagNo | Asn1Tags.ContextSpecific;
+                int size = 1;
+                int val = length;
 
-                if (_isExplicit)
+                while ((val >>= 8) != 0)
                 {
-                    int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.ContextSpecific;
-					MemoryStream bOut = new MemoryStream();
-                    WriteDerEncoded(bOut, tag, bytes);
-                    WriteDerEncoded(Out, newTag, bOut.ToArray());
+                    size++;
                 }
-                else
-                {
-					if ((tag & Asn1Tags.Constructed) != 0)
-					{
-						tagNum |= Asn1Tags.Constructed;
-					}
 
-					WriteDerEncoded(Out, tagNum, bytes);
+                outStream.WriteByte((byte)(size | 0x80));
+
+                for (int i = (size - 1) * 8; i >= 0; i -= 8)
+                {
+                    outStream.WriteByte((byte)(length >> i));
                 }
             }
             else
             {
-                WriteDerEncoded(Out, tag, bytes);
+                outStream.WriteByte((byte)length);
             }
         }
-
-		internal static void WriteDerEncoded(
-            Stream	outStr,
-            int		tag,
-            Stream	inStr)
-        {
-			WriteDerEncoded(outStr, tag, Streams.ReadAll(inStr));
-        }
     }
 }
diff --git a/crypto/src/asn1/DERSequenceGenerator.cs b/crypto/src/asn1/DERSequenceGenerator.cs
index 12c978508..be240a86c 100644
--- a/crypto/src/asn1/DERSequenceGenerator.cs
+++ b/crypto/src/asn1/DERSequenceGenerator.cs
@@ -7,21 +7,22 @@ namespace Org.BouncyCastle.Asn1
 	{
 		private readonly MemoryStream _bOut = new MemoryStream();
 
-		public DerSequenceGenerator(
-			Stream outStream)
+		public DerSequenceGenerator(Stream outStream)
 			: base(outStream)
 		{
 		}
 
-		public DerSequenceGenerator(
-			Stream	outStream,
-			int		tagNo,
-			bool	isExplicit)
+		public DerSequenceGenerator(Stream outStream, int tagNo, bool isExplicit)
 			: base(outStream, tagNo, isExplicit)
 		{
 		}
 
-		public override void AddObject(Asn1Encodable obj)
+        protected override void Finish()
+        {
+            WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray());
+        }
+
+        public override void AddObject(Asn1Encodable obj)
 		{
             obj.EncodeTo(_bOut, Asn1Encodable.Der);
 		}
@@ -35,10 +36,5 @@ namespace Org.BouncyCastle.Asn1
 		{
 			return _bOut;
 		}
-
-		public override void Close()
-		{
-			WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray());
-		}
 	}
 }
diff --git a/crypto/src/asn1/DERSetGenerator.cs b/crypto/src/asn1/DERSetGenerator.cs
index 677241798..642744951 100644
--- a/crypto/src/asn1/DERSetGenerator.cs
+++ b/crypto/src/asn1/DERSetGenerator.cs
@@ -7,21 +7,22 @@ namespace Org.BouncyCastle.Asn1
 	{
 		private readonly MemoryStream _bOut = new MemoryStream();
 
-		public DerSetGenerator(
-			Stream outStream)
+		public DerSetGenerator(Stream outStream)
 			: base(outStream)
 		{
 		}
 
-		public DerSetGenerator(
-			Stream	outStream,
-			int		tagNo,
-			bool	isExplicit)
+		public DerSetGenerator(Stream outStream, int tagNo, bool isExplicit)
 			: base(outStream, tagNo, isExplicit)
 		{
 		}
 
-		public override void AddObject(Asn1Encodable obj)
+        protected override void Finish()
+        {
+            WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray());
+        }
+
+        public override void AddObject(Asn1Encodable obj)
 		{
             obj.EncodeTo(_bOut, Asn1Encodable.Der);
 		}
@@ -35,10 +36,5 @@ namespace Org.BouncyCastle.Asn1
 		{
 			return _bOut;
 		}
-
-		public override void Close()
-		{
-			WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray());
-		}
 	}
 }
diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
index fd2c743bb..054a9c45e 100644
--- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
@@ -140,31 +140,30 @@ namespace Org.BouncyCastle.Cms
 				authGen.AddObject(new DerInteger(AuthenticatedData.CalculateVersion(null)));
 
 				Stream authRaw = authGen.GetRawOutputStream();
-				Asn1Generator recipGen = _berEncodeRecipientSet
-					?	(Asn1Generator) new BerSetGenerator(authRaw)
-					:	new DerSetGenerator(authRaw);
-
-				foreach (Asn1Encodable ae in recipientInfos)
+				using (var recipGen = _berEncodeRecipientSet
+					? (Asn1Generator)new BerSetGenerator(authRaw)
+					: new DerSetGenerator(authRaw))
 				{
-					recipGen.AddObject(ae);
-				}
-
-				recipGen.Close();
+                    foreach (Asn1Encodable ae in recipientInfos)
+                    {
+                        recipGen.AddObject(ae);
+                    }
+                }
 
 				authGen.AddObject(macAlgId);
 
 				BerSequenceGenerator eiGen = new BerSequenceGenerator(authRaw);
 				eiGen.AddObject(CmsObjectIdentifiers.Data);
 
-				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
-					eiGen.GetRawOutputStream(), 0, true, _bufferSize);
+                BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
+                Stream octetOutputStream = octGen.GetOctetOutputStream(_bufferSize);
 
                 IMac mac = MacUtilities.GetMac(macAlgId.Algorithm);
 				// TODO Confirm no ParametersWithRandom needed
 	            mac.Init(cipherParameters);
 				Stream mOut = new TeeOutputStream(octetOutputStream, new MacSink(mac));
 
-				return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen);
+				return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen, octGen);
 			}
 			catch (SecurityUtilityException e)
 			{
@@ -214,23 +213,26 @@ namespace Org.BouncyCastle.Cms
 		{
 			private readonly Stream					macStream;
 			private readonly IMac					mac;
-			private readonly BerSequenceGenerator	cGen;
+            private readonly BerSequenceGenerator	cGen;
 			private readonly BerSequenceGenerator	authGen;
 			private readonly BerSequenceGenerator	eiGen;
+            private readonly BerOctetStringGenerator octGen;
 
-			public CmsAuthenticatedDataOutputStream(
+            public CmsAuthenticatedDataOutputStream(
 				Stream					macStream,
 				IMac					mac,
-				BerSequenceGenerator	cGen,
+                BerSequenceGenerator	cGen,
 				BerSequenceGenerator	authGen,
-				BerSequenceGenerator	eiGen)
-			{
+				BerSequenceGenerator	eiGen,
+                BerOctetStringGenerator octGen)
+            {
 				this.macStream = macStream;
 				this.mac = mac;
 				this.cGen = cGen;
 				this.authGen = authGen;
 				this.eiGen = eiGen;
-			}
+                this.octGen = octGen;
+            }
 
             public override void Write(byte[] buffer, int offset, int count)
             {
@@ -255,17 +257,18 @@ namespace Org.BouncyCastle.Cms
                 {
                     macStream.Dispose();
 
-                    // TODO Parent context(s) should really be be closed explicitly
+					// TODO Parent context(s) should really be be closed explicitly
 
-				    eiGen.Close();
+					octGen.Dispose();
+				    eiGen.Dispose();
 
 				    // [TODO] auth attributes go here 
 				    byte[] macOctets = MacUtilities.DoFinal(mac);
 				    authGen.AddObject(new DerOctetString(macOctets));
 				    // [TODO] unauth attributes go here
 
-				    authGen.Close();
-				    cGen.Close();
+				    authGen.Dispose();
+				    cGen.Dispose();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
index 64a978c6d..f992a8269 100644
--- a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
@@ -87,11 +87,11 @@ namespace Org.BouncyCastle.Cms
 
 			eiGen.AddObject(new DerObjectIdentifier(contentOid));
 
-			Stream octetStream = CmsUtilities.CreateBerOctetOutputStream(
-				eiGen.GetRawOutputStream(), 0, true, _bufferSize);
+            BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
+            Stream octetStream = octGen.GetOctetOutputStream(_bufferSize);
 
-			return new CmsCompressedOutputStream(
-				Utilities.IO.Compression.ZLib.CompressOutput(octetStream, -1), sGen, cGen, eiGen);
+            return new CmsCompressedOutputStream(
+				Utilities.IO.Compression.ZLib.CompressOutput(octetStream, -1), sGen, cGen, eiGen, octGen);
 		}
 
 		private class CmsCompressedOutputStream
@@ -101,17 +101,20 @@ namespace Org.BouncyCastle.Cms
 			private BerSequenceGenerator _sGen;
 			private BerSequenceGenerator _cGen;
 			private BerSequenceGenerator _eiGen;
+			private BerOctetStringGenerator _octGen;
 
-			internal CmsCompressedOutputStream(
+            internal CmsCompressedOutputStream(
 				Stream					outStream,
 				BerSequenceGenerator	sGen,
 				BerSequenceGenerator	cGen,
-				BerSequenceGenerator	eiGen)
+				BerSequenceGenerator	eiGen,
+                BerOctetStringGenerator octGen)
 			{
 				_out = outStream;
 				_sGen = sGen;
 				_cGen = cGen;
 				_eiGen = eiGen;
+				_octGen = octGen;
 			}
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -137,11 +140,12 @@ namespace Org.BouncyCastle.Cms
                 {
                     _out.Dispose();
 
-                    // TODO Parent context(s) should really be be closed explicitly
+					// TODO Parent context(s) should really be be closed explicitly
 
-                    _eiGen.Close();
-				    _cGen.Close();
-				    _sGen.Close();
+					_octGen.Dispose();
+                    _eiGen.Dispose();
+				    _cGen.Dispose();
+				    _sGen.Dispose();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
index cfd3dde10..64d501a41 100644
--- a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
@@ -142,29 +142,28 @@ namespace Org.BouncyCastle.Cms
 				envGen.AddObject(this.Version);
 
 				Stream envRaw = envGen.GetRawOutputStream();
-				Asn1Generator recipGen = _berEncodeRecipientSet
-					?	(Asn1Generator) new BerSetGenerator(envRaw)
-					:	new DerSetGenerator(envRaw);
-
-				foreach (Asn1Encodable ae in recipientInfos)
+				using (var recipGen = _berEncodeRecipientSet
+					? (Asn1Generator)new BerSetGenerator(envRaw)
+					: new DerSetGenerator(envRaw))
 				{
-					recipGen.AddObject(ae);
-				}
-
-				recipGen.Close();
+                    foreach (Asn1Encodable ae in recipientInfos)
+                    {
+                        recipGen.AddObject(ae);
+                    }
+                }
 
 				BerSequenceGenerator eiGen = new BerSequenceGenerator(envRaw);
 				eiGen.AddObject(CmsObjectIdentifiers.Data);
 				eiGen.AddObject(encAlgID);
 
-				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
-					eiGen.GetRawOutputStream(), 0, false, _bufferSize);
+                BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, false);
+                Stream octetOutputStream = octGen.GetOctetOutputStream(_bufferSize);
 
                 IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.Algorithm);
 				cipher.Init(true, new ParametersWithRandom(cipherParameters, m_random));
 				CipherStream cOut = new CipherStream(octetOutputStream, null, cipher);
 
-				return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen);
+				return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen, octGen);
 			}
 			catch (SecurityUtilityException e)
 			{
@@ -220,19 +219,22 @@ namespace Org.BouncyCastle.Cms
 			private readonly BerSequenceGenerator	_cGen;
 			private readonly BerSequenceGenerator	_envGen;
 			private readonly BerSequenceGenerator	_eiGen;
+			private readonly BerOctetStringGenerator _octGen;
 
-			public CmsEnvelopedDataOutputStream(
+            public CmsEnvelopedDataOutputStream(
 				CmsEnvelopedGenerator	outer,
 				CipherStream			outStream,
 				BerSequenceGenerator	cGen,
 				BerSequenceGenerator	envGen,
-				BerSequenceGenerator	eiGen)
+				BerSequenceGenerator	eiGen,
+                BerOctetStringGenerator octGen)
 			{
 				_outer = outer;
 				_out = outStream;
 				_cGen = cGen;
 				_envGen = envGen;
 				_eiGen = eiGen;
+				_octGen = octGen;
 			}
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -258,9 +260,10 @@ namespace Org.BouncyCastle.Cms
  				{
                     _out.Dispose();
 
-                    // TODO Parent context(s) should really be closed explicitly
+					// TODO Parent context(s) should really be closed explicitly
 
-                    _eiGen.Close();
+					_octGen.Dispose();
+                    _eiGen.Dispose();
 
                     if (_outer.unprotectedAttributeGenerator != null)
                     {
@@ -272,8 +275,8 @@ namespace Org.BouncyCastle.Cms
                         _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
                     }
 
-                    _envGen.Close();
-                    _cGen.Close();
+                    _envGen.Dispose();
+                    _cGen.Dispose();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index a4e960ba6..33b661761 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -570,18 +570,23 @@ namespace Org.BouncyCastle.Cms
 			BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
             eiGen.AddObject(contentTypeOid);
 
-        	// If encapsulating, add the data as an octet string in the sequence
-			Stream encapStream = encapsulate
-				?	CmsUtilities.CreateBerOctetOutputStream(eiGen.GetRawOutputStream(), 0, true, _bufferSize)
-				:	null;
+			BerOctetStringGenerator octGen = null;
+			Stream encapStream = null;
 
-        	// Also send the data to 'dataOutputStream' if necessary
-			Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream);
+            // If encapsulating, add the data as an octet string in the sequence
+            if (encapsulate)
+			{
+                octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
+                encapStream = octGen.GetOctetOutputStream(_bufferSize);
+            }
+
+            // Also send the data to 'dataOutputStream' if necessary
+            Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream);
 
         	// Let all the digests see the data as it is written
 			Stream digStream = AttachDigestsToOutputStream(m_messageDigests.Values, teeStream);
 
-			return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
+			return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen, octGen);
         }
 
 		private void RegisterDigestOid(
@@ -761,14 +766,16 @@ namespace Org.BouncyCastle.Cms
             private BerSequenceGenerator	_sGen;
             private BerSequenceGenerator	_sigGen;
             private BerSequenceGenerator	_eiGen;
+			private BerOctetStringGenerator _octGen;
 
-			public CmsSignedDataOutputStream(
+            public CmsSignedDataOutputStream(
 				CmsSignedDataStreamGenerator	outer,
 				Stream							outStream,
                 string							contentOID,
                 BerSequenceGenerator			sGen,
                 BerSequenceGenerator			sigGen,
-                BerSequenceGenerator			eiGen)
+                BerSequenceGenerator			eiGen,
+                BerOctetStringGenerator			octGen)
             {
 				this.outer = outer;
 
@@ -777,6 +784,7 @@ namespace Org.BouncyCastle.Cms
                 _sGen = sGen;
                 _sigGen = sigGen;
                 _eiGen = eiGen;
+				_octGen = octGen;
             }
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -811,7 +819,10 @@ namespace Org.BouncyCastle.Cms
 
                 // TODO Parent context(s) should really be be closed explicitly
 
-                _eiGen.Close();
+				// Only for encapsulation
+				_octGen?.Dispose();
+
+                _eiGen.Dispose();
 
                 outer.m_digests.Clear();    // clear the current preserved digest state
 
@@ -896,8 +907,8 @@ namespace Org.BouncyCastle.Cms
 
                 WriteToGenerator(_sigGen, new DerSet(signerInfos));
 
-				_sigGen.Close();
-                _sGen.Close();
+				_sigGen.Dispose();
+                _sGen.Dispose();
             }
 
 			private static void WriteToGenerator(Asn1Generator ag, Asn1Encodable ae)
diff --git a/crypto/src/cms/CMSUtils.cs b/crypto/src/cms/CMSUtils.cs
index 1a1577c4e..99258c995 100644
--- a/crypto/src/cms/CMSUtils.cs
+++ b/crypto/src/cms/CMSUtils.cs
@@ -176,12 +176,6 @@ namespace Org.BouncyCastle.Cms
 			return new DerSet(v);
 		}
 
-		internal static Stream CreateBerOctetOutputStream(Stream s, int tagNo, bool isExplicit, int bufferSize)
-		{
-			BerOctetStringGenerator octGen = new BerOctetStringGenerator(s, tagNo, isExplicit);
-			return octGen.GetOctetOutputStream(bufferSize);
-		}
-
 		internal static TbsCertificateStructure GetTbsCertificateStructure(X509Certificate cert)
 		{
 			return TbsCertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetTbsCertificate()));
diff --git a/crypto/test/src/asn1/test/ASN1SequenceParserTest.cs b/crypto/test/src/asn1/test/ASN1SequenceParserTest.cs
index 030da04cb..fd85a58fb 100644
--- a/crypto/test/src/asn1/test/ASN1SequenceParserTest.cs
+++ b/crypto/test/src/asn1/test/ASN1SequenceParserTest.cs
@@ -1,4 +1,3 @@
-using System;
 using System.IO;
 
 using NUnit.Framework;
@@ -6,7 +5,6 @@ using NUnit.Framework;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Encoders;
-using Org.BouncyCastle.Utilities.Test;
 
 namespace Org.BouncyCastle.Asn1.Tests
 {
@@ -30,13 +28,11 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestDerWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut);
-
-			seqGen.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen.AddObject(new DerObjectIdentifier("1.1"));
-
-			seqGen.Close();
+			using (var seqGen = new DerSequenceGenerator(bOut))
+			{
+                seqGen.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen.AddObject(new DerObjectIdentifier("1.1"));
+            }
 
 			Assert.IsTrue(Arrays.AreEqual(seqData, bOut.ToArray()), "basic DER writing test failed.");
         }
@@ -45,34 +41,29 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestNestedDerWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            DerSequenceGenerator seqGen1 = new DerSequenceGenerator(bOut);
-
-			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
-
-			DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream());
-
-			seqGen2.AddObject(new DerInteger(BigInteger.One));
-
-			seqGen2.Close();
+			using (var seqGen1 = new DerSequenceGenerator(bOut))
+			{
+                seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen1.AddObject(new DerObjectIdentifier("1.1"));
 
-			seqGen1.Close();
+                using (var seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream()))
+                {
+                    seqGen2.AddObject(new DerInteger(BigInteger.One));
+                }
+            }
 
-			Assert.IsTrue(Arrays.AreEqual(nestedSeqData, bOut.ToArray()), "nested DER writing test failed.");
+            Assert.IsTrue(Arrays.AreEqual(nestedSeqData, bOut.ToArray()), "nested DER writing test failed.");
         }
 
 		[Test]
 		public void TestDerExplicitTaggedSequenceWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut, 1, true);
-
-            seqGen.AddObject(new DerInteger(BigInteger.Zero));
-
-            seqGen.AddObject(new DerObjectIdentifier("1.1"));
-
-            seqGen.Close();
+            using (var seqGen = new DerSequenceGenerator(bOut, 1, true))
+            {
+                seqGen.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen.AddObject(new DerObjectIdentifier("1.1"));
+            }
 
             Assert.IsTrue(Arrays.AreEqual(expTagSeqData, bOut.ToArray()), "explicit tag writing test failed.");
         }
@@ -81,34 +72,29 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestDerImplicitTaggedSequenceWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut, 1, false);
-
-			seqGen.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen.AddObject(new DerObjectIdentifier("1.1"));
-
-			seqGen.Close();
+            using (var seqGen = new DerSequenceGenerator(bOut, 1, false))
+            {
+                seqGen.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen.AddObject(new DerObjectIdentifier("1.1"));
+            }
 
-			Assert.IsTrue(Arrays.AreEqual(implTagSeqData, bOut.ToArray()), "implicit tag writing test failed.");
+            Assert.IsTrue(Arrays.AreEqual(implTagSeqData, bOut.ToArray()), "implicit tag writing test failed.");
         }
 
 		[Test]
 		public void TestNestedExplicitTagDerWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            DerSequenceGenerator  seqGen1 = new DerSequenceGenerator(bOut);
-
-            seqGen1.AddObject(new DerInteger(BigInteger.Zero));
-
-            seqGen1.AddObject(new DerObjectIdentifier("1.1"));
-
-            DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, true);
-
-            seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
-
-            seqGen2.Close();
+            using (var seqGen1 = new DerSequenceGenerator(bOut))
+            {
+                seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen1.AddObject(new DerObjectIdentifier("1.1"));
 
-            seqGen1.Close();
+                using (var seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, true))
+                {
+                    seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+                }
+            }
 
             Assert.IsTrue(Arrays.AreEqual(nestedSeqExpTagData, bOut.ToArray()), "nested explicit tagged DER writing test failed.");
         }
@@ -117,34 +103,29 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestNestedImplicitTagDerWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            DerSequenceGenerator seqGen1 = new DerSequenceGenerator(bOut);
-
-			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
-
-			DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, false);
-
-			seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
-
-			seqGen2.Close();
+            using (var seqGen1 = new DerSequenceGenerator(bOut))
+            {
+                seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen1.AddObject(new DerObjectIdentifier("1.1"));
 
-			seqGen1.Close();
+                using (var seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, false))
+                {
+                    seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+                }
+            }
 
-			Assert.IsTrue(Arrays.AreEqual(nestedSeqImpTagData, bOut.ToArray()), "nested implicit tagged DER writing test failed.");
+            Assert.IsTrue(Arrays.AreEqual(nestedSeqImpTagData, bOut.ToArray()), "nested implicit tagged DER writing test failed.");
         }
 
 		[Test]
 		public void TestBerWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            BerSequenceGenerator seqGen = new BerSequenceGenerator(bOut);
-
-			seqGen.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen.AddObject(new DerObjectIdentifier("1.1"));
-
-			seqGen.Close();
+            using (var seqGen = new BerSequenceGenerator(bOut))
+            {
+                seqGen.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen.AddObject(new DerObjectIdentifier("1.1"));
+            }
 
 			Assert.IsTrue(Arrays.AreEqual(berSeqData, bOut.ToArray()), "basic BER writing test failed.");
         }
@@ -153,49 +134,42 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestNestedBerDerWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            BerSequenceGenerator seqGen1 = new BerSequenceGenerator(bOut);
-
-			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
-
-			DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream());
-
-			seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
-
-			seqGen2.Close();
+            using (var seqGen1 = new BerSequenceGenerator(bOut))
+            {
+                seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen1.AddObject(new DerObjectIdentifier("1.1"));
 
-			seqGen1.Close();
+                using (var seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream()))
+                {
+                    seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+                }
+            }
 
-			Assert.IsTrue(Arrays.AreEqual(berDerNestedSeqData, bOut.ToArray()), "nested BER/DER writing test failed.");
+            Assert.IsTrue(Arrays.AreEqual(berDerNestedSeqData, bOut.ToArray()), "nested BER/DER writing test failed.");
         }
 
 		[Test]
 		public void TestNestedBerWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            BerSequenceGenerator seqGen1 = new BerSequenceGenerator(bOut);
-
-			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
-
-			BerSequenceGenerator seqGen2 = new BerSequenceGenerator(seqGen1.GetRawOutputStream());
-
-			seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
-
-			seqGen2.Close();
+            using (var seqGen1 = new BerSequenceGenerator(bOut))
+            {
+                seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen1.AddObject(new DerObjectIdentifier("1.1"));
 
-			seqGen1.Close();
+                using (var seqGen2 = new BerSequenceGenerator(seqGen1.GetRawOutputStream()))
+                {
+                    seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+                }
+            }
 
-			Assert.IsTrue(Arrays.AreEqual(berNestedSeqData, bOut.ToArray()), "nested BER writing test failed.");
+            Assert.IsTrue(Arrays.AreEqual(berNestedSeqData, bOut.ToArray()), "nested BER writing test failed.");
         }
 
 		[Test]
 		public void TestDerReading()
         {
             Asn1StreamParser aIn = new Asn1StreamParser(seqData);
-
 			Asn1SequenceParser seq = (Asn1SequenceParser)aIn.ReadObject();
             int count = 0;
 
@@ -206,12 +180,12 @@ namespace Org.BouncyCastle.Asn1.Tests
             {
                 switch (count)
                 {
-                    case 0:
-                        Assert.IsTrue(o is DerInteger);
-                        break;
-                    case 1:
-                        Assert.IsTrue(o is DerObjectIdentifier);
-                        break;
+                case 0:
+                    Assert.IsTrue(o is DerInteger);
+                    break;
+                case 1:
+                    Assert.IsTrue(o is DerObjectIdentifier);
+                    break;
                 }
                 count++;
             }
@@ -219,39 +193,38 @@ namespace Org.BouncyCastle.Asn1.Tests
 			Assert.AreEqual(2, count, "wrong number of objects in sequence");
         }
 
-		private void doTestNestedReading(
+		private void DoTestNestedReading(
             byte[] data)
         {
             Asn1StreamParser aIn = new Asn1StreamParser(data);
-
 			Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject();
-            object o = null;
             int count = 0;
 
 			Assert.IsNotNull(seq, "null sequence returned");
 
-			while ((o = seq.ReadObject()) != null)
+            object o;
+            while ((o = seq.ReadObject()) != null)
             {
                 switch (count)
                 {
-                    case 0:
-                        Assert.IsTrue(o is DerInteger);
-                        break;
-                    case 1:
-                        Assert.IsTrue(o is DerObjectIdentifier);
-                        break;
-                    case 2:
-                        Assert.IsTrue(o is Asn1SequenceParser);
-
-						Asn1SequenceParser s = (Asn1SequenceParser)o;
-
-						// NB: Must exhaust the nested parser
-						while (s.ReadObject() != null)
-						{
-							// Ignore
-						}
-
-						break;
+                case 0:
+                    Assert.IsTrue(o is DerInteger);
+                    break;
+                case 1:
+                    Assert.IsTrue(o is DerObjectIdentifier);
+                    break;
+                case 2:
+                    Assert.IsTrue(o is Asn1SequenceParser);
+
+					Asn1SequenceParser s = (Asn1SequenceParser)o;
+
+					// NB: Must exhaust the nested parser
+					while (s.ReadObject() != null)
+					{
+						// Ignore
+					}
+
+					break;
                 }
                 count++;
             }
@@ -262,30 +235,29 @@ namespace Org.BouncyCastle.Asn1.Tests
 		[Test]
 		public void TestNestedDerReading()
         {
-            doTestNestedReading(nestedSeqData);
+            DoTestNestedReading(nestedSeqData);
         }
 
 		[Test]
 		public void TestBerReading()
         {
             Asn1StreamParser aIn = new Asn1StreamParser(berSeqData);
-
 			Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject();
-            object o = null;
             int count = 0;
 
 			Assert.IsNotNull(seq, "null sequence returned");
 
-			while ((o = seq.ReadObject()) != null)
+            object o;
+            while ((o = seq.ReadObject()) != null)
             {
                 switch (count)
                 {
-                    case 0:
-                        Assert.IsTrue(o is DerInteger);
-                        break;
-                    case 1:
-                        Assert.IsTrue(o is DerObjectIdentifier);
-                        break;
+                case 0:
+                    Assert.IsTrue(o is DerInteger);
+                    break;
+                case 1:
+                    Assert.IsTrue(o is DerObjectIdentifier);
+                    break;
                 }
                 count++;
             }
@@ -296,59 +268,56 @@ namespace Org.BouncyCastle.Asn1.Tests
 		[Test]
 		public void TestNestedBerDerReading()
         {
-            doTestNestedReading(berDerNestedSeqData);
+            DoTestNestedReading(berDerNestedSeqData);
         }
 
 		[Test]
 		public void TestNestedBerReading()
         {
-            doTestNestedReading(berNestedSeqData);
+            DoTestNestedReading(berNestedSeqData);
         }
 
 		[Test]
 		public void TestBerExplicitTaggedSequenceWriting()
         {
             MemoryStream bOut = new MemoryStream();
-            BerSequenceGenerator seqGen = new BerSequenceGenerator(bOut, 1, true);
-
-			seqGen.AddObject(new DerInteger(BigInteger.Zero));
-
-			seqGen.AddObject(new DerObjectIdentifier("1.1"));
-
-			seqGen.Close();
+            using (var seqGen = new BerSequenceGenerator(bOut, 1, true))
+            {
+                seqGen.AddObject(new DerInteger(BigInteger.Zero));
+                seqGen.AddObject(new DerObjectIdentifier("1.1"));
+            }
 
-			Assert.IsTrue(Arrays.AreEqual(berExpTagSeqData, bOut.ToArray()), "explicit BER tag writing test failed.");
+            Assert.IsTrue(Arrays.AreEqual(berExpTagSeqData, bOut.ToArray()), "explicit BER tag writing test failed.");
         }
 
 		[Test]
 		public void TestSequenceWithDerNullReading()
 		{
-			doTestParseWithNull(berSeqWithDERNullData);
+			DoTestParseWithNull(berSeqWithDERNullData);
 		}
 
-		private void doTestParseWithNull(
-			byte[] data)
+		private void DoTestParseWithNull(byte[] data)
 		{
 			Asn1StreamParser aIn = new Asn1StreamParser(data);
 			Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject();
-			object o;
 			int count = 0;
 
 			Assert.IsNotNull(seq, "null sequence returned");
 
-			while ((o = seq.ReadObject()) != null)
+            object o;
+            while ((o = seq.ReadObject()) != null)
 			{
 				switch (count)
 				{
-					case 0:
-						Assert.IsTrue(o is Asn1Null);
-						break;
-					case 1:
-						Assert.IsTrue(o is DerInteger);
-						break;
-					case 2:
-						Assert.IsTrue(o is DerObjectIdentifier);
-						break;
+				case 0:
+					Assert.IsTrue(o is Asn1Null);
+					break;
+				case 1:
+					Assert.IsTrue(o is DerInteger);
+					break;
+				case 2:
+					Assert.IsTrue(o is DerObjectIdentifier);
+					break;
 				}
 				count++;
 			}
diff --git a/crypto/test/src/asn1/test/OctetStringTest.cs b/crypto/test/src/asn1/test/OctetStringTest.cs
index 8bae1b057..959d16c32 100644
--- a/crypto/test/src/asn1/test/OctetStringTest.cs
+++ b/crypto/test/src/asn1/test/OctetStringTest.cs
@@ -14,16 +14,16 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestReadingWriting()
 		{
 			MemoryStream bOut = new MemoryStream();
-			BerOctetStringGenerator octGen = new BerOctetStringGenerator(bOut);
+            using (var octGen = new BerOctetStringGenerator(bOut))
+            {
+                using (var outStream = octGen.GetOctetOutputStream())
+                {
+                    outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+                    outStream.Write(new byte[4], 0, 4);
+                }
+            }
 
-			Stream outStream = octGen.GetOctetOutputStream();
-
-			outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
-			outStream.Write(new byte[4], 0, 4);
-
-			outStream.Close();
-
-			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+            Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
 
 			BerOctetStringParser s = (BerOctetStringParser)aIn.ReadObject();
 
@@ -42,16 +42,16 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestReadingWritingZeroInLength()
 		{
 			MemoryStream bOut = new MemoryStream();
-			BerOctetStringGenerator octGen = new BerOctetStringGenerator(bOut);
-
-			Stream outStream = octGen.GetOctetOutputStream();
+            using (var octGen = new BerOctetStringGenerator(bOut))
+            {
+                using (var outStream = octGen.GetOctetOutputStream())
+                {
+                    outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+                    outStream.Write(new byte[512], 0, 512);  // forces a zero to appear in length
+                }
+            }
 
-			outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
-			outStream.Write(new byte[512], 0, 512);  // forces a zero to appear in length
-
-			outStream.Close();
-
-			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+            Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
 
 			BerOctetStringParser s = (BerOctetStringParser)aIn.ReadObject();
 
@@ -70,29 +70,28 @@ namespace Org.BouncyCastle.Asn1.Tests
 		public void TestReadingWritingNested()
 		{
 			MemoryStream bOut = new MemoryStream();
-			BerSequenceGenerator sGen = new BerSequenceGenerator(bOut);
-			BerOctetStringGenerator octGen = new BerOctetStringGenerator(sGen.GetRawOutputStream());
-
-			Stream outStream = octGen.GetOctetOutputStream();
-
-			BerSequenceGenerator inSGen = new BerSequenceGenerator(outStream);
-
-			BerOctetStringGenerator inOctGen = new BerOctetStringGenerator(inSGen.GetRawOutputStream());
-
-			Stream inOut = inOctGen.GetOctetOutputStream();
-
-			inOut.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
-			inOut.Write(new byte[10], 0, 10);
-
-			inOut.Close();
-
-			inSGen.Close();
-
-			outStream.Close();
-
-			sGen.Close();
-
-			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+			using (var sGen = new BerSequenceGenerator(bOut))
+			{
+				using (var octGen = new BerOctetStringGenerator(sGen.GetRawOutputStream()))
+				{
+					using (var outStream = octGen.GetOctetOutputStream())
+					{
+						using (var inSGen = new BerSequenceGenerator(outStream))
+						{
+							using (var inOctGen = new BerOctetStringGenerator(inSGen.GetRawOutputStream()))
+							{
+								using (var inOut = inOctGen.GetOctetOutputStream())
+								{
+									inOut.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+									inOut.Write(new byte[10], 0, 10);
+								}
+							}
+						}
+                    }
+                }
+            }
+
+            Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
 
 			BerSequenceParser sq = (BerSequenceParser)aIn.ReadObject();
 
@@ -120,50 +119,49 @@ namespace Org.BouncyCastle.Asn1.Tests
 		{
 			MemoryStream bOut = new MemoryStream();
 
-			BerSequenceGenerator sGen = new BerSequenceGenerator(bOut);
-
-			sGen.AddObject(new DerObjectIdentifier(CmsObjectIdentifiers.CompressedData.Id));
-
-			BerSequenceGenerator cGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true);
-
-			cGen.AddObject(new DerInteger(0));
-
-			//
-			// AlgorithmIdentifier
-			//
-			DerSequenceGenerator algGen = new DerSequenceGenerator(cGen.GetRawOutputStream());
-
-			algGen.AddObject(new DerObjectIdentifier("1.2"));
-
-			algGen.Close();
-
-			//
-			// Encapsulated ContentInfo
-			//
-			BerSequenceGenerator eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream());
-
-			eiGen.AddObject(new DerObjectIdentifier("1.1"));
-
-			BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
-
-			//
-			// output containing zeroes
-			//
-			Stream outStream = octGen.GetOctetOutputStream();
-
-			outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
-			outStream.Write(new byte[4], 0, 4);
-			outStream.Write(new byte[20], 0, 20);
-
-			outStream.Close();
-			eiGen.Close();
-			cGen.Close();
-			sGen.Close();
-
-			//
-			// reading back
-			//
-			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+			using (var sGen = new BerSequenceGenerator(bOut))
+			{
+				sGen.AddObject(new DerObjectIdentifier(CmsObjectIdentifiers.CompressedData.Id));
+
+				using (var cGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true))
+				{
+					cGen.AddObject(new DerInteger(0));
+
+					//
+					// AlgorithmIdentifier
+					//
+					using (var algGen = new DerSequenceGenerator(cGen.GetRawOutputStream()))
+					{
+						algGen.AddObject(new DerObjectIdentifier("1.2"));
+					}
+
+					//
+					// Encapsulated ContentInfo
+					//
+					using (var eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream()))
+					{
+						eiGen.AddObject(new DerObjectIdentifier("1.1"));
+
+						using (var octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true))
+						{
+							//
+							// output containing zeroes
+							//
+							using (var outStream = octGen.GetOctetOutputStream())
+							{
+								outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+								outStream.Write(new byte[4], 0, 4);
+								outStream.Write(new byte[20], 0, 20);
+							}
+						}
+					}
+				}
+            }
+
+            //
+            // reading back
+            //
+            Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
 
 			ContentInfoParser cp = new ContentInfoParser((Asn1SequenceParser)aIn.ReadObject());