179 lines
4.9 KiB
C#
179 lines
4.9 KiB
C#
using System;
|
|
|
|
using Org.BouncyCastle.Utilities;
|
|
|
|
namespace Org.BouncyCastle.Asn1
|
|
{
|
|
/**
|
|
* ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
|
|
* a [n] where n is some number - these are assumed to follow the construction
|
|
* rules (as with sequences).
|
|
*/
|
|
public abstract class Asn1TaggedObject
|
|
: Asn1Object, Asn1TaggedObjectParser
|
|
{
|
|
internal int tagNo;
|
|
// internal bool empty;
|
|
internal bool explicitly = true;
|
|
internal Asn1Encodable obj;
|
|
|
|
static public Asn1TaggedObject GetInstance(
|
|
Asn1TaggedObject obj,
|
|
bool explicitly)
|
|
{
|
|
if (explicitly)
|
|
{
|
|
return (Asn1TaggedObject) obj.GetObject();
|
|
}
|
|
|
|
throw new ArgumentException("implicitly tagged tagged object");
|
|
}
|
|
|
|
static public Asn1TaggedObject GetInstance(
|
|
object obj)
|
|
{
|
|
if (obj == null || obj is Asn1TaggedObject)
|
|
{
|
|
return (Asn1TaggedObject) obj;
|
|
}
|
|
|
|
throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
|
|
}
|
|
|
|
/**
|
|
* @param tagNo the tag number for this object.
|
|
* @param obj the tagged object.
|
|
*/
|
|
protected Asn1TaggedObject(
|
|
int tagNo,
|
|
Asn1Encodable obj)
|
|
{
|
|
this.explicitly = true;
|
|
this.tagNo = tagNo;
|
|
this.obj = obj;
|
|
}
|
|
|
|
/**
|
|
* @param explicitly true if the object is explicitly tagged.
|
|
* @param tagNo the tag number for this object.
|
|
* @param obj the tagged object.
|
|
*/
|
|
protected Asn1TaggedObject(
|
|
bool explicitly,
|
|
int tagNo,
|
|
Asn1Encodable obj)
|
|
{
|
|
// IAsn1Choice marker interface 'insists' on explicit tagging
|
|
this.explicitly = explicitly || (obj is IAsn1Choice);
|
|
this.tagNo = tagNo;
|
|
this.obj = obj;
|
|
}
|
|
|
|
protected override bool Asn1Equals(
|
|
Asn1Object asn1Object)
|
|
{
|
|
Asn1TaggedObject other = asn1Object as Asn1TaggedObject;
|
|
|
|
if (other == null)
|
|
return false;
|
|
|
|
return this.tagNo == other.tagNo
|
|
// && this.empty == other.empty
|
|
&& this.explicitly == other.explicitly // TODO Should this be part of equality?
|
|
&& Platform.Equals(GetObject(), other.GetObject());
|
|
}
|
|
|
|
protected override int Asn1GetHashCode()
|
|
{
|
|
int code = tagNo.GetHashCode();
|
|
|
|
// TODO: actually this is wrong - the problem is that a re-encoded
|
|
// object may end up with a different hashCode due to implicit
|
|
// tagging. As implicit tagging is ambiguous if a sequence is involved
|
|
// it seems the only correct method for both equals and hashCode is to
|
|
// compare the encodings...
|
|
// code ^= explicitly.GetHashCode();
|
|
|
|
if (obj != null)
|
|
{
|
|
code ^= obj.GetHashCode();
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
public int TagNo
|
|
{
|
|
get { return tagNo; }
|
|
}
|
|
|
|
/**
|
|
* return whether or not the object may be explicitly tagged.
|
|
* <p>
|
|
* Note: if the object has been read from an input stream, the only
|
|
* time you can be sure if isExplicit is returning the true state of
|
|
* affairs is if it returns false. An implicitly tagged object may appear
|
|
* to be explicitly tagged, so you need to understand the context under
|
|
* which the reading was done as well, see GetObject below.</p>
|
|
*/
|
|
public bool IsExplicit()
|
|
{
|
|
return explicitly;
|
|
}
|
|
|
|
public bool IsEmpty()
|
|
{
|
|
return false; //empty;
|
|
}
|
|
|
|
/**
|
|
* return whatever was following the tag.
|
|
* <p>
|
|
* Note: tagged objects are generally context dependent if you're
|
|
* trying to extract a tagged object you should be going via the
|
|
* appropriate GetInstance method.</p>
|
|
*/
|
|
public Asn1Object GetObject()
|
|
{
|
|
if (obj != null)
|
|
{
|
|
return obj.ToAsn1Object();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Return the object held in this tagged object as a parser assuming it has
|
|
* the type of the passed in tag. If the object doesn't have a parser
|
|
* associated with it, the base object is returned.
|
|
*/
|
|
public IAsn1Convertible GetObjectParser(
|
|
int tag,
|
|
bool isExplicit)
|
|
{
|
|
switch (tag)
|
|
{
|
|
case Asn1Tags.Set:
|
|
return Asn1Set.GetInstance(this, isExplicit).Parser;
|
|
case Asn1Tags.Sequence:
|
|
return Asn1Sequence.GetInstance(this, isExplicit).Parser;
|
|
case Asn1Tags.OctetString:
|
|
return Asn1OctetString.GetInstance(this, isExplicit).Parser;
|
|
}
|
|
|
|
if (isExplicit)
|
|
{
|
|
return GetObject();
|
|
}
|
|
|
|
throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return "[" + tagNo + "]" + obj;
|
|
}
|
|
}
|
|
}
|