diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 33db1e6d7..e250fe500 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -19,6 +19,7 @@ namespace Org.BouncyCastle.Asn1
: FilterStream
{
private readonly int limit;
+ private readonly bool m_leaveOpen;
internal byte[][] tmpBuffers;
@@ -36,11 +37,6 @@ namespace Org.BouncyCastle.Asn1
return int.MaxValue;
}
- public Asn1InputStream(Stream input)
- : this(input, FindLimit(input))
- {
- }
-
/**
* Create an ASN1InputStream based on the input byte array. The length of DER objects in
* the stream is automatically limited to the length of the input array.
@@ -52,6 +48,11 @@ namespace Org.BouncyCastle.Asn1
{
}
+ public Asn1InputStream(Stream input)
+ : this(input, FindLimit(input))
+ {
+ }
+
/**
* Create an ASN1InputStream where no DER object will be longer than limit.
*
@@ -59,22 +60,41 @@ namespace Org.BouncyCastle.Asn1
* @param limit maximum size of a DER encoded object.
*/
public Asn1InputStream(Stream input, int limit)
- : this(input, limit, new byte[16][])
+ : this(input, limit, false)
+ {
+ }
+
+ public Asn1InputStream(Stream input, int limit, bool leaveOpen)
+ : this(input, limit, leaveOpen, new byte[16][])
{
}
- internal Asn1InputStream(Stream input, int limit, byte[][] tmpBuffers)
+ internal Asn1InputStream(Stream input, int limit, bool leaveOpen, byte[][] tmpBuffers)
: base(input)
{
+ if (!input.CanRead)
+ throw new ArgumentException("Expected stream to be readable", nameof(input));
+
this.limit = limit;
+ m_leaveOpen = leaveOpen;
this.tmpBuffers = tmpBuffers;
}
protected override void Dispose(bool disposing)
{
- tmpBuffers = null;
+ if (disposing)
+ {
+ tmpBuffers = null;
+ }
- base.Dispose(disposing);
+ if (m_leaveOpen)
+ {
+ base.Detach(disposing);
+ }
+ else
+ {
+ base.Dispose(disposing);
+ }
}
/**
@@ -146,7 +166,10 @@ namespace Org.BouncyCastle.Asn1
if (remaining < 1)
return new Asn1EncodableVector(0);
- return new Asn1InputStream(defIn, remaining, tmpBuffers).ReadVector();
+ using (var sub = new Asn1InputStream(defIn, remaining, leaveOpen: true, tmpBuffers))
+ {
+ return sub.ReadVector();
+ }
}
internal virtual Asn1Sequence CreateDLSequence(DefiniteLengthInputStream defIn)
diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs
index 745674930..588c3733d 100644
--- a/crypto/src/asn1/Asn1OutputStream.cs
+++ b/crypto/src/asn1/Asn1OutputStream.cs
@@ -18,20 +18,56 @@ namespace Org.BouncyCastle.Asn1
public static Asn1OutputStream Create(Stream output)
{
- return new Asn1OutputStream(output);
+ return Create(output, Asn1Encodable.Ber);
}
public static Asn1OutputStream Create(Stream output, string encoding)
{
+ return Create(output, encoding, false);
+ }
+
+ public static Asn1OutputStream Create(Stream output, string encoding, bool leaveOpen)
+ {
+ if (Asn1Encodable.Der.Equals(encoding))
+ return new DerOutputStream(output, leaveOpen);
+
+ return new Asn1OutputStream(output, leaveOpen);
+ }
+
+ internal static int GetEncodingType(string encoding)
+ {
if (Asn1Encodable.Der.Equals(encoding))
- return new DerOutputStream(output);
+ return EncodingDer;
+
+ return EncodingBer;
+ }
- return new Asn1OutputStream(output);
+ private readonly bool m_leaveOpen;
+
+ internal Asn1OutputStream(Stream output, bool leaveOpen)
+ : base(output)
+ {
+ if (!output.CanWrite)
+ throw new ArgumentException("Expected stream to be writable", nameof(output));
+
+ m_leaveOpen = leaveOpen;
}
- internal Asn1OutputStream(Stream os)
- : base(os)
+ protected override void Dispose(bool disposing)
{
+ if (disposing)
+ {
+ FlushInternal();
+ }
+
+ if (m_leaveOpen)
+ {
+ base.Detach(disposing);
+ }
+ else
+ {
+ base.Dispose(disposing);
+ }
}
public virtual void WriteObject(Asn1Encodable asn1Encodable)
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index 5472802a2..ed2b85010 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -54,7 +54,7 @@ namespace Org.BouncyCastle.Asn1
{
_buf = buf;
_off = 0;
- _derOut = Asn1OutputStream.Create(outStream, Asn1Encodable.Der);
+ _derOut = Asn1OutputStream.Create(outStream, Asn1Encodable.Der, leaveOpen: true);
}
public override void Write(byte[] buffer, int offset, int count)
@@ -145,7 +145,7 @@ namespace Org.BouncyCastle.Asn1
_off = 0;
}
- _derOut.FlushInternal();
+ _derOut.Dispose();
}
base.Dispose(disposing);
}
diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs
index 6304ca852..509bd436b 100644
--- a/crypto/src/asn1/DerOutputStream.cs
+++ b/crypto/src/asn1/DerOutputStream.cs
@@ -6,8 +6,8 @@ namespace Org.BouncyCastle.Asn1
internal class DerOutputStream
: Asn1OutputStream
{
- internal DerOutputStream(Stream os)
- : base(os)
+ internal DerOutputStream(Stream os, bool leaveOpen)
+ : base(os, leaveOpen)
{
}
diff --git a/crypto/src/asn1/LazyASN1InputStream.cs b/crypto/src/asn1/LazyASN1InputStream.cs
index 8dfbba122..8807416f4 100644
--- a/crypto/src/asn1/LazyASN1InputStream.cs
+++ b/crypto/src/asn1/LazyASN1InputStream.cs
@@ -16,8 +16,18 @@ namespace Org.BouncyCastle.Asn1
{
}
- internal LazyAsn1InputStream(Stream input, int limit, byte[][] tmpBuffers)
- : base(input, limit, tmpBuffers)
+ public LazyAsn1InputStream(Stream input, int limit)
+ : base(input, limit)
+ {
+ }
+
+ public LazyAsn1InputStream(Stream input, int limit, bool leaveOpen)
+ : base(input, limit, leaveOpen)
+ {
+ }
+
+ internal LazyAsn1InputStream(Stream input, int limit, bool leaveOpen, byte[][] tmpBuffers)
+ : base(input, limit, leaveOpen, tmpBuffers)
{
}
@@ -37,7 +47,10 @@ namespace Org.BouncyCastle.Asn1
if (remaining < 1)
return new Asn1EncodableVector(0);
- return new LazyAsn1InputStream(defIn, remaining, tmpBuffers).ReadVector();
+ using (var sub = new LazyAsn1InputStream(defIn, remaining, leaveOpen: true, tmpBuffers))
+ {
+ return sub.ReadVector();
+ }
}
}
}
diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs
index 3a19f1276..67fbba979 100644
--- a/crypto/src/asn1/util/Asn1Dump.cs
+++ b/crypto/src/asn1/util/Asn1Dump.cs
@@ -256,11 +256,13 @@ namespace Org.BouncyCastle.Asn1.Utilities
/// <summary>Parse ASN.1 objects from input <see cref="Stream"/>, and write them to the output.</summary>
public static void Dump(Stream input, TextWriter output)
{
- Asn1InputStream asn1InputStream = new Asn1InputStream(input);
- Asn1Object asn1Object;
- while ((asn1Object = asn1InputStream.ReadObject()) != null)
+ using (var asn1In = new Asn1InputStream(input, int.MaxValue, leaveOpen: true))
{
- output.Write(DumpAsString(asn1Object));
+ Asn1Object asn1Object;
+ while ((asn1Object = asn1In.ReadObject()) != null)
+ {
+ output.Write(DumpAsString(asn1Object));
+ }
}
}
|