diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs
index 1abf0e0bd..d60a85348 100644
--- a/crypto/src/asn1/Asn1Object.cs
+++ b/crypto/src/asn1/Asn1Object.cs
@@ -13,23 +13,7 @@ namespace Org.BouncyCastle.Asn1
public override void EncodeTo(Stream output, string encoding)
{
- Asn1OutputStream asn1Out = Asn1OutputStream.Create(output, encoding);
- Asn1Object asn1Object = this;
-
- if (Der.Equals(encoding))
- {
- Asn1Set asn1Set = asn1Object as Asn1Set;
- if (null != asn1Set)
- {
- /*
- * NOTE: Even a DerSet isn't necessarily already in sorted order (particularly from DerSetParser),
- * so all sets have to be converted here.
- */
- asn1Object = new DerSet(asn1Set.elements);
- }
- }
-
- asn1Out.WriteObject(asn1Object);
+ Asn1OutputStream.Create(output, encoding).WriteObject(this);
}
/// <summary>Create a base ASN.1 object from a byte array.</summary>
diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs
index 5746d1c59..e6eec563e 100644
--- a/crypto/src/asn1/Asn1OutputStream.cs
+++ b/crypto/src/asn1/Asn1OutputStream.cs
@@ -29,6 +29,29 @@ namespace Org.BouncyCastle.Asn1
{
}
+ public override void WriteObject(Asn1Encodable encodable)
+ {
+ if (null == encodable)
+ throw new IOException("null object detected");
+
+ WritePrimitive(encodable.ToAsn1Object());
+ FlushInternal();
+ }
+
+ public override void WriteObject(Asn1Object primitive)
+ {
+ if (null == primitive)
+ throw new IOException("null object detected");
+
+ WritePrimitive(primitive);
+ FlushInternal();
+ }
+
+ internal void FlushInternal()
+ {
+ // Placeholder to support future internal buffering
+ }
+
internal override bool IsBer
{
get { return true; }
@@ -42,27 +65,16 @@ namespace Org.BouncyCastle.Asn1
}
}
- public override void WriteObject(Asn1Encodable obj)
+ internal virtual void WritePrimitive(Asn1Object primitive)
{
- if (obj == null)
- {
- WriteNull();
- }
- else
- {
- obj.ToAsn1Object().Encode(this);
- }
+ primitive.Encode(this);
}
- public override void WriteObject(Asn1Object obj)
+ internal virtual void WritePrimitives(Asn1Object[] primitives)
{
- if (obj == null)
- {
- WriteNull();
- }
- else
+ for (int i = 0, count = primitives.Length; i < count; ++i)
{
- obj.Encode(this);
+ WritePrimitive(primitives[i]);
}
}
}
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index de039014b..4a7f1e8e5 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -112,6 +112,8 @@ namespace Org.BouncyCastle.Asn1
DerOctetString.Encode(_derOut, _buf, 0, _off);
}
+ _derOut.FlushInternal();
+
_gen.WriteBerEnd();
}
base.Dispose(disposing);
@@ -124,7 +126,9 @@ namespace Org.BouncyCastle.Asn1
DerOctetString.Encode(_derOut, _buf, 0, _off);
}
- _gen.WriteBerEnd();
+ _derOut.FlushInternal();
+
+ _gen.WriteBerEnd();
base.Close();
}
#endif
diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs
index 9dadc24ba..097f77610 100644
--- a/crypto/src/asn1/BerTaggedObject.cs
+++ b/crypto/src/asn1/BerTaggedObject.cs
@@ -51,7 +51,7 @@ namespace Org.BouncyCastle.Asn1
{
if (asn1Out.IsBer)
{
- asn1Out.WriteTag(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo);
+ asn1Out.WriteIdentifier(true, Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo);
asn1Out.WriteByte(0x80);
if (!IsEmpty())
@@ -86,12 +86,12 @@ namespace Org.BouncyCastle.Asn1
foreach (Asn1Encodable o in eObj)
{
- asn1Out.WriteObject(o);
+ asn1Out.WritePrimitive(o.ToAsn1Object());
}
}
else
{
- asn1Out.WriteObject(obj);
+ asn1Out.WritePrimitive(obj.ToAsn1Object());
}
}
diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs
index 3ecdcd11f..84d1af44b 100644
--- a/crypto/src/asn1/DerOutputStream.cs
+++ b/crypto/src/asn1/DerOutputStream.cs
@@ -15,43 +15,52 @@ namespace Org.BouncyCastle.Asn1
{
}
+ public virtual void WriteObject(Asn1Encodable encodable)
+ {
+ new DerOutputStreamNew(s).WriteObject(encodable);
+ }
+
+ public virtual void WriteObject(Asn1Object primitive)
+ {
+ new DerOutputStreamNew(s).WriteObject(primitive);
+ }
+
internal virtual bool IsBer
{
get { return false; }
}
- private void WriteLength(
- int length)
+ internal void WriteDL(int length)
{
- if (length > 127)
- {
- int size = 1;
- uint val = (uint)length;
-
- while ((val >>= 8) != 0)
- {
- size++;
- }
-
- WriteByte((byte)(size | 0x80));
-
- for (int i = (size - 1) * 8; i >= 0; i -= 8)
- {
- WriteByte((byte)(length >> i));
- }
- }
- else
- {
- WriteByte((byte)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(
+ internal void WriteEncoded(
int tag,
byte[] bytes)
{
WriteByte((byte)tag);
- WriteLength(bytes.Length);
+ WriteDL(bytes.Length);
Write(bytes, 0, bytes.Length);
}
@@ -61,7 +70,7 @@ namespace Org.BouncyCastle.Asn1
byte[] bytes)
{
WriteByte((byte)tag);
- WriteLength(bytes.Length + 1);
+ WriteDL(bytes.Length + 1);
WriteByte(first);
Write(bytes, 0, bytes.Length);
}
@@ -73,85 +82,55 @@ namespace Org.BouncyCastle.Asn1
int length)
{
WriteByte((byte)tag);
- WriteLength(length);
+ WriteDL(length);
Write(bytes, offset, length);
}
- internal void WriteTag(
- int flags,
- int tagNo)
- {
- if (tagNo < 31)
- {
- WriteByte((byte)(flags | tagNo));
- }
- else
- {
- WriteByte((byte)(flags | 0x1f));
- if (tagNo < 128)
- {
- WriteByte((byte)tagNo);
- }
- else
- {
- byte[] stack = new byte[5];
- int pos = stack.Length;
-
- stack[--pos] = (byte)(tagNo & 0x7F);
-
- do
- {
- tagNo >>= 7;
- stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
- }
- while (tagNo > 127);
-
- Write(stack, pos, stack.Length - pos);
- }
- }
- }
-
internal void WriteEncoded(
int flags,
int tagNo,
byte[] bytes)
{
- WriteTag(flags, tagNo);
- WriteLength(bytes.Length);
+ WriteIdentifier(true, flags, tagNo);
+ WriteDL(bytes.Length);
Write(bytes, 0, bytes.Length);
}
- protected void WriteNull()
- {
- WriteByte(Asn1Tags.Null);
- WriteByte(0x00);
- }
-
- public virtual void WriteObject(
- Asn1Encodable obj)
- {
- if (obj == null)
- {
- WriteNull();
- }
- else
- {
- obj.ToAsn1Object().Encode(new DerOutputStreamNew(s));
- }
- }
+ internal void WriteIdentifier(bool withID, int identifier)
+ {
+ if (withID)
+ {
+ WriteByte((byte)identifier);
+ }
+ }
- public virtual void WriteObject(
- Asn1Object obj)
- {
- if (obj == null)
- {
- WriteNull();
- }
- else
- {
- obj.Encode(new DerOutputStreamNew(s));
- }
- }
+ 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 class DerOutputStreamNew
@@ -166,5 +145,20 @@ namespace Org.BouncyCastle.Asn1
{
get { return false; }
}
+
+ internal override void WritePrimitive(Asn1Object primitive)
+ {
+ Asn1Set asn1Set = primitive as Asn1Set;
+ if (null != asn1Set)
+ {
+ /*
+ * NOTE: Even a DerSet isn't necessarily already in sorted order (particularly from DerSetParser),
+ * so all sets have to be converted here.
+ */
+ primitive = new DerSet(asn1Set.elements);
+ }
+
+ primitive.Encode(this);
+ }
}
}
diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs
index 182d5ee47..40776ace3 100644
--- a/crypto/src/asn1/DerTaggedObject.cs
+++ b/crypto/src/asn1/DerTaggedObject.cs
@@ -58,7 +58,7 @@ namespace Org.BouncyCastle.Asn1
// need to mark constructed types... (preserve Constructed tag)
//
int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged;
- asn1Out.WriteTag(flags, tagNo);
+ asn1Out.WriteIdentifier(true, flags, tagNo);
asn1Out.Write(bytes, 1, bytes.Length - 1);
}
}
|