diff --git a/Crypto/src/asn1/x509/AccessDescription.cs b/Crypto/src/asn1/x509/AccessDescription.cs
new file mode 100644
index 000000000..09b5b5920
--- /dev/null
+++ b/Crypto/src/asn1/x509/AccessDescription.cs
@@ -0,0 +1,83 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The AccessDescription object.
+ * <pre>
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ * </pre>
+ */
+ public class AccessDescription
+ : Asn1Encodable
+ {
+ public readonly static DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier("1.3.6.1.5.5.7.48.2");
+ public readonly static DerObjectIdentifier IdADOcsp = new DerObjectIdentifier("1.3.6.1.5.5.7.48.1");
+
+ private readonly DerObjectIdentifier accessMethod;
+ private readonly GeneralName accessLocation;
+
+ public static AccessDescription GetInstance(
+ object obj)
+ {
+ if (obj is AccessDescription)
+ return (AccessDescription) obj;
+
+ if (obj is Asn1Sequence)
+ return new AccessDescription((Asn1Sequence) obj);
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private AccessDescription(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("wrong number of elements in sequence");
+
+ accessMethod = DerObjectIdentifier.GetInstance(seq[0]);
+ accessLocation = GeneralName.GetInstance(seq[1]);
+ }
+
+ /**
+ * create an AccessDescription with the oid and location provided.
+ */
+ public AccessDescription(
+ DerObjectIdentifier oid,
+ GeneralName location)
+ {
+ accessMethod = oid;
+ accessLocation = location;
+ }
+
+ /**
+ *
+ * @return the access method.
+ */
+ public DerObjectIdentifier AccessMethod
+ {
+ get { return accessMethod; }
+ }
+
+ /**
+ *
+ * @return the access location
+ */
+ public GeneralName AccessLocation
+ {
+ get { return accessLocation; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(accessMethod, accessLocation);
+ }
+
+ public override string ToString()
+ {
+ return "AccessDescription: Oid(" + this.accessMethod.Id + ")";
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AlgorithmIdentifier.cs b/Crypto/src/asn1/x509/AlgorithmIdentifier.cs
new file mode 100644
index 000000000..caf9e77c9
--- /dev/null
+++ b/Crypto/src/asn1/x509/AlgorithmIdentifier.cs
@@ -0,0 +1,110 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AlgorithmIdentifier
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier objectID;
+ private readonly Asn1Encodable parameters;
+ private readonly bool parametersDefined;
+
+ public static AlgorithmIdentifier GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static AlgorithmIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is AlgorithmIdentifier)
+ return (AlgorithmIdentifier) obj;
+
+ if (obj is DerObjectIdentifier)
+ return new AlgorithmIdentifier((DerObjectIdentifier) obj);
+
+ if (obj is string)
+ return new AlgorithmIdentifier((string) obj);
+
+ if (obj is Asn1Sequence)
+ return new AlgorithmIdentifier((Asn1Sequence) obj);
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public AlgorithmIdentifier(
+ DerObjectIdentifier objectID)
+ {
+ this.objectID = objectID;
+ }
+
+ public AlgorithmIdentifier(
+ string objectID)
+ {
+ this.objectID = new DerObjectIdentifier(objectID);
+ }
+
+ public AlgorithmIdentifier(
+ DerObjectIdentifier objectID,
+ Asn1Encodable parameters)
+ {
+ this.objectID = objectID;
+ this.parameters = parameters;
+ this.parametersDefined = true;
+ }
+
+ internal AlgorithmIdentifier(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ this.objectID = DerObjectIdentifier.GetInstance(seq[0]);
+ this.parametersDefined = (seq.Count == 2);
+
+ if (parametersDefined)
+ {
+ this.parameters = seq[1];
+ }
+ }
+
+ public virtual DerObjectIdentifier ObjectID
+ {
+ get { return objectID; }
+ }
+
+ public Asn1Encodable Parameters
+ {
+ get { return parameters; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AlgorithmIdentifier ::= Sequence {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(objectID);
+
+ if (parametersDefined)
+ {
+ if (parameters != null)
+ {
+ v.Add(parameters);
+ }
+ else
+ {
+ v.Add(DerNull.Instance);
+ }
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AttCertIssuer.cs b/Crypto/src/asn1/x509/AttCertIssuer.cs
new file mode 100644
index 000000000..e9314fa92
--- /dev/null
+++ b/Crypto/src/asn1/x509/AttCertIssuer.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AttCertIssuer
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal readonly Asn1Encodable obj;
+ internal readonly Asn1Object choiceObj;
+
+ public static AttCertIssuer GetInstance(
+ object obj)
+ {
+ if (obj is AttCertIssuer)
+ {
+ return (AttCertIssuer)obj;
+ }
+ else if (obj is V2Form)
+ {
+ return new AttCertIssuer(V2Form.GetInstance(obj));
+ }
+ else if (obj is GeneralNames)
+ {
+ return new AttCertIssuer((GeneralNames)obj);
+ }
+ else if (obj is Asn1TaggedObject)
+ {
+ return new AttCertIssuer(V2Form.GetInstance((Asn1TaggedObject)obj, false));
+ }
+ else if (obj is Asn1Sequence)
+ {
+ return new AttCertIssuer(GeneralNames.GetInstance(obj));
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static AttCertIssuer GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(obj.GetObject()); // must be explictly tagged
+ }
+
+ /// <summary>
+ /// Don't use this one if you are trying to be RFC 3281 compliant.
+ /// Use it for v1 attribute certificates only.
+ /// </summary>
+ /// <param name="names">Our GeneralNames structure</param>
+ public AttCertIssuer(
+ GeneralNames names)
+ {
+ obj = names;
+ choiceObj = obj.ToAsn1Object();
+ }
+
+ public AttCertIssuer(
+ V2Form v2Form)
+ {
+ obj = v2Form;
+ choiceObj = new DerTaggedObject(false, 0, obj);
+ }
+
+ public Asn1Encodable Issuer
+ {
+ get { return obj; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AttCertIssuer ::= CHOICE {
+ * v1Form GeneralNames, -- MUST NOT be used in this
+ * -- profile
+ * v2Form [0] V2Form -- v2 only
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return choiceObj;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AttCertValidityPeriod.cs b/Crypto/src/asn1/x509/AttCertValidityPeriod.cs
new file mode 100644
index 000000000..7f86cd0b8
--- /dev/null
+++ b/Crypto/src/asn1/x509/AttCertValidityPeriod.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AttCertValidityPeriod
+ : Asn1Encodable
+ {
+ private readonly DerGeneralizedTime notBeforeTime;
+ private readonly DerGeneralizedTime notAfterTime;
+
+ public static AttCertValidityPeriod GetInstance(
+ object obj)
+ {
+ if (obj is AttCertValidityPeriod || obj == null)
+ {
+ return (AttCertValidityPeriod) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new AttCertValidityPeriod((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static AttCertValidityPeriod GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ private AttCertValidityPeriod(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ notBeforeTime = DerGeneralizedTime.GetInstance(seq[0]);
+ notAfterTime = DerGeneralizedTime.GetInstance(seq[1]);
+ }
+
+ public AttCertValidityPeriod(
+ DerGeneralizedTime notBeforeTime,
+ DerGeneralizedTime notAfterTime)
+ {
+ this.notBeforeTime = notBeforeTime;
+ this.notAfterTime = notAfterTime;
+ }
+
+ public DerGeneralizedTime NotBeforeTime
+ {
+ get { return notBeforeTime; }
+ }
+
+ public DerGeneralizedTime NotAfterTime
+ {
+ get { return notAfterTime; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AttCertValidityPeriod ::= Sequence {
+ * notBeforeTime GeneralizedTime,
+ * notAfterTime GeneralizedTime
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(notBeforeTime, notAfterTime);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/Attribute.cs b/Crypto/src/asn1/x509/Attribute.cs
new file mode 100644
index 000000000..d26db93e9
--- /dev/null
+++ b/Crypto/src/asn1/x509/Attribute.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AttributeX509
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier attrType;
+ private readonly Asn1Set attrValues;
+
+ /**
+ * return an Attr object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static AttributeX509 GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is AttributeX509)
+ {
+ return (AttributeX509) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new AttributeX509((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private AttributeX509(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ attrType = DerObjectIdentifier.GetInstance(seq[0]);
+ attrValues = Asn1Set.GetInstance(seq[1]);
+ }
+
+ public AttributeX509(
+ DerObjectIdentifier attrType,
+ Asn1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public DerObjectIdentifier AttrType
+ {
+ get { return attrType; }
+ }
+
+ public Asn1Encodable[] GetAttributeValues()
+ {
+ return attrValues.ToArray();
+ }
+
+ public Asn1Set AttrValues
+ {
+ get { return attrValues; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * Attr ::= Sequence {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues Set OF AttributeValue
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(attrType, attrValues);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AttributeCertificate.cs b/Crypto/src/asn1/x509/AttributeCertificate.cs
new file mode 100644
index 000000000..5f85910da
--- /dev/null
+++ b/Crypto/src/asn1/x509/AttributeCertificate.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AttributeCertificate
+ : Asn1Encodable
+ {
+ private readonly AttributeCertificateInfo acinfo;
+ private readonly AlgorithmIdentifier signatureAlgorithm;
+ private readonly DerBitString signatureValue;
+
+ /**
+ * @param obj
+ * @return
+ */
+ public static AttributeCertificate GetInstance(
+ object obj)
+ {
+ if (obj is AttributeCertificate)
+ return (AttributeCertificate) obj;
+
+ if (obj != null)
+ return new AttributeCertificate(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public AttributeCertificate(
+ AttributeCertificateInfo acinfo,
+ AlgorithmIdentifier signatureAlgorithm,
+ DerBitString signatureValue)
+ {
+ this.acinfo = acinfo;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signatureValue = signatureValue;
+ }
+
+ private AttributeCertificate(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ this.acinfo = AttributeCertificateInfo.GetInstance(seq[0]);
+ this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+ this.signatureValue = DerBitString.GetInstance(seq[2]);
+ }
+
+ public AttributeCertificateInfo ACInfo
+ {
+ get { return acinfo; }
+ }
+
+ public AlgorithmIdentifier SignatureAlgorithm
+ {
+ get { return signatureAlgorithm; }
+ }
+
+ public DerBitString SignatureValue
+ {
+ get { return signatureValue; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AttributeCertificate ::= Sequence {
+ * acinfo AttributeCertificateInfo,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(acinfo, signatureAlgorithm, signatureValue);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AttributeCertificateInfo.cs b/Crypto/src/asn1/x509/AttributeCertificateInfo.cs
new file mode 100644
index 000000000..dcef3d472
--- /dev/null
+++ b/Crypto/src/asn1/x509/AttributeCertificateInfo.cs
@@ -0,0 +1,156 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AttributeCertificateInfo
+ : Asn1Encodable
+ {
+ internal readonly DerInteger version;
+ internal readonly Holder holder;
+ internal readonly AttCertIssuer issuer;
+ internal readonly AlgorithmIdentifier signature;
+ internal readonly DerInteger serialNumber;
+ internal readonly AttCertValidityPeriod attrCertValidityPeriod;
+ internal readonly Asn1Sequence attributes;
+ internal readonly DerBitString issuerUniqueID;
+ internal readonly X509Extensions extensions;
+
+ public static AttributeCertificateInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public static AttributeCertificateInfo GetInstance(
+ object obj)
+ {
+ if (obj is AttributeCertificateInfo)
+ {
+ return (AttributeCertificateInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new AttributeCertificateInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private AttributeCertificateInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 7 || seq.Count > 9)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ this.version = DerInteger.GetInstance(seq[0]);
+ this.holder = Holder.GetInstance(seq[1]);
+ this.issuer = AttCertIssuer.GetInstance(seq[2]);
+ this.signature = AlgorithmIdentifier.GetInstance(seq[3]);
+ this.serialNumber = DerInteger.GetInstance(seq[4]);
+ this.attrCertValidityPeriod = AttCertValidityPeriod.GetInstance(seq[5]);
+ this.attributes = Asn1Sequence.GetInstance(seq[6]);
+
+ for (int i = 7; i < seq.Count; i++)
+ {
+ Asn1Encodable obj = (Asn1Encodable) seq[i];
+
+ if (obj is DerBitString)
+ {
+ this.issuerUniqueID = DerBitString.GetInstance(seq[i]);
+ }
+ else if (obj is Asn1Sequence || obj is X509Extensions)
+ {
+ this.extensions = X509Extensions.GetInstance(seq[i]);
+ }
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public Holder Holder
+ {
+ get { return holder; }
+ }
+
+ public AttCertIssuer Issuer
+ {
+ get { return issuer; }
+ }
+
+ public AlgorithmIdentifier Signature
+ {
+ get { return signature; }
+ }
+
+ public DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ public AttCertValidityPeriod AttrCertValidityPeriod
+ {
+ get { return attrCertValidityPeriod; }
+ }
+
+ public Asn1Sequence Attributes
+ {
+ get { return attributes; }
+ }
+
+ public DerBitString IssuerUniqueID
+ {
+ get { return issuerUniqueID; }
+ }
+
+ public X509Extensions Extensions
+ {
+ get { return extensions; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AttributeCertificateInfo ::= Sequence {
+ * version AttCertVersion -- version is v2,
+ * holder Holder,
+ * issuer AttCertIssuer,
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes Sequence OF Attr,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ *
+ * AttCertVersion ::= Integer { v2(1) }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, holder, issuer, signature, serialNumber,
+ attrCertValidityPeriod, attributes);
+
+ if (issuerUniqueID != null)
+ {
+ v.Add(issuerUniqueID);
+ }
+
+ if (extensions != null)
+ {
+ v.Add(extensions);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AttributeTable.cs b/Crypto/src/asn1/x509/AttributeTable.cs
new file mode 100644
index 000000000..87b112f01
--- /dev/null
+++ b/Crypto/src/asn1/x509/AttributeTable.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class AttributeTable
+ {
+ private readonly IDictionary attributes;
+
+ public AttributeTable(
+ IDictionary attrs)
+ {
+ this.attributes = Platform.CreateHashtable(attrs);
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public AttributeTable(
+ Hashtable attrs)
+ {
+ this.attributes = Platform.CreateHashtable(attrs);
+ }
+#endif
+
+ public AttributeTable(
+ Asn1EncodableVector v)
+ {
+ this.attributes = Platform.CreateHashtable(v.Count);
+
+ for (int i = 0; i != v.Count; i++)
+ {
+ AttributeX509 a = AttributeX509.GetInstance(v[i]);
+
+ attributes.Add(a.AttrType, a);
+ }
+ }
+
+ public AttributeTable(
+ Asn1Set s)
+ {
+ this.attributes = Platform.CreateHashtable(s.Count);
+
+ for (int i = 0; i != s.Count; i++)
+ {
+ AttributeX509 a = AttributeX509.GetInstance(s[i]);
+
+ attributes.Add(a.AttrType, a);
+ }
+ }
+
+ public AttributeX509 Get(
+ DerObjectIdentifier oid)
+ {
+ return (AttributeX509) attributes[oid];
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete("Use 'ToDictionary' instead")]
+ public Hashtable ToHashtable()
+ {
+ return new Hashtable(attributes);
+ }
+#endif
+
+ public IDictionary ToDictionary()
+ {
+ return Platform.CreateHashtable(attributes);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AuthorityInformationAccess.cs b/Crypto/src/asn1/x509/AuthorityInformationAccess.cs
new file mode 100644
index 000000000..3eeba8cd2
--- /dev/null
+++ b/Crypto/src/asn1/x509/AuthorityInformationAccess.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The AuthorityInformationAccess object.
+ * <pre>
+ * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+ *
+ * AuthorityInfoAccessSyntax ::=
+ * Sequence SIZE (1..MAX) OF AccessDescription
+ * AccessDescription ::= Sequence {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ *
+ * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+ * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+ * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+ * </pre>
+ */
+ public class AuthorityInformationAccess
+ : Asn1Encodable
+ {
+ private readonly AccessDescription[] descriptions;
+
+ public static AuthorityInformationAccess GetInstance(
+ object obj)
+ {
+ if (obj is AuthorityInformationAccess)
+ return (AuthorityInformationAccess) obj;
+
+ if (obj is Asn1Sequence)
+ return new AuthorityInformationAccess((Asn1Sequence) obj);
+
+ if (obj is X509Extension)
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private AuthorityInformationAccess(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1)
+ throw new ArgumentException("sequence may not be empty");
+
+ this.descriptions = new AccessDescription[seq.Count];
+
+ for (int i = 0; i < seq.Count; ++i)
+ {
+ descriptions[i] = AccessDescription.GetInstance(seq[i]);
+ }
+ }
+
+ /**
+ * create an AuthorityInformationAccess with the oid and location provided.
+ */
+ [Obsolete("Use version taking an AccessDescription instead")]
+ public AuthorityInformationAccess(
+ DerObjectIdentifier oid,
+ GeneralName location)
+ {
+ this.descriptions = new AccessDescription[]{ new AccessDescription(oid, location) };
+ }
+
+ public AuthorityInformationAccess(
+ AccessDescription description)
+ {
+ this.descriptions = new AccessDescription[]{ description };
+ }
+
+ public AccessDescription[] GetAccessDescriptions()
+ {
+ return (AccessDescription[]) descriptions.Clone();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(descriptions);
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder();
+ string sep = Platform.NewLine;
+
+ buf.Append("AuthorityInformationAccess:");
+ buf.Append(sep);
+
+ foreach (AccessDescription description in descriptions)
+ {
+ buf.Append(" ");
+ buf.Append(description);
+ buf.Append(sep);
+ }
+
+ return buf.ToString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/AuthorityKeyIdentifier.cs b/Crypto/src/asn1/x509/AuthorityKeyIdentifier.cs
new file mode 100644
index 000000000..12ccacfc7
--- /dev/null
+++ b/Crypto/src/asn1/x509/AuthorityKeyIdentifier.cs
@@ -0,0 +1,211 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The AuthorityKeyIdentifier object.
+ * <pre>
+ * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+ *
+ * AuthorityKeyIdentifier ::= Sequence {
+ * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * </pre>
+ *
+ */
+ public class AuthorityKeyIdentifier
+ : Asn1Encodable
+ {
+ internal readonly Asn1OctetString keyidentifier;
+ internal readonly GeneralNames certissuer;
+ internal readonly DerInteger certserno;
+
+ public static AuthorityKeyIdentifier GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static AuthorityKeyIdentifier GetInstance(
+ object obj)
+ {
+ if (obj is AuthorityKeyIdentifier)
+ {
+ return (AuthorityKeyIdentifier) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new AuthorityKeyIdentifier((Asn1Sequence) obj);
+ }
+
+ if (obj is X509Extension)
+ {
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ protected internal AuthorityKeyIdentifier(
+ Asn1Sequence seq)
+ {
+ foreach (Asn1TaggedObject o in seq)
+ {
+ switch (o.TagNo)
+ {
+ case 0:
+ this.keyidentifier = Asn1OctetString.GetInstance(o, false);
+ break;
+ case 1:
+ this.certissuer = GeneralNames.GetInstance(o, false);
+ break;
+ case 2:
+ this.certserno = DerInteger.GetInstance(o, false);
+ break;
+ default:
+ throw new ArgumentException("illegal tag");
+ }
+ }
+ }
+
+ /**
+ *
+ * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
+ * from SubjectPublicKeyInfo as defined in RFC2459.
+ *
+ * Example of making a AuthorityKeyIdentifier:
+ * <pre>
+ * SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
+ * publicKey.getEncoded()).readObject());
+ * AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+ * </pre>
+ *
+ **/
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki)
+ {
+ IDigest digest = new Sha1Digest();
+ byte[] resBuf = new byte[digest.GetDigestSize()];
+
+ byte[] bytes = spki.PublicKeyData.GetBytes();
+ digest.BlockUpdate(bytes, 0, bytes.Length);
+ digest.DoFinal(resBuf, 0);
+ this.keyidentifier = new DerOctetString(resBuf);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with the GeneralNames tag and
+ * the serial number provided as well.
+ */
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki,
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ IDigest digest = new Sha1Digest();
+ byte[] resBuf = new byte[digest.GetDigestSize()];
+
+ byte[] bytes = spki.PublicKeyData.GetBytes();
+ digest.BlockUpdate(bytes, 0, bytes.Length);
+ digest.DoFinal(resBuf, 0);
+
+ this.keyidentifier = new DerOctetString(resBuf);
+ this.certissuer = name;
+ this.certserno = new DerInteger(serialNumber);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with the GeneralNames tag and
+ * the serial number provided.
+ */
+ public AuthorityKeyIdentifier(
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ this.keyidentifier = null;
+ this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object());
+ this.certserno = new DerInteger(serialNumber);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with a precomputed key identifier
+ */
+ public AuthorityKeyIdentifier(
+ byte[] keyIdentifier)
+ {
+ this.keyidentifier = new DerOctetString(keyIdentifier);
+ this.certissuer = null;
+ this.certserno = null;
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with a precomupted key identifier
+ * and the GeneralNames tag and the serial number provided as well.
+ */
+ public AuthorityKeyIdentifier(
+ byte[] keyIdentifier,
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ this.keyidentifier = new DerOctetString(keyIdentifier);
+ this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object());
+ this.certserno = new DerInteger(serialNumber);
+ }
+
+ public byte[] GetKeyIdentifier()
+ {
+ return keyidentifier == null ? null : keyidentifier.GetOctets();
+ }
+
+ public GeneralNames AuthorityCertIssuer
+ {
+ get { return certissuer; }
+ }
+
+ public BigInteger AuthorityCertSerialNumber
+ {
+ get { return certserno == null ? null : certserno.Value; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (keyidentifier != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, keyidentifier));
+ }
+
+ if (certissuer != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, certissuer));
+ }
+
+ if (certserno != null)
+ {
+ v.Add(new DerTaggedObject(false, 2, certserno));
+ }
+
+ return new DerSequence(v);
+ }
+
+ public override string ToString()
+ {
+ return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.GetOctets() + ")");
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/BasicConstraints.cs b/Crypto/src/asn1/x509/BasicConstraints.cs
new file mode 100644
index 000000000..522cb61cc
--- /dev/null
+++ b/Crypto/src/asn1/x509/BasicConstraints.cs
@@ -0,0 +1,133 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class BasicConstraints
+ : Asn1Encodable
+ {
+ private readonly DerBoolean cA;
+ private readonly DerInteger pathLenConstraint;
+
+ public static BasicConstraints GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static BasicConstraints GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is BasicConstraints)
+ {
+ return (BasicConstraints) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new BasicConstraints((Asn1Sequence) obj);
+ }
+
+ if (obj is X509Extension)
+ {
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private BasicConstraints(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 0)
+ {
+ if (seq[0] is DerBoolean)
+ {
+ this.cA = DerBoolean.GetInstance(seq[0]);
+ }
+ else
+ {
+ this.pathLenConstraint = DerInteger.GetInstance(seq[0]);
+ }
+
+ if (seq.Count > 1)
+ {
+ if (this.cA == null)
+ throw new ArgumentException("wrong sequence in constructor", "seq");
+
+ this.pathLenConstraint = DerInteger.GetInstance(seq[1]);
+ }
+ }
+ }
+
+ public BasicConstraints(
+ bool cA)
+ {
+ if (cA)
+ {
+ this.cA = DerBoolean.True;
+ }
+ }
+
+ /**
+ * create a cA=true object for the given path length constraint.
+ *
+ * @param pathLenConstraint
+ */
+ public BasicConstraints(
+ int pathLenConstraint)
+ {
+ this.cA = DerBoolean.True;
+ this.pathLenConstraint = new DerInteger(pathLenConstraint);
+ }
+
+ public bool IsCA()
+ {
+ return cA != null && cA.IsTrue;
+ }
+
+ public BigInteger PathLenConstraint
+ {
+ get { return pathLenConstraint == null ? null : pathLenConstraint.Value; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * BasicConstraints := Sequence {
+ * cA Boolean DEFAULT FALSE,
+ * pathLenConstraint Integer (0..MAX) OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (cA != null)
+ {
+ v.Add(cA);
+ }
+
+ if (pathLenConstraint != null) // yes some people actually do this when cA is false...
+ {
+ v.Add(pathLenConstraint);
+ }
+
+ return new DerSequence(v);
+ }
+
+ public override string ToString()
+ {
+ if (pathLenConstraint == null)
+ {
+ return "BasicConstraints: isCa(" + this.IsCA() + ")";
+ }
+
+ return "BasicConstraints: isCa(" + this.IsCA() + "), pathLenConstraint = " + pathLenConstraint.Value;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/CRLDistPoint.cs b/Crypto/src/asn1/x509/CRLDistPoint.cs
new file mode 100644
index 000000000..2b5c19798
--- /dev/null
+++ b/Crypto/src/asn1/x509/CRLDistPoint.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class CrlDistPoint
+ : Asn1Encodable
+ {
+ internal readonly Asn1Sequence seq;
+
+ public static CrlDistPoint GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static CrlDistPoint GetInstance(
+ object obj)
+ {
+ if (obj is CrlDistPoint || obj == null)
+ {
+ return (CrlDistPoint) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new CrlDistPoint((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private CrlDistPoint(
+ Asn1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ public CrlDistPoint(
+ DistributionPoint[] points)
+ {
+ seq = new DerSequence(points);
+ }
+
+ /**
+ * Return the distribution points making up the sequence.
+ *
+ * @return DistributionPoint[]
+ */
+ public DistributionPoint[] GetDistributionPoints()
+ {
+ DistributionPoint[] dp = new DistributionPoint[seq.Count];
+
+ for (int i = 0; i != seq.Count; ++i)
+ {
+ dp[i] = DistributionPoint.GetInstance(seq[i]);
+ }
+
+ return dp;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * CrlDistPoint ::= Sequence SIZE {1..MAX} OF DistributionPoint
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder();
+ string sep = Platform.NewLine;
+
+ buf.Append("CRLDistPoint:");
+ buf.Append(sep);
+ DistributionPoint[] dp = GetDistributionPoints();
+ for (int i = 0; i != dp.Length; i++)
+ {
+ buf.Append(" ");
+ buf.Append(dp[i]);
+ buf.Append(sep);
+ }
+ return buf.ToString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/CRLNumber.cs b/Crypto/src/asn1/x509/CRLNumber.cs
new file mode 100644
index 000000000..d744416a5
--- /dev/null
+++ b/Crypto/src/asn1/x509/CRLNumber.cs
@@ -0,0 +1,30 @@
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The CRLNumber object.
+ * <pre>
+ * CRLNumber::= Integer(0..MAX)
+ * </pre>
+ */
+ public class CrlNumber
+ : DerInteger
+ {
+ public CrlNumber(
+ BigInteger number)
+ : base(number)
+ {
+ }
+
+ public BigInteger Number
+ {
+ get { return PositiveValue; }
+ }
+
+ public override string ToString()
+ {
+ return "CRLNumber: " + Number;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/CRLReason.cs b/Crypto/src/asn1/x509/CRLReason.cs
new file mode 100644
index 000000000..e8eb53a59
--- /dev/null
+++ b/Crypto/src/asn1/x509/CRLReason.cs
@@ -0,0 +1,61 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The CRLReason enumeration.
+ * <pre>
+ * CRLReason ::= Enumerated {
+ * unspecified (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * removeFromCRL (8),
+ * privilegeWithdrawn (9),
+ * aACompromise (10)
+ * }
+ * </pre>
+ */
+ public class CrlReason
+ : DerEnumerated
+ {
+ public const int Unspecified = 0;
+ public const int KeyCompromise = 1;
+ public const int CACompromise = 2;
+ public const int AffiliationChanged = 3;
+ public const int Superseded = 4;
+ public const int CessationOfOperation = 5;
+ public const int CertificateHold = 6;
+ // 7 -> Unknown
+ public const int RemoveFromCrl = 8;
+ public const int PrivilegeWithdrawn = 9;
+ public const int AACompromise = 10;
+
+ private static readonly string[] ReasonString = new string[]
+ {
+ "Unspecified", "KeyCompromise", "CACompromise", "AffiliationChanged",
+ "Superseded", "CessationOfOperation", "CertificateHold", "Unknown",
+ "RemoveFromCrl", "PrivilegeWithdrawn", "AACompromise"
+ };
+
+ public CrlReason(
+ int reason)
+ : base(reason)
+ {
+ }
+
+ public CrlReason(
+ DerEnumerated reason)
+ : base(reason.Value.IntValue)
+ {
+ }
+
+ public override string ToString()
+ {
+ int reason = Value.IntValue;
+ string str = (reason < 0 || reason > 10) ? "Invalid" : ReasonString[reason];
+ return "CrlReason: " + str;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/CertPolicyId.cs b/Crypto/src/asn1/x509/CertPolicyId.cs
new file mode 100644
index 000000000..11cebcdd7
--- /dev/null
+++ b/Crypto/src/asn1/x509/CertPolicyId.cs
@@ -0,0 +1,20 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * CertPolicyId, used in the CertificatePolicies and PolicyMappings
+ * X509V3 Extensions.
+ *
+ * <pre>
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ * </pre>
+ */
+ public class CertPolicyID
+ : DerObjectIdentifier
+ {
+ public CertPolicyID(
+ string id)
+ : base(id)
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/CertificateList.cs b/Crypto/src/asn1/x509/CertificateList.cs
new file mode 100644
index 000000000..0412e0816
--- /dev/null
+++ b/Crypto/src/asn1/x509/CertificateList.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * PKIX RFC-2459
+ *
+ * The X.509 v2 CRL syntax is as follows. For signature calculation,
+ * the data that is to be signed is ASN.1 Der encoded.
+ *
+ * <pre>
+ * CertificateList ::= Sequence {
+ * tbsCertList TbsCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ * </pre>
+ */
+ public class CertificateList
+ : Asn1Encodable
+ {
+ private readonly TbsCertificateList tbsCertList;
+ private readonly AlgorithmIdentifier sigAlgID;
+ private readonly DerBitString sig;
+
+ public static CertificateList GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static CertificateList GetInstance(
+ object obj)
+ {
+ if (obj is CertificateList)
+ return (CertificateList) obj;
+
+ if (obj != null)
+ return new CertificateList(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ private CertificateList(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("sequence wrong size for CertificateList", "seq");
+
+ tbsCertList = TbsCertificateList.GetInstance(seq[0]);
+ sigAlgID = AlgorithmIdentifier.GetInstance(seq[1]);
+ sig = DerBitString.GetInstance(seq[2]);
+ }
+
+ public TbsCertificateList TbsCertList
+ {
+ get { return tbsCertList; }
+ }
+
+ public CrlEntry[] GetRevokedCertificates()
+ {
+ return tbsCertList.GetRevokedCertificates();
+ }
+
+ public IEnumerable GetRevokedCertificateEnumeration()
+ {
+ return tbsCertList.GetRevokedCertificateEnumeration();
+ }
+
+ public AlgorithmIdentifier SignatureAlgorithm
+ {
+ get { return sigAlgID; }
+ }
+
+ public DerBitString Signature
+ {
+ get { return sig; }
+ }
+
+ public int Version
+ {
+ get { return tbsCertList.Version; }
+ }
+
+ public X509Name Issuer
+ {
+ get { return tbsCertList.Issuer; }
+ }
+
+ public Time ThisUpdate
+ {
+ get { return tbsCertList.ThisUpdate; }
+ }
+
+ public Time NextUpdate
+ {
+ get { return tbsCertList.NextUpdate; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(tbsCertList, sigAlgID, sig);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/CertificatePair.cs b/Crypto/src/asn1/x509/CertificatePair.cs
new file mode 100644
index 000000000..8baa64719
--- /dev/null
+++ b/Crypto/src/asn1/x509/CertificatePair.cs
@@ -0,0 +1,160 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * This class helps to support crossCerfificatePairs in a LDAP directory
+ * according RFC 2587
+ *
+ * <pre>
+ * crossCertificatePairATTRIBUTE::={
+ * WITH SYNTAX CertificatePair
+ * EQUALITY MATCHING RULE certificatePairExactMatch
+ * ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+ * </pre>
+ *
+ * <blockquote> The forward elements of the crossCertificatePair attribute of a
+ * CA's directory entry shall be used to store all, except self-issued
+ * certificates issued to this CA. Optionally, the reverse elements of the
+ * crossCertificatePair attribute, of a CA's directory entry may contain a
+ * subset of certificates issued by this CA to other CAs. When both the forward
+ * and the reverse elements are present in a single attribute value, issuer name
+ * in one certificate shall match the subject name in the other and vice versa,
+ * and the subject public key in one certificate shall be capable of verifying
+ * the digital signature on the other certificate and vice versa.
+ *
+ * When a reverse element is present, the forward element value and the reverse
+ * element value need not be stored in the same attribute value; in other words,
+ * they can be stored in either a single attribute value or two attribute
+ * values. </blockquote>
+ *
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ */
+ public class CertificatePair
+ : Asn1Encodable
+ {
+ private X509CertificateStructure forward, reverse;
+
+ public static CertificatePair GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CertificatePair)
+ {
+ return (CertificatePair) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new CertificatePair((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * The sequence is of type CertificatePair:
+ * <p/>
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private CertificatePair(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 1 && seq.Count != 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+ }
+
+ foreach (object obj in seq)
+ {
+ Asn1TaggedObject o = Asn1TaggedObject.GetInstance(obj);
+ if (o.TagNo == 0)
+ {
+ forward = X509CertificateStructure.GetInstance(o, true);
+ }
+ else if (o.TagNo == 1)
+ {
+ reverse = X509CertificateStructure.GetInstance(o, true);
+ }
+ else
+ {
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param forward Certificates issued to this CA.
+ * @param reverse Certificates issued by this CA to other CAs.
+ */
+ public CertificatePair(
+ X509CertificateStructure forward,
+ X509CertificateStructure reverse)
+ {
+ this.forward = forward;
+ this.reverse = reverse;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+
+ if (forward != null)
+ {
+ vec.Add(new DerTaggedObject(0, forward));
+ }
+
+ if (reverse != null)
+ {
+ vec.Add(new DerTaggedObject(1, reverse));
+ }
+
+ return new DerSequence(vec);
+ }
+
+ /**
+ * @return Returns the forward.
+ */
+ public X509CertificateStructure Forward
+ {
+ get { return forward; }
+ }
+
+ /**
+ * @return Returns the reverse.
+ */
+ public X509CertificateStructure Reverse
+ {
+ get { return reverse; }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/DSAParameter.cs b/Crypto/src/asn1/x509/DSAParameter.cs
new file mode 100644
index 000000000..b2b325f4d
--- /dev/null
+++ b/Crypto/src/asn1/x509/DSAParameter.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class DsaParameter
+ : Asn1Encodable
+ {
+ internal readonly DerInteger p, q, g;
+
+ public static DsaParameter GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static DsaParameter GetInstance(
+ object obj)
+ {
+ if(obj == null || obj is DsaParameter)
+ {
+ return (DsaParameter) obj;
+ }
+
+ if(obj is Asn1Sequence)
+ {
+ return new DsaParameter((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid DsaParameter: " + obj.GetType().Name);
+ }
+
+ public DsaParameter(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g)
+ {
+ this.p = new DerInteger(p);
+ this.q = new DerInteger(q);
+ this.g = new DerInteger(g);
+ }
+
+ private DsaParameter(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.p = DerInteger.GetInstance(seq[0]);
+ this.q = DerInteger.GetInstance(seq[1]);
+ this.g = DerInteger.GetInstance(seq[2]);
+ }
+
+ public BigInteger P
+ {
+ get { return p.PositiveValue; }
+ }
+
+ public BigInteger Q
+ {
+ get { return q.PositiveValue; }
+ }
+
+ public BigInteger G
+ {
+ get { return g.PositiveValue; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(p, q, g);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/DigestInfo.cs b/Crypto/src/asn1/x509/DigestInfo.cs
new file mode 100644
index 000000000..1dec227fa
--- /dev/null
+++ b/Crypto/src/asn1/x509/DigestInfo.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The DigestInfo object.
+ * <pre>
+ * DigestInfo::=Sequence{
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING }
+ * </pre>
+ */
+ public class DigestInfo
+ : Asn1Encodable
+ {
+ private readonly byte[] digest;
+ private readonly AlgorithmIdentifier algID;
+
+ public static DigestInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static DigestInfo GetInstance(
+ object obj)
+ {
+ if (obj is DigestInfo)
+ {
+ return (DigestInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new DigestInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public DigestInfo(
+ AlgorithmIdentifier algID,
+ byte[] digest)
+ {
+ this.digest = digest;
+ this.algID = algID;
+ }
+
+ private DigestInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ algID = AlgorithmIdentifier.GetInstance(seq[0]);
+ digest = Asn1OctetString.GetInstance(seq[1]).GetOctets();
+ }
+
+ public AlgorithmIdentifier AlgorithmID
+ {
+ get { return algID; }
+ }
+
+ public byte[] GetDigest()
+ {
+ return digest;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(algID, new DerOctetString(digest));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/DisplayText.cs b/Crypto/src/asn1/x509/DisplayText.cs
new file mode 100644
index 000000000..699f39031
--- /dev/null
+++ b/Crypto/src/asn1/x509/DisplayText.cs
@@ -0,0 +1,172 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * <code>DisplayText</code> class, used in
+ * <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
+ *
+ * <p>It stores a string in a chosen encoding.
+ * <pre>
+ * DisplayText ::= CHOICE {
+ * ia5String IA5String (SIZE (1..200)),
+ * visibleString VisibleString (SIZE (1..200)),
+ * bmpString BMPString (SIZE (1..200)),
+ * utf8String UTF8String (SIZE (1..200)) }
+ * </pre></p>
+ * @see PolicyQualifierInfo
+ * @see PolicyInformation
+ */
+ public class DisplayText
+ : Asn1Encodable, IAsn1Choice
+ {
+ /**
+ * Constant corresponding to ia5String encoding.
+ *
+ */
+ public const int ContentTypeIA5String = 0;
+ /**
+ * Constant corresponding to bmpString encoding.
+ *
+ */
+ public const int ContentTypeBmpString = 1;
+ /**
+ * Constant corresponding to utf8String encoding.
+ *
+ */
+ public const int ContentTypeUtf8String = 2;
+ /**
+ * Constant corresponding to visibleString encoding.
+ *
+ */
+ public const int ContentTypeVisibleString = 3;
+ /**
+ * Describe constant <code>DisplayTextMaximumSize</code> here.
+ *
+ */
+ public const int DisplayTextMaximumSize = 200;
+
+ internal readonly int contentType;
+ internal readonly IAsn1String contents;
+
+ /**
+ * Creates a new <code>DisplayText</code> instance.
+ *
+ * @param type the desired encoding type for the text.
+ * @param text the text to store. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(
+ int type,
+ string text)
+ {
+ if (text.Length > DisplayTextMaximumSize)
+ {
+ // RFC3280 limits these strings to 200 chars
+ // truncate the string
+ text = text.Substring(0, DisplayTextMaximumSize);
+ }
+
+ contentType = type;
+ switch (type)
+ {
+ case ContentTypeIA5String:
+ contents = (IAsn1String)new DerIA5String (text);
+ break;
+ case ContentTypeUtf8String:
+ contents = (IAsn1String)new DerUtf8String(text);
+ break;
+ case ContentTypeVisibleString:
+ contents = (IAsn1String)new DerVisibleString(text);
+ break;
+ case ContentTypeBmpString:
+ contents = (IAsn1String)new DerBmpString(text);
+ break;
+ default:
+ contents = (IAsn1String)new DerUtf8String(text);
+ break;
+ }
+ }
+
+// /**
+// * return true if the passed in string can be represented without
+// * loss as a PrintableString, false otherwise.
+// */
+// private bool CanBePrintable(
+// string str)
+// {
+// for (int i = str.Length - 1; i >= 0; i--)
+// {
+// if (str[i] > 0x007f)
+// {
+// return false;
+// }
+// }
+//
+// return true;
+// }
+
+ /**
+ * Creates a new <code>DisplayText</code> instance.
+ *
+ * @param text the text to encapsulate. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(
+ string text)
+ {
+ // by default use UTF8String
+ if (text.Length > DisplayTextMaximumSize)
+ {
+ text = text.Substring(0, DisplayTextMaximumSize);
+ }
+
+ contentType = ContentTypeUtf8String;
+ contents = new DerUtf8String(text);
+ }
+
+ /**
+ * Creates a new <code>DisplayText</code> instance.
+ * <p>Useful when reading back a <code>DisplayText</code> class
+ * from it's Asn1Encodable form.</p>
+ *
+ * @param contents an <code>Asn1Encodable</code> instance.
+ */
+ public DisplayText(
+ IAsn1String contents)
+ {
+ this.contents = contents;
+ }
+
+ public static DisplayText GetInstance(
+ object obj)
+ {
+ if (obj is IAsn1String)
+ {
+ return new DisplayText((IAsn1String) obj);
+ }
+
+ if (obj is DisplayText)
+ {
+ return (DisplayText) obj;
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return (Asn1Object) contents;
+ }
+
+ /**
+ * Returns the stored <code>string</code> object.
+ *
+ * @return the stored text as a <code>string</code>.
+ */
+ public string GetString()
+ {
+ return contents.GetString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/DistributionPoint.cs b/Crypto/src/asn1/x509/DistributionPoint.cs
new file mode 100644
index 000000000..ad1d3989e
--- /dev/null
+++ b/Crypto/src/asn1/x509/DistributionPoint.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The DistributionPoint object.
+ * <pre>
+ * DistributionPoint ::= Sequence {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * reasons [1] ReasonFlags OPTIONAL,
+ * cRLIssuer [2] GeneralNames OPTIONAL
+ * }
+ * </pre>
+ */
+ public class DistributionPoint
+ : Asn1Encodable
+ {
+ internal readonly DistributionPointName distributionPoint;
+ internal readonly ReasonFlags reasons;
+ internal readonly GeneralNames cRLIssuer;
+
+ public static DistributionPoint GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static DistributionPoint GetInstance(
+ object obj)
+ {
+ if(obj == null || obj is DistributionPoint)
+ {
+ return (DistributionPoint) obj;
+ }
+
+ if(obj is Asn1Sequence)
+ {
+ return new DistributionPoint((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid DistributionPoint: " + obj.GetType().Name);
+ }
+
+ private DistributionPoint(
+ Asn1Sequence seq)
+ {
+ for (int i = 0; i != seq.Count; i++)
+ {
+ Asn1TaggedObject t = Asn1TaggedObject.GetInstance(seq[i]);
+
+ switch (t.TagNo)
+ {
+ case 0:
+ distributionPoint = DistributionPointName.GetInstance(t, true);
+ break;
+ case 1:
+ reasons = new ReasonFlags(DerBitString.GetInstance(t, false));
+ break;
+ case 2:
+ cRLIssuer = GeneralNames.GetInstance(t, false);
+ break;
+ }
+ }
+ }
+
+ public DistributionPoint(
+ DistributionPointName distributionPointName,
+ ReasonFlags reasons,
+ GeneralNames crlIssuer)
+ {
+ this.distributionPoint = distributionPointName;
+ this.reasons = reasons;
+ this.cRLIssuer = crlIssuer;
+ }
+
+ public DistributionPointName DistributionPointName
+ {
+ get { return distributionPoint; }
+ }
+
+ public ReasonFlags Reasons
+ {
+ get { return reasons; }
+ }
+
+ public GeneralNames CrlIssuer
+ {
+ get { return cRLIssuer; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (distributionPoint != null)
+ {
+ //
+ // as this is a CHOICE it must be explicitly tagged
+ //
+ v.Add(new DerTaggedObject(0, distributionPoint));
+ }
+
+ if (reasons != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, reasons));
+ }
+
+ if (cRLIssuer != null)
+ {
+ v.Add(new DerTaggedObject(false, 2, cRLIssuer));
+ }
+
+ return new DerSequence(v);
+ }
+
+ public override string ToString()
+ {
+ string sep = Platform.NewLine;
+ StringBuilder buf = new StringBuilder();
+ buf.Append("DistributionPoint: [");
+ buf.Append(sep);
+ if (distributionPoint != null)
+ {
+ appendObject(buf, sep, "distributionPoint", distributionPoint.ToString());
+ }
+ if (reasons != null)
+ {
+ appendObject(buf, sep, "reasons", reasons.ToString());
+ }
+ if (cRLIssuer != null)
+ {
+ appendObject(buf, sep, "cRLIssuer", cRLIssuer.ToString());
+ }
+ buf.Append("]");
+ buf.Append(sep);
+ return buf.ToString();
+ }
+
+ private void appendObject(
+ StringBuilder buf,
+ string sep,
+ string name,
+ string val)
+ {
+ string indent = " ";
+
+ buf.Append(indent);
+ buf.Append(name);
+ buf.Append(":");
+ buf.Append(sep);
+ buf.Append(indent);
+ buf.Append(indent);
+ buf.Append(val);
+ buf.Append(sep);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/DistributionPointName.cs b/Crypto/src/asn1/x509/DistributionPointName.cs
new file mode 100644
index 000000000..1a9d24241
--- /dev/null
+++ b/Crypto/src/asn1/x509/DistributionPointName.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The DistributionPointName object.
+ * <pre>
+ * DistributionPointName ::= CHOICE {
+ * fullName [0] GeneralNames,
+ * nameRelativeToCRLIssuer [1] RDN
+ * }
+ * </pre>
+ */
+ public class DistributionPointName
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal readonly Asn1Encodable name;
+ internal readonly int type;
+
+ public const int FullName = 0;
+ public const int NameRelativeToCrlIssuer = 1;
+
+ public static DistributionPointName GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1TaggedObject.GetInstance(obj, true));
+ }
+
+ public static DistributionPointName GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DistributionPointName)
+ {
+ return (DistributionPointName) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new DistributionPointName((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public DistributionPointName(
+ int type,
+ Asn1Encodable name)
+ {
+ this.type = type;
+ this.name = name;
+ }
+
+ public DistributionPointName(
+ GeneralNames name)
+ : this(FullName, name)
+ {
+ }
+
+ public int PointType
+ {
+ get { return type; }
+ }
+
+ public Asn1Encodable Name
+ {
+ get { return name; }
+ }
+
+ public DistributionPointName(
+ Asn1TaggedObject obj)
+ {
+ this.type = obj.TagNo;
+
+ if (type == FullName)
+ {
+ this.name = GeneralNames.GetInstance(obj, false);
+ }
+ else
+ {
+ this.name = Asn1Set.GetInstance(obj, false);
+ }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, type, name);
+ }
+
+ public override string ToString()
+ {
+ string sep = Platform.NewLine;
+ StringBuilder buf = new StringBuilder();
+ buf.Append("DistributionPointName: [");
+ buf.Append(sep);
+ if (type == FullName)
+ {
+ appendObject(buf, sep, "fullName", name.ToString());
+ }
+ else
+ {
+ appendObject(buf, sep, "nameRelativeToCRLIssuer", name.ToString());
+ }
+ buf.Append("]");
+ buf.Append(sep);
+ return buf.ToString();
+ }
+
+ private void appendObject(
+ StringBuilder buf,
+ string sep,
+ string name,
+ string val)
+ {
+ string indent = " ";
+
+ buf.Append(indent);
+ buf.Append(name);
+ buf.Append(":");
+ buf.Append(sep);
+ buf.Append(indent);
+ buf.Append(indent);
+ buf.Append(val);
+ buf.Append(sep);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/ExtendedKeyUsage.cs b/Crypto/src/asn1/x509/ExtendedKeyUsage.cs
new file mode 100644
index 000000000..3bf79f392
--- /dev/null
+++ b/Crypto/src/asn1/x509/ExtendedKeyUsage.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The extendedKeyUsage object.
+ * <pre>
+ * extendedKeyUsage ::= Sequence SIZE (1..MAX) OF KeyPurposeId
+ * </pre>
+ */
+ public class ExtendedKeyUsage
+ : Asn1Encodable
+ {
+ internal readonly IDictionary usageTable = Platform.CreateHashtable();
+ internal readonly Asn1Sequence seq;
+
+ public static ExtendedKeyUsage GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static ExtendedKeyUsage GetInstance(
+ object obj)
+ {
+ if (obj is ExtendedKeyUsage)
+ {
+ return (ExtendedKeyUsage) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ExtendedKeyUsage((Asn1Sequence) obj);
+ }
+
+ if (obj is X509Extension)
+ {
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+ }
+
+ throw new ArgumentException("Invalid ExtendedKeyUsage: " + obj.GetType().Name);
+ }
+
+ private ExtendedKeyUsage(
+ Asn1Sequence seq)
+ {
+ this.seq = seq;
+
+ foreach (object o in seq)
+ {
+ if (!(o is DerObjectIdentifier))
+ throw new ArgumentException("Only DerObjectIdentifier instances allowed in ExtendedKeyUsage.");
+
+ this.usageTable.Add(o, o);
+ }
+ }
+
+ public ExtendedKeyUsage(
+ params KeyPurposeID[] usages)
+ {
+ this.seq = new DerSequence(usages);
+
+ foreach (KeyPurposeID usage in usages)
+ {
+ this.usageTable.Add(usage, usage);
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public ExtendedKeyUsage(
+ ArrayList usages)
+ : this((IEnumerable)usages)
+ {
+ }
+#endif
+
+ public ExtendedKeyUsage(
+ IEnumerable usages)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ foreach (Asn1Object o in usages)
+ {
+ v.Add(o);
+
+ this.usageTable.Add(o, o);
+ }
+
+ this.seq = new DerSequence(v);
+ }
+
+ public bool HasKeyPurposeId(
+ KeyPurposeID keyPurposeId)
+ {
+ return usageTable[keyPurposeId] != null;
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete("Use 'GetAllUsages'")]
+ public ArrayList GetUsages()
+ {
+ return new ArrayList(usageTable.Values);
+ }
+#endif
+
+ /**
+ * Returns all extended key usages.
+ * The returned ArrayList contains DerObjectIdentifier instances.
+ * @return An ArrayList with all key purposes.
+ */
+ public IList GetAllUsages()
+ {
+ return Platform.CreateArrayList(usageTable.Values);
+ }
+
+ public int Count
+ {
+ get { return usageTable.Count; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/GeneralName.cs b/Crypto/src/asn1/x509/GeneralName.cs
new file mode 100644
index 000000000..710ddc922
--- /dev/null
+++ b/Crypto/src/asn1/x509/GeneralName.cs
@@ -0,0 +1,418 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using NetUtils = Org.BouncyCastle.Utilities.Net;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The GeneralName object.
+ * <pre>
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ *
+ * OtherName ::= Sequence {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= Sequence {
+ * nameAssigner [0] DirectoryString OPTIONAL,
+ * partyName [1] DirectoryString }
+ * </pre>
+ */
+ public class GeneralName
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int OtherName = 0;
+ public const int Rfc822Name = 1;
+ public const int DnsName = 2;
+ public const int X400Address = 3;
+ public const int DirectoryName = 4;
+ public const int EdiPartyName = 5;
+ public const int UniformResourceIdentifier = 6;
+ public const int IPAddress = 7;
+ public const int RegisteredID = 8;
+
+ internal readonly Asn1Encodable obj;
+ internal readonly int tag;
+
+ public GeneralName(
+ X509Name directoryName)
+ {
+ this.obj = directoryName;
+ this.tag = 4;
+ }
+
+ /**
+ * When the subjectAltName extension contains an Internet mail address,
+ * the address MUST be included as an rfc822Name. The format of an
+ * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
+ *
+ * When the subjectAltName extension contains a domain name service
+ * label, the domain name MUST be stored in the dNSName (an IA5String).
+ * The name MUST be in the "preferred name syntax," as specified by RFC
+ * 1034 [RFC 1034].
+ *
+ * When the subjectAltName extension contains a URI, the name MUST be
+ * stored in the uniformResourceIdentifier (an IA5String). The name MUST
+ * be a non-relative URL, and MUST follow the URL syntax and encoding
+ * rules specified in [RFC 1738]. The name must include both a scheme
+ * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
+ * specific-part must include a fully qualified domain name or IP
+ * address as the host.
+ *
+ * When the subjectAltName extension contains a iPAddress, the address
+ * MUST be stored in the octet string in "network byte order," as
+ * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
+ * each octet is the LSB of the corresponding byte in the network
+ * address. For IP Version 4, as specified in RFC 791, the octet string
+ * MUST contain exactly four octets. For IP Version 6, as specified in
+ * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
+ * 1883].
+ */
+ public GeneralName(
+ Asn1Object name,
+ int tag)
+ {
+ this.obj = name;
+ this.tag = tag;
+ }
+
+ public GeneralName(
+ int tag,
+ Asn1Encodable name)
+ {
+ this.obj = name;
+ this.tag = tag;
+ }
+
+ /**
+ * Create a GeneralName for the given tag from the passed in string.
+ * <p>
+ * This constructor can handle:
+ * <ul>
+ * <li>rfc822Name</li>
+ * <li>iPAddress</li>
+ * <li>directoryName</li>
+ * <li>dNSName</li>
+ * <li>uniformResourceIdentifier</li>
+ * <li>registeredID</li>
+ * </ul>
+ * For x400Address, otherName and ediPartyName there is no common string
+ * format defined.
+ * </p><p>
+ * Note: A directory name can be encoded in different ways into a byte
+ * representation. Be aware of this if the byte representation is used for
+ * comparing results.
+ * </p>
+ *
+ * @param tag tag number
+ * @param name string representation of name
+ * @throws ArgumentException if the string encoding is not correct or
+ * not supported.
+ */
+ public GeneralName(
+ int tag,
+ string name)
+ {
+ this.tag = tag;
+
+ if (tag == Rfc822Name || tag == DnsName || tag == UniformResourceIdentifier)
+ {
+ this.obj = new DerIA5String(name);
+ }
+ else if (tag == RegisteredID)
+ {
+ this.obj = new DerObjectIdentifier(name);
+ }
+ else if (tag == DirectoryName)
+ {
+ this.obj = new X509Name(name);
+ }
+ else if (tag == IPAddress)
+ {
+ byte[] enc = toGeneralNameEncoding(name);
+ if (enc == null)
+ throw new ArgumentException("IP Address is invalid", "name");
+
+ this.obj = new DerOctetString(enc);
+ }
+ else
+ {
+ throw new ArgumentException("can't process string for tag: " + tag, "tag");
+ }
+ }
+
+ public static GeneralName GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is GeneralName)
+ {
+ return (GeneralName) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagObj = (Asn1TaggedObject) obj;
+ int tag = tagObj.TagNo;
+
+ switch (tag)
+ {
+ case OtherName:
+ return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
+ case Rfc822Name:
+ return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+ case DnsName:
+ return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+ case X400Address:
+ throw new ArgumentException("unknown tag: " + tag);
+ case DirectoryName:
+ return new GeneralName(tag, X509Name.GetInstance(tagObj, true));
+ case EdiPartyName:
+ return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
+ case UniformResourceIdentifier:
+ return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+ case IPAddress:
+ return new GeneralName(tag, Asn1OctetString.GetInstance(tagObj, false));
+ case RegisteredID:
+ return new GeneralName(tag, DerObjectIdentifier.GetInstance(tagObj, false));
+ }
+ }
+
+ if (obj is byte[])
+ {
+ try
+ {
+ return GetInstance(Asn1Object.FromByteArray((byte[])obj));
+ }
+ catch (IOException)
+ {
+ throw new ArgumentException("unable to parse encoded general name");
+ }
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public static GeneralName GetInstance(
+ Asn1TaggedObject tagObj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1TaggedObject.GetInstance(tagObj, true));
+ }
+
+ public int TagNo
+ {
+ get { return tag; }
+ }
+
+ public Asn1Encodable Name
+ {
+ get { return obj; }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder();
+ buf.Append(tag);
+ buf.Append(": ");
+
+ switch (tag)
+ {
+ case Rfc822Name:
+ case DnsName:
+ case UniformResourceIdentifier:
+ buf.Append(DerIA5String.GetInstance(obj).GetString());
+ break;
+ case DirectoryName:
+ buf.Append(X509Name.GetInstance(obj).ToString());
+ break;
+ default:
+ buf.Append(obj.ToString());
+ break;
+ }
+
+ return buf.ToString();
+ }
+
+ private byte[] toGeneralNameEncoding(
+ string ip)
+ {
+ if (NetUtils.IPAddress.IsValidIPv6WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv6(ip))
+ {
+ int slashIndex = ip.IndexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[16];
+ int[] parsedIp = parseIPv6(ip);
+ copyInts(parsedIp, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[32];
+ int[] parsedIp = parseIPv6(ip.Substring(0, slashIndex));
+ copyInts(parsedIp, addr, 0);
+ string mask = ip.Substring(slashIndex + 1);
+ if (mask.IndexOf(':') > 0)
+ {
+ parsedIp = parseIPv6(mask);
+ }
+ else
+ {
+ parsedIp = parseMask(mask);
+ }
+ copyInts(parsedIp, addr, 16);
+
+ return addr;
+ }
+ }
+ else if (NetUtils.IPAddress.IsValidIPv4WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv4(ip))
+ {
+ int slashIndex = ip.IndexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[4];
+
+ parseIPv4(ip, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[8];
+
+ parseIPv4(ip.Substring(0, slashIndex), addr, 0);
+
+ string mask = ip.Substring(slashIndex + 1);
+ if (mask.IndexOf('.') > 0)
+ {
+ parseIPv4(mask, addr, 4);
+ }
+ else
+ {
+ parseIPv4Mask(mask, addr, 4);
+ }
+
+ return addr;
+ }
+ }
+
+ return null;
+ }
+
+ private void parseIPv4Mask(string mask, byte[] addr, int offset)
+ {
+ int maskVal = Int32.Parse(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ addr[(i / 8) + offset] |= (byte)(1 << (i % 8));
+ }
+ }
+
+ private void parseIPv4(string ip, byte[] addr, int offset)
+ {
+ foreach (string token in ip.Split('.', '/'))
+ {
+ addr[offset++] = (byte)Int32.Parse(token);
+ }
+ }
+
+ private int[] parseMask(string mask)
+ {
+ int[] res = new int[8];
+ int maskVal = Int32.Parse(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ res[i / 16] |= 1 << (i % 16);
+ }
+ return res;
+ }
+
+ private void copyInts(int[] parsedIp, byte[] addr, int offSet)
+ {
+ for (int i = 0; i != parsedIp.Length; i++)
+ {
+ addr[(i * 2) + offSet] = (byte)(parsedIp[i] >> 8);
+ addr[(i * 2 + 1) + offSet] = (byte)parsedIp[i];
+ }
+ }
+
+ private int[] parseIPv6(string ip)
+ {
+ if (ip.StartsWith("::"))
+ {
+ ip = ip.Substring(1);
+ }
+ else if (ip.EndsWith("::"))
+ {
+ ip = ip.Substring(0, ip.Length - 1);
+ }
+
+ IEnumerator sEnum = ip.Split(':').GetEnumerator();
+
+ int index = 0;
+ int[] val = new int[8];
+
+ int doubleColon = -1;
+
+ while (sEnum.MoveNext())
+ {
+ string e = (string) sEnum.Current;
+
+ if (e.Length == 0)
+ {
+ doubleColon = index;
+ val[index++] = 0;
+ }
+ else
+ {
+ if (e.IndexOf('.') < 0)
+ {
+ val[index++] = Int32.Parse(e, NumberStyles.AllowHexSpecifier);
+ }
+ else
+ {
+ string[] tokens = e.Split('.');
+
+ val[index++] = (Int32.Parse(tokens[0]) << 8) | Int32.Parse(tokens[1]);
+ val[index++] = (Int32.Parse(tokens[2]) << 8) | Int32.Parse(tokens[3]);
+ }
+ }
+ }
+
+ if (index != val.Length)
+ {
+ Array.Copy(val, doubleColon, val, val.Length - (index - doubleColon), index - doubleColon);
+ for (int i = doubleColon; i != val.Length - (index - doubleColon); i++)
+ {
+ val[i] = 0;
+ }
+ }
+
+ return val;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ // Explicitly tagged if DirectoryName
+ return new DerTaggedObject(tag == DirectoryName, tag, obj);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/GeneralNames.cs b/Crypto/src/asn1/x509/GeneralNames.cs
new file mode 100644
index 000000000..6c5c8e690
--- /dev/null
+++ b/Crypto/src/asn1/x509/GeneralNames.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class GeneralNames
+ : Asn1Encodable
+ {
+ private readonly GeneralName[] names;
+
+ public static GeneralNames GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is GeneralNames)
+ {
+ return (GeneralNames) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new GeneralNames((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static GeneralNames GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /// <summary>Construct a GeneralNames object containing one GeneralName.</summary>
+ /// <param name="name">The name to be contained.</param>
+ public GeneralNames(
+ GeneralName name)
+ {
+ names = new GeneralName[]{ name };
+ }
+
+ public GeneralNames(
+ GeneralName[] names)
+ {
+ this.names = (GeneralName[])names.Clone();
+ }
+
+ private GeneralNames(
+ Asn1Sequence seq)
+ {
+ this.names = new GeneralName[seq.Count];
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ names[i] = GeneralName.GetInstance(seq[i]);
+ }
+ }
+
+ public GeneralName[] GetNames()
+ {
+ return (GeneralName[]) names.Clone();
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(names);
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder();
+ string sep = Platform.NewLine;
+
+ buf.Append("GeneralNames:");
+ buf.Append(sep);
+
+ foreach (GeneralName name in names)
+ {
+ buf.Append(" ");
+ buf.Append(name);
+ buf.Append(sep);
+ }
+
+ return buf.ToString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/GeneralSubtree.cs b/Crypto/src/asn1/x509/GeneralSubtree.cs
new file mode 100644
index 000000000..e918a0277
--- /dev/null
+++ b/Crypto/src/asn1/x509/GeneralSubtree.cs
@@ -0,0 +1,189 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Class for containing a restriction object subtrees in NameConstraints. See
+ * RFC 3280.
+ *
+ * <pre>
+ *
+ * GeneralSubtree ::= SEQUENCE
+ * {
+ * baseName GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see org.bouncycastle.asn1.x509.NameConstraints
+ *
+ */
+ public class GeneralSubtree
+ : Asn1Encodable
+ {
+ private readonly GeneralName baseName;
+ private readonly DerInteger minimum;
+ private readonly DerInteger maximum;
+
+ private GeneralSubtree(
+ Asn1Sequence seq)
+ {
+ baseName = GeneralName.GetInstance(seq[0]);
+
+ switch (seq.Count)
+ {
+ case 1:
+ break;
+ case 2:
+ {
+ Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[1]);
+ switch (o.TagNo)
+ {
+ case 0:
+ minimum = DerInteger.GetInstance(o, false);
+ break;
+ case 1:
+ maximum = DerInteger.GetInstance(o, false);
+ break;
+ default:
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+ }
+ break;
+ }
+ case 3:
+ {
+ {
+ Asn1TaggedObject oMin = Asn1TaggedObject.GetInstance(seq[1]);
+ if (oMin.TagNo != 0)
+ throw new ArgumentException("Bad tag number for 'minimum': " + oMin.TagNo);
+ minimum = DerInteger.GetInstance(oMin, false);
+ }
+
+ {
+ Asn1TaggedObject oMax = Asn1TaggedObject.GetInstance(seq[2]);
+ if (oMax.TagNo != 1)
+ throw new ArgumentException("Bad tag number for 'maximum': " + oMax.TagNo);
+ maximum = DerInteger.GetInstance(oMax, false);
+ }
+
+ break;
+ }
+ default:
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * According RFC 3280, the minimum and maximum fields are not used with any
+ * name forms, thus minimum MUST be zero, and maximum MUST be absent.
+ * <p>
+ * If minimum is <code>null</code>, zero is assumed, if
+ * maximum is <code>null</code>, maximum is absent.</p>
+ *
+ * @param baseName
+ * A restriction.
+ * @param minimum
+ * Minimum
+ *
+ * @param maximum
+ * Maximum
+ */
+ public GeneralSubtree(
+ GeneralName baseName,
+ BigInteger minimum,
+ BigInteger maximum)
+ {
+ this.baseName = baseName;
+ if (minimum != null)
+ {
+ this.minimum = new DerInteger(minimum);
+ }
+ if (maximum != null)
+ {
+ this.maximum = new DerInteger(maximum);
+ }
+ }
+
+ public GeneralSubtree(
+ GeneralName baseName)
+ : this(baseName, null, null)
+ {
+ }
+
+ public static GeneralSubtree GetInstance(
+ Asn1TaggedObject o,
+ bool isExplicit)
+ {
+ return new GeneralSubtree(Asn1Sequence.GetInstance(o, isExplicit));
+ }
+
+ public static GeneralSubtree GetInstance(
+ object obj)
+ {
+ if (obj == null)
+ {
+ return null;
+ }
+
+ if (obj is GeneralSubtree)
+ {
+ return (GeneralSubtree) obj;
+ }
+
+ return new GeneralSubtree(Asn1Sequence.GetInstance(obj));
+ }
+
+ public GeneralName Base
+ {
+ get { return baseName; }
+ }
+
+ public BigInteger Minimum
+ {
+ get { return minimum == null ? BigInteger.Zero : minimum.Value; }
+ }
+
+ public BigInteger Maximum
+ {
+ get { return maximum == null ? null : maximum.Value; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * GeneralSubtree ::= SEQUENCE
+ * {
+ * baseName GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(baseName);
+
+ if (minimum != null && minimum.Value.SignValue != 0)
+ {
+ v.Add(new DerTaggedObject(false, 0, minimum));
+ }
+
+ if (maximum != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, maximum));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/Holder.cs b/Crypto/src/asn1/x509/Holder.cs
new file mode 100644
index 000000000..d04f1cb60
--- /dev/null
+++ b/Crypto/src/asn1/x509/Holder.cs
@@ -0,0 +1,257 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The Holder object.
+ * <p>
+ * For an v2 attribute certificate this is:
+ *
+ * <pre>
+ * Holder ::= SEQUENCE {
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * -- the issuer and serial number of
+ * -- the holder's Public Key Certificate
+ * entityName [1] GeneralNames OPTIONAL,
+ * -- the name of the claimant or role
+ * objectDigestInfo [2] ObjectDigestInfo OPTIONAL
+ * -- used to directly authenticate the holder,
+ * -- for example, an executable
+ * }
+ * </pre>
+ * </p>
+ * <p>
+ * For an v1 attribute certificate this is:
+ *
+ * <pre>
+ * subject CHOICE {
+ * baseCertificateID [0] IssuerSerial,
+ * -- associated with a Public Key Certificate
+ * subjectName [1] GeneralNames },
+ * -- associated with a name
+ * </pre>
+ * </p>
+ */
+ public class Holder
+ : Asn1Encodable
+ {
+ internal readonly IssuerSerial baseCertificateID;
+ internal readonly GeneralNames entityName;
+ internal readonly ObjectDigestInfo objectDigestInfo;
+ private readonly int version;
+
+ public static Holder GetInstance(
+ object obj)
+ {
+ if (obj is Holder)
+ {
+ return (Holder) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Holder((Asn1Sequence) obj);
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new Holder((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor for a holder for an v1 attribute certificate.
+ *
+ * @param tagObj The ASN.1 tagged holder object.
+ */
+ public Holder(
+ Asn1TaggedObject tagObj)
+ {
+ switch (tagObj.TagNo)
+ {
+ case 0:
+ baseCertificateID = IssuerSerial.GetInstance(tagObj, false);
+ break;
+ case 1:
+ entityName = GeneralNames.GetInstance(tagObj, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag in Holder");
+ }
+
+ this.version = 0;
+ }
+
+ /**
+ * Constructor for a holder for an v2 attribute certificate. *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private Holder(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[i]);
+
+ switch (tObj.TagNo)
+ {
+ case 0:
+ baseCertificateID = IssuerSerial.GetInstance(tObj, false);
+ break;
+ case 1:
+ entityName = GeneralNames.GetInstance(tObj, false);
+ break;
+ case 2:
+ objectDigestInfo = ObjectDigestInfo.GetInstance(tObj, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag in Holder");
+ }
+ }
+
+ this.version = 1;
+ }
+
+ public Holder(
+ IssuerSerial baseCertificateID)
+ : this(baseCertificateID, 1)
+ {
+ }
+
+ /**
+ * Constructs a holder from a IssuerSerial.
+ * @param baseCertificateID The IssuerSerial.
+ * @param version The version of the attribute certificate.
+ */
+ public Holder(
+ IssuerSerial baseCertificateID,
+ int version)
+ {
+ this.baseCertificateID = baseCertificateID;
+ this.version = version;
+ }
+
+ /**
+ * Returns 1 for v2 attribute certificates or 0 for v1 attribute
+ * certificates.
+ * @return The version of the attribute certificate.
+ */
+ public int Version
+ {
+ get { return version; }
+ }
+
+ /**
+ * Constructs a holder with an entityName for v2 attribute certificates or
+ * with a subjectName for v1 attribute certificates.
+ *
+ * @param entityName The entity or subject name.
+ */
+ public Holder(
+ GeneralNames entityName)
+ : this(entityName, 1)
+ {
+ }
+
+ /**
+ * Constructs a holder with an entityName for v2 attribute certificates or
+ * with a subjectName for v1 attribute certificates.
+ *
+ * @param entityName The entity or subject name.
+ * @param version The version of the attribute certificate.
+ */
+ public Holder(
+ GeneralNames entityName,
+ int version)
+ {
+ this.entityName = entityName;
+ this.version = version;
+ }
+
+ /**
+ * Constructs a holder from an object digest info.
+ *
+ * @param objectDigestInfo The object digest info object.
+ */
+ public Holder(
+ ObjectDigestInfo objectDigestInfo)
+ {
+ this.objectDigestInfo = objectDigestInfo;
+ this.version = 1;
+ }
+
+ public IssuerSerial BaseCertificateID
+ {
+ get { return baseCertificateID; }
+ }
+
+ /**
+ * Returns the entityName for an v2 attribute certificate or the subjectName
+ * for an v1 attribute certificate.
+ *
+ * @return The entityname or subjectname.
+ */
+ public GeneralNames EntityName
+ {
+ get { return entityName; }
+ }
+
+ public ObjectDigestInfo ObjectDigestInfo
+ {
+ get { return objectDigestInfo; }
+ }
+
+ /**
+ * The Holder object.
+ * <pre>
+ * Holder ::= Sequence {
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * -- the issuer and serial number of
+ * -- the holder's Public Key Certificate
+ * entityName [1] GeneralNames OPTIONAL,
+ * -- the name of the claimant or role
+ * objectDigestInfo [2] ObjectDigestInfo OPTIONAL
+ * -- used to directly authenticate the holder,
+ * -- for example, an executable
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (version == 1)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (baseCertificateID != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, baseCertificateID));
+ }
+
+ if (entityName != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, entityName));
+ }
+
+ if (objectDigestInfo != null)
+ {
+ v.Add(new DerTaggedObject(false, 2, objectDigestInfo));
+ }
+
+ return new DerSequence(v);
+ }
+
+ if (entityName != null)
+ {
+ return new DerTaggedObject(false, 1, entityName);
+ }
+
+ return new DerTaggedObject(false, 0, baseCertificateID);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/IetfAttrSyntax.cs b/Crypto/src/asn1/x509/IetfAttrSyntax.cs
new file mode 100644
index 000000000..e719865b3
--- /dev/null
+++ b/Crypto/src/asn1/x509/IetfAttrSyntax.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
+ */
+ public class IetfAttrSyntax
+ : Asn1Encodable
+ {
+ public const int ValueOctets = 1;
+ public const int ValueOid = 2;
+ public const int ValueUtf8 = 3;
+
+ internal readonly GeneralNames policyAuthority;
+ internal readonly Asn1EncodableVector values = new Asn1EncodableVector();
+
+ internal int valueChoice = -1;
+
+ /**
+ *
+ */
+ public IetfAttrSyntax(
+ Asn1Sequence seq)
+ {
+ int i = 0;
+
+ if (seq[0] is Asn1TaggedObject)
+ {
+ policyAuthority = GeneralNames.GetInstance(((Asn1TaggedObject)seq[0]), false);
+ i++;
+ }
+ else if (seq.Count == 2)
+ { // VOMS fix
+ policyAuthority = GeneralNames.GetInstance(seq[0]);
+ i++;
+ }
+
+ if (!(seq[i] is Asn1Sequence))
+ {
+ throw new ArgumentException("Non-IetfAttrSyntax encoding");
+ }
+
+ seq = (Asn1Sequence) seq[i];
+
+ foreach (Asn1Object obj in seq)
+ {
+ int type;
+
+ if (obj is DerObjectIdentifier)
+ {
+ type = ValueOid;
+ }
+ else if (obj is DerUtf8String)
+ {
+ type = ValueUtf8;
+ }
+ else if (obj is DerOctetString)
+ {
+ type = ValueOctets;
+ }
+ else
+ {
+ throw new ArgumentException("Bad value type encoding IetfAttrSyntax");
+ }
+
+ if (valueChoice < 0)
+ {
+ valueChoice = type;
+ }
+
+ if (type != valueChoice)
+ {
+ throw new ArgumentException("Mix of value types in IetfAttrSyntax");
+ }
+
+ values.Add(obj);
+ }
+ }
+
+ public GeneralNames PolicyAuthority
+ {
+ get { return policyAuthority; }
+ }
+
+ public int ValueType
+ {
+ get { return valueChoice; }
+ }
+
+ public object[] GetValues()
+ {
+ if (this.ValueType == ValueOctets)
+ {
+ Asn1OctetString[] tmp = new Asn1OctetString[values.Count];
+
+ for (int i = 0; i != tmp.Length; i++)
+ {
+ tmp[i] = (Asn1OctetString) values[i];
+ }
+
+ return tmp;
+ }
+
+ if (this.ValueType == ValueOid)
+ {
+ DerObjectIdentifier[] tmp = new DerObjectIdentifier[values.Count];
+
+ for (int i = 0; i != tmp.Length; i++)
+ {
+ tmp[i] = (DerObjectIdentifier) values[i];
+ }
+
+ return tmp;
+ }
+
+ {
+ DerUtf8String[] tmp = new DerUtf8String[values.Count];
+
+ for (int i = 0; i != tmp.Length; i++)
+ {
+ tmp[i] = (DerUtf8String) values[i];
+ }
+
+ return tmp;
+ }
+ }
+
+ /**
+ *
+ * <pre>
+ *
+ * IetfAttrSyntax ::= Sequence {
+ * policyAuthority [0] GeneralNames OPTIONAL,
+ * values Sequence OF CHOICE {
+ * octets OCTET STRING,
+ * oid OBJECT IDENTIFIER,
+ * string UTF8String
+ * }
+ * }
+ *
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (policyAuthority != null)
+ {
+ v.Add(new DerTaggedObject(0, policyAuthority));
+ }
+
+ v.Add(new DerSequence(values));
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/IssuerSerial.cs b/Crypto/src/asn1/x509/IssuerSerial.cs
new file mode 100644
index 000000000..6a24e7333
--- /dev/null
+++ b/Crypto/src/asn1/x509/IssuerSerial.cs
@@ -0,0 +1,98 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class IssuerSerial
+ : Asn1Encodable
+ {
+ internal readonly GeneralNames issuer;
+ internal readonly DerInteger serial;
+ internal readonly DerBitString issuerUid;
+
+ public static IssuerSerial GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is IssuerSerial)
+ {
+ return (IssuerSerial) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new IssuerSerial((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static IssuerSerial GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ private IssuerSerial(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2 && seq.Count != 3)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ issuer = GeneralNames.GetInstance(seq[0]);
+ serial = DerInteger.GetInstance(seq[1]);
+
+ if (seq.Count == 3)
+ {
+ issuerUid = DerBitString.GetInstance(seq[2]);
+ }
+ }
+
+ public IssuerSerial(
+ GeneralNames issuer,
+ DerInteger serial)
+ {
+ this.issuer = issuer;
+ this.serial = serial;
+ }
+
+ public GeneralNames Issuer
+ {
+ get { return issuer; }
+ }
+
+ public DerInteger Serial
+ {
+ get { return serial; }
+ }
+
+ public DerBitString IssuerUid
+ {
+ get { return issuerUid; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * IssuerSerial ::= Sequence {
+ * issuer GeneralNames,
+ * serial CertificateSerialNumber,
+ * issuerUid UniqueIdentifier OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ issuer, serial);
+
+ if (issuerUid != null)
+ {
+ v.Add(issuerUid);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/IssuingDistributionPoint.cs b/Crypto/src/asn1/x509/IssuingDistributionPoint.cs
new file mode 100644
index 000000000..3af0d565f
--- /dev/null
+++ b/Crypto/src/asn1/x509/IssuingDistributionPoint.cs
@@ -0,0 +1,247 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * <pre>
+ * IssuingDistributionPoint ::= SEQUENCE {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
+ * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
+ * onlySomeReasons [3] ReasonFlags OPTIONAL,
+ * indirectCRL [4] BOOLEAN DEFAULT FALSE,
+ * onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+ * </pre>
+ */
+ public class IssuingDistributionPoint
+ : Asn1Encodable
+ {
+ private readonly DistributionPointName _distributionPoint;
+ private readonly bool _onlyContainsUserCerts;
+ private readonly bool _onlyContainsCACerts;
+ private readonly ReasonFlags _onlySomeReasons;
+ private readonly bool _indirectCRL;
+ private readonly bool _onlyContainsAttributeCerts;
+
+ private readonly Asn1Sequence seq;
+
+ public static IssuingDistributionPoint GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static IssuingDistributionPoint GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is IssuingDistributionPoint)
+ {
+ return (IssuingDistributionPoint) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new IssuingDistributionPoint((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * @param distributionPoint
+ * May contain an URI as pointer to most current CRL.
+ * @param onlyContainsUserCerts Covers revocation information for end certificates.
+ * @param onlyContainsCACerts Covers revocation information for CA certificates.
+ *
+ * @param onlySomeReasons
+ * Which revocation reasons does this point cover.
+ * @param indirectCRL
+ * If <code>true</code> then the CRL contains revocation
+ * information about certificates ssued by other CAs.
+ * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+ */
+ public IssuingDistributionPoint(
+ DistributionPointName distributionPoint,
+ bool onlyContainsUserCerts,
+ bool onlyContainsCACerts,
+ ReasonFlags onlySomeReasons,
+ bool indirectCRL,
+ bool onlyContainsAttributeCerts)
+ {
+ this._distributionPoint = distributionPoint;
+ this._indirectCRL = indirectCRL;
+ this._onlyContainsAttributeCerts = onlyContainsAttributeCerts;
+ this._onlyContainsCACerts = onlyContainsCACerts;
+ this._onlyContainsUserCerts = onlyContainsUserCerts;
+ this._onlySomeReasons = onlySomeReasons;
+
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+ if (distributionPoint != null)
+ { // CHOICE item so explicitly tagged
+ vec.Add(new DerTaggedObject(true, 0, distributionPoint));
+ }
+ if (onlyContainsUserCerts)
+ {
+ vec.Add(new DerTaggedObject(false, 1, DerBoolean.True));
+ }
+ if (onlyContainsCACerts)
+ {
+ vec.Add(new DerTaggedObject(false, 2, DerBoolean.True));
+ }
+ if (onlySomeReasons != null)
+ {
+ vec.Add(new DerTaggedObject(false, 3, onlySomeReasons));
+ }
+ if (indirectCRL)
+ {
+ vec.Add(new DerTaggedObject(false, 4, DerBoolean.True));
+ }
+ if (onlyContainsAttributeCerts)
+ {
+ vec.Add(new DerTaggedObject(false, 5, DerBoolean.True));
+ }
+
+ seq = new DerSequence(vec);
+ }
+
+ /**
+ * Constructor from Asn1Sequence
+ */
+ private IssuingDistributionPoint(
+ Asn1Sequence seq)
+ {
+ this.seq = seq;
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[i]);
+
+ switch (o.TagNo)
+ {
+ case 0:
+ // CHOICE so explicit
+ _distributionPoint = DistributionPointName.GetInstance(o, true);
+ break;
+ case 1:
+ _onlyContainsUserCerts = DerBoolean.GetInstance(o, false).IsTrue;
+ break;
+ case 2:
+ _onlyContainsCACerts = DerBoolean.GetInstance(o, false).IsTrue;
+ break;
+ case 3:
+ _onlySomeReasons = new ReasonFlags(ReasonFlags.GetInstance(o, false));
+ break;
+ case 4:
+ _indirectCRL = DerBoolean.GetInstance(o, false).IsTrue;
+ break;
+ case 5:
+ _onlyContainsAttributeCerts = DerBoolean.GetInstance(o, false).IsTrue;
+ break;
+ default:
+ throw new ArgumentException("unknown tag in IssuingDistributionPoint");
+ }
+ }
+ }
+
+ public bool OnlyContainsUserCerts
+ {
+ get { return _onlyContainsUserCerts; }
+ }
+
+ public bool OnlyContainsCACerts
+ {
+ get { return _onlyContainsCACerts; }
+ }
+
+ public bool IsIndirectCrl
+ {
+ get { return _indirectCRL; }
+ }
+
+ public bool OnlyContainsAttributeCerts
+ {
+ get { return _onlyContainsAttributeCerts; }
+ }
+
+ /**
+ * @return Returns the distributionPoint.
+ */
+ public DistributionPointName DistributionPoint
+ {
+ get { return _distributionPoint; }
+ }
+
+ /**
+ * @return Returns the onlySomeReasons.
+ */
+ public ReasonFlags OnlySomeReasons
+ {
+ get { return _onlySomeReasons; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+
+ public override string ToString()
+ {
+ string sep = Platform.NewLine;
+ StringBuilder buf = new StringBuilder();
+
+ buf.Append("IssuingDistributionPoint: [");
+ buf.Append(sep);
+ if (_distributionPoint != null)
+ {
+ appendObject(buf, sep, "distributionPoint", _distributionPoint.ToString());
+ }
+ if (_onlyContainsUserCerts)
+ {
+ appendObject(buf, sep, "onlyContainsUserCerts", _onlyContainsUserCerts.ToString());
+ }
+ if (_onlyContainsCACerts)
+ {
+ appendObject(buf, sep, "onlyContainsCACerts", _onlyContainsCACerts.ToString());
+ }
+ if (_onlySomeReasons != null)
+ {
+ appendObject(buf, sep, "onlySomeReasons", _onlySomeReasons.ToString());
+ }
+ if (_onlyContainsAttributeCerts)
+ {
+ appendObject(buf, sep, "onlyContainsAttributeCerts", _onlyContainsAttributeCerts.ToString());
+ }
+ if (_indirectCRL)
+ {
+ appendObject(buf, sep, "indirectCRL", _indirectCRL.ToString());
+ }
+ buf.Append("]");
+ buf.Append(sep);
+ return buf.ToString();
+ }
+
+ private void appendObject(
+ StringBuilder buf,
+ string sep,
+ string name,
+ string val)
+ {
+ string indent = " ";
+
+ buf.Append(indent);
+ buf.Append(name);
+ buf.Append(":");
+ buf.Append(sep);
+ buf.Append(indent);
+ buf.Append(indent);
+ buf.Append(val);
+ buf.Append(sep);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/KeyPurposeId.cs b/Crypto/src/asn1/x509/KeyPurposeId.cs
new file mode 100644
index 000000000..4b48a9b51
--- /dev/null
+++ b/Crypto/src/asn1/x509/KeyPurposeId.cs
@@ -0,0 +1,36 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The KeyPurposeID object.
+ * <pre>
+ * KeyPurposeID ::= OBJECT IDENTIFIER
+ * </pre>
+ */
+ public sealed class KeyPurposeID
+ : DerObjectIdentifier
+ {
+ private const string IdKP = "1.3.6.1.5.5.7.3";
+
+ private KeyPurposeID(
+ string id)
+ : base(id)
+ {
+ }
+
+ public static readonly KeyPurposeID AnyExtendedKeyUsage = new KeyPurposeID(X509Extensions.ExtendedKeyUsage.Id + ".0");
+ public static readonly KeyPurposeID IdKPServerAuth = new KeyPurposeID(IdKP + ".1");
+ public static readonly KeyPurposeID IdKPClientAuth = new KeyPurposeID(IdKP + ".2");
+ public static readonly KeyPurposeID IdKPCodeSigning = new KeyPurposeID(IdKP + ".3");
+ public static readonly KeyPurposeID IdKPEmailProtection = new KeyPurposeID(IdKP + ".4");
+ public static readonly KeyPurposeID IdKPIpsecEndSystem = new KeyPurposeID(IdKP + ".5");
+ public static readonly KeyPurposeID IdKPIpsecTunnel = new KeyPurposeID(IdKP + ".6");
+ public static readonly KeyPurposeID IdKPIpsecUser = new KeyPurposeID(IdKP + ".7");
+ public static readonly KeyPurposeID IdKPTimeStamping = new KeyPurposeID(IdKP + ".8");
+ public static readonly KeyPurposeID IdKPOcspSigning = new KeyPurposeID(IdKP + ".9");
+
+ //
+ // microsoft key purpose ids
+ //
+ public static readonly KeyPurposeID IdKPSmartCardLogon = new KeyPurposeID("1.3.6.1.4.1.311.20.2.2");
+ }
+}
diff --git a/Crypto/src/asn1/x509/KeyUsage.cs b/Crypto/src/asn1/x509/KeyUsage.cs
new file mode 100644
index 000000000..fef04e8b9
--- /dev/null
+++ b/Crypto/src/asn1/x509/KeyUsage.cs
@@ -0,0 +1,79 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The KeyUsage object.
+ * <pre>
+ * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
+ *
+ * KeyUsage ::= BIT STRING {
+ * digitalSignature (0),
+ * nonRepudiation (1),
+ * keyEncipherment (2),
+ * dataEncipherment (3),
+ * keyAgreement (4),
+ * keyCertSign (5),
+ * cRLSign (6),
+ * encipherOnly (7),
+ * decipherOnly (8) }
+ * </pre>
+ */
+ public class KeyUsage
+ : DerBitString
+ {
+ public const int DigitalSignature = (1 << 7);
+ public const int NonRepudiation = (1 << 6);
+ public const int KeyEncipherment = (1 << 5);
+ public const int DataEncipherment = (1 << 4);
+ public const int KeyAgreement = (1 << 3);
+ public const int KeyCertSign = (1 << 2);
+ public const int CrlSign = (1 << 1);
+ public const int EncipherOnly = (1 << 0);
+ public const int DecipherOnly = (1 << 15);
+
+ public static new KeyUsage GetInstance(
+ object obj)
+ {
+ if (obj is KeyUsage)
+ {
+ return (KeyUsage)obj;
+ }
+
+ if (obj is X509Extension)
+ {
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+ }
+
+ return new KeyUsage(DerBitString.GetInstance(obj));
+ }
+
+ /**
+ * Basic constructor.
+ *
+ * @param usage - the bitwise OR of the Key Usage flags giving the
+ * allowed uses for the key.
+ * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
+ */
+ public KeyUsage(
+ int usage)
+ : base(GetBytes(usage), GetPadBits(usage))
+ {
+ }
+
+ private KeyUsage(
+ DerBitString usage)
+ : base(usage.GetBytes(), usage.PadBits)
+ {
+ }
+
+ public override string ToString()
+ {
+ byte[] data = GetBytes();
+ if (data.Length == 1)
+ {
+ return "KeyUsage: 0x" + (data[0] & 0xff).ToString("X");
+ }
+
+ return "KeyUsage: 0x" + ((data[1] & 0xff) << 8 | (data[0] & 0xff)).ToString("X");
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/NameConstraints.cs b/Crypto/src/asn1/x509/NameConstraints.cs
new file mode 100644
index 000000000..c178f5b45
--- /dev/null
+++ b/Crypto/src/asn1/x509/NameConstraints.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class NameConstraints
+ : Asn1Encodable
+ {
+ private Asn1Sequence permitted, excluded;
+
+ public static NameConstraints GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is NameConstraints)
+ {
+ return (NameConstraints) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new NameConstraints((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public NameConstraints(
+ Asn1Sequence seq)
+ {
+ foreach (Asn1TaggedObject o in seq)
+ {
+ switch (o.TagNo)
+ {
+ case 0:
+ permitted = Asn1Sequence.GetInstance(o, false);
+ break;
+ case 1:
+ excluded = Asn1Sequence.GetInstance(o, false);
+ break;
+ }
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ public NameConstraints(
+ ArrayList permitted,
+ ArrayList excluded)
+ : this((IList)permitted, (IList)excluded)
+ {
+ }
+#endif
+
+ /**
+ * Constructor from a given details.
+ *
+ * <p>permitted and excluded are Vectors of GeneralSubtree objects.</p>
+ *
+ * @param permitted Permitted subtrees
+ * @param excluded Excluded subtrees
+ */
+ public NameConstraints(
+ IList permitted,
+ IList excluded)
+ {
+ if (permitted != null)
+ {
+ this.permitted = CreateSequence(permitted);
+ }
+
+ if (excluded != null)
+ {
+ this.excluded = CreateSequence(excluded);
+ }
+ }
+
+ private DerSequence CreateSequence(
+ IList subtrees)
+ {
+ GeneralSubtree[] gsts = new GeneralSubtree[subtrees.Count];
+ for (int i = 0; i < subtrees.Count; ++i)
+ {
+ gsts[i] = (GeneralSubtree)subtrees[i];
+ }
+ return new DerSequence(gsts);
+ }
+
+ public Asn1Sequence PermittedSubtrees
+ {
+ get { return permitted; }
+ }
+
+ public Asn1Sequence ExcludedSubtrees
+ {
+ get { return excluded; }
+ }
+
+ /*
+ * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees
+ * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (permitted != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, permitted));
+ }
+
+ if (excluded != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, excluded));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/NoticeReference.cs b/Crypto/src/asn1/x509/NoticeReference.cs
new file mode 100644
index 000000000..718fe92cf
--- /dev/null
+++ b/Crypto/src/asn1/x509/NoticeReference.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * <code>NoticeReference</code> class, used in
+ * <code>CertificatePolicies</code> X509 V3 extensions
+ * (in policy qualifiers).
+ *
+ * <pre>
+ * NoticeReference ::= Sequence {
+ * organization DisplayText,
+ * noticeNumbers Sequence OF Integer }
+ *
+ * </pre>
+ *
+ * @see PolicyQualifierInfo
+ * @see PolicyInformation
+ */
+ public class NoticeReference
+ : Asn1Encodable
+ {
+ internal readonly DisplayText organization;
+ internal readonly Asn1Sequence noticeNumbers;
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public NoticeReference(
+ string orgName,
+ ArrayList numbers)
+ : this(orgName, (IList)numbers)
+ {
+ }
+#endif
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ *
+ * @param orgName a <code>string</code> value
+ * @param numbers a <code>ArrayList</code> value
+ */
+ public NoticeReference(
+ string orgName,
+ IList numbers)
+ {
+ organization = new DisplayText(orgName);
+
+ object o = numbers[0];
+
+ Asn1EncodableVector av = new Asn1EncodableVector();
+ if (o is int)
+ {
+ foreach (int nm in numbers)
+ {
+ av.Add(new DerInteger(nm));
+ }
+ }
+
+ noticeNumbers = new DerSequence(av);
+ }
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ *
+ * @param orgName a <code>string</code> value
+ * @param numbers an <code>Asn1Sequence</code> value
+ */
+ public NoticeReference(
+ string orgName,
+ Asn1Sequence numbers)
+ {
+ organization = new DisplayText(orgName);
+ noticeNumbers = numbers;
+ }
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ *
+ * @param displayTextType an <code>int</code> value
+ * @param orgName a <code>string</code> value
+ * @param numbers an <code>Asn1Sequence</code> value
+ */
+ public NoticeReference(
+ int displayTextType,
+ string orgName,
+ Asn1Sequence numbers)
+ {
+ organization = new DisplayText(displayTextType, orgName);
+ noticeNumbers = numbers;
+ }
+
+ /**
+ * Creates a new <code>NoticeReference</code> instance.
+ * <p>Useful for reconstructing a <code>NoticeReference</code>
+ * instance from its encodable/encoded form.</p>
+ *
+ * @param as an <code>Asn1Sequence</code> value obtained from either
+ * calling @{link ToAsn1Object()} for a <code>NoticeReference</code>
+ * instance or from parsing it from a Der-encoded stream.
+ */
+ private NoticeReference(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ organization = DisplayText.GetInstance(seq[0]);
+ noticeNumbers = Asn1Sequence.GetInstance(seq[1]);
+ }
+
+ public static NoticeReference GetInstance(
+ object obj)
+ {
+ if (obj is NoticeReference)
+ {
+ return (NoticeReference) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new NoticeReference((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * Describe <code>ToAsn1Object</code> method here.
+ *
+ * @return a <code>Asn1Object</code> value
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(organization, noticeNumbers);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/ObjectDigestInfo.cs b/Crypto/src/asn1/x509/ObjectDigestInfo.cs
new file mode 100644
index 000000000..6d5b9c692
--- /dev/null
+++ b/Crypto/src/asn1/x509/ObjectDigestInfo.cs
@@ -0,0 +1,177 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
+ *
+ * <pre>
+ *
+ * ObjectDigestInfo ::= SEQUENCE {
+ * digestedObjectType ENUMERATED {
+ * publicKey (0),
+ * publicKeyCert (1),
+ * otherObjectTypes (2) },
+ * -- otherObjectTypes MUST NOT
+ * -- be used in this profile
+ * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
+ * digestAlgorithm AlgorithmIdentifier,
+ * objectDigest BIT STRING
+ * }
+ *
+ * </pre>
+ *
+ */
+ public class ObjectDigestInfo
+ : Asn1Encodable
+ {
+ /**
+ * The public key is hashed.
+ */
+ public const int PublicKey = 0;
+
+ /**
+ * The public key certificate is hashed.
+ */
+ public const int PublicKeyCert = 1;
+
+ /**
+ * An other object is hashed.
+ */
+ public const int OtherObjectDigest = 2;
+
+ internal readonly DerEnumerated digestedObjectType;
+ internal readonly DerObjectIdentifier otherObjectTypeID;
+ internal readonly AlgorithmIdentifier digestAlgorithm;
+ internal readonly DerBitString objectDigest;
+
+ public static ObjectDigestInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ObjectDigestInfo)
+ {
+ return (ObjectDigestInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ObjectDigestInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static ObjectDigestInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * Constructor from given details.
+ * <p>
+ * If <code>digestedObjectType</code> is not {@link #publicKeyCert} or
+ * {@link #publicKey} <code>otherObjectTypeID</code> must be given,
+ * otherwise it is ignored.</p>
+ *
+ * @param digestedObjectType The digest object type.
+ * @param otherObjectTypeID The object type ID for
+ * <code>otherObjectDigest</code>.
+ * @param digestAlgorithm The algorithm identifier for the hash.
+ * @param objectDigest The hash value.
+ */
+ public ObjectDigestInfo(
+ int digestedObjectType,
+ string otherObjectTypeID,
+ AlgorithmIdentifier digestAlgorithm,
+ byte[] objectDigest)
+ {
+ this.digestedObjectType = new DerEnumerated(digestedObjectType);
+
+ if (digestedObjectType == OtherObjectDigest)
+ {
+ this.otherObjectTypeID = new DerObjectIdentifier(otherObjectTypeID);
+ }
+
+ this.digestAlgorithm = digestAlgorithm;
+
+ this.objectDigest = new DerBitString(objectDigest);
+ }
+
+ private ObjectDigestInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 4 || seq.Count < 3)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ digestedObjectType = DerEnumerated.GetInstance(seq[0]);
+
+ int offset = 0;
+
+ if (seq.Count == 4)
+ {
+ otherObjectTypeID = DerObjectIdentifier.GetInstance(seq[1]);
+ offset++;
+ }
+
+ digestAlgorithm = AlgorithmIdentifier.GetInstance(seq[1 + offset]);
+ objectDigest = DerBitString.GetInstance(seq[2 + offset]);
+ }
+
+ public DerEnumerated DigestedObjectType
+ {
+ get { return digestedObjectType; }
+ }
+
+ public DerObjectIdentifier OtherObjectTypeID
+ {
+ get { return otherObjectTypeID; }
+ }
+
+ public AlgorithmIdentifier DigestAlgorithm
+ {
+ get { return digestAlgorithm; }
+ }
+
+ public DerBitString ObjectDigest
+ {
+ get { return objectDigest; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * <pre>
+ *
+ * ObjectDigestInfo ::= SEQUENCE {
+ * digestedObjectType ENUMERATED {
+ * publicKey (0),
+ * publicKeyCert (1),
+ * otherObjectTypes (2) },
+ * -- otherObjectTypes MUST NOT
+ * -- be used in this profile
+ * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
+ * digestAlgorithm AlgorithmIdentifier,
+ * objectDigest BIT STRING
+ * }
+ *
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(digestedObjectType);
+
+ if (otherObjectTypeID != null)
+ {
+ v.Add(otherObjectTypeID);
+ }
+
+ v.Add(digestAlgorithm, objectDigest);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/PolicyInformation.cs b/Crypto/src/asn1/x509/PolicyInformation.cs
new file mode 100644
index 000000000..29d245084
--- /dev/null
+++ b/Crypto/src/asn1/x509/PolicyInformation.cs
@@ -0,0 +1,80 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class PolicyInformation
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier policyIdentifier;
+ private readonly Asn1Sequence policyQualifiers;
+
+ private PolicyInformation(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ policyIdentifier = DerObjectIdentifier.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ policyQualifiers = Asn1Sequence.GetInstance(seq[1]);
+ }
+ }
+
+ public PolicyInformation(
+ DerObjectIdentifier policyIdentifier)
+ {
+ this.policyIdentifier = policyIdentifier;
+ }
+
+ public PolicyInformation(
+ DerObjectIdentifier policyIdentifier,
+ Asn1Sequence policyQualifiers)
+ {
+ this.policyIdentifier = policyIdentifier;
+ this.policyQualifiers = policyQualifiers;
+ }
+
+ public static PolicyInformation GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is PolicyInformation)
+ {
+ return (PolicyInformation) obj;
+ }
+
+ return new PolicyInformation(Asn1Sequence.GetInstance(obj));
+ }
+
+ public DerObjectIdentifier PolicyIdentifier
+ {
+ get { return policyIdentifier; }
+ }
+
+ public Asn1Sequence PolicyQualifiers
+ {
+ get { return policyQualifiers; }
+ }
+
+ /*
+ * PolicyInformation ::= Sequence {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers Sequence SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(policyIdentifier);
+
+ if (policyQualifiers != null)
+ {
+ v.Add(policyQualifiers);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/PolicyMappings.cs b/Crypto/src/asn1/x509/PolicyMappings.cs
new file mode 100644
index 000000000..928ad134d
--- /dev/null
+++ b/Crypto/src/asn1/x509/PolicyMappings.cs
@@ -0,0 +1,70 @@
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * PolicyMappings V3 extension, described in RFC3280.
+ * <pre>
+ * PolicyMappings ::= Sequence SIZE (1..MAX) OF Sequence {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ * </pre>
+ *
+ * @see <a href="http://www.faqs.org/rfc/rfc3280.txt">RFC 3280, section 4.2.1.6</a>
+ */
+ public class PolicyMappings
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence seq;
+
+ /**
+ * Creates a new <code>PolicyMappings</code> instance.
+ *
+ * @param seq an <code>Asn1Sequence</code> constructed as specified
+ * in RFC 3280
+ */
+ public PolicyMappings(
+ Asn1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ public PolicyMappings(
+ Hashtable mappings)
+ : this((IDictionary)mappings)
+ {
+ }
+#endif
+
+ /**
+ * Creates a new <code>PolicyMappings</code> instance.
+ *
+ * @param mappings a <code>HashMap</code> value that maps
+ * <code>string</code> oids
+ * to other <code>string</code> oids.
+ */
+ public PolicyMappings(
+ IDictionary mappings)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ foreach (string idp in mappings.Keys)
+ {
+ string sdp = (string) mappings[idp];
+
+ v.Add(
+ new DerSequence(
+ new DerObjectIdentifier(idp),
+ new DerObjectIdentifier(sdp)));
+ }
+
+ seq = new DerSequence(v);
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/PolicyQualifierId.cs b/Crypto/src/asn1/x509/PolicyQualifierId.cs
new file mode 100644
index 000000000..c858f0864
--- /dev/null
+++ b/Crypto/src/asn1/x509/PolicyQualifierId.cs
@@ -0,0 +1,28 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * PolicyQualifierId, used in the CertificatePolicies
+ * X509V3 extension.
+ *
+ * <pre>
+ * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+ * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
+ * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
+ * PolicyQualifierId ::=
+ * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+ * </pre>
+ */
+ public sealed class PolicyQualifierID : DerObjectIdentifier
+ {
+ private const string IdQt = "1.3.6.1.5.5.7.2";
+
+ private PolicyQualifierID(
+ string id)
+ : base(id)
+ {
+ }
+
+ public static readonly PolicyQualifierID IdQtCps = new PolicyQualifierID(IdQt + ".1");
+ public static readonly PolicyQualifierID IdQtUnotice = new PolicyQualifierID(IdQt + ".2");
+ }
+}
diff --git a/Crypto/src/asn1/x509/PolicyQualifierInfo.cs b/Crypto/src/asn1/x509/PolicyQualifierInfo.cs
new file mode 100644
index 000000000..187f8d3bb
--- /dev/null
+++ b/Crypto/src/asn1/x509/PolicyQualifierInfo.cs
@@ -0,0 +1,91 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Policy qualifiers, used in the X509V3 CertificatePolicies
+ * extension.
+ *
+ * <pre>
+ * PolicyQualifierInfo ::= Sequence {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ * </pre>
+ */
+ public class PolicyQualifierInfo
+ : Asn1Encodable
+ {
+ internal readonly DerObjectIdentifier policyQualifierId;
+ internal readonly Asn1Encodable qualifier;
+
+ /**
+ * Creates a new <code>PolicyQualifierInfo</code> instance.
+ *
+ * @param policyQualifierId a <code>PolicyQualifierId</code> value
+ * @param qualifier the qualifier, defined by the above field.
+ */
+ public PolicyQualifierInfo(
+ DerObjectIdentifier policyQualifierId,
+ Asn1Encodable qualifier)
+ {
+ this.policyQualifierId = policyQualifierId;
+ this.qualifier = qualifier;
+ }
+
+ /**
+ * Creates a new <code>PolicyQualifierInfo</code> containing a
+ * cPSuri qualifier.
+ *
+ * @param cps the CPS (certification practice statement) uri as a
+ * <code>string</code>.
+ */
+ public PolicyQualifierInfo(
+ string cps)
+ {
+ policyQualifierId = PolicyQualifierID.IdQtCps;
+ qualifier = new DerIA5String(cps);
+ }
+
+ /**
+ * Creates a new <code>PolicyQualifierInfo</code> instance.
+ *
+ * @param as <code>PolicyQualifierInfo</code> X509 structure
+ * encoded as an Asn1Sequence.
+ */
+ private PolicyQualifierInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ policyQualifierId = DerObjectIdentifier.GetInstance(seq[0]);
+ qualifier = seq[1];
+ }
+
+ public static PolicyQualifierInfo GetInstance(
+ object obj)
+ {
+ if (obj is PolicyQualifierInfo)
+ {
+ return (PolicyQualifierInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new PolicyQualifierInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * Returns a Der-encodable representation of this instance.
+ *
+ * @return a <code>Asn1Object</code> value
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(policyQualifierId, qualifier);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs b/Crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs
new file mode 100644
index 000000000..ad2961eb0
--- /dev/null
+++ b/Crypto/src/asn1/x509/PrivateKeyUsagePeriod.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /// <remarks>
+ /// <pre>
+ /// PrivateKeyUsagePeriod ::= SEQUENCE
+ /// {
+ /// notBefore [0] GeneralizedTime OPTIONAL,
+ /// notAfter [1] GeneralizedTime OPTIONAL }
+ /// </pre>
+ /// </remarks>
+ public class PrivateKeyUsagePeriod
+ : Asn1Encodable
+ {
+ public static PrivateKeyUsagePeriod GetInstance(
+ object obj)
+ {
+ if (obj is PrivateKeyUsagePeriod)
+ {
+ return (PrivateKeyUsagePeriod) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new PrivateKeyUsagePeriod((Asn1Sequence) obj);
+ }
+
+ if (obj is X509Extension)
+ {
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ private DerGeneralizedTime _notBefore, _notAfter;
+
+ private PrivateKeyUsagePeriod(
+ Asn1Sequence seq)
+ {
+ foreach (Asn1TaggedObject tObj in seq)
+ {
+ if (tObj.TagNo == 0)
+ {
+ _notBefore = DerGeneralizedTime.GetInstance(tObj, false);
+ }
+ else if (tObj.TagNo == 1)
+ {
+ _notAfter = DerGeneralizedTime.GetInstance(tObj, false);
+ }
+ }
+ }
+
+ public DerGeneralizedTime NotBefore
+ {
+ get { return _notBefore; }
+ }
+
+ public DerGeneralizedTime NotAfter
+ {
+ get { return _notAfter; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (_notBefore != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, _notBefore));
+ }
+
+ if (_notAfter != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, _notAfter));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/RSAPublicKeyStructure.cs b/Crypto/src/asn1/x509/RSAPublicKeyStructure.cs
new file mode 100644
index 000000000..bdcba783e
--- /dev/null
+++ b/Crypto/src/asn1/x509/RSAPublicKeyStructure.cs
@@ -0,0 +1,92 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class RsaPublicKeyStructure
+ : Asn1Encodable
+ {
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ public static RsaPublicKeyStructure GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static RsaPublicKeyStructure GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RsaPublicKeyStructure)
+ {
+ return (RsaPublicKeyStructure) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new RsaPublicKeyStructure((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid RsaPublicKeyStructure: " + obj.GetType().Name);
+ }
+
+ public RsaPublicKeyStructure(
+ BigInteger modulus,
+ BigInteger publicExponent)
+ {
+ if (modulus == null)
+ throw new ArgumentNullException("modulus");
+ if (publicExponent == null)
+ throw new ArgumentNullException("publicExponent");
+ if (modulus.SignValue <= 0)
+ throw new ArgumentException("Not a valid RSA modulus", "modulus");
+ if (publicExponent.SignValue <= 0)
+ throw new ArgumentException("Not a valid RSA public exponent", "publicExponent");
+
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ private RsaPublicKeyStructure(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ // Note: we are accepting technically incorrect (i.e. negative) values here
+ modulus = DerInteger.GetInstance(seq[0]).PositiveValue;
+ publicExponent = DerInteger.GetInstance(seq[1]).PositiveValue;
+ }
+
+ public BigInteger Modulus
+ {
+ get { return modulus; }
+ }
+
+ public BigInteger PublicExponent
+ {
+ get { return publicExponent; }
+ }
+
+ /**
+ * This outputs the key in Pkcs1v2 format.
+ * <pre>
+ * RSAPublicKey ::= Sequence {
+ * modulus Integer, -- n
+ * publicExponent Integer, -- e
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(
+ new DerInteger(Modulus),
+ new DerInteger(PublicExponent));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/ReasonFlags.cs b/Crypto/src/asn1/x509/ReasonFlags.cs
new file mode 100644
index 000000000..f204c36aa
--- /dev/null
+++ b/Crypto/src/asn1/x509/ReasonFlags.cs
@@ -0,0 +1,46 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The ReasonFlags object.
+ * <pre>
+ * ReasonFlags ::= BIT STRING {
+ * unused(0),
+ * keyCompromise(1),
+ * cACompromise(2),
+ * affiliationChanged(3),
+ * superseded(4),
+ * cessationOfOperation(5),
+ * certficateHold(6)
+ * }
+ * </pre>
+ */
+ public class ReasonFlags
+ : DerBitString
+ {
+ public const int Unused = (1 << 7);
+ public const int KeyCompromise = (1 << 6);
+ public const int CACompromise = (1 << 5);
+ public const int AffiliationChanged = (1 << 4);
+ public const int Superseded = (1 << 3);
+ public const int CessationOfOperation = (1 << 2);
+ public const int CertificateHold = (1 << 1);
+ public const int PrivilegeWithdrawn = (1 << 0);
+ public const int AACompromise = (1 << 15);
+
+ /**
+ * @param reasons - the bitwise OR of the Key Reason flags giving the
+ * allowed uses for the key.
+ */
+ public ReasonFlags(
+ int reasons)
+ : base(GetBytes(reasons), GetPadBits(reasons))
+ {
+ }
+
+ public ReasonFlags(
+ DerBitString reasons)
+ : base(reasons.GetBytes(), reasons.PadBits)
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/RoleSyntax.cs b/Crypto/src/asn1/x509/RoleSyntax.cs
new file mode 100644
index 000000000..48c3c6cae
--- /dev/null
+++ b/Crypto/src/asn1/x509/RoleSyntax.cs
@@ -0,0 +1,230 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Implementation of the RoleSyntax object as specified by the RFC3281.
+ *
+ * <pre>
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ * </pre>
+ */
+ public class RoleSyntax
+ : Asn1Encodable
+ {
+ private readonly GeneralNames roleAuthority;
+ private readonly GeneralName roleName;
+
+ /**
+ * RoleSyntax factory method.
+ * @param obj the object used to construct an instance of <code>
+ * RoleSyntax</code>. It must be an instance of <code>RoleSyntax
+ * </code> or <code>Asn1Sequence</code>.
+ * @return the instance of <code>RoleSyntax</code> built from the
+ * supplied object.
+ * @throws java.lang.ArgumentException if the object passed
+ * to the factory is not an instance of <code>RoleSyntax</code> or
+ * <code>Asn1Sequence</code>.
+ */
+ public static RoleSyntax GetInstance(
+ object obj)
+ {
+ if (obj is RoleSyntax)
+ return (RoleSyntax)obj;
+
+ if (obj != null)
+ return new RoleSyntax(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ /**
+ * Constructor.
+ * @param roleAuthority the role authority of this RoleSyntax.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralNames roleAuthority,
+ GeneralName roleName)
+ {
+ if (roleName == null
+ || roleName.TagNo != GeneralName.UniformResourceIdentifier
+ || ((IAsn1String) roleName.Name).GetString().Equals(""))
+ {
+ throw new ArgumentException("the role name MUST be non empty and MUST " +
+ "use the URI option of GeneralName");
+ }
+
+ this.roleAuthority = roleAuthority;
+ this.roleName = roleName;
+ }
+
+ /**
+ * Constructor. Invoking this constructor is the same as invoking
+ * <code>new RoleSyntax(null, roleName)</code>.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralName roleName)
+ : this(null, roleName)
+ {
+ }
+
+ /**
+ * Utility constructor. Takes a <code>string</code> argument representing
+ * the role name, builds a <code>GeneralName</code> to hold the role name
+ * and calls the constructor that takes a <code>GeneralName</code>.
+ * @param roleName
+ */
+ public RoleSyntax(
+ string roleName)
+ : this(new GeneralName(GeneralName.UniformResourceIdentifier,
+ (roleName == null)? "": roleName))
+ {
+ }
+
+ /**
+ * Constructor that builds an instance of <code>RoleSyntax</code> by
+ * extracting the encoded elements from the <code>Asn1Sequence</code>
+ * object supplied.
+ * @param seq an instance of <code>Asn1Sequence</code> that holds
+ * the encoded elements used to build this <code>RoleSyntax</code>.
+ */
+ private RoleSyntax(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ Asn1TaggedObject taggedObject = Asn1TaggedObject.GetInstance(seq[i]);
+ switch (taggedObject.TagNo)
+ {
+ case 0:
+ roleAuthority = GeneralNames.GetInstance(taggedObject, false);
+ break;
+ case 1:
+ roleName = GeneralName.GetInstance(taggedObject, true);
+ break;
+ default:
+ throw new ArgumentException("Unknown tag in RoleSyntax");
+ }
+ }
+ }
+
+ /**
+ * Gets the role authority of this RoleSyntax.
+ * @return an instance of <code>GeneralNames</code> holding the
+ * role authority of this RoleSyntax.
+ */
+ public GeneralNames RoleAuthority
+ {
+ get { return this.roleAuthority; }
+ }
+
+ /**
+ * Gets the role name of this RoleSyntax.
+ * @return an instance of <code>GeneralName</code> holding the
+ * role name of this RoleSyntax.
+ */
+ public GeneralName RoleName
+ {
+ get { return this.roleName; }
+ }
+
+ /**
+ * Gets the role name as a <code>java.lang.string</code> object.
+ * @return the role name of this RoleSyntax represented as a
+ * <code>string</code> object.
+ */
+ public string GetRoleNameAsString()
+ {
+ return ((IAsn1String) this.roleName.Name).GetString();
+ }
+
+ /**
+ * Gets the role authority as a <code>string[]</code> object.
+ * @return the role authority of this RoleSyntax represented as a
+ * <code>string[]</code> array.
+ */
+ public string[] GetRoleAuthorityAsString()
+ {
+ if (roleAuthority == null)
+ {
+ return new string[0];
+ }
+
+ GeneralName[] names = roleAuthority.GetNames();
+ string[] namesString = new string[names.Length];
+ for(int i = 0; i < names.Length; i++)
+ {
+ Asn1Encodable asn1Value = names[i].Name;
+ if (asn1Value is IAsn1String)
+ {
+ namesString[i] = ((IAsn1String) asn1Value).GetString();
+ }
+ else
+ {
+ namesString[i] = asn1Value.ToString();
+ }
+ }
+
+ return namesString;
+ }
+
+ /**
+ * Implementation of the method <code>ToAsn1Object</code> as
+ * required by the superclass <code>ASN1Encodable</code>.
+ *
+ * <pre>
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (this.roleAuthority != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, roleAuthority));
+ }
+
+ v.Add(new DerTaggedObject(true, 1, roleName));
+
+ return new DerSequence(v);
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buff = new StringBuilder("Name: " + this.GetRoleNameAsString() +
+ " - Auth: ");
+
+ if (this.roleAuthority == null || roleAuthority.GetNames().Length == 0)
+ {
+ buff.Append("N/A");
+ }
+ else
+ {
+ string[] names = this.GetRoleAuthorityAsString();
+ buff.Append('[').Append(names[0]);
+ for(int i = 1; i < names.Length; i++)
+ {
+ buff.Append(", ").Append(names[i]);
+ }
+ buff.Append(']');
+ }
+
+ return buff.ToString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/SubjectDirectoryAttributes.cs b/Crypto/src/asn1/x509/SubjectDirectoryAttributes.cs
new file mode 100644
index 000000000..c76d94d78
--- /dev/null
+++ b/Crypto/src/asn1/x509/SubjectDirectoryAttributes.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * This extension may contain further X.500 attributes of the subject. See also
+ * RFC 3039.
+ *
+ * <pre>
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * </pre>
+ *
+ * @see org.bouncycastle.asn1.x509.X509Name for AttributeType ObjectIdentifiers.
+ */
+ public class SubjectDirectoryAttributes
+ : Asn1Encodable
+ {
+ private readonly IList attributes;
+
+ public static SubjectDirectoryAttributes GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SubjectDirectoryAttributes)
+ {
+ return (SubjectDirectoryAttributes) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new SubjectDirectoryAttributes((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ *
+ * The sequence is of type SubjectDirectoryAttributes:
+ *
+ * <pre>
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * </pre>
+ *
+ * @param seq
+ * The ASN.1 sequence.
+ */
+ private SubjectDirectoryAttributes(
+ Asn1Sequence seq)
+ {
+ this.attributes = Platform.CreateArrayList();
+ foreach (object o in seq)
+ {
+ Asn1Sequence s = Asn1Sequence.GetInstance(o);
+ attributes.Add(AttributeX509.GetInstance(s));
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public SubjectDirectoryAttributes(
+ ArrayList attributes)
+ : this((IList)attributes)
+ {
+ }
+#endif
+
+ /**
+ * Constructor from an ArrayList of attributes.
+ *
+ * The ArrayList consists of attributes of type {@link Attribute Attribute}
+ *
+ * @param attributes The attributes.
+ *
+ */
+ public SubjectDirectoryAttributes(
+ IList attributes)
+ {
+ this.attributes = Platform.CreateArrayList(attributes);
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ AttributeX509[] v = new AttributeX509[attributes.Count];
+ for (int i = 0; i < attributes.Count; ++i)
+ {
+ v[i] = (AttributeX509)attributes[i];
+ }
+ return new DerSequence(v);
+ }
+
+ /**
+ * @return Returns the attributes.
+ */
+ public IEnumerable Attributes
+ {
+ get { return new EnumerableProxy(attributes); }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/SubjectKeyIdentifier.cs b/Crypto/src/asn1/x509/SubjectKeyIdentifier.cs
new file mode 100644
index 000000000..e640760f3
--- /dev/null
+++ b/Crypto/src/asn1/x509/SubjectKeyIdentifier.cs
@@ -0,0 +1,141 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The SubjectKeyIdentifier object.
+ * <pre>
+ * SubjectKeyIdentifier::= OCTET STRING
+ * </pre>
+ */
+ public class SubjectKeyIdentifier
+ : Asn1Encodable
+ {
+ private readonly byte[] keyIdentifier;
+
+ public static SubjectKeyIdentifier GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1OctetString.GetInstance(obj, explicitly));
+ }
+
+ public static SubjectKeyIdentifier GetInstance(
+ object obj)
+ {
+ if (obj is SubjectKeyIdentifier)
+ {
+ return (SubjectKeyIdentifier) obj;
+ }
+
+ if (obj is SubjectPublicKeyInfo)
+ {
+ return new SubjectKeyIdentifier((SubjectPublicKeyInfo) obj);
+ }
+
+ if (obj is Asn1OctetString)
+ {
+ return new SubjectKeyIdentifier((Asn1OctetString) obj);
+ }
+
+ if (obj is X509Extension)
+ {
+ return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+ }
+
+ throw new ArgumentException("Invalid SubjectKeyIdentifier: " + obj.GetType().Name);
+ }
+
+ public SubjectKeyIdentifier(
+ byte[] keyID)
+ {
+ if (keyID == null)
+ throw new ArgumentNullException("keyID");
+
+ this.keyIdentifier = keyID;
+ }
+
+ public SubjectKeyIdentifier(
+ Asn1OctetString keyID)
+ {
+ this.keyIdentifier = keyID.GetOctets();
+ }
+
+ /**
+ * Calculates the keyIdentifier using a SHA1 hash over the BIT STRING
+ * from SubjectPublicKeyInfo as defined in RFC3280.
+ *
+ * @param spki the subject public key info.
+ */
+ public SubjectKeyIdentifier(
+ SubjectPublicKeyInfo spki)
+ {
+ this.keyIdentifier = GetDigest(spki);
+ }
+
+ public byte[] GetKeyIdentifier()
+ {
+ return keyIdentifier;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerOctetString(keyIdentifier);
+ }
+
+ /**
+ * Return a RFC 3280 type 1 key identifier. As in:
+ * <pre>
+ * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
+ * value of the BIT STRING subjectPublicKey (excluding the tag,
+ * length, and number of unused bits).
+ * </pre>
+ * @param keyInfo the key info object containing the subjectPublicKey field.
+ * @return the key identifier.
+ */
+ public static SubjectKeyIdentifier CreateSha1KeyIdentifier(
+ SubjectPublicKeyInfo keyInfo)
+ {
+ return new SubjectKeyIdentifier(keyInfo);
+ }
+
+ /**
+ * Return a RFC 3280 type 2 key identifier. As in:
+ * <pre>
+ * (2) The keyIdentifier is composed of a four bit type field with
+ * the value 0100 followed by the least significant 60 bits of the
+ * SHA-1 hash of the value of the BIT STRING subjectPublicKey.
+ * </pre>
+ * @param keyInfo the key info object containing the subjectPublicKey field.
+ * @return the key identifier.
+ */
+ public static SubjectKeyIdentifier CreateTruncatedSha1KeyIdentifier(
+ SubjectPublicKeyInfo keyInfo)
+ {
+ byte[] dig = GetDigest(keyInfo);
+ byte[] id = new byte[8];
+
+ Array.Copy(dig, dig.Length - 8, id, 0, id.Length);
+
+ id[0] &= 0x0f;
+ id[0] |= 0x40;
+
+ return new SubjectKeyIdentifier(id);
+ }
+
+ private static byte[] GetDigest(
+ SubjectPublicKeyInfo spki)
+ {
+ IDigest digest = new Sha1Digest();
+ byte[] resBuf = new byte[digest.GetDigestSize()];
+
+ byte[] bytes = spki.PublicKeyData.GetBytes();
+ digest.BlockUpdate(bytes, 0, bytes.Length);
+ digest.DoFinal(resBuf, 0);
+ return resBuf;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/SubjectPublicKeyInfo.cs b/Crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
new file mode 100644
index 000000000..8ce4b2762
--- /dev/null
+++ b/Crypto/src/asn1/x509/SubjectPublicKeyInfo.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The object that contains the public key stored in a certficate.
+ * <p>
+ * The GetEncoded() method in the public keys in the JCE produces a DER
+ * encoded one of these.</p>
+ */
+ public class SubjectPublicKeyInfo
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier algID;
+ private readonly DerBitString keyData;
+
+ public static SubjectPublicKeyInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static SubjectPublicKeyInfo GetInstance(
+ object obj)
+ {
+ if (obj is SubjectPublicKeyInfo)
+ return (SubjectPublicKeyInfo) obj;
+
+ if (obj != null)
+ return new SubjectPublicKeyInfo(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public SubjectPublicKeyInfo(
+ AlgorithmIdentifier algID,
+ Asn1Encodable publicKey)
+ {
+ this.keyData = new DerBitString(publicKey);
+ this.algID = algID;
+ }
+
+ public SubjectPublicKeyInfo(
+ AlgorithmIdentifier algID,
+ byte[] publicKey)
+ {
+ this.keyData = new DerBitString(publicKey);
+ this.algID = algID;
+ }
+
+ private SubjectPublicKeyInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.algID = AlgorithmIdentifier.GetInstance(seq[0]);
+ this.keyData = DerBitString.GetInstance(seq[1]);
+ }
+
+ public AlgorithmIdentifier AlgorithmID
+ {
+ get { return algID; }
+ }
+
+ /**
+ * for when the public key is an encoded object - if the bitstring
+ * can't be decoded this routine raises an IOException.
+ *
+ * @exception IOException - if the bit string doesn't represent a Der
+ * encoded object.
+ */
+ public Asn1Object GetPublicKey()
+ {
+ return Asn1Object.FromByteArray(keyData.GetBytes());
+ }
+
+ /**
+ * for when the public key is raw bits...
+ */
+ public DerBitString PublicKeyData
+ {
+ get { return keyData; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SubjectPublicKeyInfo ::= Sequence {
+ * algorithm AlgorithmIdentifier,
+ * publicKey BIT STRING }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(algID, keyData);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/TBSCertList.cs b/Crypto/src/asn1/x509/TBSCertList.cs
new file mode 100644
index 000000000..b5934a230
--- /dev/null
+++ b/Crypto/src/asn1/x509/TBSCertList.cs
@@ -0,0 +1,274 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class CrlEntry
+ : Asn1Encodable
+ {
+ internal Asn1Sequence seq;
+ internal DerInteger userCertificate;
+ internal Time revocationDate;
+ internal X509Extensions crlEntryExtensions;
+
+ public CrlEntry(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 2 || seq.Count > 3)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ this.seq = seq;
+
+ userCertificate = DerInteger.GetInstance(seq[0]);
+ revocationDate = Time.GetInstance(seq[1]);
+ }
+
+ public DerInteger UserCertificate
+ {
+ get { return userCertificate; }
+ }
+
+ public Time RevocationDate
+ {
+ get { return revocationDate; }
+ }
+
+ public X509Extensions Extensions
+ {
+ get
+ {
+ if (crlEntryExtensions == null && seq.Count == 3)
+ {
+ crlEntryExtensions = X509Extensions.GetInstance(seq[2]);
+ }
+
+ return crlEntryExtensions;
+ }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+
+ /**
+ * PKIX RFC-2459 - TbsCertList object.
+ * <pre>
+ * TbsCertList ::= Sequence {
+ * version Version OPTIONAL,
+ * -- if present, shall be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * nextUpdate Time OPTIONAL,
+ * revokedCertificates Sequence OF Sequence {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, shall be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, shall be v2
+ * }
+ * </pre>
+ */
+ public class TbsCertificateList
+ : Asn1Encodable
+ {
+ private class RevokedCertificatesEnumeration
+ : IEnumerable
+ {
+ private readonly IEnumerable en;
+
+ internal RevokedCertificatesEnumeration(
+ IEnumerable en)
+ {
+ this.en = en;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return new RevokedCertificatesEnumerator(en.GetEnumerator());
+ }
+
+ private class RevokedCertificatesEnumerator
+ : IEnumerator
+ {
+ private readonly IEnumerator e;
+
+ internal RevokedCertificatesEnumerator(
+ IEnumerator e)
+ {
+ this.e = e;
+ }
+
+ public bool MoveNext()
+ {
+ return e.MoveNext();
+ }
+
+ public void Reset()
+ {
+ e.Reset();
+ }
+
+ public object Current
+ {
+ get { return new CrlEntry(Asn1Sequence.GetInstance(e.Current)); }
+ }
+ }
+ }
+
+ internal Asn1Sequence seq;
+ internal DerInteger version;
+ internal AlgorithmIdentifier signature;
+ internal X509Name issuer;
+ internal Time thisUpdate;
+ internal Time nextUpdate;
+ internal Asn1Sequence revokedCertificates;
+ internal X509Extensions crlExtensions;
+
+ public static TbsCertificateList GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static TbsCertificateList GetInstance(
+ object obj)
+ {
+ TbsCertificateList list = obj as TbsCertificateList;
+
+ if (obj == null || list != null)
+ {
+ return list;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new TbsCertificateList((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ internal TbsCertificateList(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 3 || seq.Count > 7)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ int seqPos = 0;
+
+ this.seq = seq;
+
+ if (seq[seqPos] is DerInteger)
+ {
+ version = DerInteger.GetInstance(seq[seqPos++]);
+ }
+ else
+ {
+ version = new DerInteger(0);
+ }
+
+ signature = AlgorithmIdentifier.GetInstance(seq[seqPos++]);
+ issuer = X509Name.GetInstance(seq[seqPos++]);
+ thisUpdate = Time.GetInstance(seq[seqPos++]);
+
+ if (seqPos < seq.Count
+ && (seq[seqPos] is DerUtcTime
+ || seq[seqPos] is DerGeneralizedTime
+ || seq[seqPos] is Time))
+ {
+ nextUpdate = Time.GetInstance(seq[seqPos++]);
+ }
+
+ if (seqPos < seq.Count
+ && !(seq[seqPos] is DerTaggedObject))
+ {
+ revokedCertificates = Asn1Sequence.GetInstance(seq[seqPos++]);
+ }
+
+ if (seqPos < seq.Count
+ && seq[seqPos] is DerTaggedObject)
+ {
+ crlExtensions = X509Extensions.GetInstance(seq[seqPos]);
+ }
+ }
+
+ public int Version
+ {
+ get { return version.Value.IntValue + 1; }
+ }
+
+ public DerInteger VersionNumber
+ {
+ get { return version; }
+ }
+
+ public AlgorithmIdentifier Signature
+ {
+ get { return signature; }
+ }
+
+ public X509Name Issuer
+ {
+ get { return issuer; }
+ }
+
+ public Time ThisUpdate
+ {
+ get { return thisUpdate; }
+ }
+
+ public Time NextUpdate
+ {
+ get { return nextUpdate; }
+ }
+
+ public CrlEntry[] GetRevokedCertificates()
+ {
+ if (revokedCertificates == null)
+ {
+ return new CrlEntry[0];
+ }
+
+ CrlEntry[] entries = new CrlEntry[revokedCertificates.Count];
+
+ for (int i = 0; i < entries.Length; i++)
+ {
+ entries[i] = new CrlEntry(Asn1Sequence.GetInstance(revokedCertificates[i]));
+ }
+
+ return entries;
+ }
+
+ public IEnumerable GetRevokedCertificateEnumeration()
+ {
+ if (revokedCertificates == null)
+ {
+ return EmptyEnumerable.Instance;
+ }
+
+ return new RevokedCertificatesEnumeration(revokedCertificates);
+ }
+
+ public X509Extensions Extensions
+ {
+ get { return crlExtensions; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/TBSCertificateStructure.cs b/Crypto/src/asn1/x509/TBSCertificateStructure.cs
new file mode 100644
index 000000000..fc7c39ba2
--- /dev/null
+++ b/Crypto/src/asn1/x509/TBSCertificateStructure.cs
@@ -0,0 +1,185 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The TbsCertificate object.
+ * <pre>
+ * TbsCertificate ::= Sequence {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ * </pre>
+ * <p>
+ * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+ * will parse them, but you really shouldn't be creating new ones.</p>
+ */
+ public class TbsCertificateStructure
+ : Asn1Encodable
+ {
+ internal Asn1Sequence seq;
+ internal DerInteger version;
+ internal DerInteger serialNumber;
+ internal AlgorithmIdentifier signature;
+ internal X509Name issuer;
+ internal Time startDate, endDate;
+ internal X509Name subject;
+ internal SubjectPublicKeyInfo subjectPublicKeyInfo;
+ internal DerBitString issuerUniqueID;
+ internal DerBitString subjectUniqueID;
+ internal X509Extensions extensions;
+
+ public static TbsCertificateStructure GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static TbsCertificateStructure GetInstance(
+ object obj)
+ {
+ if (obj is TbsCertificateStructure)
+ return (TbsCertificateStructure) obj;
+
+ if (obj != null)
+ return new TbsCertificateStructure(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ internal TbsCertificateStructure(
+ Asn1Sequence seq)
+ {
+ int seqStart = 0;
+
+ this.seq = seq;
+
+ //
+ // some certficates don't include a version number - we assume v1
+ //
+ if (seq[0] is DerTaggedObject)
+ {
+ version = DerInteger.GetInstance((Asn1TaggedObject)seq[0], true);
+ }
+ else
+ {
+ seqStart = -1; // field 0 is missing!
+ version = new DerInteger(0);
+ }
+
+ serialNumber = DerInteger.GetInstance(seq[seqStart + 1]);
+
+ signature = AlgorithmIdentifier.GetInstance(seq[seqStart + 2]);
+ issuer = X509Name.GetInstance(seq[seqStart + 3]);
+
+ //
+ // before and after dates
+ //
+ Asn1Sequence dates = (Asn1Sequence)seq[seqStart + 4];
+
+ startDate = Time.GetInstance(dates[0]);
+ endDate = Time.GetInstance(dates[1]);
+
+ subject = X509Name.GetInstance(seq[seqStart + 5]);
+
+ //
+ // public key info.
+ //
+ subjectPublicKeyInfo = SubjectPublicKeyInfo.GetInstance(seq[seqStart + 6]);
+
+ for (int extras = seq.Count - (seqStart + 6) - 1; extras > 0; extras--)
+ {
+ DerTaggedObject extra = (DerTaggedObject) seq[seqStart + 6 + extras];
+
+ switch (extra.TagNo)
+ {
+ case 1:
+ issuerUniqueID = DerBitString.GetInstance(extra, false);
+ break;
+ case 2:
+ subjectUniqueID = DerBitString.GetInstance(extra, false);
+ break;
+ case 3:
+ extensions = X509Extensions.GetInstance(extra);
+ break;
+ }
+ }
+ }
+
+ public int Version
+ {
+ get { return version.Value.IntValue + 1; }
+ }
+
+ public DerInteger VersionNumber
+ {
+ get { return version; }
+ }
+
+ public DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ public AlgorithmIdentifier Signature
+ {
+ get { return signature; }
+ }
+
+ public X509Name Issuer
+ {
+ get { return issuer; }
+ }
+
+ public Time StartDate
+ {
+ get { return startDate; }
+ }
+
+ public Time EndDate
+ {
+ get { return endDate; }
+ }
+
+ public X509Name Subject
+ {
+ get { return subject; }
+ }
+
+ public SubjectPublicKeyInfo SubjectPublicKeyInfo
+ {
+ get { return subjectPublicKeyInfo; }
+ }
+
+ public DerBitString IssuerUniqueID
+ {
+ get { return issuerUniqueID; }
+ }
+
+ public DerBitString SubjectUniqueID
+ {
+ get { return subjectUniqueID; }
+ }
+
+ public X509Extensions Extensions
+ {
+ get { return extensions; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/Target.cs b/Crypto/src/asn1/x509/Target.cs
new file mode 100644
index 000000000..309b28c95
--- /dev/null
+++ b/Crypto/src/asn1/x509/Target.cs
@@ -0,0 +1,139 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Target structure used in target information extension for attribute
+ * certificates from RFC 3281.
+ *
+ * <pre>
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ * </pre>
+ *
+ * <p>
+ * The targetCert field is currently not supported and must not be used
+ * according to RFC 3281.</p>
+ */
+ public class Target
+ : Asn1Encodable, IAsn1Choice
+ {
+ public enum Choice
+ {
+ Name = 0,
+ Group = 1
+ };
+
+ private readonly GeneralName targetName;
+ private readonly GeneralName targetGroup;
+
+ /**
+ * Creates an instance of a Target from the given object.
+ * <p>
+ * <code>obj</code> can be a Target or a {@link Asn1TaggedObject}</p>
+ *
+ * @param obj The object.
+ * @return A Target instance.
+ * @throws ArgumentException if the given object cannot be
+ * interpreted as Target.
+ */
+ public static Target GetInstance(
+ object obj)
+ {
+ if (obj is Target)
+ {
+ return (Target) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new Target((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1TaggedObject.
+ *
+ * @param tagObj The tagged object.
+ * @throws ArgumentException if the encoding is wrong.
+ */
+ private Target(
+ Asn1TaggedObject tagObj)
+ {
+ switch ((Choice) tagObj.TagNo)
+ {
+ case Choice.Name: // GeneralName is already a choice so explicit
+ targetName = GeneralName.GetInstance(tagObj, true);
+ break;
+ case Choice.Group:
+ targetGroup = GeneralName.GetInstance(tagObj, true);
+ break;
+ default:
+ throw new ArgumentException("unknown tag: " + tagObj.TagNo);
+ }
+ }
+
+ /**
+ * Constructor from given details.
+ * <p>
+ * Exactly one of the parameters must be not <code>null</code>.</p>
+ *
+ * @param type the choice type to apply to the name.
+ * @param name the general name.
+ * @throws ArgumentException if type is invalid.
+ */
+ public Target(
+ Choice type,
+ GeneralName name)
+ : this(new DerTaggedObject((int) type, name))
+ {
+ }
+
+ /**
+ * @return Returns the targetGroup.
+ */
+ public virtual GeneralName TargetGroup
+ {
+ get { return targetGroup; }
+ }
+
+ /**
+ * @return Returns the targetName.
+ */
+ public virtual GeneralName TargetName
+ {
+ get { return targetName; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ // GeneralName is a choice already so most be explicitly tagged
+ if (targetName != null)
+ {
+ return new DerTaggedObject(true, 0, targetName);
+ }
+
+ return new DerTaggedObject(true, 1, targetGroup);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/TargetInformation.cs b/Crypto/src/asn1/x509/TargetInformation.cs
new file mode 100644
index 000000000..75b18c0c9
--- /dev/null
+++ b/Crypto/src/asn1/x509/TargetInformation.cs
@@ -0,0 +1,123 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Target information extension for attributes certificates according to RFC
+ * 3281.
+ *
+ * <pre>
+ * SEQUENCE OF Targets
+ * </pre>
+ *
+ */
+ public class TargetInformation
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence targets;
+
+ /**
+ * Creates an instance of a TargetInformation from the given object.
+ * <p>
+ * <code>obj</code> can be a TargetInformation or a {@link Asn1Sequence}</p>
+ *
+ * @param obj The object.
+ * @return A TargetInformation instance.
+ * @throws ArgumentException if the given object cannot be interpreted as TargetInformation.
+ */
+ public static TargetInformation GetInstance(
+ object obj)
+ {
+ if (obj is TargetInformation)
+ {
+ return (TargetInformation) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new TargetInformation((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from a Asn1Sequence.
+ *
+ * @param seq The Asn1Sequence.
+ * @throws ArgumentException if the sequence does not contain
+ * correctly encoded Targets elements.
+ */
+ private TargetInformation(
+ Asn1Sequence targets)
+ {
+ this.targets = targets;
+ }
+
+ /**
+ * Returns the targets in this target information extension.
+ * <p>
+ * The ArrayList is cloned before it is returned.</p>
+ *
+ * @return Returns the targets.
+ */
+ public virtual Targets[] GetTargetsObjects()
+ {
+ Targets[] result = new Targets[targets.Count];
+
+ for (int i = 0; i < targets.Count; ++i)
+ {
+ result[i] = Targets.GetInstance(targets[i]);
+ }
+
+ return result;
+ }
+
+ /**
+ * Constructs a target information from a single targets element.
+ * According to RFC 3281 only one targets element must be produced.
+ *
+ * @param targets A Targets instance.
+ */
+ public TargetInformation(
+ Targets targets)
+ {
+ this.targets = new DerSequence(targets);
+ }
+
+ /**
+ * According to RFC 3281 only one targets element must be produced. If
+ * multiple targets are given they must be merged in
+ * into one targets element.
+ *
+ * @param targets An array with {@link Targets}.
+ */
+ public TargetInformation(
+ Target[] targets)
+ : this(new Targets(targets))
+ {
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * SEQUENCE OF Targets
+ * </pre>
+ *
+ * <p>
+ * According to RFC 3281 only one targets element must be produced. If
+ * multiple targets are given in the constructor they are merged into one
+ * targets element. If this was produced from a
+ * {@link Org.BouncyCastle.Asn1.Asn1Sequence} the encoding is kept.</p>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return targets;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/Targets.cs b/Crypto/src/asn1/x509/Targets.cs
new file mode 100644
index 000000000..3e436d8d8
--- /dev/null
+++ b/Crypto/src/asn1/x509/Targets.cs
@@ -0,0 +1,121 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Targets structure used in target information extension for attribute
+ * certificates from RFC 3281.
+ *
+ * <pre>
+ * Targets ::= SEQUENCE OF Target
+ *
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ *
+ * TargetCert ::= SEQUENCE {
+ * targetCertificate IssuerSerial,
+ * targetName GeneralName OPTIONAL,
+ * certDigestInfo ObjectDigestInfo OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see org.bouncycastle.asn1.x509.Target
+ * @see org.bouncycastle.asn1.x509.TargetInformation
+ */
+ public class Targets
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence targets;
+
+ /**
+ * Creates an instance of a Targets from the given object.
+ * <p>
+ * <code>obj</code> can be a Targets or a {@link Asn1Sequence}</p>
+ *
+ * @param obj The object.
+ * @return A Targets instance.
+ * @throws ArgumentException if the given object cannot be interpreted as Target.
+ */
+ public static Targets GetInstance(
+ object obj)
+ {
+ if (obj is Targets)
+ {
+ return (Targets) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Targets((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ *
+ * @param targets The ASN.1 SEQUENCE.
+ * @throws ArgumentException if the contents of the sequence are
+ * invalid.
+ */
+ private Targets(
+ Asn1Sequence targets)
+ {
+ this.targets = targets;
+ }
+
+ /**
+ * Constructor from given targets.
+ * <p>
+ * The ArrayList is copied.</p>
+ *
+ * @param targets An <code>ArrayList</code> of {@link Target}s.
+ * @see Target
+ * @throws ArgumentException if the ArrayList contains not only Targets.
+ */
+ public Targets(
+ Target[] targets)
+ {
+ this.targets = new DerSequence(targets);
+ }
+
+ /**
+ * Returns the targets in an <code>ArrayList</code>.
+ * <p>
+ * The ArrayList is cloned before it is returned.</p>
+ *
+ * @return Returns the targets.
+ */
+ public virtual Target[] GetTargets()
+ {
+ Target[] result = new Target[targets.Count];
+
+ for (int i = 0; i < targets.Count; ++i)
+ {
+ result[i] = Target.GetInstance(targets[i]);
+ }
+
+ return result;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * Returns:
+ *
+ * <pre>
+ * Targets ::= SEQUENCE OF Target
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return targets;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/Time.cs b/Crypto/src/asn1/x509/Time.cs
new file mode 100644
index 000000000..ca4e99ac7
--- /dev/null
+++ b/Crypto/src/asn1/x509/Time.cs
@@ -0,0 +1,120 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class Time
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal Asn1Object time;
+
+ public static Time GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(obj.GetObject());
+ }
+
+ public Time(
+ Asn1Object time)
+ {
+ if (time == null)
+ throw new ArgumentNullException("time");
+
+ if (!(time is DerUtcTime) && !(time is DerGeneralizedTime))
+ {
+ throw new ArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+ * is used.
+ */
+ public Time(
+ DateTime date)
+ {
+ string d = date.ToString("yyyyMMddHHmmss") + "Z";
+
+ int year = Int32.Parse(d.Substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new DerGeneralizedTime(d);
+ }
+ else
+ {
+ time = new DerUtcTime(d.Substring(2));
+ }
+ }
+
+ public static Time GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Time)
+ return (Time) obj;
+
+ if (obj is DerUtcTime)
+ return new Time((DerUtcTime) obj);
+
+ if (obj is DerGeneralizedTime)
+ return new Time((DerGeneralizedTime) obj);
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public string GetTime()
+ {
+ if (time is DerUtcTime)
+ {
+ return ((DerUtcTime) time).AdjustedTimeString;
+ }
+
+ return ((DerGeneralizedTime) time).GetTime();
+ }
+
+ /// <summary>
+ /// Return our time as DateTime.
+ /// </summary>
+ /// <returns>A date time.</returns>
+ public DateTime ToDateTime()
+ {
+ try
+ {
+ if (time is DerUtcTime)
+ {
+ return ((DerUtcTime)time).ToAdjustedDateTime();
+ }
+ else
+ {
+ return ((DerGeneralizedTime)time).ToDateTime();
+ }
+ }
+ catch (FormatException e)
+ {
+ // this should never happen
+ throw new InvalidOperationException("invalid date string: " + e.Message);
+ }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return time;
+ }
+
+ public override string ToString()
+ {
+ return GetTime();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/UserNotice.cs b/Crypto/src/asn1/x509/UserNotice.cs
new file mode 100644
index 000000000..2878a180f
--- /dev/null
+++ b/Crypto/src/asn1/x509/UserNotice.cs
@@ -0,0 +1,104 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * <code>UserNotice</code> class, used in
+ * <code>CertificatePolicies</code> X509 extensions (in policy
+ * qualifiers).
+ * <pre>
+ * UserNotice ::= Sequence {
+ * noticeRef NoticeReference OPTIONAL,
+ * explicitText DisplayText OPTIONAL}
+ *
+ * </pre>
+ *
+ * @see PolicyQualifierId
+ * @see PolicyInformation
+ */
+ public class UserNotice
+ : Asn1Encodable
+ {
+ internal NoticeReference noticeRef;
+ internal DisplayText explicitText;
+
+ /**
+ * Creates a new <code>UserNotice</code> instance.
+ *
+ * @param noticeRef a <code>NoticeReference</code> value
+ * @param explicitText a <code>DisplayText</code> value
+ */
+ public UserNotice(
+ NoticeReference noticeRef,
+ DisplayText explicitText)
+ {
+ this.noticeRef = noticeRef;
+ this.explicitText = explicitText;
+ }
+
+ /**
+ * Creates a new <code>UserNotice</code> instance.
+ *
+ * @param noticeRef a <code>NoticeReference</code> value
+ * @param str the explicitText field as a string.
+ */
+ public UserNotice(
+ NoticeReference noticeRef,
+ string str)
+ {
+ this.noticeRef = noticeRef;
+ this.explicitText = new DisplayText(str);
+ }
+
+ /**
+ * Creates a new <code>UserNotice</code> instance.
+ * <p>Useful from reconstructing a <code>UserNotice</code> instance
+ * from its encodable/encoded form.
+ *
+ * @param as an <code>ASN1Sequence</code> value obtained from either
+ * calling @{link toASN1Object()} for a <code>UserNotice</code>
+ * instance or from parsing it from a DER-encoded stream.</p>
+ */
+ public UserNotice(
+ Asn1Sequence seq)
+ {
+ if (seq.Count == 2)
+ {
+ noticeRef = NoticeReference.GetInstance(seq[0]);
+ explicitText = DisplayText.GetInstance(seq[1]);
+ }
+ else if (seq.Count == 1)
+ {
+ if (seq[0].ToAsn1Object() is Asn1Sequence)
+ {
+ noticeRef = NoticeReference.GetInstance(seq[0]);
+ }
+ else
+ {
+ explicitText = DisplayText.GetInstance(seq[0]);
+ }
+ }
+ else
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector av = new Asn1EncodableVector();
+
+ if (noticeRef != null)
+ {
+ av.Add(noticeRef);
+ }
+
+ if (explicitText != null)
+ {
+ av.Add(explicitText);
+ }
+
+ return new DerSequence(av);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/V1TBSCertificateGenerator.cs b/Crypto/src/asn1/x509/V1TBSCertificateGenerator.cs
new file mode 100644
index 000000000..20b525a48
--- /dev/null
+++ b/Crypto/src/asn1/x509/V1TBSCertificateGenerator.cs
@@ -0,0 +1,108 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Generator for Version 1 TbsCertificateStructures.
+ * <pre>
+ * TbsCertificate ::= Sequence {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * }
+ * </pre>
+ *
+ */
+ public class V1TbsCertificateGenerator
+ {
+ internal DerTaggedObject version = new DerTaggedObject(0, new DerInteger(0));
+ internal DerInteger serialNumber;
+ internal AlgorithmIdentifier signature;
+ internal X509Name issuer;
+ internal Time startDate, endDate;
+ internal X509Name subject;
+ internal SubjectPublicKeyInfo subjectPublicKeyInfo;
+
+ public V1TbsCertificateGenerator()
+ {
+ }
+
+ public void SetSerialNumber(
+ DerInteger serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void SetSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ public void SetIssuer(
+ X509Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void SetStartDate(
+ Time startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void SetStartDate(
+ DerUtcTime startDate)
+ {
+ this.startDate = new Time(startDate);
+ }
+
+ public void SetEndDate(
+ Time endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ public void SetEndDate(
+ DerUtcTime endDate)
+ {
+ this.endDate = new Time(endDate);
+ }
+
+ public void SetSubject(
+ X509Name subject)
+ {
+ this.subject = subject;
+ }
+
+ public void SetSubjectPublicKeyInfo(
+ SubjectPublicKeyInfo pubKeyInfo)
+ {
+ this.subjectPublicKeyInfo = pubKeyInfo;
+ }
+
+ public TbsCertificateStructure GenerateTbsCertificate()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (subject == null) || (subjectPublicKeyInfo == null))
+ {
+ throw new InvalidOperationException("not all mandatory fields set in V1 TBScertificate generator");
+ }
+
+ return new TbsCertificateStructure(
+ new DerSequence(
+ //version, - not required as default value
+ serialNumber,
+ signature,
+ issuer,
+ new DerSequence(startDate, endDate), // before and after dates
+ subject,
+ subjectPublicKeyInfo));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs b/Crypto/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs
new file mode 100644
index 000000000..02580b5b8
--- /dev/null
+++ b/Crypto/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs
@@ -0,0 +1,137 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Generator for Version 2 AttributeCertificateInfo
+ * <pre>
+ * AttributeCertificateInfo ::= Sequence {
+ * version AttCertVersion -- version is v2,
+ * holder Holder,
+ * issuer AttCertIssuer,
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes Sequence OF Attr,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ * </pre>
+ *
+ */
+ public class V2AttributeCertificateInfoGenerator
+ {
+ internal DerInteger version;
+ internal Holder holder;
+ internal AttCertIssuer issuer;
+ internal AlgorithmIdentifier signature;
+ internal DerInteger serialNumber;
+// internal AttCertValidityPeriod attrCertValidityPeriod;
+ internal Asn1EncodableVector attributes;
+ internal DerBitString issuerUniqueID;
+ internal X509Extensions extensions;
+ internal DerGeneralizedTime startDate, endDate;
+
+ public V2AttributeCertificateInfoGenerator()
+ {
+ this.version = new DerInteger(1);
+ attributes = new Asn1EncodableVector();
+ }
+
+ public void SetHolder(
+ Holder holder)
+ {
+ this.holder = holder;
+ }
+
+ public void AddAttribute(
+ string oid,
+ Asn1Encodable value)
+ {
+ attributes.Add(new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value)));
+ }
+
+ /**
+ * @param attribute
+ */
+ public void AddAttribute(AttributeX509 attribute)
+ {
+ attributes.Add(attribute);
+ }
+
+ public void SetSerialNumber(
+ DerInteger serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void SetSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ public void SetIssuer(
+ AttCertIssuer issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void SetStartDate(
+ DerGeneralizedTime startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void SetEndDate(
+ DerGeneralizedTime endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ public void SetIssuerUniqueID(
+ DerBitString issuerUniqueID)
+ {
+ this.issuerUniqueID = issuerUniqueID;
+ }
+
+ public void SetExtensions(
+ X509Extensions extensions)
+ {
+ this.extensions = extensions;
+ }
+
+ public AttributeCertificateInfo GenerateAttributeCertificateInfo()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (holder == null) || (attributes == null))
+ {
+ throw new InvalidOperationException("not all mandatory fields set in V2 AttributeCertificateInfo generator");
+ }
+
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, holder, issuer, signature, serialNumber);
+
+ //
+ // before and after dates => AttCertValidityPeriod
+ //
+ v.Add(new AttCertValidityPeriod(startDate, endDate));
+
+ // Attributes
+ v.Add(new DerSequence(attributes));
+
+ if (issuerUniqueID != null)
+ {
+ v.Add(issuerUniqueID);
+ }
+
+ if (extensions != null)
+ {
+ v.Add(extensions);
+ }
+
+ return AttributeCertificateInfo.GetInstance(new DerSequence(v));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/V2Form.cs b/Crypto/src/asn1/x509/V2Form.cs
new file mode 100644
index 000000000..a9c43357c
--- /dev/null
+++ b/Crypto/src/asn1/x509/V2Form.cs
@@ -0,0 +1,125 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class V2Form
+ : Asn1Encodable
+ {
+ internal GeneralNames issuerName;
+ internal IssuerSerial baseCertificateID;
+ internal ObjectDigestInfo objectDigestInfo;
+
+ public static V2Form GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static V2Form GetInstance(
+ object obj)
+ {
+ if (obj is V2Form)
+ {
+ return (V2Form) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new V2Form((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public V2Form(
+ GeneralNames issuerName)
+ {
+ this.issuerName = issuerName;
+ }
+
+ private V2Form(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 3)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ int index = 0;
+
+ if (!(seq[0] is Asn1TaggedObject))
+ {
+ index++;
+ this.issuerName = GeneralNames.GetInstance(seq[0]);
+ }
+
+ for (int i = index; i != seq.Count; i++)
+ {
+ Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[i]);
+ if (o.TagNo == 0)
+ {
+ baseCertificateID = IssuerSerial.GetInstance(o, false);
+ }
+ else if (o.TagNo == 1)
+ {
+ objectDigestInfo = ObjectDigestInfo.GetInstance(o, false);
+ }
+ else
+ {
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+ }
+ }
+ }
+
+ public GeneralNames IssuerName
+ {
+ get { return issuerName; }
+ }
+
+ public IssuerSerial BaseCertificateID
+ {
+ get { return baseCertificateID; }
+ }
+
+ public ObjectDigestInfo ObjectDigestInfo
+ {
+ get { return objectDigestInfo; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * V2Form ::= Sequence {
+ * issuerName GeneralNames OPTIONAL,
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * objectDigestInfo [1] ObjectDigestInfo OPTIONAL
+ * -- issuerName MUST be present in this profile
+ * -- baseCertificateID and objectDigestInfo MUST NOT
+ * -- be present in this profile
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (issuerName != null)
+ {
+ v.Add(issuerName);
+ }
+
+ if (baseCertificateID != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, baseCertificateID));
+ }
+
+ if (objectDigestInfo != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, objectDigestInfo));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/V2TBSCertListGenerator.cs b/Crypto/src/asn1/x509/V2TBSCertListGenerator.cs
new file mode 100644
index 000000000..2c929188f
--- /dev/null
+++ b/Crypto/src/asn1/x509/V2TBSCertListGenerator.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Generator for Version 2 TbsCertList structures.
+ * <pre>
+ * TbsCertList ::= Sequence {
+ * version Version OPTIONAL,
+ * -- if present, shall be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * nextUpdate Time OPTIONAL,
+ * revokedCertificates Sequence OF Sequence {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, shall be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, shall be v2
+ * }
+ * </pre>
+ *
+ * <b>Note: This class may be subject to change</b>
+ */
+ public class V2TbsCertListGenerator
+ {
+ private DerInteger version = new DerInteger(1);
+ private AlgorithmIdentifier signature;
+ private X509Name issuer;
+ private Time thisUpdate, nextUpdate;
+ private X509Extensions extensions;
+ private IList crlEntries;
+
+ public V2TbsCertListGenerator()
+ {
+ }
+
+ public void SetSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ public void SetIssuer(
+ X509Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void SetThisUpdate(
+ DerUtcTime thisUpdate)
+ {
+ this.thisUpdate = new Time(thisUpdate);
+ }
+
+ public void SetNextUpdate(
+ DerUtcTime nextUpdate)
+ {
+ this.nextUpdate = (nextUpdate != null)
+ ? new Time(nextUpdate)
+ : null;
+ }
+
+ public void SetThisUpdate(
+ Time thisUpdate)
+ {
+ this.thisUpdate = thisUpdate;
+ }
+
+ public void SetNextUpdate(
+ Time nextUpdate)
+ {
+ this.nextUpdate = nextUpdate;
+ }
+
+ public void AddCrlEntry(
+ Asn1Sequence crlEntry)
+ {
+ if (crlEntries == null)
+ {
+ crlEntries = Platform.CreateArrayList();
+ }
+
+ crlEntries.Add(crlEntry);
+ }
+
+ public void AddCrlEntry(DerInteger userCertificate, DerUtcTime revocationDate, int reason)
+ {
+ AddCrlEntry(userCertificate, new Time(revocationDate), reason);
+ }
+
+ public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, int reason)
+ {
+ AddCrlEntry(userCertificate, revocationDate, reason, null);
+ }
+
+ public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, int reason,
+ DerGeneralizedTime invalidityDate)
+ {
+ IList extOids = Platform.CreateArrayList();
+ IList extValues = Platform.CreateArrayList();
+
+ if (reason != 0)
+ {
+ CrlReason crlReason = new CrlReason(reason);
+
+ try
+ {
+ extOids.Add(X509Extensions.ReasonCode);
+ extValues.Add(new X509Extension(false, new DerOctetString(crlReason.GetEncoded())));
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("error encoding reason: " + e);
+ }
+ }
+
+ if (invalidityDate != null)
+ {
+ try
+ {
+ extOids.Add(X509Extensions.InvalidityDate);
+ extValues.Add(new X509Extension(false, new DerOctetString(invalidityDate.GetEncoded())));
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("error encoding invalidityDate: " + e);
+ }
+ }
+
+ if (extOids.Count != 0)
+ {
+ AddCrlEntry(userCertificate, revocationDate, new X509Extensions(extOids, extValues));
+ }
+ else
+ {
+ AddCrlEntry(userCertificate, revocationDate, null);
+ }
+ }
+
+ public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, X509Extensions extensions)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ userCertificate, revocationDate);
+
+ if (extensions != null)
+ {
+ v.Add(extensions);
+ }
+
+ AddCrlEntry(new DerSequence(v));
+ }
+
+ public void SetExtensions(
+ X509Extensions extensions)
+ {
+ this.extensions = extensions;
+ }
+
+ public TbsCertificateList GenerateTbsCertList()
+ {
+ if ((signature == null) || (issuer == null) || (thisUpdate == null))
+ {
+ throw new InvalidOperationException("Not all mandatory fields set in V2 TbsCertList generator.");
+ }
+
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, signature, issuer, thisUpdate);
+
+ if (nextUpdate != null)
+ {
+ v.Add(nextUpdate);
+ }
+
+ // Add CRLEntries if they exist
+ if (crlEntries != null)
+ {
+ Asn1Sequence[] certs = new Asn1Sequence[crlEntries.Count];
+ for (int i = 0; i < crlEntries.Count; ++i)
+ {
+ certs[i] = (Asn1Sequence)crlEntries[i];
+ }
+ v.Add(new DerSequence(certs));
+ }
+
+ if (extensions != null)
+ {
+ v.Add(new DerTaggedObject(0, extensions));
+ }
+
+ return new TbsCertificateList(new DerSequence(v));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/V3TBSCertificateGenerator.cs b/Crypto/src/asn1/x509/V3TBSCertificateGenerator.cs
new file mode 100644
index 000000000..beb469a0d
--- /dev/null
+++ b/Crypto/src/asn1/x509/V3TBSCertificateGenerator.cs
@@ -0,0 +1,168 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * Generator for Version 3 TbsCertificateStructures.
+ * <pre>
+ * TbsCertificate ::= Sequence {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ * </pre>
+ *
+ */
+ public class V3TbsCertificateGenerator
+ {
+ internal DerTaggedObject version = new DerTaggedObject(0, new DerInteger(2));
+ internal DerInteger serialNumber;
+ internal AlgorithmIdentifier signature;
+ internal X509Name issuer;
+ internal Time startDate, endDate;
+ internal X509Name subject;
+ internal SubjectPublicKeyInfo subjectPublicKeyInfo;
+ internal X509Extensions extensions;
+
+ private bool altNamePresentAndCritical;
+ private DerBitString issuerUniqueID;
+ private DerBitString subjectUniqueID;
+
+ public V3TbsCertificateGenerator()
+ {
+ }
+
+ public void SetSerialNumber(
+ DerInteger serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void SetSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ public void SetIssuer(
+ X509Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void SetStartDate(
+ DerUtcTime startDate)
+ {
+ this.startDate = new Time(startDate);
+ }
+
+ public void SetStartDate(
+ Time startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void SetEndDate(
+ DerUtcTime endDate)
+ {
+ this.endDate = new Time(endDate);
+ }
+
+ public void SetEndDate(
+ Time endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ public void SetSubject(
+ X509Name subject)
+ {
+ this.subject = subject;
+ }
+
+ public void SetIssuerUniqueID(
+ DerBitString uniqueID)
+ {
+ this.issuerUniqueID = uniqueID;
+ }
+
+ public void SetSubjectUniqueID(
+ DerBitString uniqueID)
+ {
+ this.subjectUniqueID = uniqueID;
+ }
+
+ public void SetSubjectPublicKeyInfo(
+ SubjectPublicKeyInfo pubKeyInfo)
+ {
+ this.subjectPublicKeyInfo = pubKeyInfo;
+ }
+
+ public void SetExtensions(
+ X509Extensions extensions)
+ {
+ this.extensions = extensions;
+
+ if (extensions != null)
+ {
+ X509Extension altName = extensions.GetExtension(X509Extensions.SubjectAlternativeName);
+
+ if (altName != null && altName.IsCritical)
+ {
+ altNamePresentAndCritical = true;
+ }
+ }
+ }
+
+ public TbsCertificateStructure GenerateTbsCertificate()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (subject == null && !altNamePresentAndCritical)
+ || (subjectPublicKeyInfo == null))
+ {
+ throw new InvalidOperationException("not all mandatory fields set in V3 TBScertificate generator");
+ }
+
+ DerSequence validity = new DerSequence(startDate, endDate); // before and after dates
+
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, serialNumber, signature, issuer, validity);
+
+ if (subject != null)
+ {
+ v.Add(subject);
+ }
+ else
+ {
+ v.Add(DerSequence.Empty);
+ }
+
+ v.Add(subjectPublicKeyInfo);
+
+ if (issuerUniqueID != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, issuerUniqueID));
+ }
+
+ if (subjectUniqueID != null)
+ {
+ v.Add(new DerTaggedObject(false, 2, subjectUniqueID));
+ }
+
+ if (extensions != null)
+ {
+ v.Add(new DerTaggedObject(3, extensions));
+ }
+
+ return new TbsCertificateStructure(new DerSequence(v));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509Attributes.cs b/Crypto/src/asn1/x509/X509Attributes.cs
new file mode 100644
index 000000000..291329a62
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509Attributes.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class X509Attributes
+ {
+ public static readonly DerObjectIdentifier RoleSyntax = new DerObjectIdentifier("2.5.4.72");
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509CertificateStructure.cs b/Crypto/src/asn1/x509/X509CertificateStructure.cs
new file mode 100644
index 000000000..e50d3563b
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509CertificateStructure.cs
@@ -0,0 +1,129 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * an X509Certificate structure.
+ * <pre>
+ * Certificate ::= Sequence {
+ * tbsCertificate TbsCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ * </pre>
+ */
+ public class X509CertificateStructure
+ : Asn1Encodable
+ {
+ private readonly TbsCertificateStructure tbsCert;
+ private readonly AlgorithmIdentifier sigAlgID;
+ private readonly DerBitString sig;
+
+ public static X509CertificateStructure GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static X509CertificateStructure GetInstance(
+ object obj)
+ {
+ if (obj is X509CertificateStructure)
+ return (X509CertificateStructure)obj;
+
+ if (obj != null)
+ return new X509CertificateStructure(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public X509CertificateStructure(
+ TbsCertificateStructure tbsCert,
+ AlgorithmIdentifier sigAlgID,
+ DerBitString sig)
+ {
+ if (tbsCert == null)
+ throw new ArgumentNullException("tbsCert");
+ if (sigAlgID == null)
+ throw new ArgumentNullException("sigAlgID");
+ if (sig == null)
+ throw new ArgumentNullException("sig");
+
+ this.tbsCert = tbsCert;
+ this.sigAlgID = sigAlgID;
+ this.sig = sig;
+ }
+
+ private X509CertificateStructure(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("sequence wrong size for a certificate", "seq");
+
+ //
+ // correct x509 certficate
+ //
+ tbsCert = TbsCertificateStructure.GetInstance(seq[0]);
+ sigAlgID = AlgorithmIdentifier.GetInstance(seq[1]);
+ sig = DerBitString.GetInstance(seq[2]);
+ }
+
+ public TbsCertificateStructure TbsCertificate
+ {
+ get { return tbsCert; }
+ }
+
+ public int Version
+ {
+ get { return tbsCert.Version; }
+ }
+
+ public DerInteger SerialNumber
+ {
+ get { return tbsCert.SerialNumber; }
+ }
+
+ public X509Name Issuer
+ {
+ get { return tbsCert.Issuer; }
+ }
+
+ public Time StartDate
+ {
+ get { return tbsCert.StartDate; }
+ }
+
+ public Time EndDate
+ {
+ get { return tbsCert.EndDate; }
+ }
+
+ public X509Name Subject
+ {
+ get { return tbsCert.Subject; }
+ }
+
+ public SubjectPublicKeyInfo SubjectPublicKeyInfo
+ {
+ get { return tbsCert.SubjectPublicKeyInfo; }
+ }
+
+ public AlgorithmIdentifier SignatureAlgorithm
+ {
+ get { return sigAlgID; }
+ }
+
+ public DerBitString Signature
+ {
+ get { return sig; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(tbsCert, sigAlgID, sig);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509DefaultEntryConverter.cs b/Crypto/src/asn1/x509/X509DefaultEntryConverter.cs
new file mode 100644
index 000000000..7282ead26
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509DefaultEntryConverter.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * The default converter for X509 DN entries when going from their
+ * string value to ASN.1 strings.
+ */
+ public class X509DefaultEntryConverter
+ : X509NameEntryConverter
+ {
+ /**
+ * Apply default conversion for the given value depending on the oid
+ * and the character range of the value.
+ *
+ * @param oid the object identifier for the DN entry
+ * @param value the value associated with it
+ * @return the ASN.1 equivalent for the string value.
+ */
+ public override Asn1Object GetConvertedValue(
+ DerObjectIdentifier oid,
+ string value)
+ {
+ if (value.Length != 0 && value[0] == '#')
+ {
+ try
+ {
+ return ConvertHexEncoded(value, 1);
+ }
+ catch (IOException)
+ {
+ throw new Exception("can't recode value for oid " + oid.Id);
+ }
+ }
+
+ if (value.Length != 0 && value[0] == '\\')
+ {
+ value = value.Substring(1);
+ }
+
+ if (oid.Equals(X509Name.EmailAddress) || oid.Equals(X509Name.DC))
+ {
+ return new DerIA5String(value);
+ }
+
+ if (oid.Equals(X509Name.DateOfBirth)) // accept time string as well as # (for compatibility)
+ {
+ return new DerGeneralizedTime(value);
+ }
+
+ if (oid.Equals(X509Name.C)
+ || oid.Equals(X509Name.SerialNumber)
+ || oid.Equals(X509Name.DnQualifier)
+ || oid.Equals(X509Name.TelephoneNumber))
+ {
+ return new DerPrintableString(value);
+ }
+
+ return new DerUtf8String(value);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509Extension.cs b/Crypto/src/asn1/x509/X509Extension.cs
new file mode 100644
index 000000000..430ce4447
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509Extension.cs
@@ -0,0 +1,79 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * an object for the elements in the X.509 V3 extension block.
+ */
+ public class X509Extension
+ {
+ internal bool critical;
+ internal Asn1OctetString value;
+
+ public X509Extension(
+ DerBoolean critical,
+ Asn1OctetString value)
+ {
+ if (critical == null)
+ {
+ throw new ArgumentNullException("critical");
+ }
+
+ this.critical = critical.IsTrue;
+ this.value = value;
+ }
+
+ public X509Extension(
+ bool critical,
+ Asn1OctetString value)
+ {
+ this.critical = critical;
+ this.value = value;
+ }
+
+ public bool IsCritical { get { return critical; } }
+
+ public Asn1OctetString Value { get { return value; } }
+
+ public Asn1Encodable GetParsedValue()
+ {
+ return ConvertValueToObject(this);
+ }
+
+ public override int GetHashCode()
+ {
+ int vh = this.Value.GetHashCode();
+
+ return IsCritical ? vh : ~vh;
+ }
+
+ public override bool Equals(
+ object obj)
+ {
+ X509Extension other = obj as X509Extension;
+ if (other == null)
+ {
+ return false;
+ }
+
+ return Value.Equals(other.Value) && IsCritical == other.IsCritical;
+ }
+
+ /// <sumary>Convert the value of the passed in extension to an object.</sumary>
+ /// <param name="ext">The extension to parse.</param>
+ /// <returns>The object the value string contains.</returns>
+ /// <exception cref="ArgumentException">If conversion is not possible.</exception>
+ public static Asn1Object ConvertValueToObject(
+ X509Extension ext)
+ {
+ try
+ {
+ return Asn1Object.FromByteArray(ext.Value.GetOctets());
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("can't convert extension", e);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509Extensions.cs b/Crypto/src/asn1/x509/X509Extensions.cs
new file mode 100644
index 000000000..1896450f5
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509Extensions.cs
@@ -0,0 +1,451 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public class X509Extensions
+ : Asn1Encodable
+ {
+ /**
+ * Subject Directory Attributes
+ */
+ public static readonly DerObjectIdentifier SubjectDirectoryAttributes = new DerObjectIdentifier("2.5.29.9");
+
+ /**
+ * Subject Key Identifier
+ */
+ public static readonly DerObjectIdentifier SubjectKeyIdentifier = new DerObjectIdentifier("2.5.29.14");
+
+ /**
+ * Key Usage
+ */
+ public static readonly DerObjectIdentifier KeyUsage = new DerObjectIdentifier("2.5.29.15");
+
+ /**
+ * Private Key Usage Period
+ */
+ public static readonly DerObjectIdentifier PrivateKeyUsagePeriod = new DerObjectIdentifier("2.5.29.16");
+
+ /**
+ * Subject Alternative Name
+ */
+ public static readonly DerObjectIdentifier SubjectAlternativeName = new DerObjectIdentifier("2.5.29.17");
+
+ /**
+ * Issuer Alternative Name
+ */
+ public static readonly DerObjectIdentifier IssuerAlternativeName = new DerObjectIdentifier("2.5.29.18");
+
+ /**
+ * Basic Constraints
+ */
+ public static readonly DerObjectIdentifier BasicConstraints = new DerObjectIdentifier("2.5.29.19");
+
+ /**
+ * CRL Number
+ */
+ public static readonly DerObjectIdentifier CrlNumber = new DerObjectIdentifier("2.5.29.20");
+
+ /**
+ * Reason code
+ */
+ public static readonly DerObjectIdentifier ReasonCode = new DerObjectIdentifier("2.5.29.21");
+
+ /**
+ * Hold Instruction Code
+ */
+ public static readonly DerObjectIdentifier InstructionCode = new DerObjectIdentifier("2.5.29.23");
+
+ /**
+ * Invalidity Date
+ */
+ public static readonly DerObjectIdentifier InvalidityDate = new DerObjectIdentifier("2.5.29.24");
+
+ /**
+ * Delta CRL indicator
+ */
+ public static readonly DerObjectIdentifier DeltaCrlIndicator = new DerObjectIdentifier("2.5.29.27");
+
+ /**
+ * Issuing Distribution Point
+ */
+ public static readonly DerObjectIdentifier IssuingDistributionPoint = new DerObjectIdentifier("2.5.29.28");
+
+ /**
+ * Certificate Issuer
+ */
+ public static readonly DerObjectIdentifier CertificateIssuer = new DerObjectIdentifier("2.5.29.29");
+
+ /**
+ * Name Constraints
+ */
+ public static readonly DerObjectIdentifier NameConstraints = new DerObjectIdentifier("2.5.29.30");
+
+ /**
+ * CRL Distribution Points
+ */
+ public static readonly DerObjectIdentifier CrlDistributionPoints = new DerObjectIdentifier("2.5.29.31");
+
+ /**
+ * Certificate Policies
+ */
+ public static readonly DerObjectIdentifier CertificatePolicies = new DerObjectIdentifier("2.5.29.32");
+
+ /**
+ * Policy Mappings
+ */
+ public static readonly DerObjectIdentifier PolicyMappings = new DerObjectIdentifier("2.5.29.33");
+
+ /**
+ * Authority Key Identifier
+ */
+ public static readonly DerObjectIdentifier AuthorityKeyIdentifier = new DerObjectIdentifier("2.5.29.35");
+
+ /**
+ * Policy Constraints
+ */
+ public static readonly DerObjectIdentifier PolicyConstraints = new DerObjectIdentifier("2.5.29.36");
+
+ /**
+ * Extended Key Usage
+ */
+ public static readonly DerObjectIdentifier ExtendedKeyUsage = new DerObjectIdentifier("2.5.29.37");
+
+ /**
+ * Freshest CRL
+ */
+ public static readonly DerObjectIdentifier FreshestCrl = new DerObjectIdentifier("2.5.29.46");
+
+ /**
+ * Inhibit Any Policy
+ */
+ public static readonly DerObjectIdentifier InhibitAnyPolicy = new DerObjectIdentifier("2.5.29.54");
+
+ /**
+ * Authority Info Access
+ */
+ public static readonly DerObjectIdentifier AuthorityInfoAccess = new DerObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+ /**
+ * Subject Info Access
+ */
+ public static readonly DerObjectIdentifier SubjectInfoAccess = new DerObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+ /**
+ * Logo Type
+ */
+ public static readonly DerObjectIdentifier LogoType = new DerObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+ /**
+ * BiometricInfo
+ */
+ public static readonly DerObjectIdentifier BiometricInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+ /**
+ * QCStatements
+ */
+ public static readonly DerObjectIdentifier QCStatements = new DerObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+ /**
+ * Audit identity extension in attribute certificates.
+ */
+ public static readonly DerObjectIdentifier AuditIdentity = new DerObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+ /**
+ * NoRevAvail extension in attribute certificates.
+ */
+ public static readonly DerObjectIdentifier NoRevAvail = new DerObjectIdentifier("2.5.29.56");
+
+ /**
+ * TargetInformation extension in attribute certificates.
+ */
+ public static readonly DerObjectIdentifier TargetInformation = new DerObjectIdentifier("2.5.29.55");
+
+ private readonly IDictionary extensions = Platform.CreateHashtable();
+ private readonly IList ordering;
+
+ public static X509Extensions GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static X509Extensions GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is X509Extensions)
+ {
+ return (X509Extensions) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new X509Extensions((Asn1Sequence) obj);
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return GetInstance(((Asn1TaggedObject) obj).GetObject());
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ *
+ * the extensions are a list of constructed sequences, either with (Oid, OctetString) or (Oid, Boolean, OctetString)
+ */
+ private X509Extensions(
+ Asn1Sequence seq)
+ {
+ this.ordering = Platform.CreateArrayList();
+
+ foreach (Asn1Encodable ae in seq)
+ {
+ Asn1Sequence s = Asn1Sequence.GetInstance(ae.ToAsn1Object());
+
+ if (s.Count < 2 || s.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + s.Count);
+
+ DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(s[0].ToAsn1Object());
+
+ bool isCritical = s.Count == 3
+ && DerBoolean.GetInstance(s[1].ToAsn1Object()).IsTrue;
+
+ Asn1OctetString octets = Asn1OctetString.GetInstance(s[s.Count - 1].ToAsn1Object());
+
+ extensions.Add(oid, new X509Extension(isCritical, octets));
+ ordering.Add(oid);
+ }
+ }
+
+ /**
+ * constructor from a table of extensions.
+ * <p>
+ * it's is assumed the table contains Oid/string pairs.</p>
+ */
+ public X509Extensions(
+ IDictionary extensions)
+ : this(null, extensions)
+ {
+ }
+
+ /**
+ * Constructor from a table of extensions with ordering.
+ * <p>
+ * It's is assumed the table contains Oid/string pairs.</p>
+ */
+ public X509Extensions(
+ IList ordering,
+ IDictionary extensions)
+ {
+ if (ordering == null)
+ {
+ this.ordering = Platform.CreateArrayList(extensions.Keys);
+ }
+ else
+ {
+ this.ordering = Platform.CreateArrayList(ordering);
+ }
+
+ foreach (DerObjectIdentifier oid in this.ordering)
+ {
+ this.extensions.Add(oid, (X509Extension)extensions[oid]);
+ }
+ }
+
+ /**
+ * Constructor from two vectors
+ *
+ * @param objectIDs an ArrayList of the object identifiers.
+ * @param values an ArrayList of the extension values.
+ */
+ public X509Extensions(
+ IList oids,
+ IList values)
+ {
+ this.ordering = Platform.CreateArrayList(oids);
+
+ int count = 0;
+ foreach (DerObjectIdentifier oid in this.ordering)
+ {
+ this.extensions.Add(oid, (X509Extension)values[count++]);
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ /**
+ * constructor from a table of extensions.
+ * <p>
+ * it's is assumed the table contains Oid/string pairs.</p>
+ */
+ [Obsolete]
+ public X509Extensions(
+ Hashtable extensions)
+ : this(null, extensions)
+ {
+ }
+
+ /**
+ * Constructor from a table of extensions with ordering.
+ * <p>
+ * It's is assumed the table contains Oid/string pairs.</p>
+ */
+ [Obsolete]
+ public X509Extensions(
+ ArrayList ordering,
+ Hashtable extensions)
+ {
+ if (ordering == null)
+ {
+ this.ordering = Platform.CreateArrayList(extensions.Keys);
+ }
+ else
+ {
+ this.ordering = Platform.CreateArrayList(ordering);
+ }
+
+ foreach (DerObjectIdentifier oid in this.ordering)
+ {
+ this.extensions.Add(oid, (X509Extension) extensions[oid]);
+ }
+ }
+
+ /**
+ * Constructor from two vectors
+ *
+ * @param objectIDs an ArrayList of the object identifiers.
+ * @param values an ArrayList of the extension values.
+ */
+ [Obsolete]
+ public X509Extensions(
+ ArrayList oids,
+ ArrayList values)
+ {
+ this.ordering = Platform.CreateArrayList(oids);
+
+ int count = 0;
+ foreach (DerObjectIdentifier oid in this.ordering)
+ {
+ this.extensions.Add(oid, (X509Extension) values[count++]);
+ }
+ }
+#endif
+
+ [Obsolete("Use ExtensionOids IEnumerable property")]
+ public IEnumerator Oids()
+ {
+ return ExtensionOids.GetEnumerator();
+ }
+
+ /**
+ * return an Enumeration of the extension field's object ids.
+ */
+ public IEnumerable ExtensionOids
+ {
+ get { return new EnumerableProxy(ordering); }
+ }
+
+ /**
+ * return the extension represented by the object identifier
+ * passed in.
+ *
+ * @return the extension if it's present, null otherwise.
+ */
+ public X509Extension GetExtension(
+ DerObjectIdentifier oid)
+ {
+ return (X509Extension) extensions[oid];
+ }
+
+ /**
+ * <pre>
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnId EXTENSION.&id ({ExtensionSet}),
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+
+ foreach (DerObjectIdentifier oid in ordering)
+ {
+ X509Extension ext = (X509Extension) extensions[oid];
+ Asn1EncodableVector v = new Asn1EncodableVector(oid);
+
+ if (ext.IsCritical)
+ {
+ v.Add(DerBoolean.True);
+ }
+
+ v.Add(ext.Value);
+
+ vec.Add(new DerSequence(v));
+ }
+
+ return new DerSequence(vec);
+ }
+
+ public bool Equivalent(
+ X509Extensions other)
+ {
+ if (extensions.Count != other.extensions.Count)
+ return false;
+
+ foreach (DerObjectIdentifier oid in extensions.Keys)
+ {
+ if (!extensions[oid].Equals(other.extensions[oid]))
+ return false;
+ }
+
+ return true;
+ }
+
+ public DerObjectIdentifier[] GetExtensionOids()
+ {
+ return ToOidArray(ordering);
+ }
+
+ public DerObjectIdentifier[] GetNonCriticalExtensionOids()
+ {
+ return GetExtensionOids(false);
+ }
+
+ public DerObjectIdentifier[] GetCriticalExtensionOids()
+ {
+ return GetExtensionOids(true);
+ }
+
+ private DerObjectIdentifier[] GetExtensionOids(bool isCritical)
+ {
+ IList oids = Platform.CreateArrayList();
+
+ foreach (DerObjectIdentifier oid in this.ordering)
+ {
+ X509Extension ext = (X509Extension)extensions[oid];
+ if (ext.IsCritical == isCritical)
+ {
+ oids.Add(oid);
+ }
+ }
+
+ return ToOidArray(oids);
+ }
+
+ private static DerObjectIdentifier[] ToOidArray(IList oids)
+ {
+ DerObjectIdentifier[] oidArray = new DerObjectIdentifier[oids.Count];
+ oids.CopyTo(oidArray, 0);
+ return oidArray;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509ExtensionsGenerator.cs b/Crypto/src/asn1/x509/X509ExtensionsGenerator.cs
new file mode 100644
index 000000000..d6f567b22
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509ExtensionsGenerator.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /// <remarks>Generator for X.509 extensions</remarks>
+ public class X509ExtensionsGenerator
+ {
+ private IDictionary extensions = Platform.CreateHashtable();
+ private IList extOrdering = Platform.CreateArrayList();
+
+ /// <summary>Reset the generator</summary>
+ public void Reset()
+ {
+ extensions = Platform.CreateHashtable();
+ extOrdering = Platform.CreateArrayList();
+ }
+
+ /// <summary>
+ /// Add an extension with the given oid and the passed in value to be included
+ /// in the OCTET STRING associated with the extension.
+ /// </summary>
+ /// <param name="oid">OID for the extension.</param>
+ /// <param name="critical">True if critical, false otherwise.</param>
+ /// <param name="extValue">The ASN.1 object to be included in the extension.</param>
+ public void AddExtension(
+ DerObjectIdentifier oid,
+ bool critical,
+ Asn1Encodable extValue)
+ {
+ byte[] encoded;
+ try
+ {
+ encoded = extValue.GetDerEncoded();
+ }
+ catch (Exception e)
+ {
+ throw new ArgumentException("error encoding value: " + e);
+ }
+
+ this.AddExtension(oid, critical, encoded);
+ }
+
+ /// <summary>
+ /// Add an extension with the given oid and the passed in byte array to be wrapped
+ /// in the OCTET STRING associated with the extension.
+ /// </summary>
+ /// <param name="oid">OID for the extension.</param>
+ /// <param name="critical">True if critical, false otherwise.</param>
+ /// <param name="extValue">The byte array to be wrapped.</param>
+ public void AddExtension(
+ DerObjectIdentifier oid,
+ bool critical,
+ byte[] extValue)
+ {
+ if (extensions.Contains(oid))
+ {
+ throw new ArgumentException("extension " + oid + " already added");
+ }
+
+ extOrdering.Add(oid);
+ extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue)));
+ }
+
+ /// <summary>Return true if there are no extension present in this generator.</summary>
+ /// <returns>True if empty, false otherwise</returns>
+ public bool IsEmpty
+ {
+ get { return extOrdering.Count < 1; }
+ }
+
+ /// <summary>Generate an X509Extensions object based on the current state of the generator.</summary>
+ /// <returns>An <c>X509Extensions</c> object</returns>
+ public X509Extensions Generate()
+ {
+ return new X509Extensions(extOrdering, extensions);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509Name.cs b/Crypto/src/asn1/x509/X509Name.cs
new file mode 100644
index 000000000..b459cbe1b
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509Name.cs
@@ -0,0 +1,1189 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+#if (SILVERLIGHT || PORTABLE)
+using System.Collections.Generic;
+#endif
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * <pre>
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY }
+ * </pre>
+ */
+ public class X509Name
+ : Asn1Encodable
+ {
+ /**
+ * country code - StringType(SIZE(2))
+ */
+ public static readonly DerObjectIdentifier C = new DerObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier O = new DerObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier OU = new DerObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ */
+ public static readonly DerObjectIdentifier T = new DerObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier CN = new DerObjectIdentifier("2.5.4.3");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier Street = new DerObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier SerialNumber = new DerObjectIdentifier("2.5.4.5");
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier L = new DerObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static readonly DerObjectIdentifier ST = new DerObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static readonly DerObjectIdentifier Surname = new DerObjectIdentifier("2.5.4.4");
+ public static readonly DerObjectIdentifier GivenName = new DerObjectIdentifier("2.5.4.42");
+ public static readonly DerObjectIdentifier Initials = new DerObjectIdentifier("2.5.4.43");
+ public static readonly DerObjectIdentifier Generation = new DerObjectIdentifier("2.5.4.44");
+ public static readonly DerObjectIdentifier UniqueIdentifier = new DerObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static readonly DerObjectIdentifier BusinessCategory = new DerObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static readonly DerObjectIdentifier PostalCode = new DerObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static readonly DerObjectIdentifier DnQualifier = new DerObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static readonly DerObjectIdentifier Pseudonym = new DerObjectIdentifier(
+ "2.5.4.65");
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static readonly DerObjectIdentifier DateOfBirth = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static readonly DerObjectIdentifier PlaceOfBirth = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static readonly DerObjectIdentifier Gender = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static readonly DerObjectIdentifier CountryOfCitizenship = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static readonly DerObjectIdentifier CountryOfResidence = new DerObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static readonly DerObjectIdentifier NameAtBirth = new DerObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static readonly DerObjectIdentifier PostalAddress = new DerObjectIdentifier("2.5.4.16");
+
+ /**
+ * RFC 2256 dmdName
+ */
+ public static readonly DerObjectIdentifier DmdName = new DerObjectIdentifier("2.5.4.54");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static readonly DerObjectIdentifier TelephoneNumber = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+ /**
+ * id-at-name
+ */
+ public static readonly DerObjectIdentifier Name = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.</p>
+ */
+ public static readonly DerObjectIdentifier EmailAddress = PkcsObjectIdentifiers.Pkcs9AtEmailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static readonly DerObjectIdentifier UnstructuredName = PkcsObjectIdentifiers.Pkcs9AtUnstructuredName;
+ public static readonly DerObjectIdentifier UnstructuredAddress = PkcsObjectIdentifiers.Pkcs9AtUnstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static readonly DerObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static readonly DerObjectIdentifier DC = new DerObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static readonly DerObjectIdentifier UID = new DerObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * determines whether or not strings should be processed and printed
+ * from back to front.
+ */
+// public static bool DefaultReverse = false;
+ public static bool DefaultReverse
+ {
+ get { return defaultReverse[0]; }
+ set { defaultReverse[0] = value; }
+ }
+
+ private static readonly bool[] defaultReverse = { false };
+
+#if (SILVERLIGHT || PORTABLE)
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ public static readonly IDictionary DefaultSymbols = Platform.CreateHashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 2253
+ */
+ public static readonly IDictionary RFC2253Symbols = Platform.CreateHashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 1779
+ *
+ */
+ public static readonly IDictionary RFC1779Symbols = Platform.CreateHashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ public static readonly IDictionary DefaultLookup = Platform.CreateHashtable();
+#else
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ public static readonly Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 2253
+ */
+ public static readonly Hashtable RFC2253Symbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 1779
+ *
+ */
+ public static readonly Hashtable RFC1779Symbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ public static readonly Hashtable DefaultLookup = new Hashtable();
+#endif
+
+ static X509Name()
+ {
+ DefaultSymbols.Add(C, "C");
+ DefaultSymbols.Add(O, "O");
+ DefaultSymbols.Add(T, "T");
+ DefaultSymbols.Add(OU, "OU");
+ DefaultSymbols.Add(CN, "CN");
+ DefaultSymbols.Add(L, "L");
+ DefaultSymbols.Add(ST, "ST");
+ DefaultSymbols.Add(SerialNumber, "SERIALNUMBER");
+ DefaultSymbols.Add(EmailAddress, "E");
+ DefaultSymbols.Add(DC, "DC");
+ DefaultSymbols.Add(UID, "UID");
+ DefaultSymbols.Add(Street, "STREET");
+ DefaultSymbols.Add(Surname, "SURNAME");
+ DefaultSymbols.Add(GivenName, "GIVENNAME");
+ DefaultSymbols.Add(Initials, "INITIALS");
+ DefaultSymbols.Add(Generation, "GENERATION");
+ DefaultSymbols.Add(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.Add(UnstructuredName, "unstructuredName");
+ DefaultSymbols.Add(UniqueIdentifier, "UniqueIdentifier");
+ DefaultSymbols.Add(DnQualifier, "DN");
+ DefaultSymbols.Add(Pseudonym, "Pseudonym");
+ DefaultSymbols.Add(PostalAddress, "PostalAddress");
+ DefaultSymbols.Add(NameAtBirth, "NameAtBirth");
+ DefaultSymbols.Add(CountryOfCitizenship, "CountryOfCitizenship");
+ DefaultSymbols.Add(CountryOfResidence, "CountryOfResidence");
+ DefaultSymbols.Add(Gender, "Gender");
+ DefaultSymbols.Add(PlaceOfBirth, "PlaceOfBirth");
+ DefaultSymbols.Add(DateOfBirth, "DateOfBirth");
+ DefaultSymbols.Add(PostalCode, "PostalCode");
+ DefaultSymbols.Add(BusinessCategory, "BusinessCategory");
+ DefaultSymbols.Add(TelephoneNumber, "TelephoneNumber");
+
+ RFC2253Symbols.Add(C, "C");
+ RFC2253Symbols.Add(O, "O");
+ RFC2253Symbols.Add(OU, "OU");
+ RFC2253Symbols.Add(CN, "CN");
+ RFC2253Symbols.Add(L, "L");
+ RFC2253Symbols.Add(ST, "ST");
+ RFC2253Symbols.Add(Street, "STREET");
+ RFC2253Symbols.Add(DC, "DC");
+ RFC2253Symbols.Add(UID, "UID");
+
+ RFC1779Symbols.Add(C, "C");
+ RFC1779Symbols.Add(O, "O");
+ RFC1779Symbols.Add(OU, "OU");
+ RFC1779Symbols.Add(CN, "CN");
+ RFC1779Symbols.Add(L, "L");
+ RFC1779Symbols.Add(ST, "ST");
+ RFC1779Symbols.Add(Street, "STREET");
+
+ DefaultLookup.Add("c", C);
+ DefaultLookup.Add("o", O);
+ DefaultLookup.Add("t", T);
+ DefaultLookup.Add("ou", OU);
+ DefaultLookup.Add("cn", CN);
+ DefaultLookup.Add("l", L);
+ DefaultLookup.Add("st", ST);
+ DefaultLookup.Add("serialnumber", SerialNumber);
+ DefaultLookup.Add("street", Street);
+ DefaultLookup.Add("emailaddress", E);
+ DefaultLookup.Add("dc", DC);
+ DefaultLookup.Add("e", E);
+ DefaultLookup.Add("uid", UID);
+ DefaultLookup.Add("surname", Surname);
+ DefaultLookup.Add("givenname", GivenName);
+ DefaultLookup.Add("initials", Initials);
+ DefaultLookup.Add("generation", Generation);
+ DefaultLookup.Add("unstructuredaddress", UnstructuredAddress);
+ DefaultLookup.Add("unstructuredname", UnstructuredName);
+ DefaultLookup.Add("uniqueidentifier", UniqueIdentifier);
+ DefaultLookup.Add("dn", DnQualifier);
+ DefaultLookup.Add("pseudonym", Pseudonym);
+ DefaultLookup.Add("postaladdress", PostalAddress);
+ DefaultLookup.Add("nameofbirth", NameAtBirth);
+ DefaultLookup.Add("countryofcitizenship", CountryOfCitizenship);
+ DefaultLookup.Add("countryofresidence", CountryOfResidence);
+ DefaultLookup.Add("gender", Gender);
+ DefaultLookup.Add("placeofbirth", PlaceOfBirth);
+ DefaultLookup.Add("dateofbirth", DateOfBirth);
+ DefaultLookup.Add("postalcode", PostalCode);
+ DefaultLookup.Add("businesscategory", BusinessCategory);
+ DefaultLookup.Add("telephonenumber", TelephoneNumber);
+ }
+
+ private readonly IList ordering = Platform.CreateArrayList();
+ private readonly X509NameEntryConverter converter;
+
+ private IList values = Platform.CreateArrayList();
+ private IList added = Platform.CreateArrayList();
+ private Asn1Sequence seq;
+
+ /**
+ * Return a X509Name based on the passed in tagged object.
+ *
+ * @param obj tag object holding name.
+ * @param explicitly true if explicitly tagged false otherwise.
+ * @return the X509Name
+ */
+ public static X509Name GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static X509Name GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is X509Name)
+ return (X509Name)obj;
+
+ if (obj != null)
+ return new X509Name(Asn1Sequence.GetInstance(obj));
+
+ throw new ArgumentException("null object in factory", "obj");
+ }
+
+ protected X509Name()
+ {
+ }
+
+ /**
+ * Constructor from Asn1Sequence
+ *
+ * the principal will be a list of constructed sets, each containing an (OID, string) pair.
+ */
+ protected X509Name(
+ Asn1Sequence seq)
+ {
+ this.seq = seq;
+
+ foreach (Asn1Encodable asn1Obj in seq)
+ {
+ Asn1Set asn1Set = Asn1Set.GetInstance(asn1Obj.ToAsn1Object());
+
+ for (int i = 0; i < asn1Set.Count; i++)
+ {
+ Asn1Sequence s = Asn1Sequence.GetInstance(asn1Set[i].ToAsn1Object());
+
+ if (s.Count != 2)
+ throw new ArgumentException("badly sized pair");
+
+ ordering.Add(DerObjectIdentifier.GetInstance(s[0].ToAsn1Object()));
+
+ Asn1Object derValue = s[1].ToAsn1Object();
+ if (derValue is IAsn1String && !(derValue is DerUniversalString))
+ {
+ string v = ((IAsn1String)derValue).GetString();
+ if (v.StartsWith("#"))
+ {
+ v = "\\" + v;
+ }
+
+ values.Add(v);
+ }
+ else
+ {
+ values.Add("#" + Hex.ToHexString(derValue.GetEncoded()));
+ }
+
+ added.Add(i != 0);
+ }
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public X509Name(
+ ArrayList ordering,
+ Hashtable attributes)
+ : this(ordering, attributes, new X509DefaultEntryConverter())
+ {
+ }
+#endif
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ * <p>
+ * it's is assumed the table contains OID/string pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering ArrayList should contain the OIDs
+ * in the order they are meant to be encoded or printed in ToString.</p>
+ */
+ public X509Name(
+ IList ordering,
+ IDictionary attributes)
+ : this(ordering, attributes, new X509DefaultEntryConverter())
+ {
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public X509Name(
+ ArrayList ordering,
+ Hashtable attributes,
+ X509NameEntryConverter converter)
+ : this((IList)ordering, (IDictionary)attributes, converter)
+ {
+ }
+#endif
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ * <p>
+ * it's is assumed the table contains OID/string pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering ArrayList should contain the OIDs
+ * in the order they are meant to be encoded or printed in ToString.</p>
+ * <p>
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.</p>
+ */
+ public X509Name(
+ IList ordering,
+ IDictionary attributes,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ foreach (DerObjectIdentifier oid in ordering)
+ {
+ object attribute = attributes[oid];
+ if (attribute == null)
+ {
+ throw new ArgumentException("No attribute for object id - " + oid + " - passed to distinguished name");
+ }
+
+ this.ordering.Add(oid);
+ this.added.Add(false);
+ this.values.Add(attribute); // copy the hash table
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public X509Name(
+ ArrayList oids,
+ ArrayList values)
+ : this(oids, values, new X509DefaultEntryConverter())
+ {
+ }
+#endif
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ */
+ public X509Name(
+ IList oids,
+ IList values)
+ : this(oids, values, new X509DefaultEntryConverter())
+ {
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public X509Name(
+ ArrayList oids,
+ ArrayList values,
+ X509NameEntryConverter converter)
+ : this((IList)oids, (IList)values, converter)
+ {
+ }
+#endif
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ * <p>
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.</p>
+ */
+ public X509Name(
+ IList oids,
+ IList values,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ if (oids.Count != values.Count)
+ {
+ throw new ArgumentException("'oids' must be same length as 'values'.");
+ }
+
+ for (int i = 0; i < oids.Count; i++)
+ {
+ this.ordering.Add(oids[i]);
+ this.values.Add(values[i]);
+ this.added.Add(false);
+ }
+ }
+
+// private static bool IsEncoded(
+// string s)
+// {
+// return s.StartsWith("#");
+// }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes.
+ */
+ public X509Name(
+ string dirName)
+ : this(DefaultReverse, (IDictionary)DefaultLookup, dirName)
+ {
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter.
+ */
+ public X509Name(
+ string dirName,
+ X509NameEntryConverter converter)
+ : this(DefaultReverse, DefaultLookup, dirName, converter)
+ {
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. If reverse
+ * is true, create the encoded version of the sequence starting from the
+ * last element in the string.
+ */
+ public X509Name(
+ bool reverse,
+ string dirName)
+ : this(reverse, (IDictionary)DefaultLookup, dirName)
+ {
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter. If reverse is true the ASN.1 sequence representing the DN will
+ * be built by starting at the end of the string, rather than the start.
+ */
+ public X509Name(
+ bool reverse,
+ string dirName,
+ X509NameEntryConverter converter)
+ : this(reverse, DefaultLookup, dirName, converter)
+ {
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public X509Name(
+ bool reverse,
+ Hashtable lookUp,
+ string dirName)
+ : this(reverse, lookUp, dirName, new X509DefaultEntryConverter())
+ {
+ }
+#endif
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a DerObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically.
+ * <br/>
+ * If reverse is true, create the encoded version of the sequence
+ * starting from the last element in the string.
+ * @param reverse true if we should start scanning from the end (RFC 2553).
+ * @param lookUp table of names and their oids.
+ * @param dirName the X.500 string to be parsed.
+ */
+ public X509Name(
+ bool reverse,
+ IDictionary lookUp,
+ string dirName)
+ : this(reverse, lookUp, dirName, new X509DefaultEntryConverter())
+ {
+ }
+
+ private DerObjectIdentifier DecodeOid(
+ string name,
+ IDictionary lookUp)
+ {
+ if (name.ToUpperInvariant().StartsWith("OID."))
+ {
+ return new DerObjectIdentifier(name.Substring(4));
+ }
+ else if (name[0] >= '0' && name[0] <= '9')
+ {
+ return new DerObjectIdentifier(name);
+ }
+
+ DerObjectIdentifier oid = (DerObjectIdentifier)lookUp[name.ToLowerInvariant()];
+ if (oid == null)
+ {
+ throw new ArgumentException("Unknown object id - " + name + " - passed to distinguished name");
+ }
+
+ return oid;
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a DerObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically. The passed in converter is used to convert the
+ * string values to the right of each equals sign to their ASN.1 counterparts.
+ * <br/>
+ * @param reverse true if we should start scanning from the end, false otherwise.
+ * @param lookUp table of names and oids.
+ * @param dirName the string dirName
+ * @param converter the converter to convert string values into their ASN.1 equivalents
+ */
+ public X509Name(
+ bool reverse,
+ IDictionary lookUp,
+ string dirName,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+ X509NameTokenizer nTok = new X509NameTokenizer(dirName);
+
+ while (nTok.HasMoreTokens())
+ {
+ string token = nTok.NextToken();
+ int index = token.IndexOf('=');
+
+ if (index == -1)
+ {
+ throw new ArgumentException("badly formated directory string");
+ }
+
+ string name = token.Substring(0, index);
+ string value = token.Substring(index + 1);
+ DerObjectIdentifier oid = DecodeOid(name, lookUp);
+
+ if (value.IndexOf('+') > 0)
+ {
+ X509NameTokenizer vTok = new X509NameTokenizer(value, '+');
+ string v = vTok.NextToken();
+
+ this.ordering.Add(oid);
+ this.values.Add(v);
+ this.added.Add(false);
+
+ while (vTok.HasMoreTokens())
+ {
+ string sv = vTok.NextToken();
+ int ndx = sv.IndexOf('=');
+
+ string nm = sv.Substring(0, ndx);
+ string vl = sv.Substring(ndx + 1);
+ this.ordering.Add(DecodeOid(nm, lookUp));
+ this.values.Add(vl);
+ this.added.Add(true);
+ }
+ }
+ else
+ {
+ this.ordering.Add(oid);
+ this.values.Add(value);
+ this.added.Add(false);
+ }
+ }
+
+ if (reverse)
+ {
+// this.ordering.Reverse();
+// this.values.Reverse();
+// this.added.Reverse();
+ IList o = Platform.CreateArrayList();
+ IList v = Platform.CreateArrayList();
+ IList a = Platform.CreateArrayList();
+ int count = 1;
+
+ for (int i = 0; i < this.ordering.Count; i++)
+ {
+ if (!((bool) this.added[i]))
+ {
+ count = 0;
+ }
+
+ int index = count++;
+
+ o.Insert(index, this.ordering[i]);
+ v.Insert(index, this.values[i]);
+ a.Insert(index, this.added[i]);
+ }
+
+ this.ordering = o;
+ this.values = v;
+ this.added = a;
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ /**
+ * return an ArrayList of the oids in the name, in the order they were found.
+ */
+ [Obsolete("Use 'GetOidList' instead")]
+ public ArrayList GetOids()
+ {
+ return new ArrayList(ordering);
+ }
+#endif
+
+ /**
+ * return an IList of the oids in the name, in the order they were found.
+ */
+ public IList GetOidList()
+ {
+ return Platform.CreateArrayList(ordering);
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ /**
+ * return an ArrayList of the values found in the name, in the order they
+ * were found.
+ */
+ [Obsolete("Use 'GetValueList' instead")]
+ public ArrayList GetValues()
+ {
+ return new ArrayList(values);
+ }
+#endif
+
+ /**
+ * return an IList of the values found in the name, in the order they
+ * were found.
+ */
+ public IList GetValueList()
+ {
+ return Platform.CreateArrayList(values);
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ /**
+ * return an ArrayList of the values found in the name, in the order they
+ * were found, with the DN label corresponding to passed in oid.
+ */
+ public ArrayList GetValues(
+ DerObjectIdentifier oid)
+ {
+ ArrayList v = new ArrayList();
+ DoGetValueList(oid, v);
+ return v;
+ }
+#endif
+
+ /**
+ * return an IList of the values found in the name, in the order they
+ * were found, with the DN label corresponding to passed in oid.
+ */
+ public IList GetValueList(DerObjectIdentifier oid)
+ {
+ IList v = Platform.CreateArrayList();
+ DoGetValueList(oid, v);
+ return v;
+ }
+
+ private void DoGetValueList(DerObjectIdentifier oid, IList v)
+ {
+ for (int i = 0; i != values.Count; i++)
+ {
+ if (ordering[i].Equals(oid))
+ {
+ string val = (string)values[i];
+
+ if (val.StartsWith("\\#"))
+ {
+ val = val.Substring(1);
+ }
+
+ v.Add(val);
+ }
+ }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ if (seq == null)
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+ Asn1EncodableVector sVec = new Asn1EncodableVector();
+ DerObjectIdentifier lstOid = null;
+
+ for (int i = 0; i != ordering.Count; i++)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
+ string str = (string)values[i];
+
+ if (lstOid == null
+ || ((bool)this.added[i]))
+ {
+ }
+ else
+ {
+ vec.Add(new DerSet(sVec));
+ sVec = new Asn1EncodableVector();
+ }
+
+ sVec.Add(
+ new DerSequence(
+ oid,
+ converter.GetConvertedValue(oid, str)));
+
+ lstOid = oid;
+ }
+
+ vec.Add(new DerSet(sVec));
+
+ seq = new DerSequence(vec);
+ }
+
+ return seq;
+ }
+
+ /// <param name="other">The X509Name object to test equivalency against.</param>
+ /// <param name="inOrder">If true, the order of elements must be the same,
+ /// as well as the values associated with each element.</param>
+ public bool Equivalent(
+ X509Name other,
+ bool inOrder)
+ {
+ if (!inOrder)
+ return this.Equivalent(other);
+
+ if (other == null)
+ return false;
+
+ if (other == this)
+ return true;
+
+ int orderingSize = ordering.Count;
+
+ if (orderingSize != other.ordering.Count)
+ return false;
+
+ for (int i = 0; i < orderingSize; i++)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier) ordering[i];
+ DerObjectIdentifier oOid = (DerObjectIdentifier) other.ordering[i];
+
+ if (!oid.Equals(oOid))
+ return false;
+
+ string val = (string) values[i];
+ string oVal = (string) other.values[i];
+
+ if (!equivalentStrings(val, oVal))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * test for equivalence - note: case is ignored.
+ */
+ public bool Equivalent(
+ X509Name other)
+ {
+ if (other == null)
+ return false;
+
+ if (other == this)
+ return true;
+
+ int orderingSize = ordering.Count;
+
+ if (orderingSize != other.ordering.Count)
+ {
+ return false;
+ }
+
+ bool[] indexes = new bool[orderingSize];
+ int start, end, delta;
+
+ if (ordering[0].Equals(other.ordering[0])) // guess forward
+ {
+ start = 0;
+ end = orderingSize;
+ delta = 1;
+ }
+ else // guess reversed - most common problem
+ {
+ start = orderingSize - 1;
+ end = -1;
+ delta = -1;
+ }
+
+ for (int i = start; i != end; i += delta)
+ {
+ bool found = false;
+ DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
+ string value = (string)values[i];
+
+ for (int j = 0; j < orderingSize; j++)
+ {
+ if (indexes[j])
+ {
+ continue;
+ }
+
+ DerObjectIdentifier oOid = (DerObjectIdentifier)other.ordering[j];
+
+ if (oid.Equals(oOid))
+ {
+ string oValue = (string)other.values[j];
+
+ if (equivalentStrings(value, oValue))
+ {
+ indexes[j] = true;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool equivalentStrings(
+ string s1,
+ string s2)
+ {
+ string v1 = canonicalize(s1);
+ string v2 = canonicalize(s2);
+
+ if (!v1.Equals(v2))
+ {
+ v1 = stripInternalSpaces(v1);
+ v2 = stripInternalSpaces(v2);
+
+ if (!v1.Equals(v2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static string canonicalize(
+ string s)
+ {
+ string v = s.ToLowerInvariant().Trim();
+
+ if (v.StartsWith("#"))
+ {
+ Asn1Object obj = decodeObject(v);
+
+ if (obj is IAsn1String)
+ {
+ v = ((IAsn1String)obj).GetString().ToLowerInvariant().Trim();
+ }
+ }
+
+ return v;
+ }
+
+ private static Asn1Object decodeObject(
+ string v)
+ {
+ try
+ {
+ return Asn1Object.FromByteArray(Hex.Decode(v.Substring(1)));
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("unknown encoding in name: " + e.Message, e);
+ }
+ }
+
+ private static string stripInternalSpaces(
+ string str)
+ {
+ StringBuilder res = new StringBuilder();
+
+ if (str.Length != 0)
+ {
+ char c1 = str[0];
+
+ res.Append(c1);
+
+ for (int k = 1; k < str.Length; k++)
+ {
+ char c2 = str[k];
+ if (!(c1 == ' ' && c2 == ' '))
+ {
+ res.Append(c2);
+ }
+ c1 = c2;
+ }
+ }
+
+ return res.ToString();
+ }
+
+ private void AppendValue(
+ StringBuilder buf,
+ IDictionary oidSymbols,
+ DerObjectIdentifier oid,
+ string val)
+ {
+ string sym = (string)oidSymbols[oid];
+
+ if (sym != null)
+ {
+ buf.Append(sym);
+ }
+ else
+ {
+ buf.Append(oid.Id);
+ }
+
+ buf.Append('=');
+
+ int index = buf.Length;
+
+ buf.Append(val);
+
+ int end = buf.Length;
+
+ if (val.StartsWith("\\#"))
+ {
+ index += 2;
+ }
+
+ while (index != end)
+ {
+ if ((buf[index] == ',')
+ || (buf[index] == '"')
+ || (buf[index] == '\\')
+ || (buf[index] == '+')
+ || (buf[index] == '=')
+ || (buf[index] == '<')
+ || (buf[index] == '>')
+ || (buf[index] == ';'))
+ {
+ buf.Insert(index++, "\\");
+ end++;
+ }
+
+ index++;
+ }
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public string ToString(
+ bool reverse,
+ Hashtable oidSymbols)
+ {
+ return ToString(reverse, (IDictionary)oidSymbols);
+ }
+#endif
+
+ /**
+ * convert the structure to a string - if reverse is true the
+ * oids and values are listed out starting with the last element
+ * in the sequence (ala RFC 2253), otherwise the string will begin
+ * with the first element of the structure. If no string definition
+ * for the oid is found in oidSymbols the string value of the oid is
+ * added. Two standard symbol tables are provided DefaultSymbols, and
+ * RFC2253Symbols as part of this class.
+ *
+ * @param reverse if true start at the end of the sequence and work back.
+ * @param oidSymbols look up table strings for oids.
+ */
+ public string ToString(
+ bool reverse,
+ IDictionary oidSymbols)
+ {
+#if (SILVERLIGHT || PORTABLE)
+ List<object> components = new List<object>();
+#else
+ ArrayList components = new ArrayList();
+#endif
+
+ StringBuilder ava = null;
+
+ for (int i = 0; i < ordering.Count; i++)
+ {
+ if ((bool) added[i])
+ {
+ ava.Append('+');
+ AppendValue(ava, oidSymbols,
+ (DerObjectIdentifier)ordering[i],
+ (string)values[i]);
+ }
+ else
+ {
+ ava = new StringBuilder();
+ AppendValue(ava, oidSymbols,
+ (DerObjectIdentifier)ordering[i],
+ (string)values[i]);
+ components.Add(ava);
+ }
+ }
+
+ if (reverse)
+ {
+ components.Reverse();
+ }
+
+ StringBuilder buf = new StringBuilder();
+
+ if (components.Count > 0)
+ {
+ buf.Append(components[0].ToString());
+
+ for (int i = 1; i < components.Count; ++i)
+ {
+ buf.Append(',');
+ buf.Append(components[i].ToString());
+ }
+ }
+
+ return buf.ToString();
+ }
+
+ public override string ToString()
+ {
+ return ToString(DefaultReverse, (IDictionary)DefaultSymbols);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509NameEntryConverter.cs b/Crypto/src/asn1/x509/X509NameEntryConverter.cs
new file mode 100644
index 000000000..5872656a9
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509NameEntryConverter.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * It turns out that the number of standard ways the fields in a DN should be
+ * encoded into their ASN.1 counterparts is rapidly approaching the
+ * number of machines on the internet. By default the X509Name class
+ * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+ * <p>
+ * An example of an encoder look like below:
+ * <pre>
+ * public class X509DirEntryConverter
+ * : X509NameEntryConverter
+ * {
+ * public Asn1Object GetConvertedValue(
+ * DerObjectIdentifier oid,
+ * string value)
+ * {
+ * if (str.Length() != 0 && str.charAt(0) == '#')
+ * {
+ * return ConvertHexEncoded(str, 1);
+ * }
+ * if (oid.Equals(EmailAddress))
+ * {
+ * return new DerIA5String(str);
+ * }
+ * else if (CanBePrintable(str))
+ * {
+ * return new DerPrintableString(str);
+ * }
+ * else if (CanBeUTF8(str))
+ * {
+ * return new DerUtf8String(str);
+ * }
+ * else
+ * {
+ * return new DerBmpString(str);
+ * }
+ * }
+ * }
+ * </pre>
+ * </p>
+ */
+ public abstract class X509NameEntryConverter
+ {
+ /**
+ * Convert an inline encoded hex string rendition of an ASN.1
+ * object back into its corresponding ASN.1 object.
+ *
+ * @param str the hex encoded object
+ * @param off the index at which the encoding starts
+ * @return the decoded object
+ */
+ protected Asn1Object ConvertHexEncoded(
+ string hexString,
+ int offset)
+ {
+ string str = hexString.Substring(offset);
+
+ return Asn1Object.FromByteArray(Hex.Decode(str));
+ }
+
+ /**
+ * return true if the passed in string can be represented without
+ * loss as a PrintableString, false otherwise.
+ */
+ protected bool CanBePrintable(
+ string str)
+ {
+ return DerPrintableString.IsPrintableString(str);
+ }
+
+ /**
+ * Convert the passed in string value into the appropriate ASN.1
+ * encoded object.
+ *
+ * @param oid the oid associated with the value in the DN.
+ * @param value the value of the particular DN component.
+ * @return the ASN.1 equivalent for the value.
+ */
+ public abstract Asn1Object GetConvertedValue(DerObjectIdentifier oid, string value);
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509NameTokenizer.cs b/Crypto/src/asn1/x509/X509NameTokenizer.cs
new file mode 100644
index 000000000..ab5529535
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509NameTokenizer.cs
@@ -0,0 +1,104 @@
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+ public class X509NameTokenizer
+ {
+ private string value;
+ private int index;
+ private char separator;
+ private StringBuilder buffer = new StringBuilder();
+
+ public X509NameTokenizer(
+ string oid)
+ : this(oid, ',')
+ {
+ }
+
+ public X509NameTokenizer(
+ string oid,
+ char separator)
+ {
+ this.value = oid;
+ this.index = -1;
+ this.separator = separator;
+ }
+
+ public bool HasMoreTokens()
+ {
+ return index != value.Length;
+ }
+
+ public string NextToken()
+ {
+ if (index == value.Length)
+ {
+ return null;
+ }
+
+ int end = index + 1;
+ bool quoted = false;
+ bool escaped = false;
+
+ buffer.Remove(0, buffer.Length);
+
+ while (end != value.Length)
+ {
+ char c = value[end];
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ else
+ {
+ buffer.Append(c);
+ escaped = false;
+ }
+ }
+ else
+ {
+ if (escaped || quoted)
+ {
+ if (c == '#' && buffer[buffer.Length - 1] == '=')
+ {
+ buffer.Append('\\');
+ }
+ else if (c == '+' && separator != '+')
+ {
+ buffer.Append('\\');
+ }
+ buffer.Append(c);
+ escaped = false;
+ }
+ else if (c == '\\')
+ {
+ escaped = true;
+ }
+ else if (c == separator)
+ {
+ break;
+ }
+ else
+ {
+ buffer.Append(c);
+ }
+ }
+
+ end++;
+ }
+
+ index = end;
+
+ return buffer.ToString().Trim();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/X509ObjectIdentifiers.cs b/Crypto/src/asn1/x509/X509ObjectIdentifiers.cs
new file mode 100644
index 000000000..f00e31475
--- /dev/null
+++ b/Crypto/src/asn1/x509/X509ObjectIdentifiers.cs
@@ -0,0 +1,59 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+ public abstract class X509ObjectIdentifiers
+ {
+ //
+ // base id
+ //
+ internal const string ID = "2.5.4";
+
+ public static readonly DerObjectIdentifier CommonName = new DerObjectIdentifier(ID + ".3");
+ public static readonly DerObjectIdentifier CountryName = new DerObjectIdentifier(ID + ".6");
+ public static readonly DerObjectIdentifier LocalityName = new DerObjectIdentifier(ID + ".7");
+ public static readonly DerObjectIdentifier StateOrProvinceName = new DerObjectIdentifier(ID + ".8");
+ public static readonly DerObjectIdentifier Organization = new DerObjectIdentifier(ID + ".10");
+ public static readonly DerObjectIdentifier OrganizationalUnitName = new DerObjectIdentifier(ID + ".11");
+
+ public static readonly DerObjectIdentifier id_at_telephoneNumber = new DerObjectIdentifier(ID + ".20");
+ public static readonly DerObjectIdentifier id_at_name = new DerObjectIdentifier(ID + ".41");
+
+ // id-SHA1 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ public static readonly DerObjectIdentifier IdSha1 = new DerObjectIdentifier("1.3.14.3.2.26");
+
+ //
+ // ripemd160 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RipeMD-160(1)}
+ //
+ public static readonly DerObjectIdentifier RipeMD160 = new DerObjectIdentifier("1.3.36.3.2.1");
+
+ //
+ // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
+ //
+ public static readonly DerObjectIdentifier RipeMD160WithRsaEncryption = new DerObjectIdentifier("1.3.36.3.3.1.2");
+
+ public static readonly DerObjectIdentifier IdEARsa = new DerObjectIdentifier("2.5.8.1.1");
+
+ // id-pkix
+ public static readonly DerObjectIdentifier IdPkix = new DerObjectIdentifier("1.3.6.1.5.5.7");
+
+ //
+ // private internet extensions
+ //
+ public static readonly DerObjectIdentifier IdPE = new DerObjectIdentifier(IdPkix + ".1");
+
+ //
+ // authority information access
+ //
+ public static readonly DerObjectIdentifier IdAD = new DerObjectIdentifier(IdPkix + ".48");
+ public static readonly DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier(IdAD + ".2");
+ public static readonly DerObjectIdentifier IdADOcsp = new DerObjectIdentifier(IdAD + ".1");
+
+ //
+ // OID for ocsp and crl uri in AuthorityInformationAccess extension
+ //
+ public static readonly DerObjectIdentifier OcspAccessMethod = IdADOcsp;
+ public static readonly DerObjectIdentifier CrlAccessMethod = IdADCAIssuers;
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/BiometricData.cs b/Crypto/src/asn1/x509/qualified/BiometricData.cs
new file mode 100644
index 000000000..61d7c99cb
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/BiometricData.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The BiometricData object.
+ * <pre>
+ * BiometricData ::= SEQUENCE {
+ * typeOfBiometricData TypeOfBiometricData,
+ * hashAlgorithm AlgorithmIdentifier,
+ * biometricDataHash OCTET STRING,
+ * sourceDataUri IA5String OPTIONAL }
+ * </pre>
+ */
+ public class BiometricData
+ : Asn1Encodable
+ {
+ private readonly TypeOfBiometricData typeOfBiometricData;
+ private readonly AlgorithmIdentifier hashAlgorithm;
+ private readonly Asn1OctetString biometricDataHash;
+ private readonly DerIA5String sourceDataUri;
+
+ public static BiometricData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is BiometricData)
+ {
+ return (BiometricData)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new BiometricData(Asn1Sequence.GetInstance(obj));
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ private BiometricData(
+ Asn1Sequence seq)
+ {
+ typeOfBiometricData = TypeOfBiometricData.GetInstance(seq[0]);
+ hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+ biometricDataHash = Asn1OctetString.GetInstance(seq[2]);
+
+ if (seq.Count > 3)
+ {
+ sourceDataUri = DerIA5String.GetInstance(seq[3]);
+ }
+ }
+
+ public BiometricData(
+ TypeOfBiometricData typeOfBiometricData,
+ AlgorithmIdentifier hashAlgorithm,
+ Asn1OctetString biometricDataHash,
+ DerIA5String sourceDataUri)
+ {
+ this.typeOfBiometricData = typeOfBiometricData;
+ this.hashAlgorithm = hashAlgorithm;
+ this.biometricDataHash = biometricDataHash;
+ this.sourceDataUri = sourceDataUri;
+ }
+
+ public BiometricData(
+ TypeOfBiometricData typeOfBiometricData,
+ AlgorithmIdentifier hashAlgorithm,
+ Asn1OctetString biometricDataHash)
+ {
+ this.typeOfBiometricData = typeOfBiometricData;
+ this.hashAlgorithm = hashAlgorithm;
+ this.biometricDataHash = biometricDataHash;
+ this.sourceDataUri = null;
+ }
+
+ public TypeOfBiometricData TypeOfBiometricData
+ {
+ get { return typeOfBiometricData; }
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return hashAlgorithm; }
+ }
+
+ public Asn1OctetString BiometricDataHash
+ {
+ get { return biometricDataHash; }
+ }
+
+ public DerIA5String SourceDataUri
+ {
+ get { return sourceDataUri; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector seq = new Asn1EncodableVector(
+ typeOfBiometricData, hashAlgorithm, biometricDataHash);
+
+ if (sourceDataUri != null)
+ {
+ seq.Add(sourceDataUri);
+ }
+
+ return new DerSequence(seq);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs b/Crypto/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs
new file mode 100644
index 000000000..86a4eee0a
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs
@@ -0,0 +1,19 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ public abstract class EtsiQCObjectIdentifiers
+ {
+ //
+ // base id
+ //
+ public static readonly DerObjectIdentifier IdEtsiQcs = new DerObjectIdentifier("0.4.0.1862.1");
+
+ public static readonly DerObjectIdentifier IdEtsiQcsQcCompliance = new DerObjectIdentifier(IdEtsiQcs+".1");
+ public static readonly DerObjectIdentifier IdEtsiQcsLimitValue = new DerObjectIdentifier(IdEtsiQcs+".2");
+ public static readonly DerObjectIdentifier IdEtsiQcsRetentionPeriod = new DerObjectIdentifier(IdEtsiQcs+".3");
+ public static readonly DerObjectIdentifier IdEtsiQcsQcSscd = new DerObjectIdentifier(IdEtsiQcs+".4");
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs b/Crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs
new file mode 100644
index 000000000..3300562c8
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/Iso4217CurrencyCode.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The Iso4217CurrencyCode object.
+ * <pre>
+ * Iso4217CurrencyCode ::= CHOICE {
+ * alphabetic PrintableString (SIZE 3), --Recommended
+ * numeric INTEGER (1..999) }
+ * -- Alphabetic or numeric currency code as defined in ISO 4217
+ * -- It is recommended that the Alphabetic form is used
+ * </pre>
+ */
+ public class Iso4217CurrencyCode
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal const int AlphabeticMaxSize = 3;
+ internal const int NumericMinSize = 1;
+ internal const int NumericMaxSize = 999;
+
+ internal Asn1Encodable obj;
+// internal int numeric;
+
+ public static Iso4217CurrencyCode GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Iso4217CurrencyCode)
+ {
+ return (Iso4217CurrencyCode) obj;
+ }
+
+ if (obj is DerInteger)
+ {
+ DerInteger numericobj = DerInteger.GetInstance(obj);
+ int numeric = numericobj.Value.IntValue;
+ return new Iso4217CurrencyCode(numeric);
+ }
+
+ if (obj is DerPrintableString)
+ {
+ DerPrintableString alphabetic = DerPrintableString.GetInstance(obj);
+ return new Iso4217CurrencyCode(alphabetic.GetString());
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public Iso4217CurrencyCode(
+ int numeric)
+ {
+ if (numeric > NumericMaxSize || numeric < NumericMinSize)
+ {
+ throw new ArgumentException("wrong size in numeric code : not in (" +NumericMinSize +".."+ NumericMaxSize +")");
+ }
+
+ obj = new DerInteger(numeric);
+ }
+
+ public Iso4217CurrencyCode(
+ string alphabetic)
+ {
+ if (alphabetic.Length > AlphabeticMaxSize)
+ {
+ throw new ArgumentException("wrong size in alphabetic code : max size is " + AlphabeticMaxSize);
+ }
+
+ obj = new DerPrintableString(alphabetic);
+ }
+
+ public bool IsAlphabetic { get { return obj is DerPrintableString; } }
+
+ public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } }
+
+ public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return obj.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/MonetaryValue.cs b/Crypto/src/asn1/x509/qualified/MonetaryValue.cs
new file mode 100644
index 000000000..45e113671
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/MonetaryValue.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The MonetaryValue object.
+ * <pre>
+ * MonetaryValue ::= SEQUENCE {
+ * currency Iso4217CurrencyCode,
+ * amount INTEGER,
+ * exponent INTEGER }
+ * -- value = amount * 10^exponent
+ * </pre>
+ */
+ public class MonetaryValue
+ : Asn1Encodable
+ {
+ internal Iso4217CurrencyCode currency;
+ internal DerInteger amount;
+ internal DerInteger exponent;
+
+ public static MonetaryValue GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is MonetaryValue)
+ {
+ return (MonetaryValue) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new MonetaryValue(Asn1Sequence.GetInstance(obj));
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ private MonetaryValue(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ currency = Iso4217CurrencyCode.GetInstance(seq[0]);
+ amount = DerInteger.GetInstance(seq[1]);
+ exponent = DerInteger.GetInstance(seq[2]);
+ }
+
+ public MonetaryValue(
+ Iso4217CurrencyCode currency,
+ int amount,
+ int exponent)
+ {
+ this.currency = currency;
+ this.amount = new DerInteger(amount);
+ this.exponent = new DerInteger(exponent);
+ }
+
+ public Iso4217CurrencyCode Currency
+ {
+ get { return currency; }
+ }
+
+ public BigInteger Amount
+ {
+ get { return amount.Value; }
+ }
+
+ public BigInteger Exponent
+ {
+ get { return exponent.Value; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(currency, amount, exponent);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/QCStatement.cs b/Crypto/src/asn1/x509/qualified/QCStatement.cs
new file mode 100644
index 000000000..317f03447
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/QCStatement.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The QCStatement object.
+ * <pre>
+ * QCStatement ::= SEQUENCE {
+ * statementId OBJECT IDENTIFIER,
+ * statementInfo ANY DEFINED BY statementId OPTIONAL}
+ * </pre>
+ */
+ public class QCStatement
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier qcStatementId;
+ private readonly Asn1Encodable qcStatementInfo;
+
+ public static QCStatement GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is QCStatement)
+ {
+ return (QCStatement) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new QCStatement(Asn1Sequence.GetInstance(obj));
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ private QCStatement(
+ Asn1Sequence seq)
+ {
+ qcStatementId = DerObjectIdentifier.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ qcStatementInfo = seq[1];
+ }
+ }
+
+ public QCStatement(
+ DerObjectIdentifier qcStatementId)
+ {
+ this.qcStatementId = qcStatementId;
+ }
+
+ public QCStatement(
+ DerObjectIdentifier qcStatementId,
+ Asn1Encodable qcStatementInfo)
+ {
+ this.qcStatementId = qcStatementId;
+ this.qcStatementInfo = qcStatementInfo;
+ }
+
+ public DerObjectIdentifier StatementId
+ {
+ get { return qcStatementId; }
+ }
+
+ public Asn1Encodable StatementInfo
+ {
+ get { return qcStatementInfo; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector seq = new Asn1EncodableVector(qcStatementId);
+
+ if (qcStatementInfo != null)
+ {
+ seq.Add(qcStatementInfo);
+ }
+
+ return new DerSequence(seq);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs b/Crypto/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs
new file mode 100644
index 000000000..8ebd69edb
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs
@@ -0,0 +1,21 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ public sealed class Rfc3739QCObjectIdentifiers
+ {
+ private Rfc3739QCObjectIdentifiers()
+ {
+ }
+
+ //
+ // base id
+ //
+ public static readonly DerObjectIdentifier IdQcs = new DerObjectIdentifier("1.3.6.1.5.5.7.11");
+
+ public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV1 = new DerObjectIdentifier(IdQcs+".1");
+ public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV2 = new DerObjectIdentifier(IdQcs+".2");
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/SemanticsInformation.cs b/Crypto/src/asn1/x509/qualified/SemanticsInformation.cs
new file mode 100644
index 000000000..72e7cd0e1
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/SemanticsInformation.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The SemanticsInformation object.
+ * <pre>
+ * SemanticsInformation ::= SEQUENCE {
+ * semanticsIdentifier OBJECT IDENTIFIER OPTIONAL,
+ * nameRegistrationAuthorities NameRegistrationAuthorities
+ * OPTIONAL }
+ * (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
+ * WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
+ *
+ * NameRegistrationAuthorities ::= SEQUENCE SIZE (1..MAX) OF
+ * GeneralName
+ * </pre>
+ */
+ public class SemanticsInformation
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier semanticsIdentifier;
+ private readonly GeneralName[] nameRegistrationAuthorities;
+
+ public static SemanticsInformation GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SemanticsInformation)
+ {
+ return (SemanticsInformation) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new SemanticsInformation(Asn1Sequence.GetInstance(obj));
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public SemanticsInformation(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1)
+ {
+ throw new ArgumentException("no objects in SemanticsInformation");
+ }
+
+ IEnumerator e = seq.GetEnumerator();
+ e.MoveNext();
+ object obj = e.Current;
+ if (obj is DerObjectIdentifier)
+ {
+ semanticsIdentifier = DerObjectIdentifier.GetInstance(obj);
+ if (e.MoveNext())
+ {
+ obj = e.Current;
+ }
+ else
+ {
+ obj = null;
+ }
+ }
+
+ if (obj != null)
+ {
+ Asn1Sequence generalNameSeq = Asn1Sequence.GetInstance(obj );
+ nameRegistrationAuthorities = new GeneralName[generalNameSeq.Count];
+ for (int i= 0; i < generalNameSeq.Count; i++)
+ {
+ nameRegistrationAuthorities[i] = GeneralName.GetInstance(generalNameSeq[i]);
+ }
+ }
+ }
+
+ public SemanticsInformation(
+ DerObjectIdentifier semanticsIdentifier,
+ GeneralName[] generalNames)
+ {
+ this.semanticsIdentifier = semanticsIdentifier;
+ this.nameRegistrationAuthorities = generalNames;
+ }
+
+ public SemanticsInformation(
+ DerObjectIdentifier semanticsIdentifier)
+ {
+ this.semanticsIdentifier = semanticsIdentifier;
+ }
+
+ public SemanticsInformation(
+ GeneralName[] generalNames)
+ {
+ this.nameRegistrationAuthorities = generalNames;
+ }
+
+ public DerObjectIdentifier SemanticsIdentifier { get { return semanticsIdentifier; } }
+
+ public GeneralName[] GetNameRegistrationAuthorities()
+ {
+ return nameRegistrationAuthorities;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector seq = new Asn1EncodableVector();
+
+ if (this.semanticsIdentifier != null)
+ {
+ seq.Add(semanticsIdentifier);
+ }
+
+ if (this.nameRegistrationAuthorities != null)
+ {
+ seq.Add(new DerSequence(nameRegistrationAuthorities));
+ }
+
+ return new DerSequence(seq);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs b/Crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs
new file mode 100644
index 000000000..a77e54acb
--- /dev/null
+++ b/Crypto/src/asn1/x509/qualified/TypeOfBiometricData.cs
@@ -0,0 +1,91 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+ /**
+ * The TypeOfBiometricData object.
+ * <pre>
+ * TypeOfBiometricData ::= CHOICE {
+ * predefinedBiometricType PredefinedBiometricType,
+ * biometricDataOid OBJECT IDENTIFIER }
+ *
+ * PredefinedBiometricType ::= INTEGER {
+ * picture(0),handwritten-signature(1)}
+ * (picture|handwritten-signature)
+ * </pre>
+ */
+ public class TypeOfBiometricData
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int Picture = 0;
+ public const int HandwrittenSignature = 1;
+
+ internal Asn1Encodable obj;
+
+ public static TypeOfBiometricData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is TypeOfBiometricData)
+ {
+ return (TypeOfBiometricData) obj;
+ }
+
+ if (obj is DerInteger)
+ {
+ DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj);
+ int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue;
+
+ return new TypeOfBiometricData(predefinedBiometricType);
+ }
+
+ if (obj is DerObjectIdentifier)
+ {
+ DerObjectIdentifier BiometricDataOid = DerObjectIdentifier.GetInstance(obj);
+ return new TypeOfBiometricData(BiometricDataOid);
+ }
+
+ throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public TypeOfBiometricData(
+ int predefinedBiometricType)
+ {
+ if (predefinedBiometricType == Picture || predefinedBiometricType == HandwrittenSignature)
+ {
+ obj = new DerInteger(predefinedBiometricType);
+ }
+ else
+ {
+ throw new ArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
+ }
+ }
+
+ public TypeOfBiometricData(
+ DerObjectIdentifier biometricDataOid)
+ {
+ obj = biometricDataOid;
+ }
+
+ public bool IsPredefined
+ {
+ get { return obj is DerInteger; }
+ }
+
+ public int PredefinedBiometricType
+ {
+ get { return ((DerInteger) obj).Value.IntValue; }
+ }
+
+ public DerObjectIdentifier BiometricDataOid
+ {
+ get { return (DerObjectIdentifier) obj; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return obj.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/sigi/NameOrPseudonym.cs b/Crypto/src/asn1/x509/sigi/NameOrPseudonym.cs
new file mode 100644
index 000000000..222895cf1
--- /dev/null
+++ b/Crypto/src/asn1/x509/sigi/NameOrPseudonym.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.X509.SigI
+{
+ /**
+ * Structure for a name or pseudonym.
+ *
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ *
+ * @see org.bouncycastle.asn1.x509.sigi.PersonalData
+ *
+ */
+ public class NameOrPseudonym
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly DirectoryString pseudonym;
+ private readonly DirectoryString surname;
+ private readonly Asn1Sequence givenName;
+
+ public static NameOrPseudonym GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is NameOrPseudonym)
+ {
+ return (NameOrPseudonym)obj;
+ }
+
+ if (obj is IAsn1String)
+ {
+ return new NameOrPseudonym(DirectoryString.GetInstance(obj));
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new NameOrPseudonym((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from DERString.
+ * <p/>
+ * The sequence is of type NameOrPseudonym:
+ * <p/>
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ * @param pseudonym pseudonym value to use.
+ */
+ public NameOrPseudonym(
+ DirectoryString pseudonym)
+ {
+ this.pseudonym = pseudonym;
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * The sequence is of type NameOrPseudonym:
+ * <p/>
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private NameOrPseudonym(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ if (!(seq[0] is IAsn1String))
+ throw new ArgumentException("Bad object encountered: " + seq[0].GetType().Name);
+
+ surname = DirectoryString.GetInstance(seq[0]);
+ givenName = Asn1Sequence.GetInstance(seq[1]);
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param pseudonym The pseudonym.
+ */
+ public NameOrPseudonym(
+ string pseudonym)
+ : this(new DirectoryString(pseudonym))
+ {
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param surname The surname.
+ * @param givenName A sequence of directory strings making up the givenName
+ */
+ public NameOrPseudonym(
+ DirectoryString surname,
+ Asn1Sequence givenName)
+ {
+ this.surname = surname;
+ this.givenName = givenName;
+ }
+
+ public DirectoryString Pseudonym
+ {
+ get { return pseudonym; }
+ }
+
+ public DirectoryString Surname
+ {
+ get { return surname; }
+ }
+
+ public DirectoryString[] GetGivenName()
+ {
+ DirectoryString[] items = new DirectoryString[givenName.Count];
+ int count = 0;
+ foreach (object o in givenName)
+ {
+ items[count++] = DirectoryString.GetInstance(o);
+ }
+ return items;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (pseudonym != null)
+ {
+ return pseudonym.ToAsn1Object();
+ }
+
+ return new DerSequence(surname, givenName);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/sigi/PersonalData.cs b/Crypto/src/asn1/x509/sigi/PersonalData.cs
new file mode 100644
index 000000000..6acdc7308
--- /dev/null
+++ b/Crypto/src/asn1/x509/sigi/PersonalData.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509.SigI
+{
+ /**
+ * Contains personal data for the otherName field in the subjectAltNames
+ * extension.
+ * <p/>
+ * <pre>
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see org.bouncycastle.asn1.x509.sigi.NameOrPseudonym
+ * @see org.bouncycastle.asn1.x509.sigi.SigIObjectIdentifiers
+ */
+ public class PersonalData
+ : Asn1Encodable
+ {
+ private readonly NameOrPseudonym nameOrPseudonym;
+ private readonly BigInteger nameDistinguisher;
+ private readonly DerGeneralizedTime dateOfBirth;
+ private readonly DirectoryString placeOfBirth;
+ private readonly string gender;
+ private readonly DirectoryString postalAddress;
+
+ public static PersonalData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is PersonalData)
+ {
+ return (PersonalData) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new PersonalData((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * The sequence is of type NameOrPseudonym:
+ * <p/>
+ * <pre>
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private PersonalData(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ IEnumerator e = seq.GetEnumerator();
+ e.MoveNext();
+
+ nameOrPseudonym = NameOrPseudonym.GetInstance(e.Current);
+
+ while (e.MoveNext())
+ {
+ Asn1TaggedObject o = Asn1TaggedObject.GetInstance(e.Current);
+ int tag = o.TagNo;
+ switch (tag)
+ {
+ case 0:
+ nameDistinguisher = DerInteger.GetInstance(o, false).Value;
+ break;
+ case 1:
+ dateOfBirth = DerGeneralizedTime.GetInstance(o, false);
+ break;
+ case 2:
+ placeOfBirth = DirectoryString.GetInstance(o, true);
+ break;
+ case 3:
+ gender = DerPrintableString.GetInstance(o, false).GetString();
+ break;
+ case 4:
+ postalAddress = DirectoryString.GetInstance(o, true);
+ break;
+ default:
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param nameOrPseudonym Name or pseudonym.
+ * @param nameDistinguisher Name distinguisher.
+ * @param dateOfBirth Date of birth.
+ * @param placeOfBirth Place of birth.
+ * @param gender Gender.
+ * @param postalAddress Postal Address.
+ */
+ public PersonalData(
+ NameOrPseudonym nameOrPseudonym,
+ BigInteger nameDistinguisher,
+ DerGeneralizedTime dateOfBirth,
+ DirectoryString placeOfBirth,
+ string gender,
+ DirectoryString postalAddress)
+ {
+ this.nameOrPseudonym = nameOrPseudonym;
+ this.dateOfBirth = dateOfBirth;
+ this.gender = gender;
+ this.nameDistinguisher = nameDistinguisher;
+ this.postalAddress = postalAddress;
+ this.placeOfBirth = placeOfBirth;
+ }
+
+ public NameOrPseudonym NameOrPseudonym
+ {
+ get { return nameOrPseudonym; }
+ }
+
+ public BigInteger NameDistinguisher
+ {
+ get { return nameDistinguisher; }
+ }
+
+ public DerGeneralizedTime DateOfBirth
+ {
+ get { return dateOfBirth; }
+ }
+
+ public DirectoryString PlaceOfBirth
+ {
+ get { return placeOfBirth; }
+ }
+
+ public string Gender
+ {
+ get { return gender; }
+ }
+
+ public DirectoryString PostalAddress
+ {
+ get { return postalAddress; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+ vec.Add(nameOrPseudonym);
+ if (nameDistinguisher != null)
+ {
+ vec.Add(new DerTaggedObject(false, 0, new DerInteger(nameDistinguisher)));
+ }
+ if (dateOfBirth != null)
+ {
+ vec.Add(new DerTaggedObject(false, 1, dateOfBirth));
+ }
+ if (placeOfBirth != null)
+ {
+ vec.Add(new DerTaggedObject(true, 2, placeOfBirth));
+ }
+ if (gender != null)
+ {
+ vec.Add(new DerTaggedObject(false, 3, new DerPrintableString(gender, true)));
+ }
+ if (postalAddress != null)
+ {
+ vec.Add(new DerTaggedObject(true, 4, postalAddress));
+ }
+ return new DerSequence(vec);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs b/Crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs
new file mode 100644
index 000000000..682311adc
--- /dev/null
+++ b/Crypto/src/asn1/x509/sigi/SigIObjectIdentifiers.cs
@@ -0,0 +1,49 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509.SigI
+{
+ /**
+ * Object Identifiers of SigI specifciation (German Signature Law
+ * Interoperability specification).
+ */
+ public sealed class SigIObjectIdentifiers
+ {
+ private SigIObjectIdentifiers()
+ {
+ }
+
+ public readonly static DerObjectIdentifier IdSigI = new DerObjectIdentifier("1.3.36.8");
+
+ /**
+ * Key purpose IDs for German SigI (Signature Interoperability
+ * Specification)
+ */
+ public readonly static DerObjectIdentifier IdSigIKP = new DerObjectIdentifier(IdSigI + ".2");
+
+ /**
+ * Certificate policy IDs for German SigI (Signature Interoperability
+ * Specification)
+ */
+ public readonly static DerObjectIdentifier IdSigICP = new DerObjectIdentifier(IdSigI + ".1");
+
+ /**
+ * Other Name IDs for German SigI (Signature Interoperability Specification)
+ */
+ public readonly static DerObjectIdentifier IdSigION = new DerObjectIdentifier(IdSigI + ".4");
+
+ /**
+ * To be used for for the generation of directory service certificates.
+ */
+ public static readonly DerObjectIdentifier IdSigIKPDirectoryService = new DerObjectIdentifier(IdSigIKP + ".1");
+
+ /**
+ * ID for PersonalData
+ */
+ public static readonly DerObjectIdentifier IdSigIONPersonalData = new DerObjectIdentifier(IdSigION + ".1");
+
+ /**
+ * Certificate is conform to german signature law.
+ */
+ public static readonly DerObjectIdentifier IdSigICPSigConform = new DerObjectIdentifier(IdSigICP + ".1");
+ }
+}
|