diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs
index bc48d24e5..39c2aec28 100644
--- a/crypto/src/asn1/DerApplicationSpecific.cs
+++ b/crypto/src/asn1/DerApplicationSpecific.cs
@@ -11,225 +11,219 @@ namespace Org.BouncyCastle.Asn1
public class DerApplicationSpecific
: Asn1Object
{
- private readonly bool isConstructed;
- private readonly int tag;
- private readonly byte[] octets;
-
- internal DerApplicationSpecific(
- bool isConstructed,
- int tag,
- byte[] octets)
- {
- this.isConstructed = isConstructed;
- this.tag = tag;
- this.octets = octets;
- }
-
- public DerApplicationSpecific(
- int tag,
- byte[] octets)
- : this(false, tag, octets)
- {
- }
-
- public DerApplicationSpecific(
- int tag,
- Asn1Encodable obj)
- : this(true, tag, obj)
- {
- }
-
- public DerApplicationSpecific(
- bool isExplicit,
- int tag,
- Asn1Encodable obj)
- {
- Asn1Object asn1Obj = obj.ToAsn1Object();
-
- byte[] data = asn1Obj.GetDerEncoded();
-
- this.isConstructed = Asn1TaggedObject.IsConstructed(isExplicit, asn1Obj);
- this.tag = tag;
-
- if (isExplicit)
- {
- this.octets = data;
- }
- else
- {
- int lenBytes = GetLengthOfHeader(data);
- byte[] tmp = new byte[data.Length - lenBytes];
- Array.Copy(data, lenBytes, tmp, 0, tmp.Length);
- this.octets = tmp;
- }
- }
-
- public DerApplicationSpecific(
- int tagNo,
- Asn1EncodableVector vec)
- {
- this.tag = tagNo;
- this.isConstructed = true;
- MemoryStream bOut = new MemoryStream();
-
- for (int i = 0; i != vec.Count; i++)
- {
- try
- {
- byte[] bs = vec[i].GetDerEncoded();
- bOut.Write(bs, 0, bs.Length);
- }
- catch (IOException e)
- {
- throw new InvalidOperationException("malformed object", e);
- }
- }
- this.octets = bOut.ToArray();
- }
-
- private int GetLengthOfHeader(
- byte[] data)
- {
- int length = data[1]; // TODO: assumes 1 byte tag
-
- if (length == 0x80)
+ public static DerApplicationSpecific GetInstance(object obj)
+ {
+ if (obj == null || obj is DerApplicationSpecific)
{
- return 2; // indefinite-length encoding
+ return (DerApplicationSpecific)obj;
}
-
- if (length > 127)
+ else if (obj is byte[])
{
- int size = length & 0x7f;
-
- // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
- if (size > 4)
+ try
{
- throw new InvalidOperationException("DER length more than 4 bytes: " + size);
+ return GetInstance(FromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("failed to construct application-specific from byte[]: " + e.Message);
}
-
- return size + 2;
}
- return 2;
+ throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
}
- public bool IsConstructed()
+ internal readonly Asn1TaggedObject m_taggedObject;
+
+ /**
+ * Create an application specific object from the passed in data. This will assume
+ * the data does not represent a constructed object.
+ *
+ * @param tagNo the tag number for this object.
+ * @param contentsOctets the encoding of the object's body.
+ */
+ public DerApplicationSpecific(int tagNo, byte[] contentsOctets)
+ : this(new DerTaggedObject(false, Asn1Tags.Application, tagNo, new DerOctetString(contentsOctets)))
{
- return isConstructed;
}
- public byte[] GetContents()
+ /**
+ * Create an application specific object with a tagging of explicit/constructed.
+ *
+ * @param tag the tag number for this object.
+ * @param object the object to be contained.
+ */
+ public DerApplicationSpecific(int tag, Asn1Encodable baseEncodable)
+ : this(true, tag, baseEncodable)
{
- return octets;
}
- public int ApplicationTag
+ /**
+ * Create an application specific object with the tagging style given by the value of explicit.
+ *
+ * @param explicit true if the object is explicitly tagged.
+ * @param tagNo the tag number for this object.
+ * @param baseEncodable the object to be contained.
+ */
+ public DerApplicationSpecific(bool isExplicit, int tagNo, Asn1Encodable baseEncodable)
+ : this(new DerTaggedObject(isExplicit, Asn1Tags.Application, tagNo, baseEncodable))
{
- get { return tag; }
}
- /**
- * Return the enclosed object assuming explicit tagging.
- *
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public Asn1Object GetObject()
+ /**
+ * Create an application specific object which is marked as constructed
+ *
+ * @param tagNo the tag number for this object.
+ * @param contentsElements the objects making up the application specific object.
+ */
+ public DerApplicationSpecific(int tagNo, Asn1EncodableVector contentsElements)
+ : this(new DerTaggedObject(false, Asn1Tags.Application, tagNo, DerSequence.FromVector(contentsElements)))
{
- return FromByteArray(GetContents());
- }
+ }
- /**
- * Return the enclosed object assuming implicit tagging.
- *
- * @param derTagNo the type tag that should be applied to the object's contents.
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public Asn1Object GetObject(
- int derTagNo)
- {
- if (derTagNo >= 0x1f)
- throw new IOException("unsupported tag number");
+ internal DerApplicationSpecific(Asn1TaggedObject taggedObject)
+ //: base(taggedObject.explicitness, CheckTagClass(taggedObject.tagClass), taggedObject.tagNo,
+ // taggedObject.obj)
+ {
+ CheckTagClass(taggedObject.TagClass);
- byte[] orig = this.GetEncoded();
- byte[] tmp = ReplaceTagNumber(derTagNo, orig);
+ this.m_taggedObject = taggedObject;
+ }
- if ((orig[0] & Asn1Tags.Constructed) != 0)
- {
- tmp[0] |= Asn1Tags.Constructed;
- }
+ public int ApplicationTag
+ {
+ get { return m_taggedObject.TagNo; }
+ }
- return FromByteArray(tmp);
- }
+ public byte[] GetContents()
+ {
+ return m_taggedObject.GetContents();
+ }
- internal override bool EncodeConstructed(int encoding)
+ public Asn1Object GetEnclosedObject()
{
- return isConstructed;
+ return m_taggedObject.GetBaseObject().ToAsn1Object();
}
- internal override int EncodedLength(int encoding, bool withID)
+ [Obsolete("Use GetEnclosedObject instead")]
+ public Asn1Object GetObject()
{
- return Asn1OutputStream.GetLengthOfEncodingDL(withID, tag, octets.Length);
+ return GetEnclosedObject();
}
- internal override void Encode(Asn1OutputStream asn1Out, bool withID)
+ public Asn1Object GetObject(int tagNo)
+ {
+ // TODO[asn1] Implement Asn1TaggedObject.GetBaseUniversal
+ //return taggedObject.GetBaseUniversal(false, tagNo);
+
+ if (tagNo >= 0x1F)
+ throw new IOException("unsupported tag number");
+
+ byte[] orig = this.GetEncoded();
+ byte[] tmp = ReplaceTagNumber(tagNo, orig);
+
+ if ((orig[0] & Asn1Tags.Constructed) != 0)
+ {
+ tmp[0] |= Asn1Tags.Constructed;
+ }
+
+ return FromByteArray(tmp);
+ }
+
+ public bool HasApplicationTag(int tagNo)
+ {
+ return m_taggedObject.HasTag(Asn1Tags.Application, tagNo);
+ }
+
+ public bool IsConstructed()
+ {
+ return m_taggedObject.IsConstructed();
+ }
+
+ /**
+ * DerApplicationSpecific uses an internal Asn1TaggedObject for the
+ * implementation, and will soon be deprecated in favour of using
+ * Asn1TaggedObject with a tag class of {@link Asn1Tags#Application}. This method
+ * lets you get the internal Asn1TaggedObject so that client code can begin the
+ * migration.
+ */
+ public Asn1TaggedObject TaggedObject
{
- int flags = Asn1Tags.Application;
- if (isConstructed)
- {
- flags |= Asn1Tags.Constructed;
- }
+ get { return m_taggedObject; }
+ }
- asn1Out.WriteEncodingDL(withID, flags, tag, octets);
- }
+ protected override bool Asn1Equals(Asn1Object asn1Object)
+ {
+ Asn1TaggedObject that;
+ if (asn1Object is DerApplicationSpecific)
+ {
+ that = ((DerApplicationSpecific)asn1Object).m_taggedObject;
+ }
+ else if (asn1Object is Asn1TaggedObject)
+ {
+ that = (Asn1TaggedObject)asn1Object;
+ }
+ else
+ {
+ return false;
+ }
+
+ return m_taggedObject.Equals(that);
+ }
- protected override bool Asn1Equals(
- Asn1Object asn1Object)
+ protected override int Asn1GetHashCode()
{
- DerApplicationSpecific other = asn1Object as DerApplicationSpecific;
+ return m_taggedObject.CallAsn1GetHashCode();
+ }
- if (other == null)
- return false;
+ internal override bool EncodeConstructed(int encoding)
+ {
+ return m_taggedObject.EncodeConstructed(encoding);
+ }
- return this.isConstructed == other.isConstructed
- && this.tag == other.tag
- && Arrays.AreEqual(this.octets, other.octets);
+ internal override int EncodedLength(int encoding, bool withID)
+ {
+ return m_taggedObject.EncodedLength(encoding, withID);
}
- protected override int Asn1GetHashCode()
- {
- return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets);
+ internal override void Encode(Asn1OutputStream asn1Out, bool withID)
+ {
+ m_taggedObject.Encode(asn1Out, withID);
}
- private byte[] ReplaceTagNumber(
- int newTag,
- byte[] input)
- {
- int tagNo = input[0] & 0x1f;
- int index = 1;
+ private byte[] ReplaceTagNumber(int newTag, byte[] input)
+ {
+ int tagNo = input[0] & 0x1f;
+ int index = 1;
// with tagged object tag number is bottom 5 bits, or stored at the start of the content
- if (tagNo == 0x1f)
- {
- int b = input[index++];
+ if (tagNo == 0x1f)
+ {
+ int b = input[index++];
// X.690-0207 8.1.2.4.2
- // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
- if ((b & 0x7f) == 0) // Note: -1 will pass
- throw new IOException("corrupted stream - invalid high tag number found");
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ throw new IOException("corrupted stream - invalid high tag number found");
while ((b & 0x80) != 0)
- {
- b = input[index++];
- }
- }
+ {
+ b = input[index++];
+ }
+ }
int remaining = input.Length - index;
byte[] tmp = new byte[1 + remaining];
tmp[0] = (byte)newTag;
- Array.Copy(input, index, tmp, 1, remaining);
- return tmp;
- }
+ Array.Copy(input, index, tmp, 1, remaining);
+ return tmp;
+ }
+
+ private static int CheckTagClass(int tagClass)
+ {
+ if (Asn1Tags.Application != tagClass)
+ throw new ArgumentException();
+
+ return tagClass;
+ }
}
}
|