diff --git a/Crypto/src/asn1/ASN1Generator.cs b/Crypto/src/asn1/ASN1Generator.cs
new file mode 100644
index 000000000..e56051736
--- /dev/null
+++ b/Crypto/src/asn1/ASN1Generator.cs
@@ -0,0 +1,27 @@
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public abstract class Asn1Generator
+ {
+ private Stream _out;
+
+ protected Asn1Generator(
+ Stream outStream)
+ {
+ _out = outStream;
+ }
+
+ protected Stream Out
+ {
+ get { return _out; }
+ }
+
+ public abstract void AddObject(Asn1Encodable obj);
+
+ public abstract Stream GetRawOutputStream();
+
+ public abstract void Close();
+ }
+}
diff --git a/Crypto/src/asn1/ASN1OctetStringParser.cs b/Crypto/src/asn1/ASN1OctetStringParser.cs
new file mode 100644
index 000000000..5815aa42f
--- /dev/null
+++ b/Crypto/src/asn1/ASN1OctetStringParser.cs
@@ -0,0 +1,10 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public interface Asn1OctetStringParser
+ : IAsn1Convertible
+ {
+ Stream GetOctetStream();
+ }
+}
diff --git a/Crypto/src/asn1/ASN1SequenceParser.cs b/Crypto/src/asn1/ASN1SequenceParser.cs
new file mode 100644
index 000000000..9e88ac788
--- /dev/null
+++ b/Crypto/src/asn1/ASN1SequenceParser.cs
@@ -0,0 +1,8 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public interface Asn1SequenceParser
+ : IAsn1Convertible
+ {
+ IAsn1Convertible ReadObject();
+ }
+}
diff --git a/Crypto/src/asn1/ASN1SetParser.cs b/Crypto/src/asn1/ASN1SetParser.cs
new file mode 100644
index 000000000..d1b9c64e2
--- /dev/null
+++ b/Crypto/src/asn1/ASN1SetParser.cs
@@ -0,0 +1,8 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public interface Asn1SetParser
+ : IAsn1Convertible
+ {
+ IAsn1Convertible ReadObject();
+ }
+}
diff --git a/Crypto/src/asn1/ASN1StreamParser.cs b/Crypto/src/asn1/ASN1StreamParser.cs
new file mode 100644
index 000000000..6c256db53
--- /dev/null
+++ b/Crypto/src/asn1/ASN1StreamParser.cs
@@ -0,0 +1,232 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class Asn1StreamParser
+ {
+ private readonly Stream _in;
+ private readonly int _limit;
+
+ public Asn1StreamParser(
+ Stream inStream)
+ : this(inStream, Asn1InputStream.FindLimit(inStream))
+ {
+ }
+
+ public Asn1StreamParser(
+ Stream inStream,
+ int limit)
+ {
+ if (!inStream.CanRead)
+ throw new ArgumentException("Expected stream to be readable", "inStream");
+
+ this._in = inStream;
+ this._limit = limit;
+ }
+
+ public Asn1StreamParser(
+ byte[] encoding)
+ : this(new MemoryStream(encoding, false), encoding.Length)
+ {
+ }
+
+ internal IAsn1Convertible ReadIndef(int tagValue)
+ {
+ // Note: INDEF => CONSTRUCTED
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagValue)
+ {
+ case Asn1Tags.External:
+ return new DerExternalParser(this);
+ case Asn1Tags.OctetString:
+ return new BerOctetStringParser(this);
+ case Asn1Tags.Sequence:
+ return new BerSequenceParser(this);
+ case Asn1Tags.Set:
+ return new BerSetParser(this);
+ default:
+ throw new Asn1Exception("unknown BER object encountered: 0x" + tagValue.ToString("X"));
+ }
+ }
+
+ internal IAsn1Convertible ReadImplicit(bool constructed, int tag)
+ {
+ if (_in is IndefiniteLengthInputStream)
+ {
+ if (!constructed)
+ throw new IOException("indefinite length primitive encoding encountered");
+
+ return ReadIndef(tag);
+ }
+
+ if (constructed)
+ {
+ switch (tag)
+ {
+ case Asn1Tags.Set:
+ return new DerSetParser(this);
+ case Asn1Tags.Sequence:
+ return new DerSequenceParser(this);
+ case Asn1Tags.OctetString:
+ return new BerOctetStringParser(this);
+ }
+ }
+ else
+ {
+ switch (tag)
+ {
+ case Asn1Tags.Set:
+ throw new Asn1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
+ case Asn1Tags.Sequence:
+ throw new Asn1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
+ case Asn1Tags.OctetString:
+ return new DerOctetStringParser((DefiniteLengthInputStream)_in);
+ }
+ }
+
+ throw new Asn1Exception("implicit tagging not implemented");
+ }
+
+ internal Asn1Object ReadTaggedObject(bool constructed, int tag)
+ {
+ if (!constructed)
+ {
+ // Note: !CONSTRUCTED => IMPLICIT
+ DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
+ return new DerTaggedObject(false, tag, new DerOctetString(defIn.ToArray()));
+ }
+
+ Asn1EncodableVector v = ReadVector();
+
+ if (_in is IndefiniteLengthInputStream)
+ {
+ return v.Count == 1
+ ? new BerTaggedObject(true, tag, v[0])
+ : new BerTaggedObject(false, tag, BerSequence.FromVector(v));
+ }
+
+ return v.Count == 1
+ ? new DerTaggedObject(true, tag, v[0])
+ : new DerTaggedObject(false, tag, DerSequence.FromVector(v));
+ }
+
+ public virtual IAsn1Convertible ReadObject()
+ {
+ int tag = _in.ReadByte();
+ if (tag == -1)
+ return null;
+
+ // turn of looking for "00" while we resolve the tag
+ Set00Check(false);
+
+ //
+ // calculate tag number
+ //
+ int tagNo = Asn1InputStream.ReadTagNumber(_in, tag);
+
+ bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+ //
+ // calculate length
+ //
+ int length = Asn1InputStream.ReadLength(_in, _limit);
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ throw new IOException("indefinite length primitive encoding encountered");
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
+ Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit);
+
+ if ((tag & Asn1Tags.Application) != 0)
+ {
+ return new BerApplicationSpecificParser(tagNo, sp);
+ }
+
+ if ((tag & Asn1Tags.Tagged) != 0)
+ {
+ return new BerTaggedObjectParser(true, tagNo, sp);
+ }
+
+ return sp.ReadIndef(tagNo);
+ }
+ else
+ {
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+ if ((tag & Asn1Tags.Application) != 0)
+ {
+ return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
+ }
+
+ if ((tag & Asn1Tags.Tagged) != 0)
+ {
+ return new BerTaggedObjectParser(isConstructed, tagNo, new Asn1StreamParser(defIn));
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BitString)
+ switch (tagNo)
+ {
+ case Asn1Tags.OctetString:
+ //
+ // yes, people actually do this...
+ //
+ return new BerOctetStringParser(new Asn1StreamParser(defIn));
+ case Asn1Tags.Sequence:
+ return new DerSequenceParser(new Asn1StreamParser(defIn));
+ case Asn1Tags.Set:
+ return new DerSetParser(new Asn1StreamParser(defIn));
+ case Asn1Tags.External:
+ return new DerExternalParser(new Asn1StreamParser(defIn));
+ default:
+ // TODO Add DerUnknownTagParser class?
+ return new DerUnknownTag(true, tagNo, defIn.ToArray());
+ }
+ }
+
+ // Some primitive encodings can be handled by parsers too...
+ switch (tagNo)
+ {
+ case Asn1Tags.OctetString:
+ return new DerOctetStringParser(defIn);
+ }
+
+ try
+ {
+ return Asn1InputStream.CreatePrimitiveDerObject(tagNo, defIn.ToArray());
+ }
+ catch (ArgumentException e)
+ {
+ throw new Asn1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ private void Set00Check(
+ bool enabled)
+ {
+ if (_in is IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream) _in).SetEofOn00(enabled);
+ }
+ }
+
+ internal Asn1EncodableVector ReadVector()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ IAsn1Convertible obj;
+ while ((obj = ReadObject()) != null)
+ {
+ v.Add(obj.ToAsn1Object());
+ }
+
+ return v;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ASN1TaggedObjectParser.cs b/Crypto/src/asn1/ASN1TaggedObjectParser.cs
new file mode 100644
index 000000000..32327a269
--- /dev/null
+++ b/Crypto/src/asn1/ASN1TaggedObjectParser.cs
@@ -0,0 +1,10 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public interface Asn1TaggedObjectParser
+ : IAsn1Convertible
+ {
+ int TagNo { get; }
+
+ IAsn1Convertible GetObjectParser(int tag, bool isExplicit);
+ }
+}
diff --git a/Crypto/src/asn1/Asn1Encodable.cs b/Crypto/src/asn1/Asn1Encodable.cs
new file mode 100644
index 000000000..e3dd9a14c
--- /dev/null
+++ b/Crypto/src/asn1/Asn1Encodable.cs
@@ -0,0 +1,78 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public abstract class Asn1Encodable
+ : IAsn1Convertible
+ {
+ public const string Der = "DER";
+ public const string Ber = "BER";
+
+ public byte[] GetEncoded()
+ {
+ MemoryStream bOut = new MemoryStream();
+ Asn1OutputStream aOut = new Asn1OutputStream(bOut);
+
+ aOut.WriteObject(this);
+
+ return bOut.ToArray();
+ }
+
+ public byte[] GetEncoded(
+ string encoding)
+ {
+ if (encoding.Equals(Der))
+ {
+ MemoryStream bOut = new MemoryStream();
+ DerOutputStream dOut = new DerOutputStream(bOut);
+
+ dOut.WriteObject(this);
+
+ return bOut.ToArray();
+ }
+
+ return GetEncoded();
+ }
+
+ /**
+ * Return the DER encoding of the object, null if the DER encoding can not be made.
+ *
+ * @return a DER byte array, null otherwise.
+ */
+ public byte[] GetDerEncoded()
+ {
+ try
+ {
+ return GetEncoded(Der);
+ }
+ catch (IOException)
+ {
+ return null;
+ }
+ }
+
+ public sealed override int GetHashCode()
+ {
+ return ToAsn1Object().CallAsn1GetHashCode();
+ }
+
+ public sealed override bool Equals(
+ object obj)
+ {
+ if (obj == this)
+ return true;
+
+ IAsn1Convertible other = obj as IAsn1Convertible;
+
+ if (other == null)
+ return false;
+
+ Asn1Object o1 = ToAsn1Object();
+ Asn1Object o2 = other.ToAsn1Object();
+
+ return o1 == o2 || o1.CallAsn1Equals(o2);
+ }
+
+ public abstract Asn1Object ToAsn1Object();
+ }
+}
diff --git a/Crypto/src/asn1/Asn1EncodableVector.cs b/Crypto/src/asn1/Asn1EncodableVector.cs
new file mode 100644
index 000000000..49532fe57
--- /dev/null
+++ b/Crypto/src/asn1/Asn1EncodableVector.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class Asn1EncodableVector
+ : IEnumerable
+ {
+ private IList v = Platform.CreateArrayList();
+
+ public static Asn1EncodableVector FromEnumerable(
+ IEnumerable e)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ foreach (Asn1Encodable obj in e)
+ {
+ v.Add(obj);
+ }
+ return v;
+ }
+
+// public Asn1EncodableVector()
+// {
+// }
+
+ public Asn1EncodableVector(
+ params Asn1Encodable[] v)
+ {
+ Add(v);
+ }
+
+// public void Add(
+// Asn1Encodable obj)
+// {
+// v.Add(obj);
+// }
+
+ public void Add(
+ params Asn1Encodable[] objs)
+ {
+ foreach (Asn1Encodable obj in objs)
+ {
+ v.Add(obj);
+ }
+ }
+
+ public void AddOptional(
+ params Asn1Encodable[] objs)
+ {
+ if (objs != null)
+ {
+ foreach (Asn1Encodable obj in objs)
+ {
+ if (obj != null)
+ {
+ v.Add(obj);
+ }
+ }
+ }
+ }
+
+ public Asn1Encodable this[
+ int index]
+ {
+ get { return (Asn1Encodable) v[index]; }
+ }
+
+ [Obsolete("Use 'object[index]' syntax instead")]
+ public Asn1Encodable Get(
+ int index)
+ {
+ return this[index];
+ }
+
+ [Obsolete("Use 'Count' property instead")]
+ public int Size
+ {
+ get { return v.Count; }
+ }
+
+ public int Count
+ {
+ get { return v.Count; }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return v.GetEnumerator();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1Exception.cs b/Crypto/src/asn1/Asn1Exception.cs
new file mode 100644
index 000000000..dfc1641a4
--- /dev/null
+++ b/Crypto/src/asn1/Asn1Exception.cs
@@ -0,0 +1,27 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class Asn1Exception
+ : IOException
+ {
+ public Asn1Exception()
+ : base()
+ {
+ }
+
+ public Asn1Exception(
+ string message)
+ : base(message)
+ {
+ }
+
+ public Asn1Exception(
+ string message,
+ Exception exception)
+ : base(message, exception)
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1InputStream.cs b/Crypto/src/asn1/Asn1InputStream.cs
new file mode 100644
index 000000000..9a9761653
--- /dev/null
+++ b/Crypto/src/asn1/Asn1InputStream.cs
@@ -0,0 +1,339 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * a general purpose ASN.1 decoder - note: this class differs from the
+ * others in that it returns null after it has read the last object in
+ * the stream. If an ASN.1 Null is encountered a Der/BER Null object is
+ * returned.
+ */
+ public class Asn1InputStream
+ : FilterStream
+ {
+ private readonly int limit;
+
+ internal static int FindLimit(Stream input)
+ {
+ if (input is LimitedInputStream)
+ {
+ return ((LimitedInputStream)input).GetRemaining();
+ }
+ else if (input is MemoryStream)
+ {
+ MemoryStream mem = (MemoryStream)input;
+ return (int)(mem.Length - mem.Position);
+ }
+
+ return int.MaxValue;
+ }
+
+ public Asn1InputStream(
+ Stream inputStream)
+ : this(inputStream, FindLimit(inputStream))
+ {
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ */
+ public Asn1InputStream(
+ Stream inputStream,
+ int limit)
+ : base(inputStream)
+ {
+ this.limit = limit;
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ */
+ public Asn1InputStream(
+ byte[] input)
+ : this(new MemoryStream(input, false), input.Length)
+ {
+ }
+
+ /**
+ * build an object given its tag and the number of bytes to construct it from.
+ */
+ private Asn1Object BuildObject(
+ int tag,
+ int tagNo,
+ int length)
+ {
+ bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length);
+
+ if ((tag & Asn1Tags.Application) != 0)
+ {
+ return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
+ }
+
+ if ((tag & Asn1Tags.Tagged) != 0)
+ {
+ return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo);
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BitString)
+ switch (tagNo)
+ {
+ case Asn1Tags.OctetString:
+ //
+ // yes, people actually do this...
+ //
+ return new BerOctetString(BuildDerEncodableVector(defIn));
+ case Asn1Tags.Sequence:
+ return CreateDerSequence(defIn);
+ case Asn1Tags.Set:
+ return CreateDerSet(defIn);
+ case Asn1Tags.External:
+ return new DerExternal(BuildDerEncodableVector(defIn));
+ default:
+ return new DerUnknownTag(true, tagNo, defIn.ToArray());
+ }
+ }
+
+ return CreatePrimitiveDerObject(tagNo, defIn.ToArray());
+ }
+
+ internal Asn1EncodableVector BuildEncodableVector()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ Asn1Object o;
+ while ((o = ReadObject()) != null)
+ {
+ v.Add(o);
+ }
+
+ return v;
+ }
+
+ internal virtual Asn1EncodableVector BuildDerEncodableVector(
+ DefiniteLengthInputStream dIn)
+ {
+ return new Asn1InputStream(dIn).BuildEncodableVector();
+ }
+
+ internal virtual DerSequence CreateDerSequence(
+ DefiniteLengthInputStream dIn)
+ {
+ return DerSequence.FromVector(BuildDerEncodableVector(dIn));
+ }
+
+ internal virtual DerSet CreateDerSet(
+ DefiniteLengthInputStream dIn)
+ {
+ return DerSet.FromVector(BuildDerEncodableVector(dIn), false);
+ }
+
+ public Asn1Object ReadObject()
+ {
+ int tag = ReadByte();
+ if (tag <= 0)
+ {
+ if (tag == 0)
+ throw new IOException("unexpected end-of-contents marker");
+
+ return null;
+ }
+
+ //
+ // calculate tag number
+ //
+ int tagNo = ReadTagNumber(this.s, tag);
+
+ bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+ //
+ // calculate length
+ //
+ int length = ReadLength(this.s, limit);
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ throw new IOException("indefinite length primitive encoding encountered");
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit);
+ Asn1StreamParser sp = new Asn1StreamParser(indIn, limit);
+
+ if ((tag & Asn1Tags.Application) != 0)
+ {
+ return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object();
+ }
+
+ if ((tag & Asn1Tags.Tagged) != 0)
+ {
+ return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object();
+ }
+
+ // TODO There are other tags that may be constructed (e.g. BitString)
+ switch (tagNo)
+ {
+ case Asn1Tags.OctetString:
+ return new BerOctetStringParser(sp).ToAsn1Object();
+ case Asn1Tags.Sequence:
+ return new BerSequenceParser(sp).ToAsn1Object();
+ case Asn1Tags.Set:
+ return new BerSetParser(sp).ToAsn1Object();
+ case Asn1Tags.External:
+ return new DerExternalParser(sp).ToAsn1Object();
+ default:
+ throw new IOException("unknown BER object encountered");
+ }
+ }
+ else
+ {
+ try
+ {
+ return BuildObject(tag, tagNo, length);
+ }
+ catch (ArgumentException e)
+ {
+ throw new Asn1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ internal static int ReadTagNumber(
+ Stream s,
+ int tag)
+ {
+ int tagNo = tag & 0x1f;
+
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = s.ReadByte();
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new IOException("Corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = s.ReadByte();
+ }
+
+ if (b < 0)
+ throw new EndOfStreamException("EOF found inside tag value.");
+
+ tagNo |= (b & 0x7f);
+ }
+
+ return tagNo;
+ }
+
+ internal static int ReadLength(
+ Stream s,
+ int limit)
+ {
+ int length = s.ReadByte();
+ if (length < 0)
+ throw new EndOfStreamException("EOF found when length expected");
+
+ if (length == 0x80)
+ return -1; // indefinite-length encoding
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ throw new IOException("DER length more than 4 bytes: " + size);
+
+ length = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int next = s.ReadByte();
+
+ if (next < 0)
+ throw new EndOfStreamException("EOF found reading length");
+
+ length = (length << 8) + next;
+ }
+
+ if (length < 0)
+ throw new IOException("Corrupted stream - negative length found");
+
+ if (length >= limit) // after all we must have read at least 1 byte
+ throw new IOException("Corrupted stream - out of bounds length found");
+ }
+
+ return length;
+ }
+
+ internal static Asn1Object CreatePrimitiveDerObject(
+ int tagNo,
+ byte[] bytes)
+ {
+ switch (tagNo)
+ {
+ case Asn1Tags.BitString:
+ return DerBitString.FromAsn1Octets(bytes);
+ case Asn1Tags.BmpString:
+ return new DerBmpString(bytes);
+ case Asn1Tags.Boolean:
+ return new DerBoolean(bytes);
+ case Asn1Tags.Enumerated:
+ return new DerEnumerated(bytes);
+ case Asn1Tags.GeneralizedTime:
+ return new DerGeneralizedTime(bytes);
+ case Asn1Tags.GeneralString:
+ return new DerGeneralString(bytes);
+ case Asn1Tags.IA5String:
+ return new DerIA5String(bytes);
+ case Asn1Tags.Integer:
+ return new DerInteger(bytes);
+ case Asn1Tags.Null:
+ return DerNull.Instance; // actual content is ignored (enforce 0 length?)
+ case Asn1Tags.NumericString:
+ return new DerNumericString(bytes);
+ case Asn1Tags.ObjectIdentifier:
+ return new DerObjectIdentifier(bytes);
+ case Asn1Tags.OctetString:
+ return new DerOctetString(bytes);
+ case Asn1Tags.PrintableString:
+ return new DerPrintableString(bytes);
+ case Asn1Tags.T61String:
+ return new DerT61String(bytes);
+ case Asn1Tags.UniversalString:
+ return new DerUniversalString(bytes);
+ case Asn1Tags.UtcTime:
+ return new DerUtcTime(bytes);
+ case Asn1Tags.Utf8String:
+ return new DerUtf8String(bytes);
+ case Asn1Tags.VisibleString:
+ return new DerVisibleString(bytes);
+ default:
+ return new DerUnknownTag(false, tagNo, bytes);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1Null.cs b/Crypto/src/asn1/Asn1Null.cs
new file mode 100644
index 000000000..d54019f67
--- /dev/null
+++ b/Crypto/src/asn1/Asn1Null.cs
@@ -0,0 +1,18 @@
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * A Null object.
+ */
+ public abstract class Asn1Null
+ : Asn1Object
+ {
+ internal Asn1Null()
+ {
+ }
+
+ public override string ToString()
+ {
+ return "NULL";
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1Object.cs b/Crypto/src/asn1/Asn1Object.cs
new file mode 100644
index 000000000..08bd599c1
--- /dev/null
+++ b/Crypto/src/asn1/Asn1Object.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public abstract class Asn1Object
+ : Asn1Encodable
+ {
+ /// <summary>Create a base ASN.1 object from a byte array.</summary>
+ /// <param name="data">The byte array to parse.</param>
+ /// <returns>The base ASN.1 object represented by the byte array.</returns>
+ /// <exception cref="IOException">If there is a problem parsing the data.</exception>
+ public static Asn1Object FromByteArray(
+ byte[] data)
+ {
+ try
+ {
+ return new Asn1InputStream(data).ReadObject();
+ }
+ catch (InvalidCastException)
+ {
+ throw new IOException("cannot recognise object in stream");
+ }
+ }
+
+ /// <summary>Read a base ASN.1 object from a stream.</summary>
+ /// <param name="inStr">The stream to parse.</param>
+ /// <returns>The base ASN.1 object represented by the byte array.</returns>
+ /// <exception cref="IOException">If there is a problem parsing the data.</exception>
+ public static Asn1Object FromStream(
+ Stream inStr)
+ {
+ try
+ {
+ return new Asn1InputStream(inStr).ReadObject();
+ }
+ catch (InvalidCastException)
+ {
+ throw new IOException("cannot recognise object in stream");
+ }
+ }
+
+ public sealed override Asn1Object ToAsn1Object()
+ {
+ return this;
+ }
+
+ internal abstract void Encode(DerOutputStream derOut);
+
+ protected abstract bool Asn1Equals(Asn1Object asn1Object);
+ protected abstract int Asn1GetHashCode();
+
+ internal bool CallAsn1Equals(Asn1Object obj)
+ {
+ return Asn1Equals(obj);
+ }
+
+ internal int CallAsn1GetHashCode()
+ {
+ return Asn1GetHashCode();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1OctetString.cs b/Crypto/src/asn1/Asn1OctetString.cs
new file mode 100644
index 000000000..9c738a8f2
--- /dev/null
+++ b/Crypto/src/asn1/Asn1OctetString.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public abstract class Asn1OctetString
+ : Asn1Object, Asn1OctetStringParser
+ {
+ internal byte[] str;
+
+ /**
+ * return an Octet string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static Asn1OctetString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is Asn1OctetString)
+ {
+ return GetInstance(o);
+ }
+
+ return BerOctetString.FromSequence(Asn1Sequence.GetInstance(o));
+ }
+
+ /**
+ * return an Octet string from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static Asn1OctetString GetInstance(object obj)
+ {
+ if (obj == null || obj is Asn1OctetString)
+ {
+ return (Asn1OctetString)obj;
+ }
+
+ // TODO: this needs to be deleted in V2
+ if (obj is Asn1TaggedObject)
+ return GetInstance(((Asn1TaggedObject)obj).GetObject());
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ internal Asn1OctetString(
+ byte[] str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = str;
+ }
+
+ internal Asn1OctetString(
+ Asn1Encodable obj)
+ {
+ try
+ {
+ this.str = obj.GetEncoded(Asn1Encodable.Der);
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("Error processing object : " + e.ToString());
+ }
+ }
+
+ public Stream GetOctetStream()
+ {
+ return new MemoryStream(str, false);
+ }
+
+ public Asn1OctetStringParser Parser
+ {
+ get { return this; }
+ }
+
+ public virtual byte[] GetOctets()
+ {
+ return str;
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(GetOctets());
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerOctetString other = asn1Object as DerOctetString;
+
+ if (other == null)
+ return false;
+
+ return Arrays.AreEqual(GetOctets(), other.GetOctets());
+ }
+
+ public override string ToString()
+ {
+ return "#" + Hex.ToHexString(str);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1OutputStream.cs b/Crypto/src/asn1/Asn1OutputStream.cs
new file mode 100644
index 000000000..39c8b1e5e
--- /dev/null
+++ b/Crypto/src/asn1/Asn1OutputStream.cs
@@ -0,0 +1,35 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class Asn1OutputStream
+ : DerOutputStream
+ {
+ public Asn1OutputStream(Stream os) : base(os)
+ {
+ }
+
+ [Obsolete("Use version taking an Asn1Encodable arg instead")]
+ public override void WriteObject(
+ object obj)
+ {
+ if (obj == null)
+ {
+ WriteNull();
+ }
+ else if (obj is Asn1Object)
+ {
+ ((Asn1Object)obj).Encode(this);
+ }
+ else if (obj is Asn1Encodable)
+ {
+ ((Asn1Encodable)obj).ToAsn1Object().Encode(this);
+ }
+ else
+ {
+ throw new IOException("object not Asn1Encodable");
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1ParsingException.cs b/Crypto/src/asn1/Asn1ParsingException.cs
new file mode 100644
index 000000000..8827d8329
--- /dev/null
+++ b/Crypto/src/asn1/Asn1ParsingException.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class Asn1ParsingException
+ : InvalidOperationException
+ {
+ public Asn1ParsingException()
+ : base()
+ {
+ }
+
+ public Asn1ParsingException(
+ string message)
+ : base(message)
+ {
+ }
+
+ public Asn1ParsingException(
+ string message,
+ Exception exception)
+ : base(message, exception)
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1Sequence.cs b/Crypto/src/asn1/Asn1Sequence.cs
new file mode 100644
index 000000000..3131ead84
--- /dev/null
+++ b/Crypto/src/asn1/Asn1Sequence.cs
@@ -0,0 +1,255 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public abstract class Asn1Sequence
+ : Asn1Object, IEnumerable
+ {
+ private readonly IList seq;
+
+ /**
+ * return an Asn1Sequence from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static Asn1Sequence GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Asn1Sequence)
+ {
+ return (Asn1Sequence)obj;
+ }
+ else if (obj is byte[])
+ {
+ try
+ {
+ return Asn1Sequence.GetInstance(Asn1Object.FromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new ArgumentException("Failed to construct sequence from byte[]", e);
+ }
+ }
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * Return an ASN1 sequence from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * sequence - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sequences you really <b>should</b>
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @param explicitly true if the object is meant to be explicitly tagged,
+ * false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static Asn1Sequence GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ Asn1Object inner = obj.GetObject();
+
+ if (explicitly)
+ {
+ if (!obj.IsExplicit())
+ throw new ArgumentException("object implicit - explicit expected.");
+
+ return (Asn1Sequence) inner;
+ }
+
+ //
+ // constructed object which appears to be explicitly tagged
+ // when it should be implicit means we have to add the
+ // surrounding sequence.
+ //
+ if (obj.IsExplicit())
+ {
+ if (obj is BerTaggedObject)
+ {
+ return new BerSequence(inner);
+ }
+
+ return new DerSequence(inner);
+ }
+
+ if (inner is Asn1Sequence)
+ {
+ return (Asn1Sequence) inner;
+ }
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ protected internal Asn1Sequence(
+ int capacity)
+ {
+ seq = Platform.CreateArrayList(capacity);
+ }
+
+ public virtual IEnumerator GetEnumerator()
+ {
+ return seq.GetEnumerator();
+ }
+
+ [Obsolete("Use GetEnumerator() instead")]
+ public IEnumerator GetObjects()
+ {
+ return GetEnumerator();
+ }
+
+ private class Asn1SequenceParserImpl
+ : Asn1SequenceParser
+ {
+ private readonly Asn1Sequence outer;
+ private readonly int max;
+ private int index;
+
+ public Asn1SequenceParserImpl(
+ Asn1Sequence outer)
+ {
+ this.outer = outer;
+ this.max = outer.Count;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ if (index == max)
+ return null;
+
+ Asn1Encodable obj = outer[index++];
+
+ if (obj is Asn1Sequence)
+ return ((Asn1Sequence)obj).Parser;
+
+ if (obj is Asn1Set)
+ return ((Asn1Set)obj).Parser;
+
+ // NB: Asn1OctetString implements Asn1OctetStringParser directly
+// if (obj is Asn1OctetString)
+// return ((Asn1OctetString)obj).Parser;
+
+ return obj;
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ return outer;
+ }
+ }
+
+ public virtual Asn1SequenceParser Parser
+ {
+ get { return new Asn1SequenceParserImpl(this); }
+ }
+
+ /**
+ * return the object at the sequence position indicated by index.
+ *
+ * @param index the sequence number (starting at zero) of the object
+ * @return the object at the sequence position indicated by index.
+ */
+ public virtual Asn1Encodable this[int index]
+ {
+ get { return (Asn1Encodable) seq[index]; }
+ }
+
+ [Obsolete("Use 'object[index]' syntax instead")]
+ public Asn1Encodable GetObjectAt(
+ int index)
+ {
+ return this[index];
+ }
+
+ [Obsolete("Use 'Count' property instead")]
+ public int Size
+ {
+ get { return Count; }
+ }
+
+ public virtual int Count
+ {
+ get { return seq.Count; }
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ int hc = Count;
+
+ foreach (object o in this)
+ {
+ hc *= 17;
+ if (o == null)
+ {
+ hc ^= DerNull.Instance.GetHashCode();
+ }
+ else
+ {
+ hc ^= o.GetHashCode();
+ }
+ }
+
+ return hc;
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ Asn1Sequence other = asn1Object as Asn1Sequence;
+
+ if (other == null)
+ return false;
+
+ if (Count != other.Count)
+ return false;
+
+ IEnumerator s1 = GetEnumerator();
+ IEnumerator s2 = other.GetEnumerator();
+
+ while (s1.MoveNext() && s2.MoveNext())
+ {
+ Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
+ Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
+
+ if (!o1.Equals(o2))
+ return false;
+ }
+
+ return true;
+ }
+
+ private Asn1Encodable GetCurrent(IEnumerator e)
+ {
+ Asn1Encodable encObj = (Asn1Encodable)e.Current;
+
+ // unfortunately null was allowed as a substitute for DER null
+ if (encObj == null)
+ return DerNull.Instance;
+
+ return encObj;
+ }
+
+ protected internal void AddObject(
+ Asn1Encodable obj)
+ {
+ seq.Add(obj);
+ }
+
+ public override string ToString()
+ {
+ return CollectionUtilities.ToString(seq);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1Set.cs b/Crypto/src/asn1/Asn1Set.cs
new file mode 100644
index 000000000..f5b66495c
--- /dev/null
+++ b/Crypto/src/asn1/Asn1Set.cs
@@ -0,0 +1,326 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1
+{
+ abstract public class Asn1Set
+ : Asn1Object, IEnumerable
+ {
+ private readonly IList _set;
+
+ /**
+ * return an ASN1Set from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static Asn1Set GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Asn1Set)
+ {
+ return (Asn1Set)obj;
+ }
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * Return an ASN1 set from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * set - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sets you really <b>should</b>
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @param explicitly true if the object is meant to be explicitly tagged
+ * false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static Asn1Set GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ Asn1Object inner = obj.GetObject();
+
+ if (explicitly)
+ {
+ if (!obj.IsExplicit())
+ throw new ArgumentException("object implicit - explicit expected.");
+
+ return (Asn1Set) inner;
+ }
+
+ //
+ // constructed object which appears to be explicitly tagged
+ // and it's really implicit means we have to add the
+ // surrounding sequence.
+ //
+ if (obj.IsExplicit())
+ {
+ return new DerSet(inner);
+ }
+
+ if (inner is Asn1Set)
+ {
+ return (Asn1Set) inner;
+ }
+
+ //
+ // in this case the parser returns a sequence, convert it
+ // into a set.
+ //
+ if (inner is Asn1Sequence)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ Asn1Sequence s = (Asn1Sequence) inner;
+
+ foreach (Asn1Encodable ae in s)
+ {
+ v.Add(ae);
+ }
+
+ // TODO Should be able to construct set directly from sequence?
+ return new DerSet(v, false);
+ }
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ protected internal Asn1Set(
+ int capacity)
+ {
+ _set = Platform.CreateArrayList(capacity);
+ }
+
+ public virtual IEnumerator GetEnumerator()
+ {
+ return _set.GetEnumerator();
+ }
+
+ [Obsolete("Use GetEnumerator() instead")]
+ public IEnumerator GetObjects()
+ {
+ return GetEnumerator();
+ }
+
+ /**
+ * return the object at the set position indicated by index.
+ *
+ * @param index the set number (starting at zero) of the object
+ * @return the object at the set position indicated by index.
+ */
+ public virtual Asn1Encodable this[int index]
+ {
+ get { return (Asn1Encodable) _set[index]; }
+ }
+
+ [Obsolete("Use 'object[index]' syntax instead")]
+ public Asn1Encodable GetObjectAt(
+ int index)
+ {
+ return this[index];
+ }
+
+ [Obsolete("Use 'Count' property instead")]
+ public int Size
+ {
+ get { return Count; }
+ }
+
+ public virtual int Count
+ {
+ get { return _set.Count; }
+ }
+
+ public virtual Asn1Encodable[] ToArray()
+ {
+ Asn1Encodable[] values = new Asn1Encodable[this.Count];
+ for (int i = 0; i < this.Count; ++i)
+ {
+ values[i] = this[i];
+ }
+ return values;
+ }
+
+ private class Asn1SetParserImpl
+ : Asn1SetParser
+ {
+ private readonly Asn1Set outer;
+ private readonly int max;
+ private int index;
+
+ public Asn1SetParserImpl(
+ Asn1Set outer)
+ {
+ this.outer = outer;
+ this.max = outer.Count;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ if (index == max)
+ return null;
+
+ Asn1Encodable obj = outer[index++];
+ if (obj is Asn1Sequence)
+ return ((Asn1Sequence)obj).Parser;
+
+ if (obj is Asn1Set)
+ return ((Asn1Set)obj).Parser;
+
+ // NB: Asn1OctetString implements Asn1OctetStringParser directly
+// if (obj is Asn1OctetString)
+// return ((Asn1OctetString)obj).Parser;
+
+ return obj;
+ }
+
+ public virtual Asn1Object ToAsn1Object()
+ {
+ return outer;
+ }
+ }
+
+ public Asn1SetParser Parser
+ {
+ get { return new Asn1SetParserImpl(this); }
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ int hc = Count;
+
+ foreach (object o in this)
+ {
+ hc *= 17;
+ if (o == null)
+ {
+ hc ^= DerNull.Instance.GetHashCode();
+ }
+ else
+ {
+ hc ^= o.GetHashCode();
+ }
+ }
+
+ return hc;
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ Asn1Set other = asn1Object as Asn1Set;
+
+ if (other == null)
+ return false;
+
+ if (Count != other.Count)
+ {
+ return false;
+ }
+
+ IEnumerator s1 = GetEnumerator();
+ IEnumerator s2 = other.GetEnumerator();
+
+ while (s1.MoveNext() && s2.MoveNext())
+ {
+ Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
+ Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
+
+ if (!o1.Equals(o2))
+ return false;
+ }
+
+ return true;
+ }
+
+ private Asn1Encodable GetCurrent(IEnumerator e)
+ {
+ Asn1Encodable encObj = (Asn1Encodable)e.Current;
+
+ // unfortunately null was allowed as a substitute for DER null
+ if (encObj == null)
+ return DerNull.Instance;
+
+ return encObj;
+ }
+
+ /**
+ * return true if a <= b (arrays are assumed padded with zeros).
+ */
+ private bool LessThanOrEqual(
+ byte[] a,
+ byte[] b)
+ {
+ int len = System.Math.Min(a.Length, b.Length);
+ for (int i = 0; i != len; ++i)
+ {
+ if (a[i] != b[i])
+ {
+ return a[i] < b[i];
+ }
+ }
+ return len == a.Length;
+ }
+
+ protected internal void Sort()
+ {
+ if (_set.Count > 1)
+ {
+ bool swapped = true;
+ int lastSwap = _set.Count - 1;
+
+ while (swapped)
+ {
+ int index = 0;
+ int swapIndex = 0;
+ byte[] a = ((Asn1Encodable) _set[0]).GetEncoded();
+
+ swapped = false;
+
+ while (index != lastSwap)
+ {
+ byte[] b = ((Asn1Encodable) _set[index + 1]).GetEncoded();
+
+ if (LessThanOrEqual(a, b))
+ {
+ a = b;
+ }
+ else
+ {
+ object o = _set[index];
+ _set[index] = _set[index + 1];
+ _set[index + 1] = o;
+
+ swapped = true;
+ swapIndex = index;
+ }
+
+ index++;
+ }
+
+ lastSwap = swapIndex;
+ }
+ }
+ }
+
+ protected internal void AddObject(
+ Asn1Encodable obj)
+ {
+ _set.Add(obj);
+ }
+
+ public override string ToString()
+ {
+ return CollectionUtilities.ToString(_set);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1TaggedObject.cs b/Crypto/src/asn1/Asn1TaggedObject.cs
new file mode 100644
index 000000000..2e480738a
--- /dev/null
+++ b/Crypto/src/asn1/Asn1TaggedObject.cs
@@ -0,0 +1,178 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+ public abstract class Asn1TaggedObject
+ : Asn1Object, Asn1TaggedObjectParser
+ {
+ internal int tagNo;
+// internal bool empty;
+ internal bool explicitly = true;
+ internal Asn1Encodable obj;
+
+ static public Asn1TaggedObject GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ if (explicitly)
+ {
+ return (Asn1TaggedObject) obj.GetObject();
+ }
+
+ throw new ArgumentException("implicitly tagged tagged object");
+ }
+
+ static public Asn1TaggedObject GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Asn1TaggedObject)
+ {
+ return (Asn1TaggedObject) obj;
+ }
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ protected Asn1TaggedObject(
+ int tagNo,
+ Asn1Encodable obj)
+ {
+ this.explicitly = true;
+ this.tagNo = tagNo;
+ this.obj = obj;
+ }
+
+ /**
+ * @param explicitly true if the object is explicitly tagged.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ protected Asn1TaggedObject(
+ bool explicitly,
+ int tagNo,
+ Asn1Encodable obj)
+ {
+ // IAsn1Choice marker interface 'insists' on explicit tagging
+ this.explicitly = explicitly || (obj is IAsn1Choice);
+ this.tagNo = tagNo;
+ this.obj = obj;
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ Asn1TaggedObject other = asn1Object as Asn1TaggedObject;
+
+ if (other == null)
+ return false;
+
+ return this.tagNo == other.tagNo
+// && this.empty == other.empty
+ && this.explicitly == other.explicitly // TODO Should this be part of equality?
+ && Platform.Equals(GetObject(), other.GetObject());
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ int code = tagNo.GetHashCode();
+
+ // TODO: actually this is wrong - the problem is that a re-encoded
+ // object may end up with a different hashCode due to implicit
+ // tagging. As implicit tagging is ambiguous if a sequence is involved
+ // it seems the only correct method for both equals and hashCode is to
+ // compare the encodings...
+// code ^= explicitly.GetHashCode();
+
+ if (obj != null)
+ {
+ code ^= obj.GetHashCode();
+ }
+
+ return code;
+ }
+
+ public int TagNo
+ {
+ get { return tagNo; }
+ }
+
+ /**
+ * return whether or not the object may be explicitly tagged.
+ * <p>
+ * Note: if the object has been read from an input stream, the only
+ * time you can be sure if isExplicit is returning the true state of
+ * affairs is if it returns false. An implicitly tagged object may appear
+ * to be explicitly tagged, so you need to understand the context under
+ * which the reading was done as well, see GetObject below.</p>
+ */
+ public bool IsExplicit()
+ {
+ return explicitly;
+ }
+
+ public bool IsEmpty()
+ {
+ return false; //empty;
+ }
+
+ /**
+ * return whatever was following the tag.
+ * <p>
+ * Note: tagged objects are generally context dependent if you're
+ * trying to extract a tagged object you should be going via the
+ * appropriate GetInstance method.</p>
+ */
+ public Asn1Object GetObject()
+ {
+ if (obj != null)
+ {
+ return obj.ToAsn1Object();
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the object held in this tagged object as a parser assuming it has
+ * the type of the passed in tag. If the object doesn't have a parser
+ * associated with it, the base object is returned.
+ */
+ public IAsn1Convertible GetObjectParser(
+ int tag,
+ bool isExplicit)
+ {
+ switch (tag)
+ {
+ case Asn1Tags.Set:
+ return Asn1Set.GetInstance(this, isExplicit).Parser;
+ case Asn1Tags.Sequence:
+ return Asn1Sequence.GetInstance(this, isExplicit).Parser;
+ case Asn1Tags.OctetString:
+ return Asn1OctetString.GetInstance(this, isExplicit).Parser;
+ }
+
+ if (isExplicit)
+ {
+ return GetObject();
+ }
+
+ throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
+ }
+
+ public override string ToString()
+ {
+ return "[" + tagNo + "]" + obj;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/Asn1Tags.cs b/Crypto/src/asn1/Asn1Tags.cs
new file mode 100644
index 000000000..32ac6bc6c
--- /dev/null
+++ b/Crypto/src/asn1/Asn1Tags.cs
@@ -0,0 +1,36 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class Asn1Tags
+ {
+ public const int Boolean = 0x01;
+ public const int Integer = 0x02;
+ public const int BitString = 0x03;
+ public const int OctetString = 0x04;
+ public const int Null = 0x05;
+ public const int ObjectIdentifier = 0x06;
+ public const int External = 0x08;
+ public const int Enumerated = 0x0a;
+ public const int Sequence = 0x10;
+ public const int SequenceOf = 0x10; // for completeness
+ public const int Set = 0x11;
+ public const int SetOf = 0x11; // for completeness
+
+ public const int NumericString = 0x12;
+ public const int PrintableString = 0x13;
+ public const int T61String = 0x14;
+ public const int VideotexString = 0x15;
+ public const int IA5String = 0x16;
+ public const int UtcTime = 0x17;
+ public const int GeneralizedTime = 0x18;
+ public const int GraphicString = 0x19;
+ public const int VisibleString = 0x1a;
+ public const int GeneralString = 0x1b;
+ public const int UniversalString = 0x1c;
+ public const int BmpString = 0x1e;
+ public const int Utf8String = 0x0c;
+
+ public const int Constructed = 0x20;
+ public const int Application = 0x40;
+ public const int Tagged = 0x80;
+ }
+}
diff --git a/Crypto/src/asn1/BERGenerator.cs b/Crypto/src/asn1/BERGenerator.cs
new file mode 100644
index 000000000..271572c02
--- /dev/null
+++ b/Crypto/src/asn1/BERGenerator.cs
@@ -0,0 +1,102 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerGenerator
+ : Asn1Generator
+ {
+ private bool _tagged = false;
+ private bool _isExplicit;
+ private int _tagNo;
+
+ protected BerGenerator(
+ Stream outStream)
+ : base(outStream)
+ {
+ }
+
+ public BerGenerator(
+ Stream outStream,
+ int tagNo,
+ bool isExplicit)
+ : base(outStream)
+ {
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ public override void AddObject(
+ Asn1Encodable obj)
+ {
+ new BerOutputStream(Out).WriteObject(obj);
+ }
+
+ public override Stream GetRawOutputStream()
+ {
+ return Out;
+ }
+
+ public override void Close()
+ {
+ WriteBerEnd();
+ }
+
+ private void WriteHdr(
+ int tag)
+ {
+ Out.WriteByte((byte) tag);
+ Out.WriteByte(0x80);
+ }
+
+ protected void WriteBerHeader(
+ int tag)
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | Asn1Tags.Tagged;
+
+ if (_isExplicit)
+ {
+ WriteHdr(tagNum | Asn1Tags.Constructed);
+ WriteHdr(tag);
+ }
+ else
+ {
+ if ((tag & Asn1Tags.Constructed) != 0)
+ {
+ WriteHdr(tagNum | Asn1Tags.Constructed);
+ }
+ else
+ {
+ WriteHdr(tagNum);
+ }
+ }
+ }
+ else
+ {
+ WriteHdr(tag);
+ }
+ }
+
+ protected void WriteBerBody(
+ Stream contentStream)
+ {
+ Streams.PipeAll(contentStream, Out);
+ }
+
+ protected void WriteBerEnd()
+ {
+ Out.WriteByte(0x00);
+ Out.WriteByte(0x00);
+
+ if (_tagged && _isExplicit) // write extra end for tag header
+ {
+ Out.WriteByte(0x00);
+ Out.WriteByte(0x00);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BEROctetStringGenerator.cs b/Crypto/src/asn1/BEROctetStringGenerator.cs
new file mode 100644
index 000000000..644060765
--- /dev/null
+++ b/Crypto/src/asn1/BEROctetStringGenerator.cs
@@ -0,0 +1,121 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerOctetStringGenerator
+ : BerGenerator
+ {
+ public BerOctetStringGenerator(Stream outStream)
+ : base(outStream)
+ {
+ WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+ }
+
+ public BerOctetStringGenerator(
+ Stream outStream,
+ int tagNo,
+ bool isExplicit)
+ : base(outStream, tagNo, isExplicit)
+ {
+ WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+ }
+
+ public Stream GetOctetOutputStream()
+ {
+ return GetOctetOutputStream(new byte[1000]); // limit for CER encoding.
+ }
+
+ public Stream GetOctetOutputStream(
+ int bufSize)
+ {
+ return bufSize < 1
+ ? GetOctetOutputStream()
+ : GetOctetOutputStream(new byte[bufSize]);
+ }
+
+ public Stream GetOctetOutputStream(
+ byte[] buf)
+ {
+ return new BufferedBerOctetStream(this, buf);
+ }
+
+ private class BufferedBerOctetStream
+ : BaseOutputStream
+ {
+ private byte[] _buf;
+ private int _off;
+ private readonly BerOctetStringGenerator _gen;
+ private readonly DerOutputStream _derOut;
+
+ internal BufferedBerOctetStream(
+ BerOctetStringGenerator gen,
+ byte[] buf)
+ {
+ _gen = gen;
+ _buf = buf;
+ _off = 0;
+ _derOut = new DerOutputStream(_gen.Out);
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ _buf[_off++] = b;
+
+ if (_off == _buf.Length)
+ {
+ DerOctetString.Encode(_derOut, _buf, 0, _off);
+ _off = 0;
+ }
+ }
+
+ public override void Write(
+ byte[] buf,
+ int offset,
+ int len)
+ {
+ while (len > 0)
+ {
+ int numToCopy = System.Math.Min(len, _buf.Length - _off);
+
+ if (numToCopy == _buf.Length)
+ {
+ DerOctetString.Encode(_derOut, buf, offset, numToCopy);
+ }
+ else
+ {
+ Array.Copy(buf, offset, _buf, _off, numToCopy);
+
+ _off += numToCopy;
+ if (_off < _buf.Length)
+ break;
+
+ DerOctetString.Encode(_derOut, _buf, 0, _off);
+ _off = 0;
+ }
+
+ offset += numToCopy;
+ len -= numToCopy;
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_off != 0)
+ {
+ DerOctetString.Encode(_derOut, _buf, 0, _off);
+ }
+
+ _gen.WriteBerEnd();
+ }
+
+ base.Dispose(disposing);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BEROctetStringParser.cs b/Crypto/src/asn1/BEROctetStringParser.cs
new file mode 100644
index 000000000..3bfd2a98d
--- /dev/null
+++ b/Crypto/src/asn1/BEROctetStringParser.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerOctetStringParser
+ : Asn1OctetStringParser
+ {
+ private readonly Asn1StreamParser _parser;
+
+ internal BerOctetStringParser(
+ Asn1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ public Stream GetOctetStream()
+ {
+ return new ConstructedOctetStream(_parser);
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ try
+ {
+ return new BerOctetString(Streams.ReadAll(GetOctetStream()));
+ }
+ catch (IOException e)
+ {
+ throw new Asn1ParsingException("IOException converting stream to byte array: " + e.Message, e);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BERSequenceGenerator.cs b/Crypto/src/asn1/BERSequenceGenerator.cs
new file mode 100644
index 000000000..5ea2c9b82
--- /dev/null
+++ b/Crypto/src/asn1/BERSequenceGenerator.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerSequenceGenerator
+ : BerGenerator
+ {
+ public BerSequenceGenerator(
+ Stream outStream)
+ : base(outStream)
+ {
+ WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence);
+ }
+
+ public BerSequenceGenerator(
+ Stream outStream,
+ int tagNo,
+ bool isExplicit)
+ : base(outStream, tagNo, isExplicit)
+ {
+ WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BERSequenceParser.cs b/Crypto/src/asn1/BERSequenceParser.cs
new file mode 100644
index 000000000..8474b8d24
--- /dev/null
+++ b/Crypto/src/asn1/BERSequenceParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerSequenceParser
+ : Asn1SequenceParser
+ {
+ private readonly Asn1StreamParser _parser;
+
+ internal BerSequenceParser(
+ Asn1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ return _parser.ReadObject();
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ return new BerSequence(_parser.ReadVector());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BERSetGenerator.cs b/Crypto/src/asn1/BERSetGenerator.cs
new file mode 100644
index 000000000..72b1f903a
--- /dev/null
+++ b/Crypto/src/asn1/BERSetGenerator.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerSetGenerator
+ : BerGenerator
+ {
+ public BerSetGenerator(
+ Stream outStream)
+ : base(outStream)
+ {
+ WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set);
+ }
+
+ public BerSetGenerator(
+ Stream outStream,
+ int tagNo,
+ bool isExplicit)
+ : base(outStream, tagNo, isExplicit)
+ {
+ WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BERSetParser.cs b/Crypto/src/asn1/BERSetParser.cs
new file mode 100644
index 000000000..aa9ccbc12
--- /dev/null
+++ b/Crypto/src/asn1/BERSetParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerSetParser
+ : Asn1SetParser
+ {
+ private readonly Asn1StreamParser _parser;
+
+ internal BerSetParser(
+ Asn1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ return _parser.ReadObject();
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ return new BerSet(_parser.ReadVector(), false);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BERTaggedObjectParser.cs b/Crypto/src/asn1/BERTaggedObjectParser.cs
new file mode 100644
index 000000000..354437a6a
--- /dev/null
+++ b/Crypto/src/asn1/BERTaggedObjectParser.cs
@@ -0,0 +1,71 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerTaggedObjectParser
+ : Asn1TaggedObjectParser
+ {
+ private bool _constructed;
+ private int _tagNumber;
+ private Asn1StreamParser _parser;
+
+ [Obsolete]
+ internal BerTaggedObjectParser(
+ int baseTag,
+ int tagNumber,
+ Stream contentStream)
+ : this((baseTag & Asn1Tags.Constructed) != 0, tagNumber, new Asn1StreamParser(contentStream))
+ {
+ }
+
+ internal BerTaggedObjectParser(
+ bool constructed,
+ int tagNumber,
+ Asn1StreamParser parser)
+ {
+ _constructed = constructed;
+ _tagNumber = tagNumber;
+ _parser = parser;
+ }
+
+ public bool IsConstructed
+ {
+ get { return _constructed; }
+ }
+
+ public int TagNo
+ {
+ get { return _tagNumber; }
+ }
+
+ public IAsn1Convertible GetObjectParser(
+ int tag,
+ bool isExplicit)
+ {
+ if (isExplicit)
+ {
+ if (!_constructed)
+ throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
+
+ return _parser.ReadObject();
+ }
+
+ return _parser.ReadImplicit(_constructed, tag);
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ try
+ {
+ return _parser.ReadTaggedObject(_constructed, _tagNumber);
+ }
+ catch (IOException e)
+ {
+ throw new Asn1ParsingException(e.Message);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerApplicationSpecific.cs b/Crypto/src/asn1/BerApplicationSpecific.cs
new file mode 100644
index 000000000..65fbecbe1
--- /dev/null
+++ b/Crypto/src/asn1/BerApplicationSpecific.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerApplicationSpecific
+ : DerApplicationSpecific
+ {
+ public BerApplicationSpecific(
+ int tagNo,
+ Asn1EncodableVector vec)
+ : base(tagNo, vec)
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerApplicationSpecificParser.cs b/Crypto/src/asn1/BerApplicationSpecificParser.cs
new file mode 100644
index 000000000..7d2c4b3e8
--- /dev/null
+++ b/Crypto/src/asn1/BerApplicationSpecificParser.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerApplicationSpecificParser
+ : IAsn1ApplicationSpecificParser
+ {
+ private readonly int tag;
+ private readonly Asn1StreamParser parser;
+
+ internal BerApplicationSpecificParser(
+ int tag,
+ Asn1StreamParser parser)
+ {
+ this.tag = tag;
+ this.parser = parser;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ return parser.ReadObject();
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ return new BerApplicationSpecific(tag, parser.ReadVector());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerNull.cs b/Crypto/src/asn1/BerNull.cs
new file mode 100644
index 000000000..0751bbac3
--- /dev/null
+++ b/Crypto/src/asn1/BerNull.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * A BER Null object.
+ */
+ public class BerNull
+ : DerNull
+ {
+ public static new readonly BerNull Instance = new BerNull(0);
+
+ [Obsolete("Use static Instance object")]
+ public BerNull()
+ {
+ }
+
+ private BerNull(int dummy) : base(dummy)
+ {
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+ {
+ derOut.WriteByte(Asn1Tags.Null);
+ }
+ else
+ {
+ base.Encode(derOut);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerOctetString.cs b/Crypto/src/asn1/BerOctetString.cs
new file mode 100644
index 000000000..a7c8ad33e
--- /dev/null
+++ b/Crypto/src/asn1/BerOctetString.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerOctetString
+ : DerOctetString, IEnumerable
+ {
+ public static BerOctetString FromSequence(Asn1Sequence seq)
+ {
+ IList v = Platform.CreateArrayList();
+
+ foreach (Asn1Encodable obj in seq)
+ {
+ v.Add(obj);
+ }
+
+ return new BerOctetString(v);
+ }
+
+ private const int MaxLength = 1000;
+
+ /**
+ * convert a vector of octet strings into a single byte string
+ */
+ private static byte[] ToBytes(
+ IEnumerable octs)
+ {
+ MemoryStream bOut = new MemoryStream();
+ foreach (DerOctetString o in octs)
+ {
+ byte[] octets = o.GetOctets();
+ bOut.Write(octets, 0, octets.Length);
+ }
+ return bOut.ToArray();
+ }
+
+ private readonly IEnumerable octs;
+
+ /// <param name="str">The octets making up the octet string.</param>
+ public BerOctetString(
+ byte[] str)
+ : base(str)
+ {
+ }
+
+ public BerOctetString(
+ IEnumerable octets)
+ : base(ToBytes(octets))
+ {
+ this.octs = octets;
+ }
+
+ public BerOctetString(
+ Asn1Object obj)
+ : base(obj)
+ {
+ }
+
+ public BerOctetString(
+ Asn1Encodable obj)
+ : base(obj.ToAsn1Object())
+ {
+ }
+
+ public override byte[] GetOctets()
+ {
+ return str;
+ }
+
+ /**
+ * return the DER octets that make up this string.
+ */
+ public IEnumerator GetEnumerator()
+ {
+ if (octs == null)
+ {
+ return GenerateOcts().GetEnumerator();
+ }
+
+ return octs.GetEnumerator();
+ }
+
+ [Obsolete("Use GetEnumerator() instead")]
+ public IEnumerator GetObjects()
+ {
+ return GetEnumerator();
+ }
+
+ private IList GenerateOcts()
+ {
+ IList vec = Platform.CreateArrayList();
+ for (int i = 0; i < str.Length; i += MaxLength)
+ {
+ int end = System.Math.Min(str.Length, i + MaxLength);
+
+ byte[] nStr = new byte[end - i];
+
+ Array.Copy(str, i, nStr, 0, nStr.Length);
+
+ vec.Add(new DerOctetString(nStr));
+ }
+ return vec;
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+ {
+ derOut.WriteByte(Asn1Tags.Constructed | Asn1Tags.OctetString);
+
+ derOut.WriteByte(0x80);
+
+ //
+ // write out the octet array
+ //
+ foreach (DerOctetString oct in this)
+ {
+ derOut.WriteObject(oct);
+ }
+
+ derOut.WriteByte(0x00);
+ derOut.WriteByte(0x00);
+ }
+ else
+ {
+ base.Encode(derOut);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerOutputStream.cs b/Crypto/src/asn1/BerOutputStream.cs
new file mode 100644
index 000000000..b3ece10d3
--- /dev/null
+++ b/Crypto/src/asn1/BerOutputStream.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ // TODO Make Obsolete in favour of Asn1OutputStream?
+ public class BerOutputStream
+ : DerOutputStream
+ {
+ public BerOutputStream(Stream os) : base(os)
+ {
+ }
+
+ [Obsolete("Use version taking an Asn1Encodable arg instead")]
+ public override void WriteObject(
+ object obj)
+ {
+ if (obj == null)
+ {
+ WriteNull();
+ }
+ else if (obj is Asn1Object)
+ {
+ ((Asn1Object)obj).Encode(this);
+ }
+ else if (obj is Asn1Encodable)
+ {
+ ((Asn1Encodable)obj).ToAsn1Object().Encode(this);
+ }
+ else
+ {
+ throw new IOException("object not BerEncodable");
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerSequence.cs b/Crypto/src/asn1/BerSequence.cs
new file mode 100644
index 000000000..70b43fc79
--- /dev/null
+++ b/Crypto/src/asn1/BerSequence.cs
@@ -0,0 +1,69 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerSequence
+ : DerSequence
+ {
+ public static new readonly BerSequence Empty = new BerSequence();
+
+ public static new BerSequence FromVector(
+ Asn1EncodableVector v)
+ {
+ return v.Count < 1 ? Empty : new BerSequence(v);
+ }
+
+ /**
+ * create an empty sequence
+ */
+ public BerSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public BerSequence(
+ Asn1Encodable obj)
+ : base(obj)
+ {
+ }
+
+ public BerSequence(
+ params Asn1Encodable[] v)
+ : base(v)
+ {
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public BerSequence(
+ Asn1EncodableVector v)
+ : base(v)
+ {
+ }
+
+ /*
+ */
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+ {
+ derOut.WriteByte(Asn1Tags.Sequence | Asn1Tags.Constructed);
+ derOut.WriteByte(0x80);
+
+ foreach (Asn1Encodable o in this)
+ {
+ derOut.WriteObject(o);
+ }
+
+ derOut.WriteByte(0x00);
+ derOut.WriteByte(0x00);
+ }
+ else
+ {
+ base.Encode(derOut);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerSet.cs b/Crypto/src/asn1/BerSet.cs
new file mode 100644
index 000000000..a181e172d
--- /dev/null
+++ b/Crypto/src/asn1/BerSet.cs
@@ -0,0 +1,70 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class BerSet
+ : DerSet
+ {
+ public static new readonly BerSet Empty = new BerSet();
+
+ public static new BerSet FromVector(
+ Asn1EncodableVector v)
+ {
+ return v.Count < 1 ? Empty : new BerSet(v);
+ }
+
+ internal static new BerSet FromVector(
+ Asn1EncodableVector v,
+ bool needsSorting)
+ {
+ return v.Count < 1 ? Empty : new BerSet(v, needsSorting);
+ }
+
+ /**
+ * create an empty sequence
+ */
+ public BerSet()
+ {
+ }
+
+ /**
+ * create a set containing one object
+ */
+ public BerSet(Asn1Encodable obj) : base(obj)
+ {
+ }
+
+ /**
+ * create a set containing a vector of objects.
+ */
+ public BerSet(Asn1EncodableVector v) : base(v, false)
+ {
+ }
+
+ internal BerSet(Asn1EncodableVector v, bool needsSorting) : base(v, needsSorting)
+ {
+ }
+
+ /*
+ */
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+ {
+ derOut.WriteByte(Asn1Tags.Set | Asn1Tags.Constructed);
+ derOut.WriteByte(0x80);
+
+ foreach (Asn1Encodable o in this)
+ {
+ derOut.WriteObject(o);
+ }
+
+ derOut.WriteByte(0x00);
+ derOut.WriteByte(0x00);
+ }
+ else
+ {
+ base.Encode(derOut);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/BerTaggedObject.cs b/Crypto/src/asn1/BerTaggedObject.cs
new file mode 100644
index 000000000..228b136cb
--- /dev/null
+++ b/Crypto/src/asn1/BerTaggedObject.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * BER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+ public class BerTaggedObject
+ : DerTaggedObject
+ {
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BerTaggedObject(
+ int tagNo,
+ Asn1Encodable obj)
+ : base(tagNo, obj)
+ {
+ }
+
+ /**
+ * @param explicitly true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BerTaggedObject(
+ bool explicitly,
+ int tagNo,
+ Asn1Encodable obj)
+ : base(explicitly, tagNo, obj)
+ {
+ }
+
+ /**
+ * create an implicitly tagged object that contains a zero
+ * length sequence.
+ */
+ public BerTaggedObject(
+ int tagNo)
+ : base(false, tagNo, BerSequence.Empty)
+ {
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+ {
+ derOut.WriteTag((byte)(Asn1Tags.Constructed | Asn1Tags.Tagged), tagNo);
+ derOut.WriteByte(0x80);
+
+ if (!IsEmpty())
+ {
+ if (!explicitly)
+ {
+ IEnumerable eObj;
+ if (obj is Asn1OctetString)
+ {
+ if (obj is BerOctetString)
+ {
+ eObj = (BerOctetString) obj;
+ }
+ else
+ {
+ Asn1OctetString octs = (Asn1OctetString)obj;
+ eObj = new BerOctetString(octs.GetOctets());
+ }
+ }
+ else if (obj is Asn1Sequence)
+ {
+ eObj = (Asn1Sequence) obj;
+ }
+ else if (obj is Asn1Set)
+ {
+ eObj = (Asn1Set) obj;
+ }
+ else
+ {
+ throw Platform.CreateNotImplementedException(obj.GetType().Name);
+ }
+
+ foreach (Asn1Encodable o in eObj)
+ {
+ derOut.WriteObject(o);
+ }
+ }
+ else
+ {
+ derOut.WriteObject(obj);
+ }
+ }
+
+ derOut.WriteByte(0x00);
+ derOut.WriteByte(0x00);
+ }
+ else
+ {
+ base.Encode(derOut);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ConstructedOctetStream.cs b/Crypto/src/asn1/ConstructedOctetStream.cs
new file mode 100644
index 000000000..1773b22cc
--- /dev/null
+++ b/Crypto/src/asn1/ConstructedOctetStream.cs
@@ -0,0 +1,102 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal class ConstructedOctetStream
+ : BaseInputStream
+ {
+ private readonly Asn1StreamParser _parser;
+
+ private bool _first = true;
+ private Stream _currentStream;
+
+ internal ConstructedOctetStream(
+ Asn1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ return 0;
+
+ Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
+
+ if (s == null)
+ return 0;
+
+ _first = false;
+ _currentStream = s.GetOctetStream();
+ }
+
+ int totalRead = 0;
+
+ for (;;)
+ {
+ int numRead = _currentStream.Read(buffer, offset + totalRead, count - totalRead);
+
+ if (numRead > 0)
+ {
+ totalRead += numRead;
+
+ if (totalRead == count)
+ return totalRead;
+ }
+ else
+ {
+ Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
+
+ if (aos == null)
+ {
+ _currentStream = null;
+ return totalRead;
+ }
+
+ _currentStream = aos.GetOctetStream();
+ }
+ }
+ }
+
+ public override int ReadByte()
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ return 0;
+
+ Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
+
+ if (s == null)
+ return 0;
+
+ _first = false;
+ _currentStream = s.GetOctetStream();
+ }
+
+ for (;;)
+ {
+ int b = _currentStream.ReadByte();
+
+ if (b >= 0)
+ {
+ return b;
+ }
+
+ Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
+
+ if (aos == null)
+ {
+ _currentStream = null;
+ return -1;
+ }
+
+ _currentStream = aos.GetOctetStream();
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DERExternal.cs b/Crypto/src/asn1/DERExternal.cs
new file mode 100644
index 000000000..a342d6520
--- /dev/null
+++ b/Crypto/src/asn1/DERExternal.cs
@@ -0,0 +1,207 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Class representing the DER-type External
+ */
+ public class DerExternal
+ : Asn1Object
+ {
+ private DerObjectIdentifier directReference;
+ private DerInteger indirectReference;
+ private Asn1Object dataValueDescriptor;
+ private int encoding;
+ private Asn1Object externalContent;
+
+ public DerExternal(
+ Asn1EncodableVector vector)
+ {
+ int offset = 0;
+ Asn1Object enc = GetObjFromVector(vector, offset);
+ if (enc is DerObjectIdentifier)
+ {
+ directReference = (DerObjectIdentifier)enc;
+ offset++;
+ enc = GetObjFromVector(vector, offset);
+ }
+ if (enc is DerInteger)
+ {
+ indirectReference = (DerInteger) enc;
+ offset++;
+ enc = GetObjFromVector(vector, offset);
+ }
+ if (!(enc is DerTaggedObject))
+ {
+ dataValueDescriptor = (Asn1Object) enc;
+ offset++;
+ enc = GetObjFromVector(vector, offset);
+ }
+ if (!(enc is DerTaggedObject))
+ {
+ throw new InvalidOperationException(
+ "No tagged object found in vector. Structure doesn't seem to be of type External");
+ }
+
+ if (vector.Count != offset + 1)
+ throw new ArgumentException("input vector too large", "vector");
+
+ if (!(enc is DerTaggedObject))
+ throw new ArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External", "vector");
+
+ DerTaggedObject obj = (DerTaggedObject)enc;
+
+ // Use property accessor to include check on value
+ Encoding = obj.TagNo;
+
+ if (encoding < 0 || encoding > 2)
+ throw new InvalidOperationException("invalid encoding value");
+
+ externalContent = obj.GetObject();
+ }
+
+ /**
+ * Creates a new instance of DerExternal
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param externalData The external data in its encoded form.
+ */
+ public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, DerTaggedObject externalData)
+ : this(directReference, indirectReference, dataValueDescriptor, externalData.TagNo, externalData.ToAsn1Object())
+ {
+ }
+
+ /**
+ * Creates a new instance of DerExternal.
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or <code>null</code> if not set.
+ * @param indirectReference The indirect reference or <code>null</code> if not set.
+ * @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+ * @param encoding The encoding to be used for the external data
+ * @param externalData The external data
+ */
+ public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, int encoding, Asn1Object externalData)
+ {
+ DirectReference = directReference;
+ IndirectReference = indirectReference;
+ DataValueDescriptor = dataValueDescriptor;
+ Encoding = encoding;
+ ExternalContent = externalData.ToAsn1Object();
+ }
+
+ internal override void Encode(DerOutputStream derOut)
+ {
+ MemoryStream ms = new MemoryStream();
+ WriteEncodable(ms, directReference);
+ WriteEncodable(ms, indirectReference);
+ WriteEncodable(ms, dataValueDescriptor);
+ WriteEncodable(ms, new DerTaggedObject(Asn1Tags.External, externalContent));
+
+ derOut.WriteEncoded(Asn1Tags.Constructed, Asn1Tags.External, ms.ToArray());
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ int ret = externalContent.GetHashCode();
+ if (directReference != null)
+ {
+ ret ^= directReference.GetHashCode();
+ }
+ if (indirectReference != null)
+ {
+ ret ^= indirectReference.GetHashCode();
+ }
+ if (dataValueDescriptor != null)
+ {
+ ret ^= dataValueDescriptor.GetHashCode();
+ }
+ return ret;
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ if (this == asn1Object)
+ return true;
+
+ DerExternal other = asn1Object as DerExternal;
+
+ if (other == null)
+ return false;
+
+ return Platform.Equals(directReference, other.directReference)
+ && Platform.Equals(indirectReference, other.indirectReference)
+ && Platform.Equals(dataValueDescriptor, other.dataValueDescriptor)
+ && externalContent.Equals(other.externalContent);
+ }
+
+ public Asn1Object DataValueDescriptor
+ {
+ get { return dataValueDescriptor; }
+ set { this.dataValueDescriptor = value; }
+ }
+
+ public DerObjectIdentifier DirectReference
+ {
+ get { return directReference; }
+ set { this.directReference = value; }
+ }
+
+ /**
+ * The encoding of the content. Valid values are
+ * <ul>
+ * <li><code>0</code> single-ASN1-type</li>
+ * <li><code>1</code> OCTET STRING</li>
+ * <li><code>2</code> BIT STRING</li>
+ * </ul>
+ */
+ public int Encoding
+ {
+ get
+ {
+ return encoding;
+ }
+ set
+ {
+ if (encoding < 0 || encoding > 2)
+ throw new InvalidOperationException("invalid encoding value: " + encoding);
+
+ this.encoding = value;
+ }
+ }
+
+ public Asn1Object ExternalContent
+ {
+ get { return externalContent; }
+ set { this.externalContent = value; }
+ }
+
+ public DerInteger IndirectReference
+ {
+ get { return indirectReference; }
+ set { this.indirectReference = value; }
+ }
+
+ private static Asn1Object GetObjFromVector(Asn1EncodableVector v, int index)
+ {
+ if (v.Count <= index)
+ throw new ArgumentException("too few objects in input vector", "v");
+
+ return v[index].ToAsn1Object();
+ }
+
+ private static void WriteEncodable(MemoryStream ms, Asn1Encodable e)
+ {
+ if (e != null)
+ {
+ byte[] bs = e.GetDerEncoded();
+ ms.Write(bs, 0, bs.Length);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DERExternalParser.cs b/Crypto/src/asn1/DERExternalParser.cs
new file mode 100644
index 000000000..70e426fed
--- /dev/null
+++ b/Crypto/src/asn1/DERExternalParser.cs
@@ -0,0 +1,26 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerExternalParser
+ : Asn1Encodable
+ {
+ private readonly Asn1StreamParser _parser;
+
+ public DerExternalParser(Asn1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ return _parser.ReadObject();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerExternal(_parser.ReadVector());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DERGenerator.cs b/Crypto/src/asn1/DERGenerator.cs
new file mode 100644
index 000000000..aab40fefa
--- /dev/null
+++ b/Crypto/src/asn1/DERGenerator.cs
@@ -0,0 +1,107 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public abstract class DerGenerator
+ : Asn1Generator
+ {
+ private bool _tagged = false;
+ private bool _isExplicit;
+ private int _tagNo;
+
+ protected DerGenerator(
+ Stream outStream)
+ : base(outStream)
+ {
+ }
+
+ protected DerGenerator(
+ Stream outStream,
+ int tagNo,
+ bool isExplicit)
+ : base(outStream)
+ {
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ private static void WriteLength(
+ Stream outStr,
+ int length)
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>= 8) != 0)
+ {
+ size++;
+ }
+
+ outStr.WriteByte((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ outStr.WriteByte((byte)(length >> i));
+ }
+ }
+ else
+ {
+ outStr.WriteByte((byte)length);
+ }
+ }
+
+ internal static void WriteDerEncoded(
+ Stream outStream,
+ int tag,
+ byte[] bytes)
+ {
+ outStream.WriteByte((byte) tag);
+ WriteLength(outStream, bytes.Length);
+ outStream.Write(bytes, 0, bytes.Length);
+ }
+
+ internal void WriteDerEncoded(
+ int tag,
+ byte[] bytes)
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | Asn1Tags.Tagged;
+
+ if (_isExplicit)
+ {
+ int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.Tagged;
+ MemoryStream bOut = new MemoryStream();
+ WriteDerEncoded(bOut, tag, bytes);
+ WriteDerEncoded(Out, newTag, bOut.ToArray());
+ }
+ else
+ {
+ if ((tag & Asn1Tags.Constructed) != 0)
+ {
+ tagNum |= Asn1Tags.Constructed;
+ }
+
+ WriteDerEncoded(Out, tagNum, bytes);
+ }
+ }
+ else
+ {
+ WriteDerEncoded(Out, tag, bytes);
+ }
+ }
+
+ internal static void WriteDerEncoded(
+ Stream outStr,
+ int tag,
+ Stream inStr)
+ {
+ WriteDerEncoded(outStr, tag, Streams.ReadAll(inStr));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DEROctetStringParser.cs b/Crypto/src/asn1/DEROctetStringParser.cs
new file mode 100644
index 000000000..b0d3ad8cf
--- /dev/null
+++ b/Crypto/src/asn1/DEROctetStringParser.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerOctetStringParser
+ : Asn1OctetStringParser
+ {
+ private readonly DefiniteLengthInputStream stream;
+
+ internal DerOctetStringParser(
+ DefiniteLengthInputStream stream)
+ {
+ this.stream = stream;
+ }
+
+ public Stream GetOctetStream()
+ {
+ return stream;
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ try
+ {
+ return new DerOctetString(stream.ToArray());
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("IOException converting stream to byte array: " + e.Message, e);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DERSequenceGenerator.cs b/Crypto/src/asn1/DERSequenceGenerator.cs
new file mode 100644
index 000000000..4c2bfd012
--- /dev/null
+++ b/Crypto/src/asn1/DERSequenceGenerator.cs
@@ -0,0 +1,40 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerSequenceGenerator
+ : DerGenerator
+ {
+ private readonly MemoryStream _bOut = new MemoryStream();
+
+ public DerSequenceGenerator(
+ Stream outStream)
+ : base(outStream)
+ {
+ }
+
+ public DerSequenceGenerator(
+ Stream outStream,
+ int tagNo,
+ bool isExplicit)
+ : base(outStream, tagNo, isExplicit)
+ {
+ }
+
+ public override void AddObject(
+ Asn1Encodable obj)
+ {
+ new DerOutputStream(_bOut).WriteObject(obj);
+ }
+
+ public override Stream GetRawOutputStream()
+ {
+ return _bOut;
+ }
+
+ public override void Close()
+ {
+ WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DERSequenceParser.cs b/Crypto/src/asn1/DERSequenceParser.cs
new file mode 100644
index 000000000..69c2b9b2d
--- /dev/null
+++ b/Crypto/src/asn1/DERSequenceParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerSequenceParser
+ : Asn1SequenceParser
+ {
+ private readonly Asn1StreamParser _parser;
+
+ internal DerSequenceParser(
+ Asn1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ return _parser.ReadObject();
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(_parser.ReadVector());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DERSetGenerator.cs b/Crypto/src/asn1/DERSetGenerator.cs
new file mode 100644
index 000000000..455ca88ac
--- /dev/null
+++ b/Crypto/src/asn1/DERSetGenerator.cs
@@ -0,0 +1,40 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerSetGenerator
+ : DerGenerator
+ {
+ private readonly MemoryStream _bOut = new MemoryStream();
+
+ public DerSetGenerator(
+ Stream outStream)
+ : base(outStream)
+ {
+ }
+
+ public DerSetGenerator(
+ Stream outStream,
+ int tagNo,
+ bool isExplicit)
+ : base(outStream, tagNo, isExplicit)
+ {
+ }
+
+ public override void AddObject(
+ Asn1Encodable obj)
+ {
+ new DerOutputStream(_bOut).WriteObject(obj);
+ }
+
+ public override Stream GetRawOutputStream()
+ {
+ return _bOut;
+ }
+
+ public override void Close()
+ {
+ WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DERSetParser.cs b/Crypto/src/asn1/DERSetParser.cs
new file mode 100644
index 000000000..d67f135be
--- /dev/null
+++ b/Crypto/src/asn1/DERSetParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerSetParser
+ : Asn1SetParser
+ {
+ private readonly Asn1StreamParser _parser;
+
+ internal DerSetParser(
+ Asn1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public IAsn1Convertible ReadObject()
+ {
+ return _parser.ReadObject();
+ }
+
+ public Asn1Object ToAsn1Object()
+ {
+ return new DerSet(_parser.ReadVector(), false);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DefiniteLengthInputStream.cs b/Crypto/src/asn1/DefiniteLengthInputStream.cs
new file mode 100644
index 000000000..cfea89f21
--- /dev/null
+++ b/Crypto/src/asn1/DefiniteLengthInputStream.cs
@@ -0,0 +1,90 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ class DefiniteLengthInputStream
+ : LimitedInputStream
+ {
+ private static readonly byte[] EmptyBytes = new byte[0];
+
+ private readonly int _originalLength;
+ private int _remaining;
+
+ internal DefiniteLengthInputStream(
+ Stream inStream,
+ int length)
+ : base(inStream, length)
+ {
+ if (length < 0)
+ throw new ArgumentException("negative lengths not allowed", "length");
+
+ this._originalLength = length;
+ this._remaining = length;
+
+ if (length == 0)
+ {
+ SetParentEofDetect(true);
+ }
+ }
+
+ internal int Remaining
+ {
+ get { return _remaining; }
+ }
+
+ public override int ReadByte()
+ {
+ if (_remaining == 0)
+ return -1;
+
+ int b = _in.ReadByte();
+
+ if (b < 0)
+ throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+
+ if (--_remaining == 0)
+ {
+ SetParentEofDetect(true);
+ }
+
+ return b;
+ }
+
+ public override int Read(
+ byte[] buf,
+ int off,
+ int len)
+ {
+ if (_remaining == 0)
+ return 0;
+
+ int toRead = System.Math.Min(len, _remaining);
+ int numRead = _in.Read(buf, off, toRead);
+
+ if (numRead < 1)
+ throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+
+ if ((_remaining -= numRead) == 0)
+ {
+ SetParentEofDetect(true);
+ }
+
+ return numRead;
+ }
+
+ internal byte[] ToArray()
+ {
+ if (_remaining == 0)
+ return EmptyBytes;
+
+ byte[] bytes = new byte[_remaining];
+ if ((_remaining -= Streams.ReadFully(_in, bytes)) != 0)
+ throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ SetParentEofDetect(true);
+ return bytes;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerApplicationSpecific.cs b/Crypto/src/asn1/DerApplicationSpecific.cs
new file mode 100644
index 000000000..394c7431e
--- /dev/null
+++ b/Crypto/src/asn1/DerApplicationSpecific.cs
@@ -0,0 +1,237 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Base class for an application specific object
+ */
+ public class DerApplicationSpecific
+ : Asn1Object
+ {
+ private readonly bool isConstructed;
+ private readonly int tag;
+ private readonly byte[] octets;
+
+ internal DerApplicationSpecific(
+ bool isConstructed,
+ int tag,
+ byte[] octets)
+ {
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.octets = octets;
+ }
+
+ public DerApplicationSpecific(
+ int tag,
+ byte[] octets)
+ : this(false, tag, octets)
+ {
+ }
+
+ public DerApplicationSpecific(
+ int tag,
+ Asn1Encodable obj)
+ : this(true, tag, obj)
+ {
+ }
+
+ public DerApplicationSpecific(
+ bool isExplicit,
+ int tag,
+ Asn1Encodable obj)
+ {
+ Asn1Object asn1Obj = obj.ToAsn1Object();
+
+ byte[] data = asn1Obj.GetDerEncoded();
+
+ this.isConstructed = isExplicit || asn1Obj is Asn1Set || asn1Obj is Asn1Sequence;
+ this.tag = tag;
+
+ if (isExplicit)
+ {
+ this.octets = data;
+ }
+ else
+ {
+ int lenBytes = GetLengthOfHeader(data);
+ byte[] tmp = new byte[data.Length - lenBytes];
+ Array.Copy(data, lenBytes, tmp, 0, tmp.Length);
+ this.octets = tmp;
+ }
+ }
+
+ public DerApplicationSpecific(
+ int tagNo,
+ Asn1EncodableVector vec)
+ {
+ this.tag = tagNo;
+ this.isConstructed = true;
+ MemoryStream bOut = new MemoryStream();
+
+ for (int i = 0; i != vec.Count; i++)
+ {
+ try
+ {
+ byte[] bs = vec[i].GetDerEncoded();
+ bOut.Write(bs, 0, bs.Length);
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("malformed object", e);
+ }
+ }
+ this.octets = bOut.ToArray();
+ }
+
+ private int GetLengthOfHeader(
+ byte[] data)
+ {
+ int length = data[1]; // TODO: assumes 1 byte tag
+
+ if (length == 0x80)
+ {
+ return 2; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new InvalidOperationException("DER length more than 4 bytes: " + size);
+ }
+
+ return size + 2;
+ }
+
+ return 2;
+ }
+
+ public bool IsConstructed()
+ {
+ return isConstructed;
+ }
+
+ public byte[] GetContents()
+ {
+ return octets;
+ }
+
+ public int ApplicationTag
+ {
+ get { return tag; }
+ }
+
+ /**
+ * Return the enclosed object assuming explicit tagging.
+ *
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public Asn1Object GetObject()
+ {
+ return FromByteArray(GetContents());
+ }
+
+ /**
+ * Return the enclosed object assuming implicit tagging.
+ *
+ * @param derTagNo the type tag that should be applied to the object's contents.
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public Asn1Object GetObject(
+ int derTagNo)
+ {
+ if (derTagNo >= 0x1f)
+ throw new IOException("unsupported tag number");
+
+ byte[] orig = this.GetEncoded();
+ byte[] tmp = ReplaceTagNumber(derTagNo, orig);
+
+ if ((orig[0] & Asn1Tags.Constructed) != 0)
+ {
+ tmp[0] |= Asn1Tags.Constructed;
+ }
+
+ return FromByteArray(tmp);;
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ int classBits = Asn1Tags.Application;
+ if (isConstructed)
+ {
+ classBits |= Asn1Tags.Constructed;
+ }
+
+ derOut.WriteEncoded(classBits, tag, octets);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerApplicationSpecific other = asn1Object as DerApplicationSpecific;
+
+ if (other == null)
+ return false;
+
+ return this.isConstructed == other.isConstructed
+ && this.tag == other.tag
+ && Arrays.AreEqual(this.octets, other.octets);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets);
+ }
+
+ private byte[] ReplaceTagNumber(
+ int newTag,
+ byte[] input)
+ {
+ int tagNo = input[0] & 0x1f;
+ int index = 1;
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = input[index++] & 0xff;
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new InvalidOperationException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = input[index++] & 0xff;
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ byte[] tmp = new byte[input.Length - index + 1];
+
+ Array.Copy(input, index, tmp, 1, tmp.Length - 1);
+
+ tmp[0] = (byte)newTag;
+
+ return tmp;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerBMPString.cs b/Crypto/src/asn1/DerBMPString.cs
new file mode 100644
index 000000000..4f7e0a635
--- /dev/null
+++ b/Crypto/src/asn1/DerBMPString.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der BMPString object.
+ */
+ public class DerBmpString
+ : DerStringBase
+ {
+ private readonly string str;
+
+ /**
+ * return a BMP string from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerBmpString GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerBmpString)
+ {
+ return (DerBmpString)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return a BMP string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerBmpString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerBmpString)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerBmpString(Asn1OctetString.GetInstance(o).GetOctets());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DerBmpString(
+ byte[] str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ char[] cs = new char[str.Length / 2];
+
+ for (int i = 0; i != cs.Length; i++)
+ {
+ cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff));
+ }
+
+ this.str = new string(cs);
+ }
+
+ /**
+ * basic constructor
+ */
+ public DerBmpString(
+ string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerBmpString other = asn1Object as DerBmpString;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ char[] c = str.ToCharArray();
+ byte[] b = new byte[c.Length * 2];
+
+ for (int i = 0; i != c.Length; i++)
+ {
+ b[2 * i] = (byte)(c[i] >> 8);
+ b[2 * i + 1] = (byte)c[i];
+ }
+
+ derOut.WriteEncoded(Asn1Tags.BmpString, b);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerBitString.cs b/Crypto/src/asn1/DerBitString.cs
new file mode 100644
index 000000000..d5cb872bc
--- /dev/null
+++ b/Crypto/src/asn1/DerBitString.cs
@@ -0,0 +1,248 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerBitString
+ : DerStringBase
+ {
+ private static readonly char[] table
+ = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ private readonly byte[] data;
+ private readonly int padBits;
+
+ /**
+ * return the correct number of pad bits for a bit string defined in
+ * a 32 bit constant
+ */
+ static internal int GetPadBits(
+ int bitString)
+ {
+ int val = 0;
+ for (int i = 3; i >= 0; i--)
+ {
+ //
+ // this may look a little odd, but if it isn't done like this pre jdk1.2
+ // JVM's break!
+ //
+ if (i != 0)
+ {
+ if ((bitString >> (i * 8)) != 0)
+ {
+ val = (bitString >> (i * 8)) & 0xFF;
+ break;
+ }
+ }
+ else
+ {
+ if (bitString != 0)
+ {
+ val = bitString & 0xFF;
+ break;
+ }
+ }
+ }
+
+ if (val == 0)
+ {
+ return 7;
+ }
+
+ int bits = 1;
+
+ while (((val <<= 1) & 0xFF) != 0)
+ {
+ bits++;
+ }
+
+ return 8 - bits;
+ }
+
+ /**
+ * return the correct number of bytes for a bit string defined in
+ * a 32 bit constant
+ */
+ static internal byte[] GetBytes(
+ int bitString)
+ {
+ int bytes = 4;
+ for (int i = 3; i >= 1; i--)
+ {
+ if ((bitString & (0xFF << (i * 8))) != 0)
+ {
+ break;
+ }
+ bytes--;
+ }
+
+ byte[] result = new byte[bytes];
+ for (int i = 0; i < bytes; i++)
+ {
+ result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
+ }
+
+ return result;
+ }
+
+ /**
+ * return a Bit string from the passed in object
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerBitString GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerBitString)
+ {
+ return (DerBitString) obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return a Bit string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerBitString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerBitString)
+ {
+ return GetInstance(o);
+ }
+
+ return FromAsn1Octets(((Asn1OctetString)o).GetOctets());
+ }
+
+ internal DerBitString(
+ byte data,
+ int padBits)
+ {
+ this.data = new byte[]{ data };
+ this.padBits = padBits;
+ }
+
+ /**
+ * @param data the octets making up the bit string.
+ * @param padBits the number of extra bits at the end of the string.
+ */
+ public DerBitString(
+ byte[] data,
+ int padBits)
+ {
+ // TODO Deep copy?
+ this.data = data;
+ this.padBits = padBits;
+ }
+
+ public DerBitString(
+ byte[] data)
+ {
+ // TODO Deep copy?
+ this.data = data;
+ }
+
+ public DerBitString(
+ Asn1Encodable obj)
+ {
+ this.data = obj.GetDerEncoded();
+ //this.padBits = 0;
+ }
+
+ public byte[] GetBytes()
+ {
+ return data;
+ }
+
+ public int PadBits
+ {
+ get { return padBits; }
+ }
+
+ /**
+ * @return the value of the bit string as an int (truncating if necessary)
+ */
+ public int IntValue
+ {
+ get
+ {
+ int value = 0;
+
+ for (int i = 0; i != data.Length && i != 4; i++)
+ {
+ value |= (data[i] & 0xff) << (8 * i);
+ }
+
+ return value;
+ }
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ byte[] bytes = new byte[GetBytes().Length + 1];
+
+ bytes[0] = (byte) PadBits;
+ Array.Copy(GetBytes(), 0, bytes, 1, bytes.Length - 1);
+
+ derOut.WriteEncoded(Asn1Tags.BitString, bytes);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return padBits.GetHashCode() ^ Arrays.GetHashCode(data);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerBitString other = asn1Object as DerBitString;
+
+ if (other == null)
+ return false;
+
+ return this.padBits == other.padBits
+ && Arrays.AreEqual(this.data, other.data);
+ }
+
+ public override string GetString()
+ {
+ StringBuilder buffer = new StringBuilder("#");
+
+ byte[] str = GetDerEncoded();
+
+ for (int i = 0; i != str.Length; i++)
+ {
+ uint ubyte = str[i];
+ buffer.Append(table[(ubyte >> 4) & 0xf]);
+ buffer.Append(table[str[i] & 0xf]);
+ }
+
+ return buffer.ToString();
+ }
+
+ internal static DerBitString FromAsn1Octets(byte[] octets)
+ {
+ if (octets.Length < 1)
+ throw new ArgumentException("truncated BIT STRING detected");
+
+ int padBits = octets[0];
+ byte[] data = new byte[octets.Length - 1];
+ Array.Copy(octets, 1, data, 0, data.Length);
+ return new DerBitString(data, padBits);
+ }
+ }
+}
+
diff --git a/Crypto/src/asn1/DerBoolean.cs b/Crypto/src/asn1/DerBoolean.cs
new file mode 100644
index 000000000..41ccae8a1
--- /dev/null
+++ b/Crypto/src/asn1/DerBoolean.cs
@@ -0,0 +1,110 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerBoolean
+ : Asn1Object
+ {
+ private readonly byte value;
+
+ public static readonly DerBoolean False = new DerBoolean(false);
+ public static readonly DerBoolean True = new DerBoolean(true);
+
+ /**
+ * return a bool from the passed in object.
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerBoolean GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerBoolean)
+ {
+ return (DerBoolean) obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return a DerBoolean from the passed in bool.
+ */
+ public static DerBoolean GetInstance(
+ bool value)
+ {
+ return value ? True : False;
+ }
+
+ /**
+ * return a Boolean from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerBoolean GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerBoolean)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerBoolean(((Asn1OctetString)o).GetOctets());
+ }
+
+ public DerBoolean(
+ byte[] val)
+ {
+ if (val.Length != 1)
+ throw new ArgumentException("byte value should have 1 byte in it", "val");
+
+ // TODO Are there any constraints on the possible byte values?
+ this.value = val[0];
+ }
+
+ private DerBoolean(
+ bool value)
+ {
+ this.value = value ? (byte)0xff : (byte)0;
+ }
+
+ public bool IsTrue
+ {
+ get { return value != 0; }
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ // TODO Should we make sure the byte value is one of '0' or '0xff' here?
+ derOut.WriteEncoded(Asn1Tags.Boolean, new byte[]{ value });
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerBoolean other = asn1Object as DerBoolean;
+
+ if (other == null)
+ return false;
+
+ return IsTrue == other.IsTrue;
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return IsTrue.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return IsTrue ? "TRUE" : "FALSE";
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerEnumerated.cs b/Crypto/src/asn1/DerEnumerated.cs
new file mode 100644
index 000000000..0e67e6dbe
--- /dev/null
+++ b/Crypto/src/asn1/DerEnumerated.cs
@@ -0,0 +1,100 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerEnumerated
+ : Asn1Object
+ {
+ private readonly byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerEnumerated GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerEnumerated)
+ {
+ return (DerEnumerated)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return an Enumerated from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerEnumerated GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerEnumerated)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerEnumerated(((Asn1OctetString)o).GetOctets());
+ }
+
+ public DerEnumerated(
+ int val)
+ {
+ bytes = BigInteger.ValueOf(val).ToByteArray();
+ }
+
+ public DerEnumerated(
+ BigInteger val)
+ {
+ bytes = val.ToByteArray();
+ }
+
+ public DerEnumerated(
+ byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public BigInteger Value
+ {
+ get
+ {
+ return new BigInteger(bytes);
+ }
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.Enumerated, bytes);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerEnumerated other = asn1Object as DerEnumerated;
+
+ if (other == null)
+ return false;
+
+ return Arrays.AreEqual(this.bytes, other.bytes);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(bytes);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerGeneralString.cs b/Crypto/src/asn1/DerGeneralString.cs
new file mode 100644
index 000000000..0e20b53bd
--- /dev/null
+++ b/Crypto/src/asn1/DerGeneralString.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerGeneralString
+ : DerStringBase
+ {
+ private readonly string str;
+
+ public static DerGeneralString GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerGeneralString)
+ {
+ return (DerGeneralString) obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: "
+ + obj.GetType().Name);
+ }
+
+ public static DerGeneralString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerGeneralString)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerGeneralString(((Asn1OctetString)o).GetOctets());
+ }
+
+ public DerGeneralString(
+ byte[] str)
+ : this(Strings.FromAsciiByteArray(str))
+ {
+ }
+
+ public DerGeneralString(
+ string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ public byte[] GetOctets()
+ {
+ return Strings.ToAsciiByteArray(str);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.GeneralString, GetOctets());
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerGeneralString other = asn1Object as DerGeneralString;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerGeneralizedTime.cs b/Crypto/src/asn1/DerGeneralizedTime.cs
new file mode 100644
index 000000000..0a0e6fd7c
--- /dev/null
+++ b/Crypto/src/asn1/DerGeneralizedTime.cs
@@ -0,0 +1,305 @@
+using System;
+using System.Globalization;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Generalized time object.
+ */
+ public class DerGeneralizedTime
+ : Asn1Object
+ {
+ private readonly string time;
+
+ /**
+ * return a generalized time from the passed in object
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerGeneralizedTime GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerGeneralizedTime)
+ {
+ return (DerGeneralizedTime)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * return a Generalized Time object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerGeneralizedTime GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerGeneralizedTime)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerGeneralizedTime(((Asn1OctetString)o).GetOctets());
+ }
+
+ /**
+ * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+ * for local time, or Z+-HHMM on the end, for difference between local
+ * time and UTC time. The fractional second amount f must consist of at
+ * least one number with trailing zeroes removed.
+ *
+ * @param time the time string.
+ * @exception ArgumentException if string is an illegal format.
+ */
+ public DerGeneralizedTime(
+ string time)
+ {
+ this.time = time;
+
+ try
+ {
+ ToDateTime();
+ }
+ catch (FormatException e)
+ {
+ throw new ArgumentException("invalid date string: " + e.Message);
+ }
+ }
+
+ /**
+ * base constructor from a local time object
+ */
+ public DerGeneralizedTime(
+ DateTime time)
+ {
+ this.time = time.ToString(@"yyyyMMddHHmmss\Z");
+ }
+
+ internal DerGeneralizedTime(
+ byte[] bytes)
+ {
+ //
+ // explicitly convert to characters
+ //
+ this.time = Strings.FromAsciiByteArray(bytes);
+ }
+
+ /**
+ * Return the time.
+ * @return The time string as it appeared in the encoded object.
+ */
+ public string TimeString
+ {
+ get { return time; }
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ * </pre>
+ * To read in the time and Get a date which is compatible with our local
+ * time zone.</p>
+ */
+ public string GetTime()
+ {
+ //
+ // standardise the format.
+ //
+ if (time[time.Length - 1] == 'Z')
+ {
+ return time.Substring(0, time.Length - 1) + "GMT+00:00";
+ }
+ else
+ {
+ int signPos = time.Length - 5;
+ char sign = time[signPos];
+ if (sign == '-' || sign == '+')
+ {
+ return time.Substring(0, signPos)
+ + "GMT"
+ + time.Substring(signPos, 3)
+ + ":"
+ + time.Substring(signPos + 3);
+ }
+ else
+ {
+ signPos = time.Length - 3;
+ sign = time[signPos];
+ if (sign == '-' || sign == '+')
+ {
+ return time.Substring(0, signPos)
+ + "GMT"
+ + time.Substring(signPos)
+ + ":00";
+ }
+ }
+ }
+
+ return time + CalculateGmtOffset();
+ }
+
+ private string CalculateGmtOffset()
+ {
+ char sign = '+';
+ DateTime time = ToDateTime();
+
+#if (SILVERLIGHT || PORTABLE)
+ long offset = time.Ticks - time.ToUniversalTime().Ticks;
+ if (offset < 0)
+ {
+ sign = '-';
+ offset = -offset;
+ }
+ int hours = (int)(offset / TimeSpan.TicksPerHour);
+ int minutes = (int)(offset / TimeSpan.TicksPerMinute) % 60;
+#else
+ // Note: GetUtcOffset incorporates Daylight Savings offset
+ TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(time);
+ if (offset.CompareTo(TimeSpan.Zero) < 0)
+ {
+ sign = '-';
+ offset = offset.Duration();
+ }
+ int hours = offset.Hours;
+ int minutes = offset.Minutes;
+#endif
+
+ return "GMT" + sign + Convert(hours) + ":" + Convert(minutes);
+ }
+
+ private static string Convert(
+ int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return time.ToString();
+ }
+
+ public DateTime ToDateTime()
+ {
+ string formatStr;
+ string d = time;
+ bool makeUniversal = false;
+
+ if (d.EndsWith("Z"))
+ {
+ if (HasFractionalSeconds)
+ {
+ int fCount = d.Length - d.IndexOf('.') - 2;
+ formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"\Z";
+ }
+ else
+ {
+ formatStr = @"yyyyMMddHHmmss\Z";
+ }
+ }
+ else if (time.IndexOf('-') > 0 || time.IndexOf('+') > 0)
+ {
+ d = GetTime();
+ makeUniversal = true;
+
+ if (HasFractionalSeconds)
+ {
+ int fCount = d.IndexOf("GMT") - 1 - d.IndexOf('.');
+ formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"'GMT'zzz";
+ }
+ else
+ {
+ formatStr = @"yyyyMMddHHmmss'GMT'zzz";
+ }
+ }
+ else
+ {
+ if (HasFractionalSeconds)
+ {
+ int fCount = d.Length - 1 - d.IndexOf('.');
+ formatStr = @"yyyyMMddHHmmss." + FString(fCount);
+ }
+ else
+ {
+ formatStr = @"yyyyMMddHHmmss";
+ }
+
+ // TODO?
+// dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+ }
+
+ return ParseDateString(d, formatStr, makeUniversal);
+ }
+
+ private string FString(
+ int count)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < count; ++i)
+ {
+ sb.Append('f');
+ }
+ return sb.ToString();
+ }
+
+ private DateTime ParseDateString(
+ string dateStr,
+ string formatStr,
+ bool makeUniversal)
+ {
+ DateTime dt = DateTime.ParseExact(
+ dateStr,
+ formatStr,
+ DateTimeFormatInfo.InvariantInfo);
+
+ return makeUniversal ? dt.ToUniversalTime() : dt;
+ }
+
+ private bool HasFractionalSeconds
+ {
+ get { return time.IndexOf('.') == 14; }
+ }
+
+ private byte[] GetOctets()
+ {
+ return Strings.ToAsciiByteArray(time);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.GeneralizedTime, GetOctets());
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerGeneralizedTime other = asn1Object as DerGeneralizedTime;
+
+ if (other == null)
+ return false;
+
+ return this.time.Equals(other.time);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return time.GetHashCode();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerIA5String.cs b/Crypto/src/asn1/DerIA5String.cs
new file mode 100644
index 000000000..9fa2cba3c
--- /dev/null
+++ b/Crypto/src/asn1/DerIA5String.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der IA5String object - this is an ascii string.
+ */
+ public class DerIA5String
+ : DerStringBase
+ {
+ private readonly string str;
+
+ /**
+ * return a IA5 string from the passed in object
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerIA5String GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerIA5String)
+ {
+ return (DerIA5String)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return an IA5 string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerIA5String GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerIA5String)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerIA5String(((Asn1OctetString)o).GetOctets());
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ public DerIA5String(
+ byte[] str)
+ : this(Strings.FromAsciiByteArray(str), false)
+ {
+ }
+
+ /**
+ * basic constructor - without validation.
+ */
+ public DerIA5String(
+ string str)
+ : this(str, false)
+ {
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws ArgumentException if validate is true and the string
+ * contains characters that should not be in an IA5String.
+ */
+ public DerIA5String(
+ string str,
+ bool validate)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+ if (validate && !IsIA5String(str))
+ throw new ArgumentException("string contains illegal characters", "str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ public byte[] GetOctets()
+ {
+ return Strings.ToAsciiByteArray(str);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.IA5String, GetOctets());
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return this.str.GetHashCode();
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerIA5String other = asn1Object as DerIA5String;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as an IA5String, false otherwise.
+ *
+ * @return true if in printable set, false otherwise.
+ */
+ public static bool IsIA5String(
+ string str)
+ {
+ foreach (char ch in str)
+ {
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerInteger.cs b/Crypto/src/asn1/DerInteger.cs
new file mode 100644
index 000000000..eb0614515
--- /dev/null
+++ b/Crypto/src/asn1/DerInteger.cs
@@ -0,0 +1,117 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerInteger
+ : Asn1Object
+ {
+ private readonly byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerInteger GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerInteger)
+ {
+ return (DerInteger)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return an Integer from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param isExplicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerInteger GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ if (obj == null)
+ throw new ArgumentNullException("obj");
+
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerInteger)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerInteger(Asn1OctetString.GetInstance(o).GetOctets());
+ }
+
+ public DerInteger(
+ int value)
+ {
+ bytes = BigInteger.ValueOf(value).ToByteArray();
+ }
+
+ public DerInteger(
+ BigInteger value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ bytes = value.ToByteArray();
+ }
+
+ public DerInteger(
+ byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public BigInteger Value
+ {
+ get { return new BigInteger(bytes); }
+ }
+
+ /**
+ * in some cases positive values Get crammed into a space,
+ * that's not quite big enough...
+ */
+ public BigInteger PositiveValue
+ {
+ get { return new BigInteger(1, bytes); }
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.Integer, bytes);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return Arrays.GetHashCode(bytes);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerInteger other = asn1Object as DerInteger;
+
+ if (other == null)
+ return false;
+
+ return Arrays.AreEqual(this.bytes, other.bytes);
+ }
+
+ public override string ToString()
+ {
+ return Value.ToString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerNull.cs b/Crypto/src/asn1/DerNull.cs
new file mode 100644
index 000000000..a802f6486
--- /dev/null
+++ b/Crypto/src/asn1/DerNull.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * A Null object.
+ */
+ public class DerNull
+ : Asn1Null
+ {
+ public static readonly DerNull Instance = new DerNull(0);
+
+ byte[] zeroBytes = new byte[0];
+
+ [Obsolete("Use static Instance object")]
+ public DerNull()
+ {
+ }
+
+ protected internal DerNull(int dummy)
+ {
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.Null, zeroBytes);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ return asn1Object is DerNull;
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return -1;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerNumericString.cs b/Crypto/src/asn1/DerNumericString.cs
new file mode 100644
index 000000000..6e2715a4d
--- /dev/null
+++ b/Crypto/src/asn1/DerNumericString.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+ */
+ public class DerNumericString
+ : DerStringBase
+ {
+ private readonly string str;
+
+ /**
+ * return a Numeric string from the passed in object
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerNumericString GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerNumericString)
+ {
+ return (DerNumericString)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return an Numeric string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerNumericString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerNumericString)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerNumericString(Asn1OctetString.GetInstance(o).GetOctets());
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ public DerNumericString(
+ byte[] str)
+ : this(Strings.FromAsciiByteArray(str), false)
+ {
+ }
+
+ /**
+ * basic constructor - without validation..
+ */
+ public DerNumericString(
+ string str)
+ : this(str, false)
+ {
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws ArgumentException if validate is true and the string
+ * contains characters that should not be in a NumericString.
+ */
+ public DerNumericString(
+ string str,
+ bool validate)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+ if (validate && !IsNumericString(str))
+ throw new ArgumentException("string contains illegal characters", "str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ public byte[] GetOctets()
+ {
+ return Strings.ToAsciiByteArray(str);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.NumericString, GetOctets());
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerNumericString other = asn1Object as DerNumericString;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+
+ /**
+ * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+ *
+ * @param str string to validate.
+ * @return true if numeric, fale otherwise.
+ */
+ public static bool IsNumericString(
+ string str)
+ {
+ foreach (char ch in str)
+ {
+ if (ch > 0x007f || (ch != ' ' && !char.IsDigit(ch)))
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerObjectIdentifier.cs b/Crypto/src/asn1/DerObjectIdentifier.cs
new file mode 100644
index 000000000..7dc963729
--- /dev/null
+++ b/Crypto/src/asn1/DerObjectIdentifier.cs
@@ -0,0 +1,242 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerObjectIdentifier
+ : Asn1Object
+ {
+ private static readonly Regex OidRegex = new Regex(@"\A[0-2](\.[0-9]+)+\z");
+
+ private readonly string identifier;
+
+ /**
+ * return an Oid from the passed in object
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerObjectIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerObjectIdentifier)
+ {
+ return (DerObjectIdentifier) obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * return an object Identifier from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerObjectIdentifier GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(obj.GetObject());
+ }
+
+ public DerObjectIdentifier(
+ string identifier)
+ {
+ if (identifier == null)
+ throw new ArgumentNullException("identifier");
+ if (!OidRegex.IsMatch(identifier))
+ throw new FormatException("string " + identifier + " not an OID");
+
+ this.identifier = identifier;
+ }
+
+ // TODO Change to ID?
+ public string Id
+ {
+ get { return identifier; }
+ }
+
+ public virtual DerObjectIdentifier Branch(string branchID)
+ {
+ return new DerObjectIdentifier(identifier + "." + branchID);
+ }
+
+ /**
+ * Return true if this oid is an extension of the passed in branch, stem.
+ * @param stem the arc or branch that is a possible parent.
+ * @return true if the branch is on the passed in stem, false otherwise.
+ */
+ public virtual bool On(DerObjectIdentifier stem)
+ {
+ string id = Id, stemId = stem.Id;
+ return id.Length > stemId.Length && id[stemId.Length] == '.' && id.StartsWith(stemId);
+ }
+
+ internal DerObjectIdentifier(
+ byte[] bytes)
+ : this(MakeOidStringFromBytes(bytes))
+ {
+ }
+
+ private void WriteField(
+ Stream outputStream,
+ long fieldValue)
+ {
+ byte[] result = new byte[9];
+ int pos = 8;
+ result[pos] = (byte)(fieldValue & 0x7f);
+ while (fieldValue >= (1L << 7))
+ {
+ fieldValue >>= 7;
+ result[--pos] = (byte)((fieldValue & 0x7f) | 0x80);
+ }
+ outputStream.Write(result, pos, 9 - pos);
+ }
+
+ private void WriteField(
+ Stream outputStream,
+ BigInteger fieldValue)
+ {
+ int byteCount = (fieldValue.BitLength + 6) / 7;
+ if (byteCount == 0)
+ {
+ outputStream.WriteByte(0);
+ }
+ else
+ {
+ BigInteger tmpValue = fieldValue;
+ byte[] tmp = new byte[byteCount];
+ for (int i = byteCount-1; i >= 0; i--)
+ {
+ tmp[i] = (byte) ((tmpValue.IntValue & 0x7f) | 0x80);
+ tmpValue = tmpValue.ShiftRight(7);
+ }
+ tmp[byteCount-1] &= 0x7f;
+ outputStream.Write(tmp, 0, tmp.Length);
+ }
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ OidTokenizer tok = new OidTokenizer(identifier);
+ MemoryStream bOut = new MemoryStream();
+ DerOutputStream dOut = new DerOutputStream(bOut);
+
+ string token = tok.NextToken();
+ int first = int.Parse(token);
+
+ token = tok.NextToken();
+ int second = int.Parse(token);
+
+ WriteField(bOut, first * 40 + second);
+
+ while (tok.HasMoreTokens)
+ {
+ token = tok.NextToken();
+ if (token.Length < 18)
+ {
+ WriteField(bOut, Int64.Parse(token));
+ }
+ else
+ {
+ WriteField(bOut, new BigInteger(token));
+ }
+ }
+
+ dOut.Dispose();
+
+ derOut.WriteEncoded(Asn1Tags.ObjectIdentifier, bOut.ToArray());
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return identifier.GetHashCode();
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerObjectIdentifier other = asn1Object as DerObjectIdentifier;
+
+ if (other == null)
+ return false;
+
+ return this.identifier.Equals(other.identifier);
+ }
+
+ public override string ToString()
+ {
+ return identifier;
+ }
+
+ private static string MakeOidStringFromBytes(
+ byte[] bytes)
+ {
+ StringBuilder objId = new StringBuilder();
+ long value = 0;
+ BigInteger bigValue = null;
+ bool first = true;
+
+ for (int i = 0; i != bytes.Length; i++)
+ {
+ int b = bytes[i];
+
+ if (value < 0x80000000000000L)
+ {
+ value = value * 128 + (b & 0x7f);
+ if ((b & 0x80) == 0) // end of number reached
+ {
+ if (first)
+ {
+ switch ((int)value / 40)
+ {
+ case 0:
+ objId.Append('0');
+ break;
+ case 1:
+ objId.Append('1');
+ value -= 40;
+ break;
+ default:
+ objId.Append('2');
+ value -= 80;
+ break;
+ }
+ first = false;
+ }
+
+ objId.Append('.');
+ objId.Append(value);
+ value = 0;
+ }
+ }
+ else
+ {
+ if (bigValue == null)
+ {
+ bigValue = BigInteger.ValueOf(value);
+ }
+ bigValue = bigValue.ShiftLeft(7);
+ bigValue = bigValue.Or(BigInteger.ValueOf(b & 0x7f));
+ if ((b & 0x80) == 0)
+ {
+ objId.Append('.');
+ objId.Append(bigValue);
+ bigValue = null;
+ value = 0;
+ }
+ }
+ }
+
+ return objId.ToString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerOctetString.cs b/Crypto/src/asn1/DerOctetString.cs
new file mode 100644
index 000000000..c046c9402
--- /dev/null
+++ b/Crypto/src/asn1/DerOctetString.cs
@@ -0,0 +1,34 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerOctetString
+ : Asn1OctetString
+ {
+ /// <param name="str">The octets making up the octet string.</param>
+ public DerOctetString(
+ byte[] str)
+ : base(str)
+ {
+ }
+
+ public DerOctetString(
+ Asn1Encodable obj)
+ : base(obj)
+ {
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.OctetString, str);
+ }
+
+ internal static void Encode(
+ DerOutputStream derOut,
+ byte[] bytes,
+ int offset,
+ int length)
+ {
+ derOut.WriteEncoded(Asn1Tags.OctetString, bytes, offset, length);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerOutputStream.cs b/Crypto/src/asn1/DerOutputStream.cs
new file mode 100644
index 000000000..f95d123f9
--- /dev/null
+++ b/Crypto/src/asn1/DerOutputStream.cs
@@ -0,0 +1,160 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerOutputStream
+ : FilterStream
+ {
+ public DerOutputStream(Stream os)
+ : base(os)
+ {
+ }
+
+ private void WriteLength(
+ int length)
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ uint val = (uint) length;
+
+ while ((val >>= 8) != 0)
+ {
+ size++;
+ }
+
+ WriteByte((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ WriteByte((byte)(length >> i));
+ }
+ }
+ else
+ {
+ WriteByte((byte)length);
+ }
+ }
+
+ internal void WriteEncoded(
+ int tag,
+ byte[] bytes)
+ {
+ WriteByte((byte) tag);
+ WriteLength(bytes.Length);
+ Write(bytes, 0, bytes.Length);
+ }
+
+ internal void WriteEncoded(
+ int tag,
+ byte[] bytes,
+ int offset,
+ int length)
+ {
+ WriteByte((byte) tag);
+ WriteLength(length);
+ Write(bytes, offset, length);
+ }
+
+ internal void WriteTag(
+ int flags,
+ int tagNo)
+ {
+ if (tagNo < 31)
+ {
+ WriteByte((byte)(flags | tagNo));
+ }
+ else
+ {
+ WriteByte((byte)(flags | 0x1f));
+ if (tagNo < 128)
+ {
+ WriteByte((byte)tagNo);
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.Length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ Write(stack, pos, stack.Length - pos);
+ }
+ }
+ }
+
+ internal void WriteEncoded(
+ int flags,
+ int tagNo,
+ byte[] bytes)
+ {
+ WriteTag(flags, tagNo);
+ WriteLength(bytes.Length);
+ Write(bytes, 0, bytes.Length);
+ }
+
+ protected void WriteNull()
+ {
+ WriteByte(Asn1Tags.Null);
+ WriteByte(0x00);
+ }
+
+ [Obsolete("Use version taking an Asn1Encodable arg instead")]
+ public virtual void WriteObject(
+ object obj)
+ {
+ if (obj == null)
+ {
+ WriteNull();
+ }
+ else if (obj is Asn1Object)
+ {
+ ((Asn1Object)obj).Encode(this);
+ }
+ else if (obj is Asn1Encodable)
+ {
+ ((Asn1Encodable)obj).ToAsn1Object().Encode(this);
+ }
+ else
+ {
+ throw new IOException("object not Asn1Object");
+ }
+ }
+
+ public virtual void WriteObject(
+ Asn1Encodable obj)
+ {
+ if (obj == null)
+ {
+ WriteNull();
+ }
+ else
+ {
+ obj.ToAsn1Object().Encode(this);
+ }
+ }
+
+ public virtual void WriteObject(
+ Asn1Object obj)
+ {
+ if (obj == null)
+ {
+ WriteNull();
+ }
+ else
+ {
+ obj.Encode(this);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerPrintableString.cs b/Crypto/src/asn1/DerPrintableString.cs
new file mode 100644
index 000000000..cd2f46b48
--- /dev/null
+++ b/Crypto/src/asn1/DerPrintableString.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der PrintableString object.
+ */
+ public class DerPrintableString
+ : DerStringBase
+ {
+ private readonly string str;
+
+ /**
+ * return a printable string from the passed in object.
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerPrintableString GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerPrintableString)
+ {
+ return (DerPrintableString)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return a Printable string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerPrintableString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerPrintableString)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerPrintableString(Asn1OctetString.GetInstance(o).GetOctets());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DerPrintableString(
+ byte[] str)
+ : this(Strings.FromAsciiByteArray(str), false)
+ {
+ }
+
+ /**
+ * basic constructor - this does not validate the string
+ */
+ public DerPrintableString(
+ string str)
+ : this(str, false)
+ {
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws ArgumentException if validate is true and the string
+ * contains characters that should not be in a PrintableString.
+ */
+ public DerPrintableString(
+ string str,
+ bool validate)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+ if (validate && !IsPrintableString(str))
+ throw new ArgumentException("string contains illegal characters", "str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ public byte[] GetOctets()
+ {
+ return Strings.ToAsciiByteArray(str);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.PrintableString, GetOctets());
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerPrintableString other = asn1Object as DerPrintableString;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as a PrintableString, false otherwise.
+ *
+ * @return true if in printable set, false otherwise.
+ */
+ public static bool IsPrintableString(
+ string str)
+ {
+ foreach (char ch in str)
+ {
+ if (ch > 0x007f)
+ return false;
+
+ if (char.IsLetterOrDigit(ch))
+ continue;
+
+// if (char.IsPunctuation(ch))
+// continue;
+
+ switch (ch)
+ {
+ case ' ':
+ case '\'':
+ case '(':
+ case ')':
+ case '+':
+ case '-':
+ case '.':
+ case ':':
+ case '=':
+ case '?':
+ case '/':
+ case ',':
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerSequence.cs b/Crypto/src/asn1/DerSequence.cs
new file mode 100644
index 000000000..dd67d2fed
--- /dev/null
+++ b/Crypto/src/asn1/DerSequence.cs
@@ -0,0 +1,85 @@
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class DerSequence
+ : Asn1Sequence
+ {
+ public static readonly DerSequence Empty = new DerSequence();
+
+ public static DerSequence FromVector(
+ Asn1EncodableVector v)
+ {
+ return v.Count < 1 ? Empty : new DerSequence(v);
+ }
+
+ /**
+ * create an empty sequence
+ */
+ public DerSequence()
+ : base(0)
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public DerSequence(
+ Asn1Encodable obj)
+ : base(1)
+ {
+ AddObject(obj);
+ }
+
+ public DerSequence(
+ params Asn1Encodable[] v)
+ : base(v.Length)
+ {
+ foreach (Asn1Encodable ae in v)
+ {
+ AddObject(ae);
+ }
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public DerSequence(
+ Asn1EncodableVector v)
+ : base(v.Count)
+ {
+ foreach (Asn1Encodable ae in v)
+ {
+ AddObject(ae);
+ }
+ }
+
+ /*
+ * A note on the implementation:
+ * <p>
+ * As Der requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputing Sequence,
+ * we also have to specify Constructed, and the objects length.
+ */
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ // TODO Intermediate buffer could be avoided if we could calculate expected length
+ MemoryStream bOut = new MemoryStream();
+ DerOutputStream dOut = new DerOutputStream(bOut);
+
+ foreach (Asn1Encodable obj in this)
+ {
+ dOut.WriteObject(obj);
+ }
+
+ dOut.Dispose();
+
+ byte[] bytes = bOut.ToArray();
+
+ derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, bytes);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerSet.cs b/Crypto/src/asn1/DerSet.cs
new file mode 100644
index 000000000..6d3f438bd
--- /dev/null
+++ b/Crypto/src/asn1/DerSet.cs
@@ -0,0 +1,108 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * A Der encoded set object
+ */
+ public class DerSet
+ : Asn1Set
+ {
+ public static readonly DerSet Empty = new DerSet();
+
+ public static DerSet FromVector(
+ Asn1EncodableVector v)
+ {
+ return v.Count < 1 ? Empty : new DerSet(v);
+ }
+
+ internal static DerSet FromVector(
+ Asn1EncodableVector v,
+ bool needsSorting)
+ {
+ return v.Count < 1 ? Empty : new DerSet(v, needsSorting);
+ }
+
+ /**
+ * create an empty set
+ */
+ public DerSet()
+ : base(0)
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public DerSet(
+ Asn1Encodable obj)
+ : base(1)
+ {
+ AddObject(obj);
+ }
+
+ public DerSet(
+ params Asn1Encodable[] v)
+ : base(v.Length)
+ {
+ foreach (Asn1Encodable o in v)
+ {
+ AddObject(o);
+ }
+
+ Sort();
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public DerSet(
+ Asn1EncodableVector v)
+ : this(v, true)
+ {
+ }
+
+ internal DerSet(
+ Asn1EncodableVector v,
+ bool needsSorting)
+ : base(v.Count)
+ {
+ foreach (Asn1Encodable o in v)
+ {
+ AddObject(o);
+ }
+
+ if (needsSorting)
+ {
+ Sort();
+ }
+ }
+
+ /*
+ * A note on the implementation:
+ * <p>
+ * As Der requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputing Set,
+ * we also have to specify Constructed, and the objects length.
+ */
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ // TODO Intermediate buffer could be avoided if we could calculate expected length
+ MemoryStream bOut = new MemoryStream();
+ DerOutputStream dOut = new DerOutputStream(bOut);
+
+ foreach (Asn1Encodable obj in this)
+ {
+ dOut.WriteObject(obj);
+ }
+
+ dOut.Dispose();
+
+ byte[] bytes = bOut.ToArray();
+
+ derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, bytes);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerStringBase.cs b/Crypto/src/asn1/DerStringBase.cs
new file mode 100644
index 000000000..2a5fb041e
--- /dev/null
+++ b/Crypto/src/asn1/DerStringBase.cs
@@ -0,0 +1,22 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public abstract class DerStringBase
+ : Asn1Object, IAsn1String
+ {
+ protected DerStringBase()
+ {
+ }
+
+ public abstract string GetString();
+
+ public override string ToString()
+ {
+ return GetString();
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return GetString().GetHashCode();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerT61String.cs b/Crypto/src/asn1/DerT61String.cs
new file mode 100644
index 000000000..4dee6f30c
--- /dev/null
+++ b/Crypto/src/asn1/DerT61String.cs
@@ -0,0 +1,102 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der T61String (also the teletex string) - 8-bit characters
+ */
+ public class DerT61String
+ : DerStringBase
+ {
+ private readonly string str;
+
+ /**
+ * return a T61 string from the passed in object.
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerT61String GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerT61String)
+ {
+ return (DerT61String)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return an T61 string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerT61String GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerT61String)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerT61String(Asn1OctetString.GetInstance(o).GetOctets());
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ public DerT61String(
+ byte[] str)
+ : this(Strings.FromByteArray(str))
+ {
+ }
+
+ /**
+ * basic constructor - with string.
+ */
+ public DerT61String(
+ string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.T61String, GetOctets());
+ }
+
+ public byte[] GetOctets()
+ {
+ return Strings.ToByteArray(str);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerT61String other = asn1Object as DerT61String;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerTaggedObject.cs b/Crypto/src/asn1/DerTaggedObject.cs
new file mode 100644
index 000000000..717d724b6
--- /dev/null
+++ b/Crypto/src/asn1/DerTaggedObject.cs
@@ -0,0 +1,72 @@
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * DER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+ public class DerTaggedObject
+ : Asn1TaggedObject
+ {
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DerTaggedObject(
+ int tagNo,
+ Asn1Encodable obj)
+ : base(tagNo, obj)
+ {
+ }
+
+ /**
+ * @param explicitly true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DerTaggedObject(
+ bool explicitly,
+ int tagNo,
+ Asn1Encodable obj)
+ : base(explicitly, tagNo, obj)
+ {
+ }
+
+ /**
+ * create an implicitly tagged object that contains a zero
+ * length sequence.
+ */
+ public DerTaggedObject(
+ int tagNo)
+ : base(false, tagNo, DerSequence.Empty)
+ {
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ if (!IsEmpty())
+ {
+ byte[] bytes = obj.GetDerEncoded();
+
+ if (explicitly)
+ {
+ derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, bytes);
+ }
+ else
+ {
+ //
+ // need to mark constructed types... (preserve Constructed tag)
+ //
+ int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged;
+ derOut.WriteTag(flags, tagNo);
+ derOut.Write(bytes, 1, bytes.Length - 1);
+ }
+ }
+ else
+ {
+ derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, new byte[0]);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerUTCTime.cs b/Crypto/src/asn1/DerUTCTime.cs
new file mode 100644
index 000000000..56fabeb47
--- /dev/null
+++ b/Crypto/src/asn1/DerUTCTime.cs
@@ -0,0 +1,263 @@
+using System;
+using System.Globalization;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * UTC time object.
+ */
+ public class DerUtcTime
+ : Asn1Object
+ {
+ private readonly string time;
+
+ /**
+ * return an UTC Time from the passed in object.
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerUtcTime GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerUtcTime)
+ {
+ return (DerUtcTime)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return an UTC Time from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerUtcTime GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerUtcTime)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerUtcTime(((Asn1OctetString)o).GetOctets());
+ }
+
+ /**
+ * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+ * never encoded. When you're creating one of these objects from scratch, that's
+ * what you want to use, otherwise we'll try to deal with whatever Gets read from
+ * the input stream... (this is why the input format is different from the GetTime()
+ * method output).
+ * <p>
+ * @param time the time string.</p>
+ */
+ public DerUtcTime(
+ string time)
+ {
+ if (time == null)
+ throw new ArgumentNullException("time");
+
+ this.time = time;
+
+ try
+ {
+ ToDateTime();
+ }
+ catch (FormatException e)
+ {
+ throw new ArgumentException("invalid date string: " + e.Message);
+ }
+ }
+
+ /**
+ * base constructor from a DateTime object
+ */
+ public DerUtcTime(
+ DateTime time)
+ {
+ this.time = time.ToString("yyMMddHHmmss") + "Z";
+ }
+
+ internal DerUtcTime(
+ byte[] bytes)
+ {
+ //
+ // explicitly convert to characters
+ //
+ this.time = Strings.FromAsciiByteArray(bytes);
+ }
+
+// public DateTime ToDateTime()
+// {
+// string tm = this.AdjustedTimeString;
+//
+// return new DateTime(
+// Int16.Parse(tm.Substring(0, 4)),
+// Int16.Parse(tm.Substring(4, 2)),
+// Int16.Parse(tm.Substring(6, 2)),
+// Int16.Parse(tm.Substring(8, 2)),
+// Int16.Parse(tm.Substring(10, 2)),
+// Int16.Parse(tm.Substring(12, 2)));
+// }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use ToAdjustedDateTime().
+ *
+ * @return the resulting date
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public DateTime ToDateTime()
+ {
+ return ParseDateString(TimeString, @"yyMMddHHmmss'GMT'zzz");
+ }
+
+ /**
+ * return the time as an adjusted date
+ * in the range of 1950 - 2049.
+ *
+ * @return a date in the range of 1950 to 2049.
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public DateTime ToAdjustedDateTime()
+ {
+ return ParseDateString(AdjustedTimeString, @"yyyyMMddHHmmss'GMT'zzz");
+ }
+
+ private DateTime ParseDateString(
+ string dateStr,
+ string formatStr)
+ {
+ DateTime dt = DateTime.ParseExact(
+ dateStr,
+ formatStr,
+ DateTimeFormatInfo.InvariantInfo);
+
+ return dt.ToUniversalTime();
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ * <p>
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ * <pre>
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz");
+ * </pre>
+ * To read in the time and Get a date which is compatible with our local
+ * time zone.</p>
+ * <p>
+ * <b>Note:</b> In some cases, due to the local date processing, this
+ * may lead to unexpected results. If you want to stick the normal
+ * convention of 1950 to 2049 use the GetAdjustedTime() method.</p>
+ */
+ public string TimeString
+ {
+ get
+ {
+ //
+ // standardise the format.
+ //
+ if (time.IndexOf('-') < 0 && time.IndexOf('+') < 0)
+ {
+ if (time.Length == 11)
+ {
+ return time.Substring(0, 10) + "00GMT+00:00";
+ }
+ else
+ {
+ return time.Substring(0, 12) + "GMT+00:00";
+ }
+ }
+ else
+ {
+ int index = time.IndexOf('-');
+ if (index < 0)
+ {
+ index = time.IndexOf('+');
+ }
+ string d = time;
+
+ if (index == time.Length - 3)
+ {
+ d += "00";
+ }
+
+ if (index == 10)
+ {
+ return d.Substring(0, 10) + "00GMT" + d.Substring(10, 3) + ":" + d.Substring(13, 2);
+ }
+ else
+ {
+ return d.Substring(0, 12) + "GMT" + d.Substring(12, 3) + ":" + d.Substring(15, 2);
+ }
+ }
+ }
+ }
+
+ [Obsolete("Use 'AdjustedTimeString' property instead")]
+ public string AdjustedTime
+ {
+ get { return AdjustedTimeString; }
+ }
+
+ /// <summary>
+ /// Return a time string as an adjusted date with a 4 digit year.
+ /// This goes in the range of 1950 - 2049.
+ /// </summary>
+ public string AdjustedTimeString
+ {
+ get
+ {
+ string d = TimeString;
+ string c = d[0] < '5' ? "20" : "19";
+
+ return c + d;
+ }
+ }
+
+ private byte[] GetOctets()
+ {
+ return Strings.ToAsciiByteArray(time);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.UtcTime, GetOctets());
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerUtcTime other = asn1Object as DerUtcTime;
+
+ if (other == null)
+ return false;
+
+ return this.time.Equals(other.time);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return time.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return time;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerUTF8String.cs b/Crypto/src/asn1/DerUTF8String.cs
new file mode 100644
index 000000000..92a50e824
--- /dev/null
+++ b/Crypto/src/asn1/DerUTF8String.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der UTF8String object.
+ */
+ public class DerUtf8String
+ : DerStringBase
+ {
+ private readonly string str;
+
+ /**
+ * return an UTF8 string from the passed in object.
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerUtf8String GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerUtf8String)
+ {
+ return (DerUtf8String)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return an UTF8 string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerUtf8String GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerUtf8String)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerUtf8String(Asn1OctetString.GetInstance(o).GetOctets());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DerUtf8String(
+ byte[] str)
+ : this(Encoding.UTF8.GetString(str, 0, str.Length))
+ {
+ }
+
+ /**
+ * basic constructor
+ */
+ public DerUtf8String(
+ string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerUtf8String other = asn1Object as DerUtf8String;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerUniversalString.cs b/Crypto/src/asn1/DerUniversalString.cs
new file mode 100644
index 000000000..305102f2f
--- /dev/null
+++ b/Crypto/src/asn1/DerUniversalString.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der UniversalString object.
+ */
+ public class DerUniversalString
+ : DerStringBase
+ {
+ private static readonly char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ private readonly byte[] str;
+
+ /**
+ * return a Universal string from the passed in object.
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerUniversalString GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerUniversalString)
+ {
+ return (DerUniversalString)obj;
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return a Universal string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerUniversalString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ Asn1Object o = obj.GetObject();
+
+ if (isExplicit || o is DerUniversalString)
+ {
+ return GetInstance(o);
+ }
+
+ return new DerUniversalString(Asn1OctetString.GetInstance(o).GetOctets());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DerUniversalString(
+ byte[] str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ StringBuilder buffer = new StringBuilder("#");
+ byte[] enc = GetDerEncoded();
+
+ for (int i = 0; i != enc.Length; i++)
+ {
+ uint ubyte = enc[i];
+ buffer.Append(table[(ubyte >> 4) & 0xf]);
+ buffer.Append(table[enc[i] & 0xf]);
+ }
+
+ return buffer.ToString();
+ }
+
+ public byte[] GetOctets()
+ {
+ return (byte[]) str.Clone();
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.UniversalString, this.str);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerUniversalString other = asn1Object as DerUniversalString;
+
+ if (other == null)
+ return false;
+
+// return this.GetString().Equals(other.GetString());
+ return Arrays.AreEqual(this.str, other.str);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerUnknownTag.cs b/Crypto/src/asn1/DerUnknownTag.cs
new file mode 100644
index 000000000..1e0e61495
--- /dev/null
+++ b/Crypto/src/asn1/DerUnknownTag.cs
@@ -0,0 +1,80 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * We insert one of these when we find a tag we don't recognise.
+ */
+ public class DerUnknownTag
+ : Asn1Object
+ {
+ private readonly bool isConstructed;
+ private readonly int tag;
+ private readonly byte[] data;
+
+ /**
+ * @param tag the tag value.
+ * @param data the contents octets.
+ */
+ public DerUnknownTag(
+ int tag,
+ byte[] data)
+ : this(false, tag, data)
+ {
+ }
+
+ public DerUnknownTag(
+ bool isConstructed,
+ int tag,
+ byte[] data)
+ {
+ if (data == null)
+ throw new ArgumentNullException("data");
+
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.data = data;
+ }
+
+ public bool IsConstructed
+ {
+ get { return isConstructed; }
+ }
+
+ public int Tag
+ {
+ get { return tag; }
+ }
+
+ public byte[] GetData()
+ {
+ return data;
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(isConstructed ? Asn1Tags.Constructed : 0, tag, data);
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerUnknownTag other = asn1Object as DerUnknownTag;
+
+ if (other == null)
+ return false;
+
+ return this.isConstructed == other.isConstructed
+ && this.tag == other.tag
+ && Arrays.AreEqual(this.data, other.data);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(data);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/DerVisibleString.cs b/Crypto/src/asn1/DerVisibleString.cs
new file mode 100644
index 000000000..84c9caade
--- /dev/null
+++ b/Crypto/src/asn1/DerVisibleString.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Der VisibleString object.
+ */
+ public class DerVisibleString
+ : DerStringBase
+ {
+ private readonly string str;
+
+ /**
+ * return a Visible string from the passed in object.
+ *
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static DerVisibleString GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DerVisibleString)
+ {
+ return (DerVisibleString)obj;
+ }
+
+ if (obj is Asn1OctetString)
+ {
+ return new DerVisibleString(((Asn1OctetString)obj).GetOctets());
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return GetInstance(((Asn1TaggedObject)obj).GetObject());
+ }
+
+ throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+ }
+
+ /**
+ * return a Visible string from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DerVisibleString GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(obj.GetObject());
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DerVisibleString(
+ byte[] str)
+ : this(Strings.FromAsciiByteArray(str))
+ {
+ }
+
+ /**
+ * basic constructor
+ */
+ public DerVisibleString(
+ string str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+
+ this.str = str;
+ }
+
+ public override string GetString()
+ {
+ return str;
+ }
+
+ public byte[] GetOctets()
+ {
+ return Strings.ToAsciiByteArray(str);
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ derOut.WriteEncoded(Asn1Tags.VisibleString, GetOctets());
+ }
+
+ protected override bool Asn1Equals(
+ Asn1Object asn1Object)
+ {
+ DerVisibleString other = asn1Object as DerVisibleString;
+
+ if (other == null)
+ return false;
+
+ return this.str.Equals(other.str);
+ }
+
+ protected override int Asn1GetHashCode()
+ {
+ return this.str.GetHashCode();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/IAsn1ApplicationSpecificParser.cs b/Crypto/src/asn1/IAsn1ApplicationSpecificParser.cs
new file mode 100644
index 000000000..89cf64c70
--- /dev/null
+++ b/Crypto/src/asn1/IAsn1ApplicationSpecificParser.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public interface IAsn1ApplicationSpecificParser
+ : IAsn1Convertible
+ {
+ IAsn1Convertible ReadObject();
+ }
+}
diff --git a/Crypto/src/asn1/IAsn1Choice.cs b/Crypto/src/asn1/IAsn1Choice.cs
new file mode 100644
index 000000000..ecd76e427
--- /dev/null
+++ b/Crypto/src/asn1/IAsn1Choice.cs
@@ -0,0 +1,17 @@
+
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * Marker interface for CHOICE objects - if you implement this in a roll-your-own
+ * object, any attempt to tag the object implicitly will convert the tag to an
+ * explicit one as the encoding rules require.
+ * <p>
+ * If you use this interface your class should also implement the getInstance
+ * pattern which takes a tag object and the tagging mode used.
+ * </p>
+ */
+ public interface IAsn1Choice
+ {
+ // marker interface
+ }
+}
diff --git a/Crypto/src/asn1/IAsn1Convertible.cs b/Crypto/src/asn1/IAsn1Convertible.cs
new file mode 100644
index 000000000..d3f83afc9
--- /dev/null
+++ b/Crypto/src/asn1/IAsn1Convertible.cs
@@ -0,0 +1,7 @@
+namespace Org.BouncyCastle.Asn1
+{
+ public interface IAsn1Convertible
+ {
+ Asn1Object ToAsn1Object();
+ }
+}
diff --git a/Crypto/src/asn1/IAsn1String.cs b/Crypto/src/asn1/IAsn1String.cs
new file mode 100644
index 000000000..cbc2635ff
--- /dev/null
+++ b/Crypto/src/asn1/IAsn1String.cs
@@ -0,0 +1,10 @@
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * basic interface for Der string objects.
+ */
+ public interface IAsn1String
+ {
+ string GetString();
+ }
+}
diff --git a/Crypto/src/asn1/IndefiniteLengthInputStream.cs b/Crypto/src/asn1/IndefiniteLengthInputStream.cs
new file mode 100644
index 000000000..56c1bdfbc
--- /dev/null
+++ b/Crypto/src/asn1/IndefiniteLengthInputStream.cs
@@ -0,0 +1,166 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ class IndefiniteLengthInputStream
+ : LimitedInputStream
+ {
+ private int _lookAhead;
+ private bool _eofOn00 = true;
+
+ internal IndefiniteLengthInputStream(
+ Stream inStream,
+ int limit)
+ : base(inStream, limit)
+ {
+ _lookAhead = RequireByte();
+ CheckForEof();
+ }
+
+ internal void SetEofOn00(
+ bool eofOn00)
+ {
+ _eofOn00 = eofOn00;
+ CheckForEof();
+ }
+
+ private bool CheckForEof()
+ {
+ if (_lookAhead == 0x00 && _eofOn00)
+ {
+ int extra = RequireByte();
+ if (extra != 0)
+ {
+ throw new IOException("malformed end-of-contents marker");
+ }
+
+ _lookAhead = -1;
+ SetParentEofDetect(true);
+ }
+ return _lookAhead < 0;
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ // Only use this optimisation if we aren't checking for 00
+ if (_eofOn00 || count <= 1)
+ return base.Read(buffer, offset, count);
+
+ if (_lookAhead < 0)
+ return 0;
+
+ int numRead = _in.Read(buffer, offset + 1, count - 1);
+
+ if (numRead <= 0)
+ {
+ // Corrupted stream
+ throw new EndOfStreamException();
+ }
+
+ buffer[offset] = (byte)_lookAhead;
+ _lookAhead = RequireByte();
+
+ return numRead + 1;
+ }
+
+ public override int ReadByte()
+ {
+ if (CheckForEof())
+ return -1;
+
+ int result = _lookAhead;
+ _lookAhead = RequireByte();
+ return result;
+ }
+
+ private int RequireByte()
+ {
+ int b = _in.ReadByte();
+ if (b < 0)
+ {
+ // Corrupted stream
+ throw new EndOfStreamException();
+ }
+ return b;
+ }
+ }
+}
+
+//using System;
+//using System.IO;
+
+//namespace Org.BouncyCastle.Asn1
+//{
+// class IndefiniteLengthInputStream
+// : LimitedInputStream
+// {
+// private bool _eofReached = false;
+// private bool _eofOn00 = true;
+
+// internal IndefiniteLengthInputStream(
+// Stream inStream,
+// int limit)
+// : base(inStream, limit)
+// {
+// }
+
+// internal void SetEofOn00(
+// bool eofOn00)
+// {
+// _eofOn00 = eofOn00;
+// }
+
+// public override int Read(
+// byte[] buffer,
+// int offset,
+// int count)
+// {
+// if (_eofReached)
+// return 0;
+
+// if (_eofOn00)
+// return base.Read(buffer, offset, count);
+
+// int numRead = _in.Read(buffer, offset, count);
+
+// if (numRead <= 0)
+// throw new EndOfStreamException();
+
+// return numRead;
+// }
+
+// public override int ReadByte()
+// {
+// if (_eofReached)
+// return -1;
+
+// int b1 = _in.ReadByte();
+
+// if (b1 < 0)
+// throw new EndOfStreamException();
+
+// if (b1 == 0 && _eofOn00)
+// {
+// int b2 = _in.ReadByte();
+
+// if (b2 < 0)
+// throw new EndOfStreamException();
+
+// if (b2 == 0)
+// {
+// _eofReached = true;
+// SetParentEofDetect(true);
+// return -1;
+// }
+
+// throw new InvalidDataException();
+// }
+
+// return b1;
+// }
+// }
+//}
diff --git a/Crypto/src/asn1/LazyASN1InputStream.cs b/Crypto/src/asn1/LazyASN1InputStream.cs
new file mode 100644
index 000000000..4cf2305fd
--- /dev/null
+++ b/Crypto/src/asn1/LazyASN1InputStream.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ public class LazyAsn1InputStream
+ : Asn1InputStream
+ {
+ public LazyAsn1InputStream(
+ byte[] input)
+ : base(input)
+ {
+ }
+
+ public LazyAsn1InputStream(
+ Stream inputStream)
+ : base(inputStream)
+ {
+ }
+
+ internal override DerSequence CreateDerSequence(
+ DefiniteLengthInputStream dIn)
+ {
+ return new LazyDerSequence(dIn.ToArray());
+ }
+
+ internal override DerSet CreateDerSet(
+ DefiniteLengthInputStream dIn)
+ {
+ return new LazyDerSet(dIn.ToArray());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/LazyDERSequence.cs b/Crypto/src/asn1/LazyDERSequence.cs
new file mode 100644
index 000000000..5e3dd076e
--- /dev/null
+++ b/Crypto/src/asn1/LazyDERSequence.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal class LazyDerSequence
+ : DerSequence
+ {
+ private byte[] encoded;
+ private bool parsed = false;
+
+ internal LazyDerSequence(
+ byte[] encoded)
+ {
+ this.encoded = encoded;
+ }
+
+ private void Parse()
+ {
+ lock (this)
+ {
+ if (!parsed)
+ {
+ Asn1InputStream e = new LazyAsn1InputStream(encoded);
+
+ Asn1Object o;
+ while ((o = e.ReadObject()) != null)
+ {
+ AddObject(o);
+ }
+
+ encoded = null;
+ parsed = true;
+ }
+ }
+ }
+
+ public override Asn1Encodable this[int index]
+ {
+ get
+ {
+ Parse();
+
+ return base[index];
+ }
+ }
+
+ public override IEnumerator GetEnumerator()
+ {
+ Parse();
+
+ return base.GetEnumerator();
+ }
+
+ public override int Count
+ {
+ get
+ {
+ Parse();
+
+ return base.Count;
+ }
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ lock (this)
+ {
+ if (parsed)
+ {
+ base.Encode(derOut);
+ }
+ else
+ {
+ derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, encoded);
+ }
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/LazyDERSet.cs b/Crypto/src/asn1/LazyDERSet.cs
new file mode 100644
index 000000000..84fce4808
--- /dev/null
+++ b/Crypto/src/asn1/LazyDERSet.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal class LazyDerSet
+ : DerSet
+ {
+ private byte[] encoded;
+ private bool parsed = false;
+
+ internal LazyDerSet(
+ byte[] encoded)
+ {
+ this.encoded = encoded;
+ }
+
+ private void Parse()
+ {
+ lock (this)
+ {
+ if (!parsed)
+ {
+ Asn1InputStream e = new LazyAsn1InputStream(encoded);
+
+ Asn1Object o;
+ while ((o = e.ReadObject()) != null)
+ {
+ AddObject(o);
+ }
+
+ encoded = null;
+ parsed = true;
+ }
+ }
+ }
+
+ public override Asn1Encodable this[int index]
+ {
+ get
+ {
+ Parse();
+
+ return base[index];
+ }
+ }
+
+ public override IEnumerator GetEnumerator()
+ {
+ Parse();
+
+ return base.GetEnumerator();
+ }
+
+ public override int Count
+ {
+ get
+ {
+ Parse();
+
+ return base.Count;
+ }
+ }
+
+ internal override void Encode(
+ DerOutputStream derOut)
+ {
+ lock (this)
+ {
+ if (parsed)
+ {
+ base.Encode(derOut);
+ }
+ else
+ {
+ derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, encoded);
+ }
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/LimitedInputStream.cs b/Crypto/src/asn1/LimitedInputStream.cs
new file mode 100644
index 000000000..62486aa77
--- /dev/null
+++ b/Crypto/src/asn1/LimitedInputStream.cs
@@ -0,0 +1,35 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+ internal abstract class LimitedInputStream
+ : BaseInputStream
+ {
+ protected readonly Stream _in;
+ private int _limit;
+
+ internal LimitedInputStream(
+ Stream inStream,
+ int limit)
+ {
+ this._in = inStream;
+ this._limit = limit;
+ }
+
+ internal virtual int GetRemaining()
+ {
+ // TODO: maybe one day this can become more accurate
+ return _limit;
+ }
+
+ protected virtual void SetParentEofDetect(bool on)
+ {
+ if (_in is IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).SetEofOn00(on);
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/OidTokenizer.cs b/Crypto/src/asn1/OidTokenizer.cs
new file mode 100644
index 000000000..6e76e8c8b
--- /dev/null
+++ b/Crypto/src/asn1/OidTokenizer.cs
@@ -0,0 +1,45 @@
+namespace Org.BouncyCastle.Asn1
+{
+ /**
+ * class for breaking up an Oid 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 OidTokenizer
+ {
+ private string oid;
+ private int index;
+
+ public OidTokenizer(
+ string oid)
+ {
+ this.oid = oid;
+ }
+
+ public bool HasMoreTokens
+ {
+ get { return index != -1; }
+ }
+
+ public string NextToken()
+ {
+ if (index == -1)
+ {
+ return null;
+ }
+
+ int end = oid.IndexOf('.', index);
+ if (end == -1)
+ {
+ string lastToken = oid.Substring(index);
+ index = -1;
+ return lastToken;
+ }
+
+ string nextToken = oid.Substring(index, end - index);
+ index = end + 1;
+ return nextToken;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/bc/BCObjectIdentifiers.cs b/Crypto/src/asn1/bc/BCObjectIdentifiers.cs
new file mode 100644
index 000000000..075e5384c
--- /dev/null
+++ b/Crypto/src/asn1/bc/BCObjectIdentifiers.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.BC
+{
+ public abstract class BCObjectIdentifiers
+ {
+ // iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
+ // 1.3.6.1.4.1.22554
+ public static readonly DerObjectIdentifier bc = new DerObjectIdentifier("1.3.6.1.4.1.22554");
+
+ // pbe(1) algorithms
+ public static readonly DerObjectIdentifier bc_pbe = new DerObjectIdentifier(bc + ".1");
+
+ // SHA-1(1)
+ public static readonly DerObjectIdentifier bc_pbe_sha1 = new DerObjectIdentifier(bc_pbe + ".1");
+
+ // SHA-2(2) . (SHA-256(1)|SHA-384(2)|SHA-512(3)|SHA-224(4))
+ public static readonly DerObjectIdentifier bc_pbe_sha256 = new DerObjectIdentifier(bc_pbe + ".2.1");
+ public static readonly DerObjectIdentifier bc_pbe_sha384 = new DerObjectIdentifier(bc_pbe + ".2.2");
+ public static readonly DerObjectIdentifier bc_pbe_sha512 = new DerObjectIdentifier(bc_pbe + ".2.3");
+ public static readonly DerObjectIdentifier bc_pbe_sha224 = new DerObjectIdentifier(bc_pbe + ".2.4");
+
+ // PKCS-5(1)|PKCS-12(2)
+ public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs5 = new DerObjectIdentifier(bc_pbe_sha1 + ".1");
+ public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12 = new DerObjectIdentifier(bc_pbe_sha1 + ".2");
+
+ public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs5 = new DerObjectIdentifier(bc_pbe_sha256 + ".1");
+ public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12 = new DerObjectIdentifier(bc_pbe_sha256 + ".2");
+
+ // AES(1) . (CBC-128(2)|CBC-192(22)|CBC-256(42))
+ public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.2");
+ public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.22");
+ public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.42");
+
+ public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.2");
+ public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.22");
+ public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.42");
+ }
+}
\ No newline at end of file
diff --git a/Crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs b/Crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs
new file mode 100644
index 000000000..3cdb128a6
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CAKeyUpdAnnContent
+ : Asn1Encodable
+ {
+ private readonly CmpCertificate oldWithNew;
+ private readonly CmpCertificate newWithOld;
+ private readonly CmpCertificate newWithNew;
+
+ private CAKeyUpdAnnContent(Asn1Sequence seq)
+ {
+ oldWithNew = CmpCertificate.GetInstance(seq[0]);
+ newWithOld = CmpCertificate.GetInstance(seq[1]);
+ newWithNew = CmpCertificate.GetInstance(seq[2]);
+ }
+
+ public static CAKeyUpdAnnContent GetInstance(object obj)
+ {
+ if (obj is CAKeyUpdAnnContent)
+ return (CAKeyUpdAnnContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new CAKeyUpdAnnContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual CmpCertificate OldWithNew
+ {
+ get { return oldWithNew; }
+ }
+
+ public virtual CmpCertificate NewWithOld
+ {
+ get { return newWithOld; }
+ }
+
+ public virtual CmpCertificate NewWithNew
+ {
+ get { return newWithNew; }
+ }
+
+ /**
+ * <pre>
+ * CAKeyUpdAnnContent ::= SEQUENCE {
+ * oldWithNew CmpCertificate, -- old pub signed with new priv
+ * newWithOld CmpCertificate, -- new pub signed with old priv
+ * newWithNew CmpCertificate -- new pub signed with new priv
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(oldWithNew, newWithOld, newWithNew);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertConfirmContent.cs b/Crypto/src/asn1/cmp/CertConfirmContent.cs
new file mode 100644
index 000000000..f4016d8d8
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertConfirmContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertConfirmContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private CertConfirmContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertConfirmContent GetInstance(object obj)
+ {
+ if (obj is CertConfirmContent)
+ return (CertConfirmContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertConfirmContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual CertStatus[] ToCertStatusArray()
+ {
+ CertStatus[] result = new CertStatus[content.Count];
+ for (int i = 0; i != result.Length; i++)
+ {
+ result[i] = CertStatus.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CertConfirmContent ::= SEQUENCE OF CertStatus
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertOrEncCert.cs b/Crypto/src/asn1/cmp/CertOrEncCert.cs
new file mode 100644
index 000000000..4c049c180
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertOrEncCert.cs
@@ -0,0 +1,85 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertOrEncCert
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly CmpCertificate certificate;
+ private readonly EncryptedValue encryptedCert;
+
+ private CertOrEncCert(Asn1TaggedObject tagged)
+ {
+ if (tagged.TagNo == 0)
+ {
+ certificate = CmpCertificate.GetInstance(tagged.GetObject());
+ }
+ else if (tagged.TagNo == 1)
+ {
+ encryptedCert = EncryptedValue.GetInstance(tagged.GetObject());
+ }
+ else
+ {
+ throw new ArgumentException("unknown tag: " + tagged.TagNo, "tagged");
+ }
+ }
+
+ public static CertOrEncCert GetInstance(object obj)
+ {
+ if (obj is CertOrEncCert)
+ return (CertOrEncCert)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new CertOrEncCert((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertOrEncCert(CmpCertificate certificate)
+ {
+ if (certificate == null)
+ throw new ArgumentNullException("certificate");
+
+ this.certificate = certificate;
+ }
+
+ public CertOrEncCert(EncryptedValue encryptedCert)
+ {
+ if (encryptedCert == null)
+ throw new ArgumentNullException("encryptedCert");
+
+ this.encryptedCert = encryptedCert;
+ }
+
+ public virtual CmpCertificate Certificate
+ {
+ get { return certificate; }
+ }
+
+ public virtual EncryptedValue EncryptedCert
+ {
+ get { return encryptedCert; }
+ }
+
+ /**
+ * <pre>
+ * CertOrEncCert ::= CHOICE {
+ * certificate [0] CMPCertificate,
+ * encryptedCert [1] EncryptedValue
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (certificate != null)
+ {
+ return new DerTaggedObject(true, 0, certificate);
+ }
+
+ return new DerTaggedObject(true, 1, encryptedCert);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertRepMessage.cs b/Crypto/src/asn1/cmp/CertRepMessage.cs
new file mode 100644
index 000000000..c22b079c8
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertRepMessage.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertRepMessage
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence caPubs;
+ private readonly Asn1Sequence response;
+
+ private CertRepMessage(Asn1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.Count > 1)
+ {
+ caPubs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[index++], true);
+ }
+
+ response = Asn1Sequence.GetInstance(seq[index]);
+ }
+
+ public static CertRepMessage GetInstance(object obj)
+ {
+ if (obj is CertRepMessage)
+ return (CertRepMessage)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertRepMessage((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertRepMessage(CmpCertificate[] caPubs, CertResponse[] response)
+ {
+ if (response == null)
+ throw new ArgumentNullException("response");
+
+ if (caPubs != null)
+ {
+ this.caPubs = new DerSequence(caPubs);
+ }
+
+ this.response = new DerSequence(response);
+ }
+
+ public virtual CmpCertificate[] GetCAPubs()
+ {
+ if (caPubs == null)
+ return null;
+
+ CmpCertificate[] results = new CmpCertificate[caPubs.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CmpCertificate.GetInstance(caPubs[i]);
+ }
+ return results;
+ }
+
+ public virtual CertResponse[] GetResponse()
+ {
+ CertResponse[] results = new CertResponse[response.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertResponse.GetInstance(response[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * CertRepMessage ::= SEQUENCE {
+ * caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL,
+ * response SEQUENCE OF CertResponse
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (caPubs != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, caPubs));
+ }
+
+ v.Add(response);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertResponse.cs b/Crypto/src/asn1/cmp/CertResponse.cs
new file mode 100644
index 000000000..246b8ce70
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertResponse.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertResponse
+ : Asn1Encodable
+ {
+ private readonly DerInteger certReqId;
+ private readonly PkiStatusInfo status;
+ private readonly CertifiedKeyPair certifiedKeyPair;
+ private readonly Asn1OctetString rspInfo;
+
+ private CertResponse(Asn1Sequence seq)
+ {
+ certReqId = DerInteger.GetInstance(seq[0]);
+ status = PkiStatusInfo.GetInstance(seq[1]);
+
+ if (seq.Count >= 3)
+ {
+ if (seq.Count == 3)
+ {
+ Asn1Encodable o = seq[2];
+ if (o is Asn1OctetString)
+ {
+ rspInfo = Asn1OctetString.GetInstance(o);
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.GetInstance(o);
+ }
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.GetInstance(seq[2]);
+ rspInfo = Asn1OctetString.GetInstance(seq[3]);
+ }
+ }
+ }
+
+ public static CertResponse GetInstance(object obj)
+ {
+ if (obj is CertResponse)
+ return (CertResponse)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertResponse((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertResponse(
+ DerInteger certReqId,
+ PkiStatusInfo status)
+ : this(certReqId, status, null, null)
+ {
+ }
+
+ public CertResponse(
+ DerInteger certReqId,
+ PkiStatusInfo status,
+ CertifiedKeyPair certifiedKeyPair,
+ Asn1OctetString rspInfo)
+ {
+ if (certReqId == null)
+ throw new ArgumentNullException("certReqId");
+
+ if (status == null)
+ throw new ArgumentNullException("status");
+
+ this.certReqId = certReqId;
+ this.status = status;
+ this.certifiedKeyPair = certifiedKeyPair;
+ this.rspInfo = rspInfo;
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual PkiStatusInfo Status
+ {
+ get { return status; }
+ }
+
+ public virtual CertifiedKeyPair CertifiedKeyPair
+ {
+ get { return certifiedKeyPair; }
+ }
+
+ /**
+ * <pre>
+ * CertResponse ::= SEQUENCE {
+ * certReqId INTEGER,
+ * -- to match this response with corresponding request (a value
+ * -- of -1 is to be used if certReqId is not specified in the
+ * -- corresponding request)
+ * status PKIStatusInfo,
+ * certifiedKeyPair CertifiedKeyPair OPTIONAL,
+ * rspInfo OCTET STRING OPTIONAL
+ * -- analogous to the id-regInfo-utf8Pairs string defined
+ * -- for regInfo in CertReqMsg [CRMF]
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReqId, status);
+ v.AddOptional(certifiedKeyPair);
+ v.AddOptional(rspInfo);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertStatus.cs b/Crypto/src/asn1/cmp/CertStatus.cs
new file mode 100644
index 000000000..52d5ac504
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertStatus.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertStatus
+ : Asn1Encodable
+ {
+ private readonly Asn1OctetString certHash;
+ private readonly DerInteger certReqId;
+ private readonly PkiStatusInfo statusInfo;
+
+ private CertStatus(Asn1Sequence seq)
+ {
+ certHash = Asn1OctetString.GetInstance(seq[0]);
+ certReqId = DerInteger.GetInstance(seq[1]);
+
+ if (seq.Count > 2)
+ {
+ statusInfo = PkiStatusInfo.GetInstance(seq[2]);
+ }
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId)
+ {
+ this.certHash = new DerOctetString(certHash);
+ this.certReqId = new DerInteger(certReqId);
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId, PkiStatusInfo statusInfo)
+ {
+ this.certHash = new DerOctetString(certHash);
+ this.certReqId = new DerInteger(certReqId);
+ this.statusInfo = statusInfo;
+ }
+
+ public static CertStatus GetInstance(object obj)
+ {
+ if (obj is CertStatus)
+ return (CertStatus)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertStatus((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual Asn1OctetString CertHash
+ {
+ get { return certHash; }
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual PkiStatusInfo StatusInfo
+ {
+ get { return statusInfo; }
+ }
+
+ /**
+ * <pre>
+ * CertStatus ::= SEQUENCE {
+ * certHash OCTET STRING,
+ * -- the hash of the certificate, using the same hash algorithm
+ * -- as is used to create and verify the certificate signature
+ * certReqId INTEGER,
+ * -- to match this confirmation with the corresponding req/rep
+ * statusInfo PKIStatusInfo OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certHash, certReqId);
+ v.AddOptional(statusInfo);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CertifiedKeyPair.cs b/Crypto/src/asn1/cmp/CertifiedKeyPair.cs
new file mode 100644
index 000000000..655dde0c5
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CertifiedKeyPair.cs
@@ -0,0 +1,114 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CertifiedKeyPair
+ : Asn1Encodable
+ {
+ private readonly CertOrEncCert certOrEncCert;
+ private readonly EncryptedValue privateKey;
+ private readonly PkiPublicationInfo publicationInfo;
+
+ private CertifiedKeyPair(Asn1Sequence seq)
+ {
+ certOrEncCert = CertOrEncCert.GetInstance(seq[0]);
+
+ if (seq.Count >= 2)
+ {
+ if (seq.Count == 2)
+ {
+ Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1]);
+ if (tagged.TagNo == 0)
+ {
+ privateKey = EncryptedValue.GetInstance(tagged.GetObject());
+ }
+ else
+ {
+ publicationInfo = PkiPublicationInfo.GetInstance(tagged.GetObject());
+ }
+ }
+ else
+ {
+ privateKey = EncryptedValue.GetInstance(Asn1TaggedObject.GetInstance(seq[1]));
+ publicationInfo = PkiPublicationInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[2]));
+ }
+ }
+ }
+
+ public static CertifiedKeyPair GetInstance(object obj)
+ {
+ if (obj is CertifiedKeyPair)
+ return (CertifiedKeyPair)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertifiedKeyPair((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert)
+ : this(certOrEncCert, null, null)
+ {
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert,
+ EncryptedValue privateKey,
+ PkiPublicationInfo publicationInfo
+ )
+ {
+ if (certOrEncCert == null)
+ throw new ArgumentNullException("certOrEncCert");
+
+ this.certOrEncCert = certOrEncCert;
+ this.privateKey = privateKey;
+ this.publicationInfo = publicationInfo;
+ }
+
+ public virtual CertOrEncCert CertOrEncCert
+ {
+ get { return certOrEncCert; }
+ }
+
+ public virtual EncryptedValue PrivateKey
+ {
+ get { return privateKey; }
+ }
+
+ public virtual PkiPublicationInfo PublicationInfo
+ {
+ get { return publicationInfo; }
+ }
+
+ /**
+ * <pre>
+ * CertifiedKeyPair ::= SEQUENCE {
+ * certOrEncCert CertOrEncCert,
+ * privateKey [0] EncryptedValue OPTIONAL,
+ * -- see [CRMF] for comment on encoding
+ * publicationInfo [1] PKIPublicationInfo OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certOrEncCert);
+
+ if (privateKey != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, privateKey));
+ }
+
+ if (publicationInfo != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, publicationInfo));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/Challenge.cs b/Crypto/src/asn1/cmp/Challenge.cs
new file mode 100644
index 000000000..bee5f96f5
--- /dev/null
+++ b/Crypto/src/asn1/cmp/Challenge.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class Challenge
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier owf;
+ private readonly Asn1OctetString witness;
+ private readonly Asn1OctetString challenge;
+
+ private Challenge(Asn1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.Count == 3)
+ {
+ owf = AlgorithmIdentifier.GetInstance(seq[index++]);
+ }
+
+ witness = Asn1OctetString.GetInstance(seq[index++]);
+ challenge = Asn1OctetString.GetInstance(seq[index]);
+ }
+
+ public static Challenge GetInstance(object obj)
+ {
+ if (obj is Challenge)
+ return (Challenge)obj;
+
+ if (obj is Asn1Sequence)
+ return new Challenge((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual AlgorithmIdentifier Owf
+ {
+ get { return owf; }
+ }
+
+ /**
+ * <pre>
+ * Challenge ::= SEQUENCE {
+ * owf AlgorithmIdentifier OPTIONAL,
+ *
+ * -- MUST be present in the first Challenge; MAY be omitted in
+ * -- any subsequent Challenge in POPODecKeyChallContent (if
+ * -- omitted, then the owf used in the immediately preceding
+ * -- Challenge is to be used).
+ *
+ * witness OCTET STRING,
+ * -- the result of applying the one-way function (owf) to a
+ * -- randomly-generated INTEGER, A. [Note that a different
+ * -- INTEGER MUST be used for each Challenge.]
+ * challenge OCTET STRING
+ * -- the encryption (under the public key for which the cert.
+ * -- request is being made) of Rand, where Rand is specified as
+ * -- Rand ::= SEQUENCE {
+ * -- int INTEGER,
+ * -- - the randomly-generated INTEGER A (above)
+ * -- sender GeneralName
+ * -- - the sender's name (as included in PKIHeader)
+ * -- }
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ v.AddOptional(owf);
+ v.Add(witness);
+ v.Add(challenge);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CmpCertificate.cs b/Crypto/src/asn1/cmp/CmpCertificate.cs
new file mode 100644
index 000000000..16ee30059
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CmpCertificate.cs
@@ -0,0 +1,80 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CmpCertificate
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly X509CertificateStructure x509v3PKCert;
+ private readonly AttributeCertificate x509v2AttrCert;
+
+ /**
+ * Note: the addition of attribute certificates is a BC extension.
+ */
+ public CmpCertificate(AttributeCertificate x509v2AttrCert)
+ {
+ this.x509v2AttrCert = x509v2AttrCert;
+ }
+
+ public CmpCertificate(X509CertificateStructure x509v3PKCert)
+ {
+ if (x509v3PKCert.Version != 3)
+ throw new ArgumentException("only version 3 certificates allowed", "x509v3PKCert");
+
+ this.x509v3PKCert = x509v3PKCert;
+ }
+
+ public static CmpCertificate GetInstance(object obj)
+ {
+ if (obj is CmpCertificate)
+ return (CmpCertificate)obj;
+
+ if (obj is Asn1Sequence)
+ return new CmpCertificate(X509CertificateStructure.GetInstance(obj));
+
+ if (obj is Asn1TaggedObject)
+ return new CmpCertificate(AttributeCertificate.GetInstance(((Asn1TaggedObject)obj).GetObject()));
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual bool IsX509v3PKCert
+ {
+ get { return x509v3PKCert != null; }
+ }
+
+ public virtual X509CertificateStructure X509v3PKCert
+ {
+ get { return x509v3PKCert; }
+ }
+
+ public virtual AttributeCertificate X509v2AttrCert
+ {
+ get { return x509v2AttrCert; }
+ }
+
+ /**
+ * <pre>
+ * CMPCertificate ::= CHOICE {
+ * x509v3PKCert Certificate
+ * x509v2AttrCert [1] AttributeCertificate
+ * }
+ * </pre>
+ * Note: the addition of attribute certificates is a BC extension.
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (x509v2AttrCert != null)
+ {
+ // explicit following CMP conventions
+ return new DerTaggedObject(true, 1, x509v2AttrCert);
+ }
+
+ return x509v3PKCert.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CmpObjectIdentifiers.cs b/Crypto/src/asn1/cmp/CmpObjectIdentifiers.cs
new file mode 100644
index 000000000..7e8274175
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CmpObjectIdentifiers.cs
@@ -0,0 +1,106 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public abstract class CmpObjectIdentifiers
+ {
+ // RFC 4210
+
+ // id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
+ public static readonly DerObjectIdentifier passwordBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.13");
+
+ // id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
+ public static readonly DerObjectIdentifier dhBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.30");
+
+ // Example InfoTypeAndValue contents include, but are not limited
+ // to, the following (un-comment in this ASN.1 module and use as
+ // appropriate for a given environment):
+ //
+ // id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ // CAProtEncCertValue ::= CMPCertificate
+ // id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ // SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ // EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ // PreferredSymmAlgValue ::= AlgorithmIdentifier
+ // id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ // CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ // id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ // CurrentCRLValue ::= CertificateList
+ // id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ // UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ // id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ // KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ // id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ // KeyPairParamRepValue ::= AlgorithmIdentifer
+ // id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ // RevPassphraseValue ::= EncryptedValue
+ // id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ // ImplicitConfirmValue ::= NULL
+ // id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ // ConfirmWaitTimeValue ::= GeneralizedTime
+ // id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ // OrigPKIMessageValue ::= PKIMessages
+ // id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ // SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ //
+ // where
+ //
+ // id-pkix OBJECT IDENTIFIER ::= {
+ // iso(1) identified-organization(3)
+ // dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+ // and
+ // id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+ public static readonly DerObjectIdentifier it_caProtEncCert = new DerObjectIdentifier("1.3.6.1.5.5.7.4.1");
+ public static readonly DerObjectIdentifier it_signKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.2");
+ public static readonly DerObjectIdentifier it_encKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.3");
+ public static readonly DerObjectIdentifier it_preferredSymAlg = new DerObjectIdentifier("1.3.6.1.5.5.7.4.4");
+ public static readonly DerObjectIdentifier it_caKeyUpdateInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.4.5");
+ public static readonly DerObjectIdentifier it_currentCRL = new DerObjectIdentifier("1.3.6.1.5.5.7.4.6");
+ public static readonly DerObjectIdentifier it_unsupportedOIDs = new DerObjectIdentifier("1.3.6.1.5.5.7.4.7");
+ public static readonly DerObjectIdentifier it_keyPairParamReq = new DerObjectIdentifier("1.3.6.1.5.5.7.4.10");
+ public static readonly DerObjectIdentifier it_keyPairParamRep = new DerObjectIdentifier("1.3.6.1.5.5.7.4.11");
+ public static readonly DerObjectIdentifier it_revPassphrase = new DerObjectIdentifier("1.3.6.1.5.5.7.4.12");
+ public static readonly DerObjectIdentifier it_implicitConfirm = new DerObjectIdentifier("1.3.6.1.5.5.7.4.13");
+ public static readonly DerObjectIdentifier it_confirmWaitTime = new DerObjectIdentifier("1.3.6.1.5.5.7.4.14");
+ public static readonly DerObjectIdentifier it_origPKIMessage = new DerObjectIdentifier("1.3.6.1.5.5.7.4.15");
+ public static readonly DerObjectIdentifier it_suppLangTags = new DerObjectIdentifier("1.3.6.1.5.5.7.4.16");
+
+ // RFC 4211
+
+ // id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ // dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
+ //
+ // arc for Internet X.509 PKI protocols and their components
+ // id-pkip OBJECT IDENTIFIER :: { id-pkix pkip(5) }
+ //
+ // arc for Registration Controls in CRMF
+ // id-regCtrl OBJECT IDENTIFIER ::= { id-pkip regCtrl(1) }
+ //
+ // arc for Registration Info in CRMF
+ // id-regInfo OBJECT IDENTIFIER ::= { id-pkip id-regInfo(2) }
+
+ public static readonly DerObjectIdentifier regCtrl_regToken = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.1");
+ public static readonly DerObjectIdentifier regCtrl_authenticator = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.2");
+ public static readonly DerObjectIdentifier regCtrl_pkiPublicationInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.3");
+ public static readonly DerObjectIdentifier regCtrl_pkiArchiveOptions = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.4");
+ public static readonly DerObjectIdentifier regCtrl_oldCertID = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.5");
+ public static readonly DerObjectIdentifier regCtrl_protocolEncrKey = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.6");
+
+ // From RFC4210:
+ // id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7}
+ public static readonly DerObjectIdentifier regCtrl_altCertTemplate = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.7");
+
+ public static readonly DerObjectIdentifier regInfo_utf8Pairs = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.1");
+ public static readonly DerObjectIdentifier regInfo_certReq = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.2");
+
+ // id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) rsadsi(113549) pkcs(1) pkcs9(9) 16 }
+ //
+ // id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types
+ //
+ // id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ public static readonly DerObjectIdentifier ct_encKeyWithID = new DerObjectIdentifier("1.2.840.113549.1.9.16.1.21");
+ }
+}
diff --git a/Crypto/src/asn1/cmp/CrlAnnContent.cs b/Crypto/src/asn1/cmp/CrlAnnContent.cs
new file mode 100644
index 000000000..3dc11d32c
--- /dev/null
+++ b/Crypto/src/asn1/cmp/CrlAnnContent.cs
@@ -0,0 +1,49 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class CrlAnnContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private CrlAnnContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CrlAnnContent GetInstance(object obj)
+ {
+ if (obj is CrlAnnContent)
+ return (CrlAnnContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new CrlAnnContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual CertificateList[] ToCertificateListArray()
+ {
+ CertificateList[] result = new CertificateList[content.Count];
+ for (int i = 0; i != result.Length; ++ i)
+ {
+ result[i] = CertificateList.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CrlAnnContent ::= SEQUENCE OF CertificateList
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/ErrorMsgContent.cs b/Crypto/src/asn1/cmp/ErrorMsgContent.cs
new file mode 100644
index 000000000..f4dc584ea
--- /dev/null
+++ b/Crypto/src/asn1/cmp/ErrorMsgContent.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class ErrorMsgContent
+ : Asn1Encodable
+ {
+ private readonly PkiStatusInfo pkiStatusInfo;
+ private readonly DerInteger errorCode;
+ private readonly PkiFreeText errorDetails;
+
+ private ErrorMsgContent(Asn1Sequence seq)
+ {
+ pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ Asn1Encodable ae = seq[pos];
+ if (ae is DerInteger)
+ {
+ errorCode = DerInteger.GetInstance(ae);
+ }
+ else
+ {
+ errorDetails = PkiFreeText.GetInstance(ae);
+ }
+ }
+ }
+
+ public static ErrorMsgContent GetInstance(object obj)
+ {
+ if (obj is ErrorMsgContent)
+ return (ErrorMsgContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new ErrorMsgContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public ErrorMsgContent(PkiStatusInfo pkiStatusInfo)
+ : this(pkiStatusInfo, null, null)
+ {
+ }
+
+ public ErrorMsgContent(
+ PkiStatusInfo pkiStatusInfo,
+ DerInteger errorCode,
+ PkiFreeText errorDetails)
+ {
+ if (pkiStatusInfo == null)
+ throw new ArgumentNullException("pkiStatusInfo");
+
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.errorCode = errorCode;
+ this.errorDetails = errorDetails;
+ }
+
+ public virtual PkiStatusInfo PkiStatusInfo
+ {
+ get { return pkiStatusInfo; }
+ }
+
+ public virtual DerInteger ErrorCode
+ {
+ get { return errorCode; }
+ }
+
+ public virtual PkiFreeText ErrorDetails
+ {
+ get { return errorDetails; }
+ }
+
+ /**
+ * <pre>
+ * ErrorMsgContent ::= SEQUENCE {
+ * pKIStatusInfo PKIStatusInfo,
+ * errorCode INTEGER OPTIONAL,
+ * -- implementation-specific error codes
+ * errorDetails PKIFreeText OPTIONAL
+ * -- implementation-specific error details
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo);
+ v.AddOptional(errorCode);
+ v.AddOptional(errorDetails);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/GenMsgContent.cs b/Crypto/src/asn1/cmp/GenMsgContent.cs
new file mode 100644
index 000000000..9f042491c
--- /dev/null
+++ b/Crypto/src/asn1/cmp/GenMsgContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class GenMsgContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private GenMsgContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenMsgContent GetInstance(object obj)
+ {
+ if (obj is GenMsgContent)
+ return (GenMsgContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new GenMsgContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public GenMsgContent(params InfoTypeAndValue[] itv)
+ {
+ content = new DerSequence(itv);
+ }
+
+ public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = InfoTypeAndValue.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/GenRepContent.cs b/Crypto/src/asn1/cmp/GenRepContent.cs
new file mode 100644
index 000000000..5bdc5550a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/GenRepContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class GenRepContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private GenRepContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenRepContent GetInstance(object obj)
+ {
+ if (obj is GenRepContent)
+ return (GenRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new GenRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public GenRepContent(params InfoTypeAndValue[] itv)
+ {
+ content = new DerSequence(itv);
+ }
+
+ public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = InfoTypeAndValue.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/InfoTypeAndValue.cs b/Crypto/src/asn1/cmp/InfoTypeAndValue.cs
new file mode 100644
index 000000000..9b51dba02
--- /dev/null
+++ b/Crypto/src/asn1/cmp/InfoTypeAndValue.cs
@@ -0,0 +1,121 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ /**
+ * Example InfoTypeAndValue contents include, but are not limited
+ * to, the following (un-comment in this ASN.1 module and use as
+ * appropriate for a given environment):
+ * <pre>
+ * id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ * CAProtEncCertValue ::= CMPCertificate
+ * id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ * SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ * EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ * PreferredSymmAlgValue ::= AlgorithmIdentifier
+ * id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ * CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ * id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ * CurrentCRLValue ::= CertificateList
+ * id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ * UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ * id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ * KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ * id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ * KeyPairParamRepValue ::= AlgorithmIdentifer
+ * id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ * RevPassphraseValue ::= EncryptedValue
+ * id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ * ImplicitConfirmValue ::= NULL
+ * id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ * ConfirmWaitTimeValue ::= GeneralizedTime
+ * id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ * OrigPKIMessageValue ::= PKIMessages
+ * id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ * SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ *
+ * where
+ *
+ * id-pkix OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+ * and
+ * id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+ * </pre>
+ */
+ public class InfoTypeAndValue
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier infoType;
+ private readonly Asn1Encodable infoValue;
+
+ private InfoTypeAndValue(Asn1Sequence seq)
+ {
+ infoType = DerObjectIdentifier.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ infoValue = (Asn1Encodable)seq[1];
+ }
+ }
+
+ public static InfoTypeAndValue GetInstance(object obj)
+ {
+ if (obj is InfoTypeAndValue)
+ return (InfoTypeAndValue)obj;
+
+ if (obj is Asn1Sequence)
+ return new InfoTypeAndValue((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public InfoTypeAndValue(
+ DerObjectIdentifier infoType)
+ {
+ this.infoType = infoType;
+ this.infoValue = null;
+ }
+
+ public InfoTypeAndValue(
+ DerObjectIdentifier infoType,
+ Asn1Encodable optionalValue)
+ {
+ this.infoType = infoType;
+ this.infoValue = optionalValue;
+ }
+
+ public virtual DerObjectIdentifier InfoType
+ {
+ get { return infoType; }
+ }
+
+ public virtual Asn1Encodable InfoValue
+ {
+ get { return infoValue; }
+ }
+
+ /**
+ * <pre>
+ * InfoTypeAndValue ::= SEQUENCE {
+ * infoType OBJECT IDENTIFIER,
+ * infoValue ANY DEFINED BY infoType OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(infoType);
+
+ if (infoValue != null)
+ {
+ v.Add(infoValue);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/KeyRecRepContent.cs b/Crypto/src/asn1/cmp/KeyRecRepContent.cs
new file mode 100644
index 000000000..b0352f048
--- /dev/null
+++ b/Crypto/src/asn1/cmp/KeyRecRepContent.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class KeyRecRepContent
+ : Asn1Encodable
+ {
+ private readonly PkiStatusInfo status;
+ private readonly CmpCertificate newSigCert;
+ private readonly Asn1Sequence caCerts;
+ private readonly Asn1Sequence keyPairHist;
+
+ private KeyRecRepContent(Asn1Sequence seq)
+ {
+ status = PkiStatusInfo.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+
+ switch (tObj.TagNo)
+ {
+ case 0:
+ newSigCert = CmpCertificate.GetInstance(tObj.GetObject());
+ break;
+ case 1:
+ caCerts = Asn1Sequence.GetInstance(tObj.GetObject());
+ break;
+ case 2:
+ keyPairHist = Asn1Sequence.GetInstance(tObj.GetObject());
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tObj.TagNo, "seq");
+ }
+ }
+ }
+
+ public static KeyRecRepContent GetInstance(object obj)
+ {
+ if (obj is KeyRecRepContent)
+ return (KeyRecRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new KeyRecRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual PkiStatusInfo Status
+ {
+ get { return status; }
+ }
+
+ public virtual CmpCertificate NewSigCert
+ {
+ get { return newSigCert; }
+ }
+
+ public virtual CmpCertificate[] GetCACerts()
+ {
+ if (caCerts == null)
+ return null;
+
+ CmpCertificate[] results = new CmpCertificate[caCerts.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CmpCertificate.GetInstance(caCerts[i]);
+ }
+ return results;
+ }
+
+ public virtual CertifiedKeyPair[] GetKeyPairHist()
+ {
+ if (keyPairHist == null)
+ return null;
+
+ CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertifiedKeyPair.GetInstance(keyPairHist[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * KeyRecRepContent ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * newSigCert [0] CMPCertificate OPTIONAL,
+ * caCerts [1] SEQUENCE SIZE (1..MAX) OF
+ * CMPCertificate OPTIONAL,
+ * keyPairHist [2] SEQUENCE SIZE (1..MAX) OF
+ * CertifiedKeyPair OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status);
+ AddOptional(v, 0, newSigCert);
+ AddOptional(v, 1, caCerts);
+ AddOptional(v, 2, keyPairHist);
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/OobCertHash.cs b/Crypto/src/asn1/cmp/OobCertHash.cs
new file mode 100644
index 000000000..63ddff7c4
--- /dev/null
+++ b/Crypto/src/asn1/cmp/OobCertHash.cs
@@ -0,0 +1,87 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class OobCertHash
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlg;
+ private readonly CertId certId;
+ private readonly DerBitString hashVal;
+
+ private OobCertHash(Asn1Sequence seq)
+ {
+ int index = seq.Count - 1;
+
+ hashVal = DerBitString.GetInstance(seq[index--]);
+
+ for (int i = index; i >= 0; i--)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[i];
+
+ if (tObj.TagNo == 0)
+ {
+ hashAlg = AlgorithmIdentifier.GetInstance(tObj, true);
+ }
+ else
+ {
+ certId = CertId.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static OobCertHash GetInstance(object obj)
+ {
+ if (obj is OobCertHash)
+ return (OobCertHash)obj;
+
+ if (obj is Asn1Sequence)
+ return new OobCertHash((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual AlgorithmIdentifier HashAlg
+ {
+ get { return hashAlg; }
+ }
+
+ public virtual CertId CertID
+ {
+ get { return certId; }
+ }
+
+ /**
+ * <pre>
+ * OobCertHash ::= SEQUENCE {
+ * hashAlg [0] AlgorithmIdentifier OPTIONAL,
+ * certId [1] CertId OPTIONAL,
+ * hashVal BIT STRING
+ * -- hashVal is calculated over the Der encoding of the
+ * -- self-signed certificate with the identifier certID.
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ AddOptional(v, 0, hashAlg);
+ AddOptional(v, 1, certId);
+ v.Add(hashVal);
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
+
diff --git a/Crypto/src/asn1/cmp/PKIBody.cs b/Crypto/src/asn1/cmp/PKIBody.cs
new file mode 100644
index 000000000..3205a907e
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIBody.cs
@@ -0,0 +1,186 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiBody
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int TYPE_INIT_REQ = 0;
+ public const int TYPE_INIT_REP = 1;
+ public const int TYPE_CERT_REQ = 2;
+ public const int TYPE_CERT_REP = 3;
+ public const int TYPE_P10_CERT_REQ = 4;
+ public const int TYPE_POPO_CHALL = 5;
+ public const int TYPE_POPO_REP = 6;
+ public const int TYPE_KEY_UPDATE_REQ = 7;
+ public const int TYPE_KEY_UPDATE_REP = 8;
+ public const int TYPE_KEY_RECOVERY_REQ = 9;
+ public const int TYPE_KEY_RECOVERY_REP = 10;
+ public const int TYPE_REVOCATION_REQ = 11;
+ public const int TYPE_REVOCATION_REP = 12;
+ public const int TYPE_CROSS_CERT_REQ = 13;
+ public const int TYPE_CROSS_CERT_REP = 14;
+ public const int TYPE_CA_KEY_UPDATE_ANN = 15;
+ public const int TYPE_CERT_ANN = 16;
+ public const int TYPE_REVOCATION_ANN = 17;
+ public const int TYPE_CRL_ANN = 18;
+ public const int TYPE_CONFIRM = 19;
+ public const int TYPE_NESTED = 20;
+ public const int TYPE_GEN_MSG = 21;
+ public const int TYPE_GEN_REP = 22;
+ public const int TYPE_ERROR = 23;
+ public const int TYPE_CERT_CONFIRM = 24;
+ public const int TYPE_POLL_REQ = 25;
+ public const int TYPE_POLL_REP = 26;
+
+ private int tagNo;
+ private Asn1Encodable body;
+
+ public static PkiBody GetInstance(object obj)
+ {
+ if (obj is PkiBody)
+ return (PkiBody)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new PkiBody((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ private PkiBody(Asn1TaggedObject tagged)
+ {
+ tagNo = tagged.TagNo;
+ body = GetBodyForType(tagNo, tagged.GetObject());
+ }
+
+ /**
+ * Creates a new PkiBody.
+ * @param type one of the TYPE_* constants
+ * @param content message content
+ */
+ public PkiBody(
+ int type,
+ Asn1Encodable content)
+ {
+ tagNo = type;
+ body = GetBodyForType(type, content);
+ }
+
+ private static Asn1Encodable GetBodyForType(
+ int type,
+ Asn1Encodable o)
+ {
+ switch (type)
+ {
+ case TYPE_INIT_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_INIT_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_CERT_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_CERT_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_P10_CERT_REQ:
+ return CertificationRequest.GetInstance(o);
+ case TYPE_POPO_CHALL:
+ return PopoDecKeyChallContent.GetInstance(o);
+ case TYPE_POPO_REP:
+ return PopoDecKeyRespContent.GetInstance(o);
+ case TYPE_KEY_UPDATE_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_KEY_UPDATE_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_KEY_RECOVERY_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_KEY_RECOVERY_REP:
+ return KeyRecRepContent.GetInstance(o);
+ case TYPE_REVOCATION_REQ:
+ return RevReqContent.GetInstance(o);
+ case TYPE_REVOCATION_REP:
+ return RevRepContent.GetInstance(o);
+ case TYPE_CROSS_CERT_REQ:
+ return CertReqMessages.GetInstance(o);
+ case TYPE_CROSS_CERT_REP:
+ return CertRepMessage.GetInstance(o);
+ case TYPE_CA_KEY_UPDATE_ANN:
+ return CAKeyUpdAnnContent.GetInstance(o);
+ case TYPE_CERT_ANN:
+ return CmpCertificate.GetInstance(o);
+ case TYPE_REVOCATION_ANN:
+ return RevAnnContent.GetInstance(o);
+ case TYPE_CRL_ANN:
+ return CrlAnnContent.GetInstance(o);
+ case TYPE_CONFIRM:
+ return PkiConfirmContent.GetInstance(o);
+ case TYPE_NESTED:
+ return PkiMessages.GetInstance(o);
+ case TYPE_GEN_MSG:
+ return GenMsgContent.GetInstance(o);
+ case TYPE_GEN_REP:
+ return GenRepContent.GetInstance(o);
+ case TYPE_ERROR:
+ return ErrorMsgContent.GetInstance(o);
+ case TYPE_CERT_CONFIRM:
+ return CertConfirmContent.GetInstance(o);
+ case TYPE_POLL_REQ:
+ return PollReqContent.GetInstance(o);
+ case TYPE_POLL_REP:
+ return PollRepContent.GetInstance(o);
+ default:
+ throw new ArgumentException("unknown tag number: " + type, "type");
+ }
+ }
+
+ public virtual int Type
+ {
+ get { return tagNo; }
+ }
+
+ public virtual Asn1Encodable Content
+ {
+ get { return body; }
+ }
+
+ /**
+ * <pre>
+ * PkiBody ::= CHOICE { -- message-specific body elements
+ * ir [0] CertReqMessages, --Initialization Request
+ * ip [1] CertRepMessage, --Initialization Response
+ * cr [2] CertReqMessages, --Certification Request
+ * cp [3] CertRepMessage, --Certification Response
+ * p10cr [4] CertificationRequest, --imported from [PKCS10]
+ * popdecc [5] POPODecKeyChallContent, --pop Challenge
+ * popdecr [6] POPODecKeyRespContent, --pop Response
+ * kur [7] CertReqMessages, --Key Update Request
+ * kup [8] CertRepMessage, --Key Update Response
+ * krr [9] CertReqMessages, --Key Recovery Request
+ * krp [10] KeyRecRepContent, --Key Recovery Response
+ * rr [11] RevReqContent, --Revocation Request
+ * rp [12] RevRepContent, --Revocation Response
+ * ccr [13] CertReqMessages, --Cross-Cert. Request
+ * ccp [14] CertRepMessage, --Cross-Cert. Response
+ * ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
+ * cann [16] CertAnnContent, --Certificate Ann.
+ * rann [17] RevAnnContent, --Revocation Ann.
+ * crlann [18] CRLAnnContent, --CRL Announcement
+ * pkiconf [19] PKIConfirmContent, --Confirmation
+ * nested [20] NestedMessageContent, --Nested Message
+ * genm [21] GenMsgContent, --General Message
+ * genp [22] GenRepContent, --General Response
+ * error [23] ErrorMsgContent, --Error Message
+ * certConf [24] CertConfirmContent, --Certificate confirm
+ * pollReq [25] PollReqContent, --Polling request
+ * pollRep [26] PollRepContent --Polling response
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(true, tagNo, body);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIConfirmContent.cs b/Crypto/src/asn1/cmp/PKIConfirmContent.cs
new file mode 100644
index 000000000..98645766a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIConfirmContent.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiConfirmContent
+ : Asn1Encodable
+ {
+ public static PkiConfirmContent GetInstance(object obj)
+ {
+ if (obj is PkiConfirmContent)
+ return (PkiConfirmContent)obj;
+
+ if (obj is Asn1Null)
+ return new PkiConfirmContent();
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiConfirmContent()
+ {
+ }
+
+ /**
+ * <pre>
+ * PkiConfirmContent ::= NULL
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return DerNull.Instance;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIFailureInfo.cs b/Crypto/src/asn1/cmp/PKIFailureInfo.cs
new file mode 100644
index 000000000..1df0e0693
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIFailureInfo.cs
@@ -0,0 +1,73 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ /**
+ * <pre>
+ * PKIFailureInfo ::= BIT STRING {
+ * badAlg (0),
+ * -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2),
+ * -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5),
+ * -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ * timeNotAvailable (14),
+ * -- the TSA's time source is not available
+ * unacceptedPolicy (15),
+ * -- the requested TSA policy is not supported by the TSA
+ * unacceptedExtension (16),
+ * -- the requested extension is not supported by the TSA
+ * addInfoNotAvailable (17)
+ * -- the additional information requested could not be understood
+ * -- or is not available
+ * systemFailure (25)
+ * -- the request cannot be handled due to system failure
+ * </pre>
+ */
+ public class PkiFailureInfo
+ : DerBitString
+ {
+ public const int BadAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier
+ public const int BadMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify)
+ public const int BadRequest = (1 << 5);
+ public const int BadTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
+ public const int BadCertId = (1 << 3); // no certificate could be found matching the provided criteria
+ public const int BadDataFormat = (1 << 2);
+ public const int WrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token
+ public const int IncorrectData = 1; // the requester's data is incorrect (for notary services)
+ public const int MissingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy)
+ public const int BadPop = (1 << 14); // the proof-of-possession failed
+ public const int TimeNotAvailable = (1 << 9); // the TSA's time source is not available
+ public const int UnacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA
+ public const int UnacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA
+ public const int AddInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available
+ public const int SystemFailure = (1 << 30); //the request cannot be handled due to system failure
+
+ /**
+ * Basic constructor.
+ */
+ public PkiFailureInfo(
+ int info)
+ : base(GetBytes(info), GetPadBits(info))
+ {
+ }
+
+ public PkiFailureInfo(
+ DerBitString info)
+ : base(info.GetBytes(), info.PadBits)
+ {
+ }
+
+ public override string ToString()
+ {
+ return "PkiFailureInfo: 0x" + this.IntValue.ToString("X");
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIFreeText.cs b/Crypto/src/asn1/cmp/PKIFreeText.cs
new file mode 100644
index 000000000..571c8d93a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIFreeText.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiFreeText
+ : Asn1Encodable
+ {
+ internal Asn1Sequence strings;
+
+ public static PkiFreeText GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public static PkiFreeText GetInstance(
+ object obj)
+ {
+ if (obj is PkiFreeText)
+ {
+ return (PkiFreeText)obj;
+ }
+ else if (obj is Asn1Sequence)
+ {
+ return new PkiFreeText((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiFreeText(
+ Asn1Sequence seq)
+ {
+ foreach (object o in seq)
+ {
+ if (!(o is DerUtf8String))
+ {
+ throw new ArgumentException("attempt to insert non UTF8 STRING into PkiFreeText");
+ }
+ }
+
+ this.strings = seq;
+ }
+
+ public PkiFreeText(
+ DerUtf8String p)
+ {
+ strings = new DerSequence(p);
+ }
+
+ /**
+ * Return the number of string elements present.
+ *
+ * @return number of elements present.
+ */
+ [Obsolete("Use 'Count' property instead")]
+ public int Size
+ {
+ get { return strings.Count; }
+ }
+
+ public int Count
+ {
+ get { return strings.Count; }
+ }
+
+ /**
+ * Return the UTF8STRING at index.
+ *
+ * @param index index of the string of interest
+ * @return the string at index.
+ */
+ public DerUtf8String this[int index]
+ {
+ get { return (DerUtf8String) strings[index]; }
+ }
+
+ [Obsolete("Use 'object[index]' syntax instead")]
+ public DerUtf8String GetStringAt(
+ int index)
+ {
+ return this[index];
+ }
+
+ /**
+ * <pre>
+ * PkiFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return strings;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIHeader.cs b/Crypto/src/asn1/cmp/PKIHeader.cs
new file mode 100644
index 000000000..e758e9f16
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIHeader.cs
@@ -0,0 +1,237 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiHeader
+ : Asn1Encodable
+ {
+ /**
+ * Value for a "null" recipient or sender.
+ */
+ public static readonly GeneralName NULL_NAME = new GeneralName(X509Name.GetInstance(new DerSequence()));
+
+ public static readonly int CMP_1999 = 1;
+ public static readonly int CMP_2000 = 2;
+
+ private readonly DerInteger pvno;
+ private readonly GeneralName sender;
+ private readonly GeneralName recipient;
+ private readonly DerGeneralizedTime messageTime;
+ private readonly AlgorithmIdentifier protectionAlg;
+ private readonly Asn1OctetString senderKID; // KeyIdentifier
+ private readonly Asn1OctetString recipKID; // KeyIdentifier
+ private readonly Asn1OctetString transactionID;
+ private readonly Asn1OctetString senderNonce;
+ private readonly Asn1OctetString recipNonce;
+ private readonly PkiFreeText freeText;
+ private readonly Asn1Sequence generalInfo;
+
+ private PkiHeader(Asn1Sequence seq)
+ {
+ pvno = DerInteger.GetInstance(seq[0]);
+ sender = GeneralName.GetInstance(seq[1]);
+ recipient = GeneralName.GetInstance(seq[2]);
+
+ for (int pos = 3; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos];
+
+ switch (tObj.TagNo)
+ {
+ case 0:
+ messageTime = DerGeneralizedTime.GetInstance(tObj, true);
+ break;
+ case 1:
+ protectionAlg = AlgorithmIdentifier.GetInstance(tObj, true);
+ break;
+ case 2:
+ senderKID = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 3:
+ recipKID = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 4:
+ transactionID = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 5:
+ senderNonce = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 6:
+ recipNonce = Asn1OctetString.GetInstance(tObj, true);
+ break;
+ case 7:
+ freeText = PkiFreeText.GetInstance(tObj, true);
+ break;
+ case 8:
+ generalInfo = Asn1Sequence.GetInstance(tObj, true);
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tObj.TagNo, "seq");
+ }
+ }
+ }
+
+ public static PkiHeader GetInstance(object obj)
+ {
+ if (obj is PkiHeader)
+ return (PkiHeader)obj;
+
+ if (obj is Asn1Sequence)
+ return new PkiHeader((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiHeader(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ : this(new DerInteger(pvno), sender, recipient)
+ {
+ }
+
+ private PkiHeader(
+ DerInteger pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public virtual DerInteger Pvno
+ {
+ get { return pvno; }
+ }
+
+ public virtual GeneralName Sender
+ {
+ get { return sender; }
+ }
+
+ public virtual GeneralName Recipient
+ {
+ get { return recipient; }
+ }
+
+ public virtual DerGeneralizedTime MessageTime
+ {
+ get { return messageTime; }
+ }
+
+ public virtual AlgorithmIdentifier ProtectionAlg
+ {
+ get { return protectionAlg; }
+ }
+
+ public virtual Asn1OctetString SenderKID
+ {
+ get { return senderKID; }
+ }
+
+ public virtual Asn1OctetString RecipKID
+ {
+ get { return recipKID; }
+ }
+
+ public virtual Asn1OctetString TransactionID
+ {
+ get { return transactionID; }
+ }
+
+ public virtual Asn1OctetString SenderNonce
+ {
+ get { return senderNonce; }
+ }
+
+ public virtual Asn1OctetString RecipNonce
+ {
+ get { return recipNonce; }
+ }
+
+ public virtual PkiFreeText FreeText
+ {
+ get { return freeText; }
+ }
+
+ public virtual InfoTypeAndValue[] GetGeneralInfo()
+ {
+ if (generalInfo == null)
+ {
+ return null;
+ }
+ InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.Count];
+ for (int i = 0; i < results.Length; i++)
+ {
+ results[i] = InfoTypeAndValue.GetInstance(generalInfo[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PkiHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, recipient);
+
+ AddOptional(v, 0, messageTime);
+ AddOptional(v, 1, protectionAlg);
+ AddOptional(v, 2, senderKID);
+ AddOptional(v, 3, recipKID);
+ AddOptional(v, 4, transactionID);
+ AddOptional(v, 5, senderNonce);
+ AddOptional(v, 6, recipNonce);
+ AddOptional(v, 7, freeText);
+ AddOptional(v, 8, generalInfo);
+
+ return new DerSequence(v);
+ }
+
+ private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIHeaderBuilder.cs b/Crypto/src/asn1/cmp/PKIHeaderBuilder.cs
new file mode 100644
index 000000000..00073c062
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIHeaderBuilder.cs
@@ -0,0 +1,223 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiHeaderBuilder
+ {
+ private DerInteger pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private DerGeneralizedTime messageTime;
+ private AlgorithmIdentifier protectionAlg;
+ private Asn1OctetString senderKID; // KeyIdentifier
+ private Asn1OctetString recipKID; // KeyIdentifier
+ private Asn1OctetString transactionID;
+ private Asn1OctetString senderNonce;
+ private Asn1OctetString recipNonce;
+ private PkiFreeText freeText;
+ private Asn1Sequence generalInfo;
+
+ public PkiHeaderBuilder(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ : this(new DerInteger(pvno), sender, recipient)
+ {
+ }
+
+ private PkiHeaderBuilder(
+ DerInteger pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public virtual PkiHeaderBuilder SetMessageTime(DerGeneralizedTime time)
+ {
+ messageTime = time;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetProtectionAlg(AlgorithmIdentifier aid)
+ {
+ protectionAlg = aid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetSenderKID(byte[] kid)
+ {
+ return SetSenderKID(kid == null ? null : new DerOctetString(kid));
+ }
+
+ public virtual PkiHeaderBuilder SetSenderKID(Asn1OctetString kid)
+ {
+ senderKID = kid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetRecipKID(byte[] kid)
+ {
+ return SetRecipKID(kid == null ? null : new DerOctetString(kid));
+ }
+
+ public virtual PkiHeaderBuilder SetRecipKID(DerOctetString kid)
+ {
+ recipKID = kid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetTransactionID(byte[] tid)
+ {
+ return SetTransactionID(tid == null ? null : new DerOctetString(tid));
+ }
+
+ public virtual PkiHeaderBuilder SetTransactionID(Asn1OctetString tid)
+ {
+ transactionID = tid;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetSenderNonce(byte[] nonce)
+ {
+ return SetSenderNonce(nonce == null ? null : new DerOctetString(nonce));
+ }
+
+ public virtual PkiHeaderBuilder SetSenderNonce(Asn1OctetString nonce)
+ {
+ senderNonce = nonce;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetRecipNonce(byte[] nonce)
+ {
+ return SetRecipNonce(nonce == null ? null : new DerOctetString(nonce));
+ }
+
+ public virtual PkiHeaderBuilder SetRecipNonce(Asn1OctetString nonce)
+ {
+ recipNonce = nonce;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetFreeText(PkiFreeText text)
+ {
+ freeText = text;
+ return this;
+ }
+
+ public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue genInfo)
+ {
+ return SetGeneralInfo(MakeGeneralInfoSeq(genInfo));
+ }
+
+ public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue[] genInfos)
+ {
+ return SetGeneralInfo(MakeGeneralInfoSeq(genInfos));
+ }
+
+ public virtual PkiHeaderBuilder SetGeneralInfo(Asn1Sequence seqOfInfoTypeAndValue)
+ {
+ generalInfo = seqOfInfoTypeAndValue;
+ return this;
+ }
+
+ private static Asn1Sequence MakeGeneralInfoSeq(
+ InfoTypeAndValue generalInfo)
+ {
+ return new DerSequence(generalInfo);
+ }
+
+ private static Asn1Sequence MakeGeneralInfoSeq(
+ InfoTypeAndValue[] generalInfos)
+ {
+ Asn1Sequence genInfoSeq = null;
+ if (generalInfos != null)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ for (int i = 0; i < generalInfos.Length; ++i)
+ {
+ v.Add(generalInfos[i]);
+ }
+ genInfoSeq = new DerSequence(v);
+ }
+ return genInfoSeq;
+ }
+
+ /**
+ * <pre>
+ * PKIHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public virtual PkiHeader Build()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, recipient);
+ AddOptional(v, 0, messageTime);
+ AddOptional(v, 1, protectionAlg);
+ AddOptional(v, 2, senderKID);
+ AddOptional(v, 3, recipKID);
+ AddOptional(v, 4, transactionID);
+ AddOptional(v, 5, senderNonce);
+ AddOptional(v, 6, recipNonce);
+ AddOptional(v, 7, freeText);
+ AddOptional(v, 8, generalInfo);
+
+ messageTime = null;
+ protectionAlg = null;
+ senderKID = null;
+ recipKID = null;
+ transactionID = null;
+ senderNonce = null;
+ recipNonce = null;
+ freeText = null;
+ generalInfo = null;
+
+ return PkiHeader.GetInstance(new DerSequence(v));
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIMessage.cs b/Crypto/src/asn1/cmp/PKIMessage.cs
new file mode 100644
index 000000000..086a2d938
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIMessage.cs
@@ -0,0 +1,140 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiMessage
+ : Asn1Encodable
+ {
+ private readonly PkiHeader header;
+ private readonly PkiBody body;
+ private readonly DerBitString protection;
+ private readonly Asn1Sequence extraCerts;
+
+ private PkiMessage(Asn1Sequence seq)
+ {
+ header = PkiHeader.GetInstance(seq[0]);
+ body = PkiBody.GetInstance(seq[1]);
+
+ for (int pos = 2; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos].ToAsn1Object();
+
+ if (tObj.TagNo == 0)
+ {
+ protection = DerBitString.GetInstance(tObj, true);
+ }
+ else
+ {
+ extraCerts = Asn1Sequence.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static PkiMessage GetInstance(object obj)
+ {
+ if (obj is PkiMessage)
+ return (PkiMessage)obj;
+
+ if (obj != null)
+ return new PkiMessage(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ /**
+ * Creates a new PkiMessage.
+ *
+ * @param header message header
+ * @param body message body
+ * @param protection message protection (may be null)
+ * @param extraCerts extra certificates (may be null)
+ */
+ public PkiMessage(
+ PkiHeader header,
+ PkiBody body,
+ DerBitString protection,
+ CmpCertificate[] extraCerts)
+ {
+ this.header = header;
+ this.body = body;
+ this.protection = protection;
+ if (extraCerts != null)
+ {
+ this.extraCerts = new DerSequence(extraCerts);
+ }
+ }
+
+ public PkiMessage(
+ PkiHeader header,
+ PkiBody body,
+ DerBitString protection)
+ : this(header, body, protection, null)
+ {
+ }
+
+ public PkiMessage(
+ PkiHeader header,
+ PkiBody body)
+ : this(header, body, null, null)
+ {
+ }
+
+ public virtual PkiHeader Header
+ {
+ get { return header; }
+ }
+
+ public virtual PkiBody Body
+ {
+ get { return body; }
+ }
+
+ public virtual DerBitString Protection
+ {
+ get { return protection; }
+ }
+
+ public virtual CmpCertificate[] GetExtraCerts()
+ {
+ if (extraCerts == null)
+ return null;
+
+ CmpCertificate[] results = new CmpCertificate[extraCerts.Count];
+ for (int i = 0; i < results.Length; ++i)
+ {
+ results[i] = CmpCertificate.GetInstance(extraCerts[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PkiMessage ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody,
+ * protection [0] PKIProtection OPTIONAL,
+ * extraCerts [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(header, body);
+
+ AddOptional(v, 0, protection);
+ AddOptional(v, 1, extraCerts);
+
+ return new DerSequence(v);
+ }
+
+ private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIMessages.cs b/Crypto/src/asn1/cmp/PKIMessages.cs
new file mode 100644
index 000000000..ddabdf4ae
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIMessages.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiMessages
+ : Asn1Encodable
+ {
+ private Asn1Sequence content;
+
+ private PkiMessages(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PkiMessages GetInstance(object obj)
+ {
+ if (obj is PkiMessages)
+ return (PkiMessages)obj;
+
+ if (obj is Asn1Sequence)
+ return new PkiMessages((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiMessages(params PkiMessage[] msgs)
+ {
+ content = new DerSequence(msgs);
+ }
+
+ public virtual PkiMessage[] ToPkiMessageArray()
+ {
+ PkiMessage[] result = new PkiMessage[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = PkiMessage.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PkiMessages ::= SEQUENCE SIZE (1..MAX) OF PkiMessage
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIStatus.cs b/Crypto/src/asn1/cmp/PKIStatus.cs
new file mode 100644
index 000000000..b03dd3d62
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIStatus.cs
@@ -0,0 +1,62 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public enum PkiStatus
+ {
+ Granted = 0,
+ GrantedWithMods = 1,
+ Rejection = 2,
+ Waiting = 3,
+ RevocationWarning = 4,
+ RevocationNotification = 5,
+ KeyUpdateWarning = 6,
+ }
+
+ public class PkiStatusEncodable
+ : Asn1Encodable
+ {
+ public static readonly PkiStatusEncodable granted = new PkiStatusEncodable(PkiStatus.Granted);
+ public static readonly PkiStatusEncodable grantedWithMods = new PkiStatusEncodable(PkiStatus.GrantedWithMods);
+ public static readonly PkiStatusEncodable rejection = new PkiStatusEncodable(PkiStatus.Rejection);
+ public static readonly PkiStatusEncodable waiting = new PkiStatusEncodable(PkiStatus.Waiting);
+ public static readonly PkiStatusEncodable revocationWarning = new PkiStatusEncodable(PkiStatus.RevocationWarning);
+ public static readonly PkiStatusEncodable revocationNotification = new PkiStatusEncodable(PkiStatus.RevocationNotification);
+ public static readonly PkiStatusEncodable keyUpdateWaiting = new PkiStatusEncodable(PkiStatus.KeyUpdateWarning);
+
+ private readonly DerInteger status;
+
+ private PkiStatusEncodable(PkiStatus status)
+ : this(new DerInteger((int)status))
+ {
+ }
+
+ private PkiStatusEncodable(DerInteger status)
+ {
+ this.status = status;
+ }
+
+ public static PkiStatusEncodable GetInstance(object obj)
+ {
+ if (obj is PkiStatusEncodable)
+ return (PkiStatusEncodable)obj;
+
+ if (obj is DerInteger)
+ return new PkiStatusEncodable((DerInteger)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual BigInteger Value
+ {
+ get { return status.Value; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return status;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PKIStatusInfo.cs b/Crypto/src/asn1/cmp/PKIStatusInfo.cs
new file mode 100644
index 000000000..2463e0081
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PKIStatusInfo.cs
@@ -0,0 +1,165 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PkiStatusInfo
+ : Asn1Encodable
+ {
+ DerInteger status;
+ PkiFreeText statusString;
+ DerBitString failInfo;
+
+ public static PkiStatusInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public static PkiStatusInfo GetInstance(
+ object obj)
+ {
+ if (obj is PkiStatusInfo)
+ {
+ return (PkiStatusInfo)obj;
+ }
+ else if (obj is Asn1Sequence)
+ {
+ return new PkiStatusInfo((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public PkiStatusInfo(
+ Asn1Sequence seq)
+ {
+ this.status = DerInteger.GetInstance(seq[0]);
+
+ this.statusString = null;
+ this.failInfo = null;
+
+ if (seq.Count > 2)
+ {
+ this.statusString = PkiFreeText.GetInstance(seq[1]);
+ this.failInfo = DerBitString.GetInstance(seq[2]);
+ }
+ else if (seq.Count > 1)
+ {
+ object obj = seq[1];
+ if (obj is DerBitString)
+ {
+ this.failInfo = DerBitString.GetInstance(obj);
+ }
+ else
+ {
+ this.statusString = PkiFreeText.GetInstance(obj);
+ }
+ }
+ }
+
+ /**
+ * @param status
+ */
+ public PkiStatusInfo(int status)
+ {
+ this.status = new DerInteger(status);
+ }
+
+ /**
+ * @param status
+ * @param statusString
+ */
+ public PkiStatusInfo(
+ int status,
+ PkiFreeText statusString)
+ {
+ this.status = new DerInteger(status);
+ this.statusString = statusString;
+ }
+
+ public PkiStatusInfo(
+ int status,
+ PkiFreeText statusString,
+ PkiFailureInfo failInfo)
+ {
+ this.status = new DerInteger(status);
+ this.statusString = statusString;
+ this.failInfo = failInfo;
+ }
+
+ public BigInteger Status
+ {
+ get
+ {
+ return status.Value;
+ }
+ }
+
+ public PkiFreeText StatusString
+ {
+ get
+ {
+ return statusString;
+ }
+ }
+
+ public DerBitString FailInfo
+ {
+ get
+ {
+ return failInfo;
+ }
+ }
+
+ /**
+ * <pre>
+ * PkiStatusInfo ::= SEQUENCE {
+ * status PKIStatus, (INTEGER)
+ * statusString PkiFreeText OPTIONAL,
+ * failInfo PkiFailureInfo OPTIONAL (BIT STRING)
+ * }
+ *
+ * PKIStatus:
+ * granted (0), -- you got exactly what you asked for
+ * grantedWithMods (1), -- you got something like what you asked for
+ * rejection (2), -- you don't get it, more information elsewhere in the message
+ * waiting (3), -- the request body part has not yet been processed, expect to hear more later
+ * revocationWarning (4), -- this message contains a warning that a revocation is imminent
+ * revocationNotification (5), -- notification that a revocation has occurred
+ * keyUpdateWarning (6) -- update already done for the oldCertId specified in CertReqMsg
+ *
+ * PkiFailureInfo:
+ * badAlg (0), -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2), -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5), -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ *
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status);
+
+ if (statusString != null)
+ {
+ v.Add(statusString);
+ }
+
+ if (failInfo!= null)
+ {
+ v.Add(failInfo);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PbmParameter.cs b/Crypto/src/asn1/cmp/PbmParameter.cs
new file mode 100644
index 000000000..59b1bd7bb
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PbmParameter.cs
@@ -0,0 +1,100 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PbmParameter
+ : Asn1Encodable
+ {
+ private Asn1OctetString salt;
+ private AlgorithmIdentifier owf;
+ private DerInteger iterationCount;
+ private AlgorithmIdentifier mac;
+
+ private PbmParameter(Asn1Sequence seq)
+ {
+ salt = Asn1OctetString.GetInstance(seq[0]);
+ owf = AlgorithmIdentifier.GetInstance(seq[1]);
+ iterationCount = DerInteger.GetInstance(seq[2]);
+ mac = AlgorithmIdentifier.GetInstance(seq[3]);
+ }
+
+ public static PbmParameter GetInstance(object obj)
+ {
+ if (obj is PbmParameter)
+ return (PbmParameter)obj;
+
+ if (obj is Asn1Sequence)
+ return new PbmParameter((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public PbmParameter(
+ byte[] salt,
+ AlgorithmIdentifier owf,
+ int iterationCount,
+ AlgorithmIdentifier mac)
+ : this(new DerOctetString(salt), owf, new DerInteger(iterationCount), mac)
+ {
+ }
+
+ public PbmParameter(
+ Asn1OctetString salt,
+ AlgorithmIdentifier owf,
+ DerInteger iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this.salt = salt;
+ this.owf = owf;
+ this.iterationCount = iterationCount;
+ this.mac = mac;
+ }
+
+ public virtual Asn1OctetString Salt
+ {
+ get { return salt; }
+ }
+
+ public virtual AlgorithmIdentifier Owf
+ {
+ get { return owf; }
+ }
+
+ public virtual DerInteger IterationCount
+ {
+ get { return iterationCount; }
+ }
+
+ public virtual AlgorithmIdentifier Mac
+ {
+ get { return mac; }
+ }
+
+ /**
+ * <pre>
+ * PbmParameter ::= SEQUENCE {
+ * salt OCTET STRING,
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this string to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * owf AlgorithmIdentifier,
+ * -- AlgId for a One-Way Function (SHA-1 recommended)
+ * iterationCount INTEGER,
+ * -- number of times the OWF is applied
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this integer to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * mac AlgorithmIdentifier
+ * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ * } -- or HMAC [RFC2104, RFC2202])
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(salt, owf, iterationCount, mac);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PollRepContent.cs b/Crypto/src/asn1/cmp/PollRepContent.cs
new file mode 100644
index 000000000..4045ac7ed
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PollRepContent.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PollRepContent
+ : Asn1Encodable
+ {
+ private readonly DerInteger certReqId;
+ private readonly DerInteger checkAfter;
+ private readonly PkiFreeText reason;
+
+ private PollRepContent(Asn1Sequence seq)
+ {
+ certReqId = DerInteger.GetInstance(seq[0]);
+ checkAfter = DerInteger.GetInstance(seq[1]);
+
+ if (seq.Count > 2)
+ {
+ reason = PkiFreeText.GetInstance(seq[2]);
+ }
+ }
+
+ public static PollRepContent GetInstance(object obj)
+ {
+ if (obj is PollRepContent)
+ return (PollRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PollRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual DerInteger CheckAfter
+ {
+ get { return checkAfter; }
+ }
+
+ public virtual PkiFreeText Reason
+ {
+ get { return reason; }
+ }
+
+ /**
+ * <pre>
+ * PollRepContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER,
+ * checkAfter INTEGER, -- time in seconds
+ * reason PKIFreeText OPTIONAL
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReqId, checkAfter);
+ v.AddOptional(reason);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PollReqContent.cs b/Crypto/src/asn1/cmp/PollReqContent.cs
new file mode 100644
index 000000000..ca2164151
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PollReqContent.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PollReqContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private PollReqContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PollReqContent GetInstance(object obj)
+ {
+ if (obj is PollReqContent)
+ return (PollReqContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PollReqContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger[][] GetCertReqIDs()
+ {
+ DerInteger[][] result = new DerInteger[content.Count][];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = SequenceToDerIntegerArray((Asn1Sequence)content[i]);
+ }
+ return result;
+ }
+
+ private static DerInteger[] SequenceToDerIntegerArray(Asn1Sequence seq)
+ {
+ DerInteger[] result = new DerInteger[seq.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = DerInteger.GetInstance(seq[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PollReqContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PopoDecKeyChallContent.cs b/Crypto/src/asn1/cmp/PopoDecKeyChallContent.cs
new file mode 100644
index 000000000..20b173b85
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PopoDecKeyChallContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PopoDecKeyChallContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private PopoDecKeyChallContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PopoDecKeyChallContent GetInstance(object obj)
+ {
+ if (obj is PopoDecKeyChallContent)
+ return (PopoDecKeyChallContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoDecKeyChallContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual Challenge[] ToChallengeArray()
+ {
+ Challenge[] result = new Challenge[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = Challenge.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PopoDecKeyChallContent ::= SEQUENCE OF Challenge
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/PopoDecKeyRespContent.cs b/Crypto/src/asn1/cmp/PopoDecKeyRespContent.cs
new file mode 100644
index 000000000..8c322e4ec
--- /dev/null
+++ b/Crypto/src/asn1/cmp/PopoDecKeyRespContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class PopoDecKeyRespContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private PopoDecKeyRespContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PopoDecKeyRespContent GetInstance(object obj)
+ {
+ if (obj is PopoDecKeyRespContent)
+ return (PopoDecKeyRespContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoDecKeyRespContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger[] ToDerIntegerArray()
+ {
+ DerInteger[] result = new DerInteger[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = DerInteger.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * PopoDecKeyRespContent ::= SEQUENCE OF INTEGER
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/ProtectedPart.cs b/Crypto/src/asn1/cmp/ProtectedPart.cs
new file mode 100644
index 000000000..db6798fee
--- /dev/null
+++ b/Crypto/src/asn1/cmp/ProtectedPart.cs
@@ -0,0 +1,58 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class ProtectedPart
+ : Asn1Encodable
+ {
+ private readonly PkiHeader header;
+ private readonly PkiBody body;
+
+ private ProtectedPart(Asn1Sequence seq)
+ {
+ header = PkiHeader.GetInstance(seq[0]);
+ body = PkiBody.GetInstance(seq[1]);
+ }
+
+ public static ProtectedPart GetInstance(object obj)
+ {
+ if (obj is ProtectedPart)
+ return (ProtectedPart)obj;
+
+ if (obj is Asn1Sequence)
+ return new ProtectedPart((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public ProtectedPart(PkiHeader header, PkiBody body)
+ {
+ this.header = header;
+ this.body = body;
+ }
+
+ public virtual PkiHeader Header
+ {
+ get { return header; }
+ }
+
+ public virtual PkiBody Body
+ {
+ get { return body; }
+ }
+
+ /**
+ * <pre>
+ * ProtectedPart ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(header, body);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevAnnContent.cs b/Crypto/src/asn1/cmp/RevAnnContent.cs
new file mode 100644
index 000000000..2c3bd5f77
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevAnnContent.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevAnnContent
+ : Asn1Encodable
+ {
+ private readonly PkiStatusEncodable status;
+ private readonly CertId certId;
+ private readonly DerGeneralizedTime willBeRevokedAt;
+ private readonly DerGeneralizedTime badSinceDate;
+ private readonly X509Extensions crlDetails;
+
+ private RevAnnContent(Asn1Sequence seq)
+ {
+ status = PkiStatusEncodable.GetInstance(seq[0]);
+ certId = CertId.GetInstance(seq[1]);
+ willBeRevokedAt = DerGeneralizedTime.GetInstance(seq[2]);
+ badSinceDate = DerGeneralizedTime.GetInstance(seq[3]);
+
+ if (seq.Count > 4)
+ {
+ crlDetails = X509Extensions.GetInstance(seq[4]);
+ }
+ }
+
+ public static RevAnnContent GetInstance(object obj)
+ {
+ if (obj is RevAnnContent)
+ return (RevAnnContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevAnnContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual PkiStatusEncodable Status
+ {
+ get { return status; }
+ }
+
+ public virtual CertId CertID
+ {
+ get { return certId; }
+ }
+
+ public virtual DerGeneralizedTime WillBeRevokedAt
+ {
+ get { return willBeRevokedAt; }
+ }
+
+ public virtual DerGeneralizedTime BadSinceDate
+ {
+ get { return badSinceDate; }
+ }
+
+ public virtual X509Extensions CrlDetails
+ {
+ get { return crlDetails; }
+ }
+
+ /**
+ * <pre>
+ * RevAnnContent ::= SEQUENCE {
+ * status PKIStatus,
+ * certId CertId,
+ * willBeRevokedAt GeneralizedTime,
+ * badSinceDate GeneralizedTime,
+ * crlDetails Extensions OPTIONAL
+ * -- extra CRL details (e.g., crl number, reason, location, etc.)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status, certId, willBeRevokedAt, badSinceDate);
+ v.AddOptional(crlDetails);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevDetails.cs b/Crypto/src/asn1/cmp/RevDetails.cs
new file mode 100644
index 000000000..1bd95f1db
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevDetails.cs
@@ -0,0 +1,75 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevDetails
+ : Asn1Encodable
+ {
+ private readonly CertTemplate certDetails;
+ private readonly X509Extensions crlEntryDetails;
+
+ private RevDetails(Asn1Sequence seq)
+ {
+ certDetails = CertTemplate.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ crlEntryDetails = X509Extensions.GetInstance(seq[1]);
+ }
+ }
+
+ public static RevDetails GetInstance(object obj)
+ {
+ if (obj is RevDetails)
+ return (RevDetails)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevDetails((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public RevDetails(CertTemplate certDetails)
+ {
+ this.certDetails = certDetails;
+ }
+
+ public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails)
+ {
+ this.crlEntryDetails = crlEntryDetails;
+ }
+
+ public virtual CertTemplate CertDetails
+ {
+ get { return certDetails; }
+ }
+
+ public virtual X509Extensions CrlEntryDetails
+ {
+ get { return crlEntryDetails; }
+ }
+
+ /**
+ * <pre>
+ * RevDetails ::= SEQUENCE {
+ * certDetails CertTemplate,
+ * -- allows requester to specify as much as they can about
+ * -- the cert. for which revocation is requested
+ * -- (e.g., for cases in which serialNumber is not available)
+ * crlEntryDetails Extensions OPTIONAL
+ * -- requested crlEntryExtensions
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certDetails);
+ v.AddOptional(crlEntryDetails);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevRepContent.cs b/Crypto/src/asn1/cmp/RevRepContent.cs
new file mode 100644
index 000000000..47987265a
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevRepContent.cs
@@ -0,0 +1,112 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevRepContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence status;
+ private readonly Asn1Sequence revCerts;
+ private readonly Asn1Sequence crls;
+
+ private RevRepContent(Asn1Sequence seq)
+ {
+ status = Asn1Sequence.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+
+ if (tObj.TagNo == 0)
+ {
+ revCerts = Asn1Sequence.GetInstance(tObj, true);
+ }
+ else
+ {
+ crls = Asn1Sequence.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static RevRepContent GetInstance(object obj)
+ {
+ if (obj is RevRepContent)
+ return (RevRepContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevRepContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual PkiStatusInfo[] GetStatus()
+ {
+ PkiStatusInfo[] results = new PkiStatusInfo[status.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = PkiStatusInfo.GetInstance(status[i]);
+ }
+ return results;
+ }
+
+ public virtual CertId[] GetRevCerts()
+ {
+ if (revCerts == null)
+ return null;
+
+ CertId[] results = new CertId[revCerts.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertId.GetInstance(revCerts[i]);
+ }
+ return results;
+ }
+
+ public virtual CertificateList[] GetCrls()
+ {
+ if (crls == null)
+ return null;
+
+ CertificateList[] results = new CertificateList[crls.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = CertificateList.GetInstance(crls[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * RevRepContent ::= SEQUENCE {
+ * status SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+ * -- in same order as was sent in RevReqContent
+ * revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+ * -- IDs for which revocation was requested
+ * -- (same order as status)
+ * crls [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+ * -- the resulting CRLs (there may be more than one)
+ * }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(status);
+ AddOptional(v, 0, revCerts);
+ AddOptional(v, 1, crls);
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(true, tagNo, obj));
+ }
+ }
+ }
+}
+
diff --git a/Crypto/src/asn1/cmp/RevRepContentBuilder.cs b/Crypto/src/asn1/cmp/RevRepContentBuilder.cs
new file mode 100644
index 000000000..cc17d1d4c
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevRepContentBuilder.cs
@@ -0,0 +1,55 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevRepContentBuilder
+ {
+ private readonly Asn1EncodableVector status = new Asn1EncodableVector();
+ private readonly Asn1EncodableVector revCerts = new Asn1EncodableVector();
+ private readonly Asn1EncodableVector crls = new Asn1EncodableVector();
+
+ public virtual RevRepContentBuilder Add(PkiStatusInfo status)
+ {
+ this.status.Add(status);
+ return this;
+ }
+
+ public virtual RevRepContentBuilder Add(PkiStatusInfo status, CertId certId)
+ {
+ if (this.status.Count != this.revCerts.Count)
+ throw new InvalidOperationException("status and revCerts sequence must be in common order");
+
+ this.status.Add(status);
+ this.revCerts.Add(certId);
+ return this;
+ }
+
+ public virtual RevRepContentBuilder AddCrl(CertificateList crl)
+ {
+ this.crls.Add(crl);
+ return this;
+ }
+
+ public virtual RevRepContent Build()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ v.Add(new DerSequence(status));
+
+ if (revCerts.Count != 0)
+ {
+ v.Add(new DerTaggedObject(true, 0, new DerSequence(revCerts)));
+ }
+
+ if (crls.Count != 0)
+ {
+ v.Add(new DerTaggedObject(true, 1, new DerSequence(crls)));
+ }
+
+ return RevRepContent.GetInstance(new DerSequence(v));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cmp/RevReqContent.cs b/Crypto/src/asn1/cmp/RevReqContent.cs
new file mode 100644
index 000000000..fbf869203
--- /dev/null
+++ b/Crypto/src/asn1/cmp/RevReqContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ public class RevReqContent
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private RevReqContent(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static RevReqContent GetInstance(object obj)
+ {
+ if (obj is RevReqContent)
+ return (RevReqContent)obj;
+
+ if (obj is Asn1Sequence)
+ return new RevReqContent((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public RevReqContent(params RevDetails[] revDetails)
+ {
+ this.content = new DerSequence(revDetails);
+ }
+
+ public virtual RevDetails[] ToRevDetailsArray()
+ {
+ RevDetails[] result = new RevDetails[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = RevDetails.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * RevReqContent ::= SEQUENCE OF RevDetails
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/Attribute.cs b/Crypto/src/asn1/cms/Attribute.cs
new file mode 100644
index 000000000..c4a104a3f
--- /dev/null
+++ b/Crypto/src/asn1/cms/Attribute.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class Attribute
+ : Asn1Encodable
+ {
+ private DerObjectIdentifier attrType;
+ private Asn1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static Attribute GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Attribute)
+ return (Attribute) obj;
+
+ if (obj is Asn1Sequence)
+ return new Attribute((Asn1Sequence) obj);
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public Attribute(
+ Asn1Sequence seq)
+ {
+ attrType = (DerObjectIdentifier)seq[0];
+ attrValues = (Asn1Set)seq[1];
+ }
+
+ public Attribute(
+ DerObjectIdentifier attrType,
+ Asn1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public DerObjectIdentifier AttrType
+ {
+ get { return attrType; }
+ }
+
+ public Asn1Set AttrValues
+ {
+ get { return attrValues; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(attrType, attrValues);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/AttributeTable.cs b/Crypto/src/asn1/cms/AttributeTable.cs
new file mode 100644
index 000000000..3c0164ce8
--- /dev/null
+++ b/Crypto/src/asn1/cms/AttributeTable.cs
@@ -0,0 +1,231 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class AttributeTable
+ {
+ private readonly IDictionary attributes;
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete]
+ public AttributeTable(
+ Hashtable attrs)
+ {
+ this.attributes = Platform.CreateHashtable(attrs);
+ }
+#endif
+
+ public AttributeTable(
+ IDictionary attrs)
+ {
+ this.attributes = Platform.CreateHashtable(attrs);
+ }
+
+ public AttributeTable(
+ Asn1EncodableVector v)
+ {
+ this.attributes = Platform.CreateHashtable(v.Count);
+
+ foreach (Asn1Encodable o in v)
+ {
+ Attribute a = Attribute.GetInstance(o);
+
+ AddAttribute(a);
+ }
+ }
+
+ public AttributeTable(
+ Asn1Set s)
+ {
+ this.attributes = Platform.CreateHashtable(s.Count);
+
+ for (int i = 0; i != s.Count; i++)
+ {
+ Attribute a = Attribute.GetInstance(s[i]);
+
+ AddAttribute(a);
+ }
+ }
+
+ public AttributeTable(
+ Attributes attrs)
+ : this(Asn1Set.GetInstance(attrs.ToAsn1Object()))
+ {
+ }
+
+ private void AddAttribute(
+ Attribute a)
+ {
+ DerObjectIdentifier oid = a.AttrType;
+ object obj = attributes[oid];
+
+ if (obj == null)
+ {
+ attributes[oid] = a;
+ }
+ else
+ {
+ IList v;
+
+ if (obj is Attribute)
+ {
+ v = Platform.CreateArrayList();
+
+ v.Add(obj);
+ v.Add(a);
+ }
+ else
+ {
+ v = (IList) obj;
+
+ v.Add(a);
+ }
+
+ attributes[oid] = v;
+ }
+ }
+
+ /// <summary>Return the first attribute matching the given OBJECT IDENTIFIER</summary>
+ public Attribute this[DerObjectIdentifier oid]
+ {
+ get
+ {
+ object obj = attributes[oid];
+
+ if (obj is IList)
+ {
+ return (Attribute)((IList)obj)[0];
+ }
+
+ return (Attribute) obj;
+ }
+ }
+
+ [Obsolete("Use 'object[oid]' syntax instead")]
+ public Attribute Get(
+ DerObjectIdentifier oid)
+ {
+ return this[oid];
+ }
+
+ /**
+ * Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
+ * empty if there are no attributes of the required type present.
+ *
+ * @param oid type of attribute required.
+ * @return a vector of all the attributes found of type oid.
+ */
+ public Asn1EncodableVector GetAll(
+ DerObjectIdentifier oid)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ object obj = attributes[oid];
+
+ if (obj is IList)
+ {
+ foreach (Attribute a in (IList)obj)
+ {
+ v.Add(a);
+ }
+ }
+ else if (obj != null)
+ {
+ v.Add((Attribute) obj);
+ }
+
+ return v;
+ }
+
+ public int Count
+ {
+ get
+ {
+ int total = 0;
+
+ foreach (object o in attributes.Values)
+ {
+ if (o is IList)
+ {
+ total += ((IList)o).Count;
+ }
+ else
+ {
+ ++total;
+ }
+ }
+
+ return total;
+ }
+ }
+
+ public IDictionary ToDictionary()
+ {
+ return Platform.CreateHashtable(attributes);
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete("Use 'ToDictionary' instead")]
+ public Hashtable ToHashtable()
+ {
+ return new Hashtable(attributes);
+ }
+#endif
+
+ public Asn1EncodableVector ToAsn1EncodableVector()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ foreach (object obj in attributes.Values)
+ {
+ if (obj is IList)
+ {
+ foreach (object el in (IList)obj)
+ {
+ v.Add(Attribute.GetInstance(el));
+ }
+ }
+ else
+ {
+ v.Add(Attribute.GetInstance(obj));
+ }
+ }
+
+ return v;
+ }
+
+ public Attributes ToAttributes()
+ {
+ return new Attributes(this.ToAsn1EncodableVector());
+ }
+
+ /**
+ * Return a new table with the passed in attribute added.
+ *
+ * @param attrType
+ * @param attrValue
+ * @return
+ */
+ public AttributeTable Add(DerObjectIdentifier attrType, Asn1Encodable attrValue)
+ {
+ AttributeTable newTable = new AttributeTable(attributes);
+
+ newTable.AddAttribute(new Attribute(attrType, new DerSet(attrValue)));
+
+ return newTable;
+ }
+
+ public AttributeTable Remove(DerObjectIdentifier attrType)
+ {
+ AttributeTable newTable = new AttributeTable(attributes);
+
+ newTable.attributes.Remove(attrType);
+
+ return newTable;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/Attributes.cs b/Crypto/src/asn1/cms/Attributes.cs
new file mode 100644
index 000000000..47cb66bdb
--- /dev/null
+++ b/Crypto/src/asn1/cms/Attributes.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class Attributes
+ : Asn1Encodable
+ {
+ private readonly Asn1Set attributes;
+
+ private Attributes(Asn1Set attributes)
+ {
+ this.attributes = attributes;
+ }
+
+ public Attributes(Asn1EncodableVector v)
+ {
+ attributes = new BerSet(v);
+ }
+
+ public static Attributes GetInstance(object obj)
+ {
+ if (obj is Attributes)
+ return (Attributes)obj;
+
+ if (obj != null)
+ return new Attributes(Asn1Set.GetInstance(obj));
+
+ return null;
+ }
+
+ /**
+ * <pre>
+ * Attributes ::=
+ * SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return attributes;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/AuthEnvelopedData.cs b/Crypto/src/asn1/cms/AuthEnvelopedData.cs
new file mode 100644
index 000000000..4260d80f9
--- /dev/null
+++ b/Crypto/src/asn1/cms/AuthEnvelopedData.cs
@@ -0,0 +1,203 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class AuthEnvelopedData
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private OriginatorInfo originatorInfo;
+ private Asn1Set recipientInfos;
+ private EncryptedContentInfo authEncryptedContentInfo;
+ private Asn1Set authAttrs;
+ private Asn1OctetString mac;
+ private Asn1Set unauthAttrs;
+
+ public AuthEnvelopedData(
+ OriginatorInfo originatorInfo,
+ Asn1Set recipientInfos,
+ EncryptedContentInfo authEncryptedContentInfo,
+ Asn1Set authAttrs,
+ Asn1OctetString mac,
+ Asn1Set unauthAttrs)
+ {
+ // "It MUST be set to 0."
+ this.version = new DerInteger(0);
+
+ this.originatorInfo = originatorInfo;
+
+ // TODO
+ // "There MUST be at least one element in the collection."
+ this.recipientInfos = recipientInfos;
+
+ this.authEncryptedContentInfo = authEncryptedContentInfo;
+
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+ this.authAttrs = authAttrs;
+
+ this.mac = mac;
+
+ this.unauthAttrs = unauthAttrs;
+ }
+
+ private AuthEnvelopedData(
+ Asn1Sequence seq)
+ {
+ int index = 0;
+
+ // TODO
+ // "It MUST be set to 0."
+ Asn1Object tmp = seq[index++].ToAsn1Object();
+ version = (DerInteger)tmp;
+
+ tmp = seq[index++].ToAsn1Object();
+ if (tmp is Asn1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject)tmp, false);
+ tmp = seq[index++].ToAsn1Object();
+ }
+
+ // TODO
+ // "There MUST be at least one element in the collection."
+ recipientInfos = Asn1Set.GetInstance(tmp);
+
+ tmp = seq[index++].ToAsn1Object();
+ authEncryptedContentInfo = EncryptedContentInfo.GetInstance(tmp);
+
+ tmp = seq[index++].ToAsn1Object();
+ if (tmp is Asn1TaggedObject)
+ {
+ authAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false);
+ tmp = seq[index++].ToAsn1Object();
+ }
+ else
+ {
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+ }
+
+ mac = Asn1OctetString.GetInstance(tmp);
+
+ if (seq.Count > index)
+ {
+ tmp = seq[index++].ToAsn1Object();
+ unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false);
+ }
+ }
+
+ /**
+ * return an AuthEnvelopedData object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static AuthEnvelopedData GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * return an AuthEnvelopedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @throws ArgumentException if the object cannot be converted.
+ */
+ public static AuthEnvelopedData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is AuthEnvelopedData)
+ return (AuthEnvelopedData)obj;
+
+ if (obj is Asn1Sequence)
+ return new AuthEnvelopedData((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid AuthEnvelopedData: " + obj.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public OriginatorInfo OriginatorInfo
+ {
+ get { return originatorInfo; }
+ }
+
+ public Asn1Set RecipientInfos
+ {
+ get { return recipientInfos; }
+ }
+
+ public EncryptedContentInfo AuthEncryptedContentInfo
+ {
+ get { return authEncryptedContentInfo; }
+ }
+
+ public Asn1Set AuthAttrs
+ {
+ get { return authAttrs; }
+ }
+
+ public Asn1OctetString Mac
+ {
+ get { return mac; }
+ }
+
+ public Asn1Set UnauthAttrs
+ {
+ get { return unauthAttrs; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AuthEnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * authEncryptedContentInfo EncryptedContentInfo,
+ * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+ if (originatorInfo != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.Add(recipientInfos, authEncryptedContentInfo);
+
+ // "authAttrs optionally contains the authenticated attributes."
+ if (authAttrs != null)
+ {
+ // "AuthAttributes MUST be DER encoded, even if the rest of the
+ // AuthEnvelopedData structure is BER encoded."
+ v.Add(new DerTaggedObject(false, 1, authAttrs));
+ }
+
+ v.Add(mac);
+
+ // "unauthAttrs optionally contains the unauthenticated attributes."
+ if (unauthAttrs != null)
+ {
+ v.Add(new DerTaggedObject(false, 2, unauthAttrs));
+ }
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/AuthEnvelopedDataParser.cs b/Crypto/src/asn1/cms/AuthEnvelopedDataParser.cs
new file mode 100644
index 000000000..35cb3bfcc
--- /dev/null
+++ b/Crypto/src/asn1/cms/AuthEnvelopedDataParser.cs
@@ -0,0 +1,145 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ *
+ * <pre>
+ * AuthEnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * authEncryptedContentInfo EncryptedContentInfo,
+ * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+ * </pre>
+ */
+ public class AuthEnvelopedDataParser
+ {
+ private Asn1SequenceParser seq;
+ private DerInteger version;
+ private IAsn1Convertible nextObject;
+ private bool originatorInfoCalled;
+
+ public AuthEnvelopedDataParser(
+ Asn1SequenceParser seq)
+ {
+ this.seq = seq;
+
+ // TODO
+ // "It MUST be set to 0."
+ this.version = (DerInteger)seq.ReadObject();
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public OriginatorInfo GetOriginatorInfo()
+ {
+ originatorInfoCalled = true;
+
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)nextObject).TagNo == 0)
+ {
+ Asn1SequenceParser originatorInfo = (Asn1SequenceParser) ((Asn1TaggedObjectParser)nextObject).GetObjectParser(Asn1Tags.Sequence, false);
+ nextObject = null;
+ return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetRecipientInfos()
+ {
+ if (!originatorInfoCalled)
+ {
+ GetOriginatorInfo();
+ }
+
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ Asn1SetParser recipientInfos = (Asn1SetParser)nextObject;
+ nextObject = null;
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfoParser GetAuthEncryptedContentInfo()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject != null)
+ {
+ Asn1SequenceParser o = (Asn1SequenceParser) nextObject;
+ nextObject = null;
+ return new EncryptedContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetAuthAttrs()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject is Asn1TaggedObjectParser)
+ {
+ IAsn1Convertible o = nextObject;
+ nextObject = null;
+ return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+ }
+
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+
+ return null;
+ }
+
+ public Asn1OctetString GetMac()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ IAsn1Convertible o = nextObject;
+ nextObject = null;
+
+ return Asn1OctetString.GetInstance(o.ToAsn1Object());
+ }
+
+ public Asn1SetParser GetUnauthAttrs()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject != null)
+ {
+ IAsn1Convertible o = nextObject;
+ nextObject = null;
+ return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/AuthenticatedData.cs b/Crypto/src/asn1/cms/AuthenticatedData.cs
new file mode 100644
index 000000000..15286d1aa
--- /dev/null
+++ b/Crypto/src/asn1/cms/AuthenticatedData.cs
@@ -0,0 +1,270 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class AuthenticatedData
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private OriginatorInfo originatorInfo;
+ private Asn1Set recipientInfos;
+ private AlgorithmIdentifier macAlgorithm;
+ private AlgorithmIdentifier digestAlgorithm;
+ private ContentInfo encapsulatedContentInfo;
+ private Asn1Set authAttrs;
+ private Asn1OctetString mac;
+ private Asn1Set unauthAttrs;
+
+ public AuthenticatedData(
+ OriginatorInfo originatorInfo,
+ Asn1Set recipientInfos,
+ AlgorithmIdentifier macAlgorithm,
+ AlgorithmIdentifier digestAlgorithm,
+ ContentInfo encapsulatedContent,
+ Asn1Set authAttrs,
+ Asn1OctetString mac,
+ Asn1Set unauthAttrs)
+ {
+ if (digestAlgorithm != null || authAttrs != null)
+ {
+ if (digestAlgorithm == null || authAttrs == null)
+ {
+ throw new ArgumentException("digestAlgorithm and authAttrs must be set together");
+ }
+ }
+
+ version = new DerInteger(CalculateVersion(originatorInfo));
+
+ this.originatorInfo = originatorInfo;
+ this.macAlgorithm = macAlgorithm;
+ this.digestAlgorithm = digestAlgorithm;
+ this.recipientInfos = recipientInfos;
+ this.encapsulatedContentInfo = encapsulatedContent;
+ this.authAttrs = authAttrs;
+ this.mac = mac;
+ this.unauthAttrs = unauthAttrs;
+ }
+
+ private AuthenticatedData(
+ Asn1Sequence seq)
+ {
+ int index = 0;
+
+ version = (DerInteger)seq[index++];
+
+ Asn1Encodable tmp = seq[index++];
+ if (tmp is Asn1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject)tmp, false);
+ tmp = seq[index++];
+ }
+
+ recipientInfos = Asn1Set.GetInstance(tmp);
+ macAlgorithm = AlgorithmIdentifier.GetInstance(seq[index++]);
+
+ tmp = seq[index++];
+ if (tmp is Asn1TaggedObject)
+ {
+ digestAlgorithm = AlgorithmIdentifier.GetInstance((Asn1TaggedObject)tmp, false);
+ tmp = seq[index++];
+ }
+
+ encapsulatedContentInfo = ContentInfo.GetInstance(tmp);
+
+ tmp = seq[index++];
+ if (tmp is Asn1TaggedObject)
+ {
+ authAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false);
+ tmp = seq[index++];
+ }
+
+ mac = Asn1OctetString.GetInstance(tmp);
+
+ if (seq.Count > index)
+ {
+ unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)seq[index], false);
+ }
+ }
+
+ /**
+ * return an AuthenticatedData object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static AuthenticatedData GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * return an AuthenticatedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @throws ArgumentException if the object cannot be converted.
+ */
+ public static AuthenticatedData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is AuthenticatedData)
+ {
+ return (AuthenticatedData)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new AuthenticatedData((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Invalid AuthenticatedData: " + obj.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public OriginatorInfo OriginatorInfo
+ {
+ get { return originatorInfo; }
+ }
+
+ public Asn1Set RecipientInfos
+ {
+ get { return recipientInfos; }
+ }
+
+ public AlgorithmIdentifier MacAlgorithm
+ {
+ get { return macAlgorithm; }
+ }
+
+ public AlgorithmIdentifier DigestAlgorithm
+ {
+ get { return digestAlgorithm; }
+ }
+
+ public ContentInfo EncapsulatedContentInfo
+ {
+ get { return encapsulatedContentInfo; }
+ }
+
+ public Asn1Set AuthAttrs
+ {
+ get { return authAttrs; }
+ }
+
+ public Asn1OctetString Mac
+ {
+ get { return mac; }
+ }
+
+ public Asn1Set UnauthAttrs
+ {
+ get { return unauthAttrs; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AuthenticatedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * macAlgorithm MessageAuthenticationCodeAlgorithm,
+ * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+ * encapContentInfo EncapsulatedContentInfo,
+ * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+ *
+ * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * MessageAuthenticationCode ::= OCTET STRING
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+ if (originatorInfo != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.Add(recipientInfos, macAlgorithm);
+
+ if (digestAlgorithm != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, digestAlgorithm));
+ }
+
+ v.Add(encapsulatedContentInfo);
+
+ if (authAttrs != null)
+ {
+ v.Add(new DerTaggedObject(false, 2, authAttrs));
+ }
+
+ v.Add(mac);
+
+ if (unauthAttrs != null)
+ {
+ v.Add(new DerTaggedObject(false, 3, unauthAttrs));
+ }
+
+ return new BerSequence(v);
+ }
+
+ public static int CalculateVersion(OriginatorInfo origInfo)
+ {
+ if (origInfo == null)
+ return 0;
+
+ int ver = 0;
+
+ foreach (object obj in origInfo.Certificates)
+ {
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tag = (Asn1TaggedObject)obj;
+
+ if (tag.TagNo == 2)
+ {
+ ver = 1;
+ }
+ else if (tag.TagNo == 3)
+ {
+ ver = 3;
+ break;
+ }
+ }
+ }
+
+ foreach (object obj in origInfo.Crls)
+ {
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tag = (Asn1TaggedObject)obj;
+
+ if (tag.TagNo == 1)
+ {
+ ver = 3;
+ break;
+ }
+ }
+ }
+
+ return ver;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/AuthenticatedDataParser.cs b/Crypto/src/asn1/cms/AuthenticatedDataParser.cs
new file mode 100644
index 000000000..4b80d1b02
--- /dev/null
+++ b/Crypto/src/asn1/cms/AuthenticatedDataParser.cs
@@ -0,0 +1,182 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * AuthenticatedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * macAlgorithm MessageAuthenticationCodeAlgorithm,
+ * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+ * encapContentInfo EncapsulatedContentInfo,
+ * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+ *
+ * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * MessageAuthenticationCode ::= OCTET STRING
+ * </pre>
+ */
+ public class AuthenticatedDataParser
+ {
+ private Asn1SequenceParser seq;
+ private DerInteger version;
+ private IAsn1Convertible nextObject;
+ private bool originatorInfoCalled;
+
+ public AuthenticatedDataParser(
+ Asn1SequenceParser seq)
+ {
+ this.seq = seq;
+ this.version = (DerInteger)seq.ReadObject();
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public OriginatorInfo GetOriginatorInfo()
+ {
+ originatorInfoCalled = true;
+
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)nextObject).TagNo == 0)
+ {
+ Asn1SequenceParser originatorInfo = (Asn1SequenceParser) ((Asn1TaggedObjectParser)nextObject).GetObjectParser(Asn1Tags.Sequence, false);
+ nextObject = null;
+ return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetRecipientInfos()
+ {
+ if (!originatorInfoCalled)
+ {
+ GetOriginatorInfo();
+ }
+
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ Asn1SetParser recipientInfos = (Asn1SetParser)nextObject;
+ nextObject = null;
+ return recipientInfos;
+ }
+
+ public AlgorithmIdentifier GetMacAlgorithm()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject != null)
+ {
+ Asn1SequenceParser o = (Asn1SequenceParser)nextObject;
+ nextObject = null;
+ return AlgorithmIdentifier.GetInstance(o.ToAsn1Object());
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier GetDigestAlgorithm()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject is Asn1TaggedObjectParser)
+ {
+ AlgorithmIdentifier obj = AlgorithmIdentifier.GetInstance(
+ (Asn1TaggedObject)nextObject.ToAsn1Object(), false);
+ nextObject = null;
+ return obj;
+ }
+
+ return null;
+ }
+
+ public ContentInfoParser GetEnapsulatedContentInfo()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject != null)
+ {
+ Asn1SequenceParser o = (Asn1SequenceParser)nextObject;
+ nextObject = null;
+ return new ContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetAuthAttrs()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject is Asn1TaggedObjectParser)
+ {
+ IAsn1Convertible o = nextObject;
+ nextObject = null;
+ return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+ }
+
+ return null;
+ }
+
+ public Asn1OctetString GetMac()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ IAsn1Convertible o = nextObject;
+ nextObject = null;
+
+ return Asn1OctetString.GetInstance(o.ToAsn1Object());
+ }
+
+ public Asn1SetParser GetUnauthAttrs()
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.ReadObject();
+ }
+
+ if (nextObject != null)
+ {
+ IAsn1Convertible o = nextObject;
+ nextObject = null;
+ return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/CMSAttributes.cs b/Crypto/src/asn1/cms/CMSAttributes.cs
new file mode 100644
index 000000000..fca2b6738
--- /dev/null
+++ b/Crypto/src/asn1/cms/CMSAttributes.cs
@@ -0,0 +1,14 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public abstract class CmsAttributes
+ {
+ public static readonly DerObjectIdentifier ContentType = PkcsObjectIdentifiers.Pkcs9AtContentType;
+ public static readonly DerObjectIdentifier MessageDigest = PkcsObjectIdentifiers.Pkcs9AtMessageDigest;
+ public static readonly DerObjectIdentifier SigningTime = PkcsObjectIdentifiers.Pkcs9AtSigningTime;
+ public static readonly DerObjectIdentifier CounterSignature = PkcsObjectIdentifiers.Pkcs9AtCounterSignature;
+ public static readonly DerObjectIdentifier ContentHint = PkcsObjectIdentifiers.IdAAContentHint;
+ }
+}
diff --git a/Crypto/src/asn1/cms/CMSObjectIdentifiers.cs b/Crypto/src/asn1/cms/CMSObjectIdentifiers.cs
new file mode 100644
index 000000000..59009bda7
--- /dev/null
+++ b/Crypto/src/asn1/cms/CMSObjectIdentifiers.cs
@@ -0,0 +1,18 @@
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public abstract class CmsObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier Data = PkcsObjectIdentifiers.Data;
+ public static readonly DerObjectIdentifier SignedData = PkcsObjectIdentifiers.SignedData;
+ public static readonly DerObjectIdentifier EnvelopedData = PkcsObjectIdentifiers.EnvelopedData;
+ public static readonly DerObjectIdentifier SignedAndEnvelopedData = PkcsObjectIdentifiers.SignedAndEnvelopedData;
+ public static readonly DerObjectIdentifier DigestedData = PkcsObjectIdentifiers.DigestedData;
+ public static readonly DerObjectIdentifier EncryptedData = PkcsObjectIdentifiers.EncryptedData;
+ public static readonly DerObjectIdentifier AuthenticatedData = PkcsObjectIdentifiers.IdCTAuthData;
+ public static readonly DerObjectIdentifier CompressedData = PkcsObjectIdentifiers.IdCTCompressedData;
+ public static readonly DerObjectIdentifier AuthEnvelopedData = PkcsObjectIdentifiers.IdCTAuthEnvelopedData;
+ public static readonly DerObjectIdentifier timestampedData = PkcsObjectIdentifiers.IdCTTimestampedData;
+ }
+}
diff --git a/Crypto/src/asn1/cms/CompressedData.cs b/Crypto/src/asn1/cms/CompressedData.cs
new file mode 100644
index 000000000..5a2869b8c
--- /dev/null
+++ b/Crypto/src/asn1/cms/CompressedData.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * RFC 3274 - CMS Compressed Data.
+ * <pre>
+ * CompressedData ::= Sequence {
+ * version CMSVersion,
+ * compressionAlgorithm CompressionAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo
+ * }
+ * </pre>
+ */
+ public class CompressedData
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private AlgorithmIdentifier compressionAlgorithm;
+ private ContentInfo encapContentInfo;
+
+ public CompressedData(
+ AlgorithmIdentifier compressionAlgorithm,
+ ContentInfo encapContentInfo)
+ {
+ this.version = new DerInteger(0);
+ this.compressionAlgorithm = compressionAlgorithm;
+ this.encapContentInfo = encapContentInfo;
+ }
+
+ public CompressedData(
+ Asn1Sequence seq)
+ {
+ this.version = (DerInteger) seq[0];
+ this.compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+ this.encapContentInfo = ContentInfo.GetInstance(seq[2]);
+ }
+
+ /**
+ * return a CompressedData object from a tagged object.
+ *
+ * @param ato the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static CompressedData GetInstance(
+ Asn1TaggedObject ato,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(ato, explicitly));
+ }
+
+ /**
+ * return a CompressedData object from the given object.
+ *
+ * @param _obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static CompressedData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CompressedData)
+ return (CompressedData)obj;
+
+ if (obj is Asn1Sequence)
+ return new CompressedData((Asn1Sequence) obj);
+
+ throw new ArgumentException("Invalid CompressedData: " + obj.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public AlgorithmIdentifier CompressionAlgorithmIdentifier
+ {
+ get { return compressionAlgorithm; }
+ }
+
+ public ContentInfo EncapContentInfo
+ {
+ get { return encapContentInfo; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new BerSequence(version, compressionAlgorithm, encapContentInfo);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/CompressedDataParser.cs b/Crypto/src/asn1/cms/CompressedDataParser.cs
new file mode 100644
index 000000000..7c53453df
--- /dev/null
+++ b/Crypto/src/asn1/cms/CompressedDataParser.cs
@@ -0,0 +1,47 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * RFC 3274 - CMS Compressed Data.
+ * <pre>
+ * CompressedData ::= SEQUENCE {
+ * version CMSVersion,
+ * compressionAlgorithm CompressionAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo
+ * }
+ * </pre>
+ */
+ public class CompressedDataParser
+ {
+ private DerInteger _version;
+ private AlgorithmIdentifier _compressionAlgorithm;
+ private ContentInfoParser _encapContentInfo;
+
+ public CompressedDataParser(
+ Asn1SequenceParser seq)
+ {
+ this._version = (DerInteger)seq.ReadObject();
+ this._compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object());
+ this._encapContentInfo = new ContentInfoParser((Asn1SequenceParser)seq.ReadObject());
+ }
+
+ public DerInteger Version
+ {
+ get { return _version; }
+ }
+
+ public AlgorithmIdentifier CompressionAlgorithmIdentifier
+ {
+ get { return _compressionAlgorithm; }
+ }
+
+ public ContentInfoParser GetEncapContentInfo()
+ {
+ return _encapContentInfo;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/ContentInfo.cs b/Crypto/src/asn1/cms/ContentInfo.cs
new file mode 100644
index 000000000..61a277535
--- /dev/null
+++ b/Crypto/src/asn1/cms/ContentInfo.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class ContentInfo
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier contentType;
+ private readonly Asn1Encodable content;
+
+ public static ContentInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ContentInfo)
+ return (ContentInfo) obj;
+
+ if (obj is Asn1Sequence)
+ return new ContentInfo((Asn1Sequence) obj);
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name);
+ }
+
+ private ContentInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ contentType = (DerObjectIdentifier) seq[0];
+
+ if (seq.Count > 1)
+ {
+ Asn1TaggedObject tagged = (Asn1TaggedObject) seq[1];
+ if (!tagged.IsExplicit() || tagged.TagNo != 0)
+ throw new ArgumentException("Bad tag for 'content'", "seq");
+
+ content = tagged.GetObject();
+ }
+ }
+
+ public ContentInfo(
+ DerObjectIdentifier contentType,
+ Asn1Encodable content)
+ {
+ this.contentType = contentType;
+ this.content = content;
+ }
+
+ public DerObjectIdentifier ContentType
+ {
+ get { return contentType; }
+ }
+
+ public Asn1Encodable Content
+ {
+ get { return content; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ContentInfo ::= Sequence {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(contentType);
+
+ if (content != null)
+ {
+ v.Add(new BerTaggedObject(0, content));
+ }
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/ContentInfoParser.cs b/Crypto/src/asn1/cms/ContentInfoParser.cs
new file mode 100644
index 000000000..541cc0f59
--- /dev/null
+++ b/Crypto/src/asn1/cms/ContentInfoParser.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ * </pre>
+ */
+ public class ContentInfoParser
+ {
+ private DerObjectIdentifier contentType;
+ private Asn1TaggedObjectParser content;
+
+ public ContentInfoParser(
+ Asn1SequenceParser seq)
+ {
+ contentType = (DerObjectIdentifier)seq.ReadObject();
+ content = (Asn1TaggedObjectParser)seq.ReadObject();
+ }
+
+ public DerObjectIdentifier ContentType
+ {
+ get { return contentType; }
+ }
+
+ public IAsn1Convertible GetContent(
+ int tag)
+ {
+ if (content == null)
+ return null;
+
+ return content.GetObjectParser(tag, true);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/EncryptedContentInfo.cs b/Crypto/src/asn1/cms/EncryptedContentInfo.cs
new file mode 100644
index 000000000..4fdc47138
--- /dev/null
+++ b/Crypto/src/asn1/cms/EncryptedContentInfo.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class EncryptedContentInfo
+ : Asn1Encodable
+ {
+ private DerObjectIdentifier contentType;
+ private AlgorithmIdentifier contentEncryptionAlgorithm;
+ private Asn1OctetString encryptedContent;
+
+ public EncryptedContentInfo(
+ DerObjectIdentifier contentType,
+ AlgorithmIdentifier contentEncryptionAlgorithm,
+ Asn1OctetString encryptedContent)
+ {
+ this.contentType = contentType;
+ this.contentEncryptionAlgorithm = contentEncryptionAlgorithm;
+ this.encryptedContent = encryptedContent;
+ }
+
+ public EncryptedContentInfo(
+ Asn1Sequence seq)
+ {
+ contentType = (DerObjectIdentifier) seq[0];
+ contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+
+ if (seq.Count > 2)
+ {
+ encryptedContent = Asn1OctetString.GetInstance(
+ (Asn1TaggedObject) seq[2], false);
+ }
+ }
+
+ /**
+ * return an EncryptedContentInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static EncryptedContentInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is EncryptedContentInfo)
+ return (EncryptedContentInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new EncryptedContentInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid EncryptedContentInfo: " + obj.GetType().Name);
+ }
+
+ public DerObjectIdentifier ContentType
+ {
+ get { return contentType; }
+ }
+
+ public AlgorithmIdentifier ContentEncryptionAlgorithm
+ {
+ get { return contentEncryptionAlgorithm; }
+ }
+
+ public Asn1OctetString EncryptedContent
+ {
+ get { return encryptedContent; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * EncryptedContentInfo ::= Sequence {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ contentType, contentEncryptionAlgorithm);
+
+ if (encryptedContent != null)
+ {
+ v.Add(new BerTaggedObject(false, 0, encryptedContent));
+ }
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/EncryptedContentInfoParser.cs b/Crypto/src/asn1/cms/EncryptedContentInfoParser.cs
new file mode 100644
index 000000000..af748b1b3
--- /dev/null
+++ b/Crypto/src/asn1/cms/EncryptedContentInfoParser.cs
@@ -0,0 +1,46 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * <pre>
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ * </pre>
+ */
+ public class EncryptedContentInfoParser
+ {
+ private DerObjectIdentifier _contentType;
+ private AlgorithmIdentifier _contentEncryptionAlgorithm;
+ private Asn1TaggedObjectParser _encryptedContent;
+
+ public EncryptedContentInfoParser(
+ Asn1SequenceParser seq)
+ {
+ _contentType = (DerObjectIdentifier)seq.ReadObject();
+ _contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object());
+ _encryptedContent = (Asn1TaggedObjectParser)seq.ReadObject();
+ }
+
+ public DerObjectIdentifier ContentType
+ {
+ get { return _contentType; }
+ }
+
+ public AlgorithmIdentifier ContentEncryptionAlgorithm
+ {
+ get { return _contentEncryptionAlgorithm; }
+ }
+
+ public IAsn1Convertible GetEncryptedContent(
+ int tag)
+ {
+ return _encryptedContent.GetObjectParser(tag, false);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/EncryptedData.cs b/Crypto/src/asn1/cms/EncryptedData.cs
new file mode 100644
index 000000000..5b8378282
--- /dev/null
+++ b/Crypto/src/asn1/cms/EncryptedData.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class EncryptedData
+ : Asn1Encodable
+ {
+ private readonly DerInteger version;
+ private readonly EncryptedContentInfo encryptedContentInfo;
+ private readonly Asn1Set unprotectedAttrs;
+
+ public static EncryptedData GetInstance(
+ object obj)
+ {
+ if (obj is EncryptedData)
+ return (EncryptedData) obj;
+
+ if (obj is Asn1Sequence)
+ return new EncryptedData((Asn1Sequence) obj);
+
+ throw new ArgumentException("Invalid EncryptedData: " + obj.GetType().Name);
+ }
+
+ public EncryptedData(
+ EncryptedContentInfo encInfo)
+ : this(encInfo, null)
+ {
+ }
+
+ public EncryptedData(
+ EncryptedContentInfo encInfo,
+ Asn1Set unprotectedAttrs)
+ {
+ if (encInfo == null)
+ throw new ArgumentNullException("encInfo");
+
+ this.version = new DerInteger((unprotectedAttrs == null) ? 0 : 2);
+ this.encryptedContentInfo = encInfo;
+ this.unprotectedAttrs = unprotectedAttrs;
+ }
+
+ private EncryptedData(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 2 || seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.version = DerInteger.GetInstance(seq[0]);
+ this.encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[1]);
+
+ if (seq.Count > 2)
+ {
+ this.unprotectedAttrs = Asn1Set.GetInstance(seq[2]);
+ }
+ }
+
+ public virtual DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public virtual EncryptedContentInfo EncryptedContentInfo
+ {
+ get { return encryptedContentInfo; }
+ }
+
+ public virtual Asn1Set UnprotectedAttrs
+ {
+ get { return unprotectedAttrs; }
+ }
+
+ /**
+ * <pre>
+ * EncryptedData ::= SEQUENCE {
+ * version CMSVersion,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(version, encryptedContentInfo);
+
+ if (unprotectedAttrs != null)
+ {
+ v.Add(new BerTaggedObject(false, 1, unprotectedAttrs));
+ }
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/EnvelopedData.cs b/Crypto/src/asn1/cms/EnvelopedData.cs
new file mode 100644
index 000000000..47cd4a9f5
--- /dev/null
+++ b/Crypto/src/asn1/cms/EnvelopedData.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class EnvelopedData
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private OriginatorInfo originatorInfo;
+ private Asn1Set recipientInfos;
+ private EncryptedContentInfo encryptedContentInfo;
+ private Asn1Set unprotectedAttrs;
+
+ public EnvelopedData(
+ OriginatorInfo originatorInfo,
+ Asn1Set recipientInfos,
+ EncryptedContentInfo encryptedContentInfo,
+ Asn1Set unprotectedAttrs)
+ {
+ if (originatorInfo != null || unprotectedAttrs != null)
+ {
+ version = new DerInteger(2);
+ }
+ else
+ {
+ version = new DerInteger(0);
+
+ foreach (object o in recipientInfos)
+ {
+ RecipientInfo ri = RecipientInfo.GetInstance(o);
+
+ if (!ri.Version.Equals(version))
+ {
+ version = new DerInteger(2);
+ break;
+ }
+ }
+ }
+
+ this.originatorInfo = originatorInfo;
+ this.recipientInfos = recipientInfos;
+ this.encryptedContentInfo = encryptedContentInfo;
+ this.unprotectedAttrs = unprotectedAttrs;
+ }
+
+ public EnvelopedData(
+ Asn1Sequence seq)
+ {
+ int index = 0;
+
+ version = (DerInteger) seq[index++];
+
+ object tmp = seq[index++];
+
+ if (tmp is Asn1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject) tmp, false);
+ tmp = seq[index++];
+ }
+
+ recipientInfos = Asn1Set.GetInstance(tmp);
+ encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[index++]);
+
+ if (seq.Count > index)
+ {
+ unprotectedAttrs = Asn1Set.GetInstance((Asn1TaggedObject) seq[index], false);
+ }
+ }
+
+ /**
+ * return an EnvelopedData object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static EnvelopedData GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return an EnvelopedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static EnvelopedData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is EnvelopedData)
+ {
+ return (EnvelopedData)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new EnvelopedData((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Invalid EnvelopedData: " + obj.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public OriginatorInfo OriginatorInfo
+ {
+ get { return originatorInfo; }
+ }
+
+ public Asn1Set RecipientInfos
+ {
+ get { return recipientInfos; }
+ }
+
+ public EncryptedContentInfo EncryptedContentInfo
+ {
+ get { return encryptedContentInfo; }
+ }
+
+ public Asn1Set UnprotectedAttrs
+ {
+ get { return unprotectedAttrs; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * EnvelopedData ::= Sequence {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+ if (originatorInfo != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.Add(recipientInfos, encryptedContentInfo);
+
+ if (unprotectedAttrs != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, unprotectedAttrs));
+ }
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/EnvelopedDataParser.cs b/Crypto/src/asn1/cms/EnvelopedDataParser.cs
new file mode 100644
index 000000000..599353791
--- /dev/null
+++ b/Crypto/src/asn1/cms/EnvelopedDataParser.cs
@@ -0,0 +1,107 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * EnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+ * }
+ * </pre>
+ */
+ public class EnvelopedDataParser
+ {
+ private Asn1SequenceParser _seq;
+ private DerInteger _version;
+ private IAsn1Convertible _nextObject;
+ private bool _originatorInfoCalled;
+
+ public EnvelopedDataParser(
+ Asn1SequenceParser seq)
+ {
+ this._seq = seq;
+ this._version = (DerInteger)seq.ReadObject();
+ }
+
+ public DerInteger Version
+ {
+ get { return _version; }
+ }
+
+ public OriginatorInfo GetOriginatorInfo()
+ {
+ _originatorInfoCalled = true;
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.ReadObject();
+ }
+
+ if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 0)
+ {
+ Asn1SequenceParser originatorInfo = (Asn1SequenceParser)
+ ((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Sequence, false);
+ _nextObject = null;
+ return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetRecipientInfos()
+ {
+ if (!_originatorInfoCalled)
+ {
+ GetOriginatorInfo();
+ }
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.ReadObject();
+ }
+
+ Asn1SetParser recipientInfos = (Asn1SetParser)_nextObject;
+ _nextObject = null;
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfoParser GetEncryptedContentInfo()
+ {
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.ReadObject();
+ }
+
+ if (_nextObject != null)
+ {
+ Asn1SequenceParser o = (Asn1SequenceParser) _nextObject;
+ _nextObject = null;
+ return new EncryptedContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetUnprotectedAttrs()
+ {
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.ReadObject();
+ }
+
+ if (_nextObject != null)
+ {
+ IAsn1Convertible o = _nextObject;
+ _nextObject = null;
+ return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/Evidence.cs b/Crypto/src/asn1/cms/Evidence.cs
new file mode 100644
index 000000000..4745e565b
--- /dev/null
+++ b/Crypto/src/asn1/cms/Evidence.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class Evidence
+ : Asn1Encodable, IAsn1Choice
+ {
+ private TimeStampTokenEvidence tstEvidence;
+
+ public Evidence(TimeStampTokenEvidence tstEvidence)
+ {
+ this.tstEvidence = tstEvidence;
+ }
+
+ private Evidence(Asn1TaggedObject tagged)
+ {
+ if (tagged.TagNo == 0)
+ {
+ this.tstEvidence = TimeStampTokenEvidence.GetInstance(tagged, false);
+ }
+ }
+
+ public static Evidence GetInstance(object obj)
+ {
+ if (obj is Evidence)
+ return (Evidence)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new Evidence(Asn1TaggedObject.GetInstance(obj));
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+ }
+
+ public virtual TimeStampTokenEvidence TstEvidence
+ {
+ get { return tstEvidence; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ if (tstEvidence != null)
+ return new DerTaggedObject(false, 0, tstEvidence);
+
+ return null;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/IssuerAndSerialNumber.cs b/Crypto/src/asn1/cms/IssuerAndSerialNumber.cs
new file mode 100644
index 000000000..ac1af961f
--- /dev/null
+++ b/Crypto/src/asn1/cms/IssuerAndSerialNumber.cs
@@ -0,0 +1,66 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class IssuerAndSerialNumber
+ : Asn1Encodable
+ {
+ private X509Name name;
+ private DerInteger serialNumber;
+
+ public static IssuerAndSerialNumber GetInstance(
+ object obj)
+ {
+ if (obj is IssuerAndSerialNumber)
+ return (IssuerAndSerialNumber)obj;
+
+ if (obj is Asn1Sequence)
+ return new IssuerAndSerialNumber((Asn1Sequence)obj);
+
+ throw new ArgumentException(
+ "Illegal object in IssuerAndSerialNumber: " + obj.GetType().Name);
+ }
+
+ public IssuerAndSerialNumber(
+ Asn1Sequence seq)
+ {
+ this.name = X509Name.GetInstance(seq[0]);
+ this.serialNumber = (DerInteger) seq[1];
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ BigInteger serialNumber)
+ {
+ this.name = name;
+ this.serialNumber = new DerInteger(serialNumber);
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ DerInteger serialNumber)
+ {
+ this.name = name;
+ this.serialNumber = serialNumber;
+ }
+
+ public X509Name Name
+ {
+ get { return name; }
+ }
+
+ public DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(name, serialNumber);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/KEKIdentifier.cs b/Crypto/src/asn1/cms/KEKIdentifier.cs
new file mode 100644
index 000000000..e5d1d9090
--- /dev/null
+++ b/Crypto/src/asn1/cms/KEKIdentifier.cs
@@ -0,0 +1,119 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class KekIdentifier
+ : Asn1Encodable
+ {
+ private Asn1OctetString keyIdentifier;
+ private DerGeneralizedTime date;
+ private OtherKeyAttribute other;
+
+ public KekIdentifier(
+ byte[] keyIdentifier,
+ DerGeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.keyIdentifier = new DerOctetString(keyIdentifier);
+ this.date = date;
+ this.other = other;
+ }
+
+ public KekIdentifier(
+ Asn1Sequence seq)
+ {
+ keyIdentifier = (Asn1OctetString) seq[0];
+
+ switch (seq.Count)
+ {
+ case 1:
+ break;
+ case 2:
+ if (seq[1] is DerGeneralizedTime)
+ {
+ date = (DerGeneralizedTime) seq[1];
+ }
+ else
+ {
+ other = OtherKeyAttribute.GetInstance(seq[2]);
+ }
+ break;
+ case 3:
+ date = (DerGeneralizedTime) seq[1];
+ other = OtherKeyAttribute.GetInstance(seq[2]);
+ break;
+ default:
+ throw new ArgumentException("Invalid KekIdentifier");
+ }
+ }
+
+ /**
+ * return a KekIdentifier object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KekIdentifier GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return a KekIdentifier object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static KekIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is KekIdentifier)
+ return (KekIdentifier)obj;
+
+ if (obj is Asn1Sequence)
+ return new KekIdentifier((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid KekIdentifier: " + obj.GetType().Name);
+ }
+
+ public Asn1OctetString KeyIdentifier
+ {
+ get { return keyIdentifier; }
+ }
+
+ public DerGeneralizedTime Date
+ {
+ get { return date; }
+ }
+
+ public OtherKeyAttribute Other
+ {
+ get { return other; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * KekIdentifier ::= Sequence {
+ * keyIdentifier OCTET STRING,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(keyIdentifier);
+ v.AddOptional(date, other);
+ return new DerSequence(v);
+ }
+ }
+}
+
diff --git a/Crypto/src/asn1/cms/KEKRecipientInfo.cs b/Crypto/src/asn1/cms/KEKRecipientInfo.cs
new file mode 100644
index 000000000..d847b50cc
--- /dev/null
+++ b/Crypto/src/asn1/cms/KEKRecipientInfo.cs
@@ -0,0 +1,106 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class KekRecipientInfo
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private KekIdentifier kekID;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private Asn1OctetString encryptedKey;
+
+ public KekRecipientInfo(
+ KekIdentifier kekID,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ Asn1OctetString encryptedKey)
+ {
+ this.version = new DerInteger(4);
+ this.kekID = kekID;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KekRecipientInfo(
+ Asn1Sequence seq)
+ {
+ version = (DerInteger) seq[0];
+ kekID = KekIdentifier.GetInstance(seq[1]);
+ keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
+ encryptedKey = (Asn1OctetString) seq[3];
+ }
+
+ /**
+ * return a KekRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KekRecipientInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return a KekRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static KekRecipientInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is KekRecipientInfo)
+ return (KekRecipientInfo)obj;
+
+ if(obj is Asn1Sequence)
+ return new KekRecipientInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid KekRecipientInfo: " + obj.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public KekIdentifier KekID
+ {
+ get { return kekID; }
+ }
+
+ public AlgorithmIdentifier KeyEncryptionAlgorithm
+ {
+ get { return keyEncryptionAlgorithm; }
+ }
+
+ public Asn1OctetString EncryptedKey
+ {
+ get { return encryptedKey; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * KekRecipientInfo ::= Sequence {
+ * version CMSVersion, -- always set to 4
+ * kekID KekIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(version, kekID, keyEncryptionAlgorithm, encryptedKey);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs b/Crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs
new file mode 100644
index 000000000..fa6fdb0f3
--- /dev/null
+++ b/Crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class KeyAgreeRecipientIdentifier
+ : Asn1Encodable, IAsn1Choice
+ {
+ /**
+ * return an KeyAgreeRecipientIdentifier object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KeyAgreeRecipientIdentifier GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * return an KeyAgreeRecipientIdentifier object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static KeyAgreeRecipientIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is KeyAgreeRecipientIdentifier)
+ return (KeyAgreeRecipientIdentifier)obj;
+
+ if (obj is Asn1Sequence)
+ return new KeyAgreeRecipientIdentifier(IssuerAndSerialNumber.GetInstance(obj));
+
+ if (obj is Asn1TaggedObject && ((Asn1TaggedObject)obj).TagNo == 0)
+ {
+ return new KeyAgreeRecipientIdentifier(RecipientKeyIdentifier.GetInstance(
+ (Asn1TaggedObject)obj, false));
+ }
+
+ throw new ArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.GetType().FullName, "obj");
+ }
+
+ private readonly IssuerAndSerialNumber issuerSerial;
+ private readonly RecipientKeyIdentifier rKeyID;
+
+ public KeyAgreeRecipientIdentifier(
+ IssuerAndSerialNumber issuerSerial)
+ {
+ this.issuerSerial = issuerSerial;
+ }
+
+ public KeyAgreeRecipientIdentifier(
+ RecipientKeyIdentifier rKeyID)
+ {
+ this.rKeyID = rKeyID;
+ }
+
+ public IssuerAndSerialNumber IssuerAndSerialNumber
+ {
+ get { return issuerSerial; }
+ }
+
+ public RecipientKeyIdentifier RKeyID
+ {
+ get { return rKeyID; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * KeyAgreeRecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * rKeyId [0] IMPLICIT RecipientKeyIdentifier
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (issuerSerial != null)
+ {
+ return issuerSerial.ToAsn1Object();
+ }
+
+ return new DerTaggedObject(false, 0, rKeyID);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs b/Crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs
new file mode 100644
index 000000000..aafb008d4
--- /dev/null
+++ b/Crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs
@@ -0,0 +1,141 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class KeyAgreeRecipientInfo
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private OriginatorIdentifierOrKey originator;
+ private Asn1OctetString ukm;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private Asn1Sequence recipientEncryptedKeys;
+
+ public KeyAgreeRecipientInfo(
+ OriginatorIdentifierOrKey originator,
+ Asn1OctetString ukm,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ Asn1Sequence recipientEncryptedKeys)
+ {
+ this.version = new DerInteger(3);
+ this.originator = originator;
+ this.ukm = ukm;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.recipientEncryptedKeys = recipientEncryptedKeys;
+ }
+
+ public KeyAgreeRecipientInfo(
+ Asn1Sequence seq)
+ {
+ int index = 0;
+
+ version = (DerInteger) seq[index++];
+ originator = OriginatorIdentifierOrKey.GetInstance(
+ (Asn1TaggedObject) seq[index++], true);
+
+ if (seq[index] is Asn1TaggedObject)
+ {
+ ukm = Asn1OctetString.GetInstance(
+ (Asn1TaggedObject) seq[index++], true);
+ }
+
+ keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(
+ seq[index++]);
+
+ recipientEncryptedKeys = (Asn1Sequence) seq[index++];
+ }
+
+ /**
+ * return a KeyAgreeRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KeyAgreeRecipientInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return a KeyAgreeRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static KeyAgreeRecipientInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is KeyAgreeRecipientInfo)
+ return (KeyAgreeRecipientInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new KeyAgreeRecipientInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException(
+ "Illegal object in KeyAgreeRecipientInfo: " + obj.GetType().Name);
+
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public OriginatorIdentifierOrKey Originator
+ {
+ get { return originator; }
+ }
+
+ public Asn1OctetString UserKeyingMaterial
+ {
+ get { return ukm; }
+ }
+
+ public AlgorithmIdentifier KeyEncryptionAlgorithm
+ {
+ get { return keyEncryptionAlgorithm; }
+ }
+
+ public Asn1Sequence RecipientEncryptedKeys
+ {
+ get { return recipientEncryptedKeys; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * KeyAgreeRecipientInfo ::= Sequence {
+ * version CMSVersion, -- always set to 3
+ * originator [0] EXPLICIT OriginatorIdentifierOrKey,
+ * ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * recipientEncryptedKeys RecipientEncryptedKeys
+ * }
+ *
+ * UserKeyingMaterial ::= OCTET STRING
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, new DerTaggedObject(true, 0, originator));
+
+ if (ukm != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, ukm));
+ }
+
+ v.Add(keyEncryptionAlgorithm, recipientEncryptedKeys);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/KeyTransRecipientInfo.cs b/Crypto/src/asn1/cms/KeyTransRecipientInfo.cs
new file mode 100644
index 000000000..aae18c59d
--- /dev/null
+++ b/Crypto/src/asn1/cms/KeyTransRecipientInfo.cs
@@ -0,0 +1,99 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class KeyTransRecipientInfo
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private RecipientIdentifier rid;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private Asn1OctetString encryptedKey;
+
+ public KeyTransRecipientInfo(
+ RecipientIdentifier rid,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ Asn1OctetString encryptedKey)
+ {
+ if (rid.ToAsn1Object() is Asn1TaggedObject)
+ {
+ this.version = new DerInteger(2);
+ }
+ else
+ {
+ this.version = new DerInteger(0);
+ }
+
+ this.rid = rid;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KeyTransRecipientInfo(
+ Asn1Sequence seq)
+ {
+ this.version = (DerInteger) seq[0];
+ this.rid = RecipientIdentifier.GetInstance(seq[1]);
+ this.keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
+ this.encryptedKey = (Asn1OctetString) seq[3];
+ }
+
+ /**
+ * return a KeyTransRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static KeyTransRecipientInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is KeyTransRecipientInfo)
+ return (KeyTransRecipientInfo) obj;
+
+ if(obj is Asn1Sequence)
+ return new KeyTransRecipientInfo((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Illegal object in KeyTransRecipientInfo: " + obj.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public RecipientIdentifier RecipientIdentifier
+ {
+ get { return rid; }
+ }
+
+ public AlgorithmIdentifier KeyEncryptionAlgorithm
+ {
+ get { return keyEncryptionAlgorithm; }
+ }
+
+ public Asn1OctetString EncryptedKey
+ {
+ get { return encryptedKey; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * KeyTransRecipientInfo ::= Sequence {
+ * version CMSVersion, -- always set to 0 or 2
+ * rid RecipientIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(version, rid, keyEncryptionAlgorithm, encryptedKey);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/MetaData.cs b/Crypto/src/asn1/cms/MetaData.cs
new file mode 100644
index 000000000..ad2b5c426
--- /dev/null
+++ b/Crypto/src/asn1/cms/MetaData.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class MetaData
+ : Asn1Encodable
+ {
+ private DerBoolean hashProtected;
+ private DerUtf8String fileName;
+ private DerIA5String mediaType;
+ private Attributes otherMetaData;
+
+ public MetaData(
+ DerBoolean hashProtected,
+ DerUtf8String fileName,
+ DerIA5String mediaType,
+ Attributes otherMetaData)
+ {
+ this.hashProtected = hashProtected;
+ this.fileName = fileName;
+ this.mediaType = mediaType;
+ this.otherMetaData = otherMetaData;
+ }
+
+ private MetaData(Asn1Sequence seq)
+ {
+ this.hashProtected = DerBoolean.GetInstance(seq[0]);
+
+ int index = 1;
+
+ if (index < seq.Count && seq[index] is DerUtf8String)
+ {
+ this.fileName = DerUtf8String.GetInstance(seq[index++]);
+ }
+ if (index < seq.Count && seq[index] is DerIA5String)
+ {
+ this.mediaType = DerIA5String.GetInstance(seq[index++]);
+ }
+ if (index < seq.Count)
+ {
+ this.otherMetaData = Attributes.GetInstance(seq[index++]);
+ }
+ }
+
+ public static MetaData GetInstance(object obj)
+ {
+ if (obj is MetaData)
+ return (MetaData)obj;
+
+ if (obj != null)
+ return new MetaData(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ /**
+ * <pre>
+ * MetaData ::= SEQUENCE {
+ * hashProtected BOOLEAN,
+ * fileName UTF8String OPTIONAL,
+ * mediaType IA5String OPTIONAL,
+ * otherMetaData Attributes OPTIONAL
+ * }
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(hashProtected);
+ v.AddOptional(fileName, mediaType, otherMetaData);
+ return new DerSequence(v);
+ }
+
+ public virtual bool IsHashProtected
+ {
+ get { return hashProtected.IsTrue; }
+ }
+
+ public virtual DerUtf8String FileName
+ {
+ get { return fileName; }
+ }
+
+ public virtual DerIA5String MediaType
+ {
+ get { return mediaType; }
+ }
+
+ public virtual Attributes OtherMetaData
+ {
+ get { return otherMetaData; }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs b/Crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
new file mode 100644
index 000000000..d33a11725
--- /dev/null
+++ b/Crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs
@@ -0,0 +1,168 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class OriginatorIdentifierOrKey
+ : Asn1Encodable, IAsn1Choice
+ {
+ private Asn1Encodable id;
+
+ public OriginatorIdentifierOrKey(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ [Obsolete("Use version taking a 'SubjectKeyIdentifier'")]
+ public OriginatorIdentifierOrKey(
+ Asn1OctetString id)
+ : this(new SubjectKeyIdentifier(id))
+ {
+ }
+
+ public OriginatorIdentifierOrKey(
+ SubjectKeyIdentifier id)
+ {
+ this.id = new DerTaggedObject(false, 0, id);
+ }
+
+ public OriginatorIdentifierOrKey(
+ OriginatorPublicKey id)
+ {
+ this.id = new DerTaggedObject(false, 1, id);
+ }
+
+ [Obsolete("Use more specific version")]
+ public OriginatorIdentifierOrKey(
+ Asn1Object id)
+ {
+ this.id = id;
+ }
+
+ private OriginatorIdentifierOrKey(
+ Asn1TaggedObject id)
+ {
+ // TODO Add validation
+ this.id = id;
+ }
+
+ /**
+ * return an OriginatorIdentifierOrKey object from a tagged object.
+ *
+ * @param o the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorIdentifierOrKey GetInstance(
+ Asn1TaggedObject o,
+ bool explicitly)
+ {
+ if (!explicitly)
+ {
+ throw new ArgumentException(
+ "Can't implicitly tag OriginatorIdentifierOrKey");
+ }
+
+ return GetInstance(o.GetObject());
+ }
+
+ /**
+ * return an OriginatorIdentifierOrKey object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static OriginatorIdentifierOrKey GetInstance(
+ object o)
+ {
+ if (o == null || o is OriginatorIdentifierOrKey)
+ return (OriginatorIdentifierOrKey)o;
+
+ if (o is IssuerAndSerialNumber)
+ return new OriginatorIdentifierOrKey((IssuerAndSerialNumber)o);
+
+ if (o is SubjectKeyIdentifier)
+ return new OriginatorIdentifierOrKey((SubjectKeyIdentifier)o);
+
+ if (o is OriginatorPublicKey)
+ return new OriginatorIdentifierOrKey((OriginatorPublicKey)o);
+
+ if (o is Asn1TaggedObject)
+ return new OriginatorIdentifierOrKey((Asn1TaggedObject)o);
+
+ throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + o.GetType().Name);
+ }
+
+ public Asn1Encodable ID
+ {
+ get { return id; }
+ }
+
+ public IssuerAndSerialNumber IssuerAndSerialNumber
+ {
+ get
+ {
+ if (id is IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber)id;
+ }
+
+ return null;
+ }
+ }
+
+ public SubjectKeyIdentifier SubjectKeyIdentifier
+ {
+ get
+ {
+ if (id is Asn1TaggedObject && ((Asn1TaggedObject)id).TagNo == 0)
+ {
+ return SubjectKeyIdentifier.GetInstance((Asn1TaggedObject)id, false);
+ }
+
+ return null;
+ }
+ }
+
+ [Obsolete("Use 'OriginatorPublicKey' property")]
+ public OriginatorPublicKey OriginatorKey
+ {
+ get { return OriginatorPublicKey; }
+ }
+
+ public OriginatorPublicKey OriginatorPublicKey
+ {
+ get
+ {
+ if (id is Asn1TaggedObject && ((Asn1TaggedObject)id).TagNo == 1)
+ {
+ return OriginatorPublicKey.GetInstance((Asn1TaggedObject)id, false);
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OriginatorIdentifierOrKey ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier,
+ * originatorKey [1] OriginatorPublicKey
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return id.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/OriginatorInfo.cs b/Crypto/src/asn1/cms/OriginatorInfo.cs
new file mode 100644
index 000000000..b4549bc36
--- /dev/null
+++ b/Crypto/src/asn1/cms/OriginatorInfo.cs
@@ -0,0 +1,121 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class OriginatorInfo
+ : Asn1Encodable
+ {
+ private Asn1Set certs;
+ private Asn1Set crls;
+
+ public OriginatorInfo(
+ Asn1Set certs,
+ Asn1Set crls)
+ {
+ this.certs = certs;
+ this.crls = crls;
+ }
+
+ public OriginatorInfo(
+ Asn1Sequence seq)
+ {
+ switch (seq.Count)
+ {
+ case 0: // empty
+ break;
+ case 1:
+ Asn1TaggedObject o = (Asn1TaggedObject) seq[0];
+ switch (o.TagNo)
+ {
+ case 0 :
+ certs = Asn1Set.GetInstance(o, false);
+ break;
+ case 1 :
+ crls = Asn1Set.GetInstance(o, false);
+ break;
+ default:
+ throw new ArgumentException("Bad tag in OriginatorInfo: " + o.TagNo);
+ }
+ break;
+ case 2:
+ certs = Asn1Set.GetInstance((Asn1TaggedObject) seq[0], false);
+ crls = Asn1Set.GetInstance((Asn1TaggedObject) seq[1], false);
+ break;
+ default:
+ throw new ArgumentException("OriginatorInfo too big");
+ }
+ }
+
+ /**
+ * return an OriginatorInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return an OriginatorInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static OriginatorInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OriginatorInfo)
+ return (OriginatorInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new OriginatorInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid OriginatorInfo: " + obj.GetType().Name);
+ }
+
+ public Asn1Set Certificates
+ {
+ get { return certs; }
+ }
+
+ public Asn1Set Crls
+ {
+ get { return crls; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OriginatorInfo ::= Sequence {
+ * certs [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (certs != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, certs));
+ }
+
+ if (crls != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, crls));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/OriginatorPublicKey.cs b/Crypto/src/asn1/cms/OriginatorPublicKey.cs
new file mode 100644
index 000000000..aabaf4386
--- /dev/null
+++ b/Crypto/src/asn1/cms/OriginatorPublicKey.cs
@@ -0,0 +1,87 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class OriginatorPublicKey
+ : Asn1Encodable
+ {
+ private AlgorithmIdentifier algorithm;
+ private DerBitString publicKey;
+
+ public OriginatorPublicKey(
+ AlgorithmIdentifier algorithm,
+ byte[] publicKey)
+ {
+ this.algorithm = algorithm;
+ this.publicKey = new DerBitString(publicKey);
+ }
+
+ public OriginatorPublicKey(
+ Asn1Sequence seq)
+ {
+ algorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+ publicKey = (DerBitString) seq[1];
+ }
+
+ /**
+ * return an OriginatorPublicKey object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorPublicKey GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return an OriginatorPublicKey object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static OriginatorPublicKey GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OriginatorPublicKey)
+ return (OriginatorPublicKey)obj;
+
+ if (obj is Asn1Sequence)
+ return new OriginatorPublicKey((Asn1Sequence) obj);
+
+ throw new ArgumentException("Invalid OriginatorPublicKey: " + obj.GetType().Name);
+ }
+
+ public AlgorithmIdentifier Algorithm
+ {
+ get { return algorithm; }
+ }
+
+ public DerBitString PublicKey
+ {
+ get { return publicKey; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OriginatorPublicKey ::= Sequence {
+ * algorithm AlgorithmIdentifier,
+ * publicKey BIT STRING
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(algorithm, publicKey);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/OtherKeyAttribute.cs b/Crypto/src/asn1/cms/OtherKeyAttribute.cs
new file mode 100644
index 000000000..271059175
--- /dev/null
+++ b/Crypto/src/asn1/cms/OtherKeyAttribute.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class OtherKeyAttribute
+ : Asn1Encodable
+ {
+ private DerObjectIdentifier keyAttrId;
+ private Asn1Encodable keyAttr;
+
+ /**
+ * return an OtherKeyAttribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static OtherKeyAttribute GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherKeyAttribute)
+ return (OtherKeyAttribute) obj;
+
+ if (obj is Asn1Sequence)
+ return new OtherKeyAttribute((Asn1Sequence) obj);
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public OtherKeyAttribute(
+ Asn1Sequence seq)
+ {
+ keyAttrId = (DerObjectIdentifier) seq[0];
+ keyAttr = seq[1];
+ }
+
+ public OtherKeyAttribute(
+ DerObjectIdentifier keyAttrId,
+ Asn1Encodable keyAttr)
+ {
+ this.keyAttrId = keyAttrId;
+ this.keyAttr = keyAttr;
+ }
+
+ public DerObjectIdentifier KeyAttrId
+ {
+ get { return keyAttrId; }
+ }
+
+ public Asn1Encodable KeyAttr
+ {
+ get { return keyAttr; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OtherKeyAttribute ::= Sequence {
+ * keyAttrId OBJECT IDENTIFIER,
+ * keyAttr ANY DEFINED BY keyAttrId OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(keyAttrId, keyAttr);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/OtherRecipientInfo.cs b/Crypto/src/asn1/cms/OtherRecipientInfo.cs
new file mode 100644
index 000000000..8b06b1946
--- /dev/null
+++ b/Crypto/src/asn1/cms/OtherRecipientInfo.cs
@@ -0,0 +1,85 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class OtherRecipientInfo
+ : Asn1Encodable
+ {
+ private DerObjectIdentifier oriType;
+ private Asn1Encodable oriValue;
+
+ public OtherRecipientInfo(
+ DerObjectIdentifier oriType,
+ Asn1Encodable oriValue)
+ {
+ this.oriType = oriType;
+ this.oriValue = oriValue;
+ }
+
+ public OtherRecipientInfo(
+ Asn1Sequence seq)
+ {
+ oriType = DerObjectIdentifier.GetInstance(seq[0]);
+ oriValue = seq[1];
+ }
+
+ /**
+ * return a OtherRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OtherRecipientInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return a OtherRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static OtherRecipientInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherRecipientInfo)
+ return (OtherRecipientInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new OtherRecipientInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid OtherRecipientInfo: " + obj.GetType().Name);
+ }
+
+ public DerObjectIdentifier OriType
+ {
+ get { return oriType; }
+ }
+
+ public Asn1Encodable OriValue
+ {
+ get { return oriValue; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OtherRecipientInfo ::= Sequence {
+ * oriType OBJECT IDENTIFIER,
+ * oriValue ANY DEFINED BY oriType }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(oriType, oriValue);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/PasswordRecipientInfo.cs b/Crypto/src/asn1/cms/PasswordRecipientInfo.cs
new file mode 100644
index 000000000..800b57951
--- /dev/null
+++ b/Crypto/src/asn1/cms/PasswordRecipientInfo.cs
@@ -0,0 +1,133 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class PasswordRecipientInfo
+ : Asn1Encodable
+ {
+ private readonly DerInteger version;
+ private readonly AlgorithmIdentifier keyDerivationAlgorithm;
+ private readonly AlgorithmIdentifier keyEncryptionAlgorithm;
+ private readonly Asn1OctetString encryptedKey;
+
+ public PasswordRecipientInfo(
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ Asn1OctetString encryptedKey)
+ {
+ this.version = new DerInteger(0);
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public PasswordRecipientInfo(
+ AlgorithmIdentifier keyDerivationAlgorithm,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ Asn1OctetString encryptedKey)
+ {
+ this.version = new DerInteger(0);
+ this.keyDerivationAlgorithm = keyDerivationAlgorithm;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public PasswordRecipientInfo(
+ Asn1Sequence seq)
+ {
+ version = (DerInteger) seq[0];
+
+ if (seq[1] is Asn1TaggedObject)
+ {
+ keyDerivationAlgorithm = AlgorithmIdentifier.GetInstance((Asn1TaggedObject) seq[1], false);
+ keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
+ encryptedKey = (Asn1OctetString) seq[3];
+ }
+ else
+ {
+ keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+ encryptedKey = (Asn1OctetString) seq[2];
+ }
+ }
+
+ /**
+ * return a PasswordRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicitly true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static PasswordRecipientInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ /**
+ * return a PasswordRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static PasswordRecipientInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is PasswordRecipientInfo)
+ return (PasswordRecipientInfo) obj;
+
+ if (obj is Asn1Sequence)
+ return new PasswordRecipientInfo((Asn1Sequence) obj);
+
+ throw new ArgumentException("Invalid PasswordRecipientInfo: " + obj.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public AlgorithmIdentifier KeyDerivationAlgorithm
+ {
+ get { return keyDerivationAlgorithm; }
+ }
+
+ public AlgorithmIdentifier KeyEncryptionAlgorithm
+ {
+ get { return keyEncryptionAlgorithm; }
+ }
+
+ public Asn1OctetString EncryptedKey
+ {
+ get { return encryptedKey; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * PasswordRecipientInfo ::= Sequence {
+ * version CMSVersion, -- Always set to 0
+ * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
+ * OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+ if (keyDerivationAlgorithm != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, keyDerivationAlgorithm));
+ }
+
+ v.Add(keyEncryptionAlgorithm, encryptedKey);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/RecipientEncryptedKey.cs b/Crypto/src/asn1/cms/RecipientEncryptedKey.cs
new file mode 100644
index 000000000..5ba25a742
--- /dev/null
+++ b/Crypto/src/asn1/cms/RecipientEncryptedKey.cs
@@ -0,0 +1,88 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class RecipientEncryptedKey
+ : Asn1Encodable
+ {
+ private readonly KeyAgreeRecipientIdentifier identifier;
+ private readonly Asn1OctetString encryptedKey;
+
+ private RecipientEncryptedKey(
+ Asn1Sequence seq)
+ {
+ identifier = KeyAgreeRecipientIdentifier.GetInstance(seq[0]);
+ encryptedKey = (Asn1OctetString) seq[1];
+ }
+
+ /**
+ * return an RecipientEncryptedKey object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static RecipientEncryptedKey GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * return a RecipientEncryptedKey object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static RecipientEncryptedKey GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RecipientEncryptedKey)
+ {
+ return (RecipientEncryptedKey) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new RecipientEncryptedKey((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid RecipientEncryptedKey: " + obj.GetType().FullName, "obj");
+ }
+
+ public RecipientEncryptedKey(
+ KeyAgreeRecipientIdentifier id,
+ Asn1OctetString encryptedKey)
+ {
+ this.identifier = id;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KeyAgreeRecipientIdentifier Identifier
+ {
+ get { return identifier; }
+ }
+
+ public Asn1OctetString EncryptedKey
+ {
+ get { return encryptedKey; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * RecipientEncryptedKey ::= SEQUENCE {
+ * rid KeyAgreeRecipientIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(identifier, encryptedKey);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/RecipientIdentifier.cs b/Crypto/src/asn1/cms/RecipientIdentifier.cs
new file mode 100644
index 000000000..4982bc16a
--- /dev/null
+++ b/Crypto/src/asn1/cms/RecipientIdentifier.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class RecipientIdentifier
+ : Asn1Encodable, IAsn1Choice
+ {
+ private Asn1Encodable id;
+
+ public RecipientIdentifier(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ public RecipientIdentifier(
+ Asn1OctetString id)
+ {
+ this.id = new DerTaggedObject(false, 0, id);
+ }
+
+ public RecipientIdentifier(
+ Asn1Object id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * return a RecipientIdentifier object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static RecipientIdentifier GetInstance(
+ object o)
+ {
+ if (o == null || o is RecipientIdentifier)
+ return (RecipientIdentifier)o;
+
+ if (o is IssuerAndSerialNumber)
+ return new RecipientIdentifier((IssuerAndSerialNumber) o);
+
+ if (o is Asn1OctetString)
+ return new RecipientIdentifier((Asn1OctetString) o);
+
+ if (o is Asn1Object)
+ return new RecipientIdentifier((Asn1Object) o);
+
+ throw new ArgumentException(
+ "Illegal object in RecipientIdentifier: " + o.GetType().Name);
+ }
+
+ public bool IsTagged
+ {
+ get { return (id is Asn1TaggedObject); }
+ }
+
+ public Asn1Encodable ID
+ {
+ get
+ {
+ if (id is Asn1TaggedObject)
+ {
+ return Asn1OctetString.GetInstance((Asn1TaggedObject) id, false);
+ }
+
+ return IssuerAndSerialNumber.GetInstance(id);
+ }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * RecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return id.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/RecipientInfo.cs b/Crypto/src/asn1/cms/RecipientInfo.cs
new file mode 100644
index 000000000..daaf5a5e4
--- /dev/null
+++ b/Crypto/src/asn1/cms/RecipientInfo.cs
@@ -0,0 +1,145 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class RecipientInfo
+ : Asn1Encodable, IAsn1Choice
+ {
+ internal Asn1Encodable info;
+
+ public RecipientInfo(
+ KeyTransRecipientInfo info)
+ {
+ this.info = info;
+ }
+
+ public RecipientInfo(
+ KeyAgreeRecipientInfo info)
+ {
+ this.info = new DerTaggedObject(false, 1, info);
+ }
+
+ public RecipientInfo(
+ KekRecipientInfo info)
+ {
+ this.info = new DerTaggedObject(false, 2, info);
+ }
+
+ public RecipientInfo(
+ PasswordRecipientInfo info)
+ {
+ this.info = new DerTaggedObject(false, 3, info);
+ }
+
+ public RecipientInfo(
+ OtherRecipientInfo info)
+ {
+ this.info = new DerTaggedObject(false, 4, info);
+ }
+
+ public RecipientInfo(
+ Asn1Object info)
+ {
+ this.info = info;
+ }
+
+ public static RecipientInfo GetInstance(
+ object o)
+ {
+ if (o == null || o is RecipientInfo)
+ return (RecipientInfo) o;
+
+ if (o is Asn1Sequence)
+ return new RecipientInfo((Asn1Sequence) o);
+
+ if (o is Asn1TaggedObject)
+ return new RecipientInfo((Asn1TaggedObject) o);
+
+ throw new ArgumentException("unknown object in factory: " + o.GetType().Name);
+ }
+
+ public DerInteger Version
+ {
+ get
+ {
+ if (info is Asn1TaggedObject)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject) info;
+
+ switch (o.TagNo)
+ {
+ case 1:
+ return KeyAgreeRecipientInfo.GetInstance(o, false).Version;
+ case 2:
+ return GetKekInfo(o).Version;
+ case 3:
+ return PasswordRecipientInfo.GetInstance(o, false).Version;
+ case 4:
+ return new DerInteger(0); // no syntax version for OtherRecipientInfo
+ default:
+ throw new InvalidOperationException("unknown tag");
+ }
+ }
+
+ return KeyTransRecipientInfo.GetInstance(info).Version;
+ }
+ }
+
+ public bool IsTagged
+ {
+ get { return info is Asn1TaggedObject; }
+ }
+
+ public Asn1Encodable Info
+ {
+ get
+ {
+ if (info is Asn1TaggedObject)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject) info;
+
+ switch (o.TagNo)
+ {
+ case 1:
+ return KeyAgreeRecipientInfo.GetInstance(o, false);
+ case 2:
+ return GetKekInfo(o);
+ case 3:
+ return PasswordRecipientInfo.GetInstance(o, false);
+ case 4:
+ return OtherRecipientInfo.GetInstance(o, false);
+ default:
+ throw new InvalidOperationException("unknown tag");
+ }
+ }
+
+ return KeyTransRecipientInfo.GetInstance(info);
+ }
+ }
+
+ private KekRecipientInfo GetKekInfo(
+ Asn1TaggedObject o)
+ {
+ // For compatibility with erroneous version, we don't always pass 'false' here
+ return KekRecipientInfo.GetInstance(o, o.IsExplicit());
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * RecipientInfo ::= CHOICE {
+ * ktri KeyTransRecipientInfo,
+ * kari [1] KeyAgreeRecipientInfo,
+ * kekri [2] KekRecipientInfo,
+ * pwri [3] PasswordRecipientInfo,
+ * ori [4] OtherRecipientInfo }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return info.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/RecipientKeyIdentifier.cs b/Crypto/src/asn1/cms/RecipientKeyIdentifier.cs
new file mode 100644
index 000000000..f3e45644b
--- /dev/null
+++ b/Crypto/src/asn1/cms/RecipientKeyIdentifier.cs
@@ -0,0 +1,137 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class RecipientKeyIdentifier
+ : Asn1Encodable
+ {
+ private Asn1OctetString subjectKeyIdentifier;
+ private DerGeneralizedTime date;
+ private OtherKeyAttribute other;
+
+ public RecipientKeyIdentifier(
+ Asn1OctetString subjectKeyIdentifier,
+ DerGeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.subjectKeyIdentifier = subjectKeyIdentifier;
+ this.date = date;
+ this.other = other;
+ }
+
+ public RecipientKeyIdentifier(
+ byte[] subjectKeyIdentifier)
+ : this(subjectKeyIdentifier, null, null)
+ {
+ }
+
+ public RecipientKeyIdentifier(
+ byte[] subjectKeyIdentifier,
+ DerGeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.subjectKeyIdentifier = new DerOctetString(subjectKeyIdentifier);
+ this.date = date;
+ this.other = other;
+ }
+
+ public RecipientKeyIdentifier(
+ Asn1Sequence seq)
+ {
+ subjectKeyIdentifier = Asn1OctetString.GetInstance(
+ seq[0]);
+
+ switch(seq.Count)
+ {
+ case 1:
+ break;
+ case 2:
+ if (seq[1] is DerGeneralizedTime)
+ {
+ date = (DerGeneralizedTime) seq[1];
+ }
+ else
+ {
+ other = OtherKeyAttribute.GetInstance(seq[2]);
+ }
+ break;
+ case 3:
+ date = (DerGeneralizedTime) seq[1];
+ other = OtherKeyAttribute.GetInstance(seq[2]);
+ break;
+ default:
+ throw new ArgumentException("Invalid RecipientKeyIdentifier");
+ }
+ }
+
+ /**
+ * return a RecipientKeyIdentifier object from a tagged object.
+ *
+ * @param _ato the tagged object holding the object we want.
+ * @param _explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static RecipientKeyIdentifier GetInstance(
+ Asn1TaggedObject ato,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(ato, explicitly));
+ }
+
+ /**
+ * return a RecipientKeyIdentifier object from the given object.
+ *
+ * @param _obj the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static RecipientKeyIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RecipientKeyIdentifier)
+ return (RecipientKeyIdentifier) obj;
+
+ if (obj is Asn1Sequence)
+ return new RecipientKeyIdentifier((Asn1Sequence) obj);
+
+ throw new ArgumentException("Invalid RecipientKeyIdentifier: " + obj.GetType().Name);
+ }
+
+ public Asn1OctetString SubjectKeyIdentifier
+ {
+ get { return subjectKeyIdentifier; }
+ }
+
+ public DerGeneralizedTime Date
+ {
+ get { return date; }
+ }
+
+ public OtherKeyAttribute OtherKeyAttribute
+ {
+ get { return other; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * RecipientKeyIdentifier ::= Sequence {
+ * subjectKeyIdentifier SubjectKeyIdentifier,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(subjectKeyIdentifier);
+ v.AddOptional(date, other);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/SignedData.cs b/Crypto/src/asn1/cms/SignedData.cs
new file mode 100644
index 000000000..40ed09f32
--- /dev/null
+++ b/Crypto/src/asn1/cms/SignedData.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * a signed data object.
+ */
+ public class SignedData
+ : Asn1Encodable
+ {
+ private readonly DerInteger version;
+ private readonly Asn1Set digestAlgorithms;
+ private readonly ContentInfo contentInfo;
+ private readonly Asn1Set certificates;
+ private readonly Asn1Set crls;
+ private readonly Asn1Set signerInfos;
+ private readonly bool certsBer;
+ private readonly bool crlsBer;
+
+ public static SignedData GetInstance(
+ object obj)
+ {
+ if (obj is SignedData)
+ return (SignedData) obj;
+
+ if (obj is Asn1Sequence)
+ return new SignedData((Asn1Sequence) obj);
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public SignedData(
+ Asn1Set digestAlgorithms,
+ ContentInfo contentInfo,
+ Asn1Set certificates,
+ Asn1Set crls,
+ Asn1Set signerInfos)
+ {
+ this.version = CalculateVersion(contentInfo.ContentType, certificates, crls, signerInfos);
+ this.digestAlgorithms = digestAlgorithms;
+ this.contentInfo = contentInfo;
+ this.certificates = certificates;
+ this.crls = crls;
+ this.signerInfos = signerInfos;
+ this.crlsBer = crls is BerSet;
+ this.certsBer = certificates is BerSet;
+ }
+
+ // RFC3852, section 5.1:
+ // IF ((certificates is present) AND
+ // (any certificates with a type of other are present)) OR
+ // ((crls is present) AND
+ // (any crls with a type of other are present))
+ // THEN version MUST be 5
+ // ELSE
+ // IF (certificates is present) AND
+ // (any version 2 attribute certificates are present)
+ // THEN version MUST be 4
+ // ELSE
+ // IF ((certificates is present) AND
+ // (any version 1 attribute certificates are present)) OR
+ // (any SignerInfo structures are version 3) OR
+ // (encapContentInfo eContentType is other than id-data)
+ // THEN version MUST be 3
+ // ELSE version MUST be 1
+ //
+ private DerInteger CalculateVersion(
+ DerObjectIdentifier contentOid,
+ Asn1Set certs,
+ Asn1Set crls,
+ Asn1Set signerInfs)
+ {
+ bool otherCert = false;
+ bool otherCrl = false;
+ bool attrCertV1Found = false;
+ bool attrCertV2Found = false;
+
+ if (certs != null)
+ {
+ foreach (object obj in certs)
+ {
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagged = (Asn1TaggedObject)obj;
+
+ if (tagged.TagNo == 1)
+ {
+ attrCertV1Found = true;
+ }
+ else if (tagged.TagNo == 2)
+ {
+ attrCertV2Found = true;
+ }
+ else if (tagged.TagNo == 3)
+ {
+ otherCert = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (otherCert)
+ {
+ return new DerInteger(5);
+ }
+
+ if (crls != null)
+ {
+ foreach (object obj in crls)
+ {
+ if (obj is Asn1TaggedObject)
+ {
+ otherCrl = true;
+ break;
+ }
+ }
+ }
+
+ if (otherCrl)
+ {
+ return new DerInteger(5);
+ }
+
+ if (attrCertV2Found)
+ {
+ return new DerInteger(4);
+ }
+
+ if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(signerInfs))
+ {
+ return new DerInteger(3);
+ }
+
+ return new DerInteger(1);
+ }
+
+ private bool CheckForVersion3(
+ Asn1Set signerInfs)
+ {
+ foreach (object obj in signerInfs)
+ {
+ SignerInfo s = SignerInfo.GetInstance(obj);
+
+ if (s.Version.Value.IntValue == 3)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private SignedData(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ version = (DerInteger)e.Current;
+
+ e.MoveNext();
+ digestAlgorithms = ((Asn1Set)e.Current);
+
+ e.MoveNext();
+ contentInfo = ContentInfo.GetInstance(e.Current);
+
+ while (e.MoveNext())
+ {
+ Asn1Object o = (Asn1Object)e.Current;
+
+ //
+ // an interesting feature of SignedData is that there appear
+ // to be varying implementations...
+ // for the moment we ignore anything which doesn't fit.
+ //
+ if (o is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagged = (Asn1TaggedObject)o;
+
+ switch (tagged.TagNo)
+ {
+ case 0:
+ certsBer = tagged is BerTaggedObject;
+ certificates = Asn1Set.GetInstance(tagged, false);
+ break;
+ case 1:
+ crlsBer = tagged is BerTaggedObject;
+ crls = Asn1Set.GetInstance(tagged, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag value " + tagged.TagNo);
+ }
+ }
+ else
+ {
+ signerInfos = (Asn1Set) o;
+ }
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public Asn1Set DigestAlgorithms
+ {
+ get { return digestAlgorithms; }
+ }
+
+ public ContentInfo EncapContentInfo
+ {
+ get { return contentInfo; }
+ }
+
+ public Asn1Set Certificates
+ {
+ get { return certificates; }
+ }
+
+ public Asn1Set CRLs
+ {
+ get { return crls; }
+ }
+
+ public Asn1Set SignerInfos
+ {
+ get { return signerInfos; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SignedData ::= Sequence {
+ * version CMSVersion,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, digestAlgorithms, contentInfo);
+
+ if (certificates != null)
+ {
+ if (certsBer)
+ {
+ v.Add(new BerTaggedObject(false, 0, certificates));
+ }
+ else
+ {
+ v.Add(new DerTaggedObject(false, 0, certificates));
+ }
+ }
+
+ if (crls != null)
+ {
+ if (crlsBer)
+ {
+ v.Add(new BerTaggedObject(false, 1, crls));
+ }
+ else
+ {
+ v.Add(new DerTaggedObject(false, 1, crls));
+ }
+ }
+
+ v.Add(signerInfos);
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/SignedDataParser.cs b/Crypto/src/asn1/cms/SignedDataParser.cs
new file mode 100644
index 000000000..341309263
--- /dev/null
+++ b/Crypto/src/asn1/cms/SignedDataParser.cs
@@ -0,0 +1,112 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * <pre>
+ * SignedData ::= SEQUENCE {
+ * version CMSVersion,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos
+ * }
+ * </pre>
+ */
+ public class SignedDataParser
+ {
+ private Asn1SequenceParser _seq;
+ private DerInteger _version;
+ private object _nextObject;
+ private bool _certsCalled;
+ private bool _crlsCalled;
+
+ public static SignedDataParser GetInstance(
+ object o)
+ {
+ if (o is Asn1Sequence)
+ return new SignedDataParser(((Asn1Sequence)o).Parser);
+
+ if (o is Asn1SequenceParser)
+ return new SignedDataParser((Asn1SequenceParser)o);
+
+ throw new IOException("unknown object encountered: " + o.GetType().Name);
+ }
+
+ public SignedDataParser(
+ Asn1SequenceParser seq)
+ {
+ this._seq = seq;
+ this._version = (DerInteger)seq.ReadObject();
+ }
+
+ public DerInteger Version
+ {
+ get { return _version; }
+ }
+
+ public Asn1SetParser GetDigestAlgorithms()
+ {
+ return (Asn1SetParser)_seq.ReadObject();
+ }
+
+ public ContentInfoParser GetEncapContentInfo()
+ {
+ return new ContentInfoParser((Asn1SequenceParser)_seq.ReadObject());
+ }
+
+ public Asn1SetParser GetCertificates()
+ {
+ _certsCalled = true;
+ _nextObject = _seq.ReadObject();
+
+ if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 0)
+ {
+ Asn1SetParser certs = (Asn1SetParser)((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Set, false);
+ _nextObject = null;
+
+ return certs;
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetCrls()
+ {
+ if (!_certsCalled)
+ throw new IOException("GetCerts() has not been called.");
+
+ _crlsCalled = true;
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.ReadObject();
+ }
+
+ if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 1)
+ {
+ Asn1SetParser crls = (Asn1SetParser)((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Set, false);
+ _nextObject = null;
+
+ return crls;
+ }
+
+ return null;
+ }
+
+ public Asn1SetParser GetSignerInfos()
+ {
+ if (!_certsCalled || !_crlsCalled)
+ throw new IOException("GetCerts() and/or GetCrls() has not been called.");
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.ReadObject();
+ }
+
+ return (Asn1SetParser)_nextObject;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/SignerIdentifier.cs b/Crypto/src/asn1/cms/SignerIdentifier.cs
new file mode 100644
index 000000000..5742cee75
--- /dev/null
+++ b/Crypto/src/asn1/cms/SignerIdentifier.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class SignerIdentifier
+ : Asn1Encodable, IAsn1Choice
+ {
+ private Asn1Encodable id;
+
+ public SignerIdentifier(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ public SignerIdentifier(
+ Asn1OctetString id)
+ {
+ this.id = new DerTaggedObject(false, 0, id);
+ }
+
+ public SignerIdentifier(
+ Asn1Object id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * return a SignerIdentifier object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static SignerIdentifier GetInstance(
+ object o)
+ {
+ if (o == null || o is SignerIdentifier)
+ return (SignerIdentifier) o;
+
+ if (o is IssuerAndSerialNumber)
+ return new SignerIdentifier((IssuerAndSerialNumber) o);
+
+ if (o is Asn1OctetString)
+ return new SignerIdentifier((Asn1OctetString) o);
+
+ if (o is Asn1Object)
+ return new SignerIdentifier((Asn1Object) o);
+
+ throw new ArgumentException(
+ "Illegal object in SignerIdentifier: " + o.GetType().Name);
+ }
+
+ public bool IsTagged
+ {
+ get { return (id is Asn1TaggedObject); }
+ }
+
+ public Asn1Encodable ID
+ {
+ get
+ {
+ if (id is Asn1TaggedObject)
+ {
+ return Asn1OctetString.GetInstance((Asn1TaggedObject)id, false);
+ }
+
+ return id;
+ }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SignerIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return id.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/SignerInfo.cs b/Crypto/src/asn1/cms/SignerInfo.cs
new file mode 100644
index 000000000..ef71ddfc4
--- /dev/null
+++ b/Crypto/src/asn1/cms/SignerInfo.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class SignerInfo
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private SignerIdentifier sid;
+ private AlgorithmIdentifier digAlgorithm;
+ private Asn1Set authenticatedAttributes;
+ private AlgorithmIdentifier digEncryptionAlgorithm;
+ private Asn1OctetString encryptedDigest;
+ private Asn1Set unauthenticatedAttributes;
+
+ public static SignerInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SignerInfo)
+ return (SignerInfo) obj;
+
+ if (obj is Asn1Sequence)
+ return new SignerInfo((Asn1Sequence) obj);
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public SignerInfo(
+ SignerIdentifier sid,
+ AlgorithmIdentifier digAlgorithm,
+ Asn1Set authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ Asn1OctetString encryptedDigest,
+ Asn1Set unauthenticatedAttributes)
+ {
+ if (sid.IsTagged)
+ {
+ this.version = new DerInteger(3);
+ }
+ else
+ {
+ this.version = new DerInteger(1);
+ }
+
+ this.sid = sid;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = unauthenticatedAttributes;
+ }
+
+ public SignerInfo(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ version = (DerInteger) e.Current;
+
+ e.MoveNext();
+ sid = SignerIdentifier.GetInstance(e.Current);
+
+ e.MoveNext();
+ digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+
+ e.MoveNext();
+ object obj = e.Current;
+
+ if (obj is Asn1TaggedObject)
+ {
+ authenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) obj, false);
+
+ e.MoveNext();
+ digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+ }
+ else
+ {
+ authenticatedAttributes = null;
+ digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj);
+ }
+
+ e.MoveNext();
+ encryptedDigest = DerOctetString.GetInstance(e.Current);
+
+ if (e.MoveNext())
+ {
+ unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) e.Current, false);
+ }
+ else
+ {
+ unauthenticatedAttributes = null;
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public SignerIdentifier SignerID
+ {
+ get { return sid; }
+ }
+
+ public Asn1Set AuthenticatedAttributes
+ {
+ get { return authenticatedAttributes; }
+ }
+
+ public AlgorithmIdentifier DigestAlgorithm
+ {
+ get { return digAlgorithm; }
+ }
+
+ public Asn1OctetString EncryptedDigest
+ {
+ get { return encryptedDigest; }
+ }
+
+ public AlgorithmIdentifier DigestEncryptionAlgorithm
+ {
+ get { return digEncryptionAlgorithm; }
+ }
+
+ public Asn1Set UnauthenticatedAttributes
+ {
+ get { return unauthenticatedAttributes; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SignerInfo ::= Sequence {
+ * version Version,
+ * SignerIdentifier sid,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+ * }
+ *
+ * EncryptedDigest ::= OCTET STRING
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, sid, digAlgorithm);
+
+ if (authenticatedAttributes != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, authenticatedAttributes));
+ }
+
+ v.Add(digEncryptionAlgorithm, encryptedDigest);
+
+ if (unauthenticatedAttributes != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, unauthenticatedAttributes));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/Time.cs b/Crypto/src/asn1/cms/Time.cs
new file mode 100644
index 000000000..d113bfa2e
--- /dev/null
+++ b/Crypto/src/asn1/cms/Time.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class Time
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly Asn1Object time;
+
+ public static Time GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(obj.GetObject());
+ }
+
+ public Time(
+ Asn1Object 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 = int.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 TimeString
+ {
+ get
+ {
+ if (time is DerUtcTime)
+ {
+ return ((DerUtcTime)time).AdjustedTimeString;
+ }
+ else
+ {
+ return ((DerGeneralizedTime)time).GetTime();
+ }
+ }
+ }
+
+ public DateTime Date
+ {
+ get
+ {
+ try
+ {
+ if (time is DerUtcTime)
+ {
+ return ((DerUtcTime)time).ToAdjustedDateTime();
+ }
+
+ 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;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/TimeStampAndCRL.cs b/Crypto/src/asn1/cms/TimeStampAndCRL.cs
new file mode 100644
index 000000000..4cb5f2a52
--- /dev/null
+++ b/Crypto/src/asn1/cms/TimeStampAndCRL.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class TimeStampAndCrl
+ : Asn1Encodable
+ {
+ private ContentInfo timeStamp;
+ private X509.CertificateList crl;
+
+ public TimeStampAndCrl(ContentInfo timeStamp)
+ {
+ this.timeStamp = timeStamp;
+ }
+
+ private TimeStampAndCrl(Asn1Sequence seq)
+ {
+ this.timeStamp = ContentInfo.GetInstance(seq[0]);
+ if (seq.Count == 2)
+ {
+ this.crl = X509.CertificateList.GetInstance(seq[1]);
+ }
+ }
+
+ public static TimeStampAndCrl GetInstance(object obj)
+ {
+ if (obj is TimeStampAndCrl)
+ return (TimeStampAndCrl)obj;
+
+ if (obj != null)
+ return new TimeStampAndCrl(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public virtual ContentInfo TimeStampToken
+ {
+ get { return this.timeStamp; }
+ }
+
+ public virtual X509.CertificateList Crl
+ {
+ get { return this.crl; }
+ }
+
+ /**
+ * <pre>
+ * TimeStampAndCRL ::= SEQUENCE {
+ * timeStamp TimeStampToken, -- according to RFC 3161
+ * crl CertificateList OPTIONAL -- according to RFC 5280
+ * }
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(timeStamp);
+ v.AddOptional(crl);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/TimeStampTokenEvidence.cs b/Crypto/src/asn1/cms/TimeStampTokenEvidence.cs
new file mode 100644
index 000000000..8625d058e
--- /dev/null
+++ b/Crypto/src/asn1/cms/TimeStampTokenEvidence.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class TimeStampTokenEvidence
+ : Asn1Encodable
+ {
+ private TimeStampAndCrl[] timeStampAndCrls;
+
+ public TimeStampTokenEvidence(TimeStampAndCrl[] timeStampAndCrls)
+ {
+ this.timeStampAndCrls = timeStampAndCrls;
+ }
+
+ public TimeStampTokenEvidence(TimeStampAndCrl timeStampAndCrl)
+ {
+ this.timeStampAndCrls = new TimeStampAndCrl[]{ timeStampAndCrl };
+ }
+
+ private TimeStampTokenEvidence(Asn1Sequence seq)
+ {
+ this.timeStampAndCrls = new TimeStampAndCrl[seq.Count];
+
+ int count = 0;
+
+ foreach (Asn1Encodable ae in seq)
+ {
+ this.timeStampAndCrls[count++] = TimeStampAndCrl.GetInstance(ae.ToAsn1Object());
+ }
+ }
+
+ public static TimeStampTokenEvidence GetInstance(Asn1TaggedObject tagged, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(tagged, isExplicit));
+ }
+
+ public static TimeStampTokenEvidence GetInstance(object obj)
+ {
+ if (obj is TimeStampTokenEvidence)
+ return (TimeStampTokenEvidence)obj;
+
+ if (obj != null)
+ return new TimeStampTokenEvidence(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public virtual TimeStampAndCrl[] ToTimeStampAndCrlArray()
+ {
+ return (TimeStampAndCrl[])timeStampAndCrls.Clone();
+ }
+
+ /**
+ * <pre>
+ * TimeStampTokenEvidence ::=
+ * SEQUENCE SIZE(1..MAX) OF TimeStampAndCrl
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(timeStampAndCrls);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/TimeStampedData.cs b/Crypto/src/asn1/cms/TimeStampedData.cs
new file mode 100644
index 000000000..15448a923
--- /dev/null
+++ b/Crypto/src/asn1/cms/TimeStampedData.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class TimeStampedData
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private DerIA5String dataUri;
+ private MetaData metaData;
+ private Asn1OctetString content;
+ private Evidence temporalEvidence;
+
+ public TimeStampedData(DerIA5String dataUri, MetaData metaData, Asn1OctetString content,
+ Evidence temporalEvidence)
+ {
+ this.version = new DerInteger(1);
+ this.dataUri = dataUri;
+ this.metaData = metaData;
+ this.content = content;
+ this.temporalEvidence = temporalEvidence;
+ }
+
+ private TimeStampedData(Asn1Sequence seq)
+ {
+ this.version = DerInteger.GetInstance(seq[0]);
+
+ int index = 1;
+ if (seq[index] is DerIA5String)
+ {
+ this.dataUri = DerIA5String.GetInstance(seq[index++]);
+ }
+ if (seq[index] is MetaData || seq[index] is Asn1Sequence)
+ {
+ this.metaData = MetaData.GetInstance(seq[index++]);
+ }
+ if (seq[index] is Asn1OctetString)
+ {
+ this.content = Asn1OctetString.GetInstance(seq[index++]);
+ }
+ this.temporalEvidence = Evidence.GetInstance(seq[index]);
+ }
+
+ public static TimeStampedData GetInstance(object obj)
+ {
+ if (obj is TimeStampedData)
+ return (TimeStampedData)obj;
+
+ if (obj != null)
+ return new TimeStampedData(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public virtual DerIA5String DataUri
+ {
+ get { return dataUri; }
+ }
+
+ public MetaData MetaData
+ {
+ get { return metaData; }
+ }
+
+ public Asn1OctetString Content
+ {
+ get { return content; }
+ }
+
+ public Evidence TemporalEvidence
+ {
+ get { return temporalEvidence; }
+ }
+
+ /**
+ * <pre>
+ * TimeStampedData ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * dataUri IA5String OPTIONAL,
+ * metaData MetaData OPTIONAL,
+ * content OCTET STRING OPTIONAL,
+ * temporalEvidence Evidence
+ * }
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(version);
+ v.AddOptional(dataUri, metaData, content);
+ v.Add(temporalEvidence);
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/TimeStampedDataParser.cs b/Crypto/src/asn1/cms/TimeStampedDataParser.cs
new file mode 100644
index 000000000..90307bff9
--- /dev/null
+++ b/Crypto/src/asn1/cms/TimeStampedDataParser.cs
@@ -0,0 +1,76 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class TimeStampedDataParser
+ {
+ private DerInteger version;
+ private DerIA5String dataUri;
+ private MetaData metaData;
+ private Asn1OctetStringParser content;
+ private Evidence temporalEvidence;
+ private Asn1SequenceParser parser;
+
+ private TimeStampedDataParser(Asn1SequenceParser parser)
+ {
+ this.parser = parser;
+ this.version = DerInteger.GetInstance(parser.ReadObject());
+
+ Asn1Object obj = parser.ReadObject().ToAsn1Object();
+
+ if (obj is DerIA5String)
+ {
+ this.dataUri = DerIA5String.GetInstance(obj);
+ obj = parser.ReadObject().ToAsn1Object();
+ }
+
+ if (//obj is MetaData ||
+ obj is Asn1SequenceParser)
+ {
+ this.metaData = MetaData.GetInstance(obj.ToAsn1Object());
+ obj = parser.ReadObject().ToAsn1Object();
+ }
+
+ if (obj is Asn1OctetStringParser)
+ {
+ this.content = (Asn1OctetStringParser)obj;
+ }
+ }
+
+ public static TimeStampedDataParser GetInstance(object obj)
+ {
+ if (obj is Asn1Sequence)
+ return new TimeStampedDataParser(((Asn1Sequence)obj).Parser);
+
+ if (obj is Asn1SequenceParser)
+ return new TimeStampedDataParser((Asn1SequenceParser)obj);
+
+ return null;
+ }
+
+ public virtual DerIA5String DataUri
+ {
+ get { return dataUri; }
+ }
+
+ public virtual MetaData MetaData
+ {
+ get { return metaData; }
+ }
+
+ public virtual Asn1OctetStringParser Content
+ {
+ get { return content; }
+ }
+
+ public virtual Evidence GetTemporalEvidence()
+ {
+ if (temporalEvidence == null)
+ {
+ temporalEvidence = Evidence.GetInstance(parser.ReadObject().ToAsn1Object());
+ }
+
+ return temporalEvidence;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs b/Crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs
new file mode 100644
index 000000000..53c5c706b
--- /dev/null
+++ b/Crypto/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs
@@ -0,0 +1,103 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms.Ecc
+{
+ public class MQVuserKeyingMaterial
+ : Asn1Encodable
+ {
+ private OriginatorPublicKey ephemeralPublicKey;
+ private Asn1OctetString addedukm;
+
+ public MQVuserKeyingMaterial(
+ OriginatorPublicKey ephemeralPublicKey,
+ Asn1OctetString addedukm)
+ {
+ // TODO Check ephemeralPublicKey not null
+
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ this.addedukm = addedukm;
+ }
+
+ private MQVuserKeyingMaterial(
+ Asn1Sequence seq)
+ {
+ // TODO Check seq has either 1 or 2 elements
+
+ this.ephemeralPublicKey = OriginatorPublicKey.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ this.addedukm = Asn1OctetString.GetInstance(
+ (Asn1TaggedObject)seq[1], true);
+ }
+ }
+
+ /**
+ * return an AuthEnvelopedData object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param isExplicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws ArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static MQVuserKeyingMaterial GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * return an AuthEnvelopedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @throws ArgumentException if the object cannot be converted.
+ */
+ public static MQVuserKeyingMaterial GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is MQVuserKeyingMaterial)
+ {
+ return (MQVuserKeyingMaterial)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new MQVuserKeyingMaterial((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Invalid MQVuserKeyingMaterial: " + obj.GetType().Name);
+ }
+
+ public OriginatorPublicKey EphemeralPublicKey
+ {
+ get { return ephemeralPublicKey; }
+ }
+
+ public Asn1OctetString AddedUkm
+ {
+ get { return addedukm; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * MQVuserKeyingMaterial ::= SEQUENCE {
+ * ephemeralPublicKey OriginatorPublicKey,
+ * addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(ephemeralPublicKey);
+
+ if (addedukm != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, addedukm));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/AttributeTypeAndValue.cs b/Crypto/src/asn1/crmf/AttributeTypeAndValue.cs
new file mode 100644
index 000000000..823668992
--- /dev/null
+++ b/Crypto/src/asn1/crmf/AttributeTypeAndValue.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class AttributeTypeAndValue
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier type;
+ private readonly Asn1Encodable value;
+
+ private AttributeTypeAndValue(Asn1Sequence seq)
+ {
+ type = (DerObjectIdentifier)seq[0];
+ value = (Asn1Encodable)seq[1];
+ }
+
+ public static AttributeTypeAndValue GetInstance(object obj)
+ {
+ if (obj is AttributeTypeAndValue)
+ return (AttributeTypeAndValue)obj;
+
+ if (obj is Asn1Sequence)
+ return new AttributeTypeAndValue((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public AttributeTypeAndValue(
+ String oid,
+ Asn1Encodable value)
+ : this(new DerObjectIdentifier(oid), value)
+ {
+ }
+
+ public AttributeTypeAndValue(
+ DerObjectIdentifier type,
+ Asn1Encodable value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public virtual DerObjectIdentifier Type
+ {
+ get { return type; }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get { return value; }
+ }
+
+ /**
+ * <pre>
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY DEFINED BY type }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(type, value);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/CertId.cs b/Crypto/src/asn1/crmf/CertId.cs
new file mode 100644
index 000000000..10c2cc8b4
--- /dev/null
+++ b/Crypto/src/asn1/crmf/CertId.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertId
+ : Asn1Encodable
+ {
+ private readonly GeneralName issuer;
+ private readonly DerInteger serialNumber;
+
+ private CertId(Asn1Sequence seq)
+ {
+ issuer = GeneralName.GetInstance(seq[0]);
+ serialNumber = DerInteger.GetInstance(seq[1]);
+ }
+
+ public static CertId GetInstance(object obj)
+ {
+ if (obj is CertId)
+ return (CertId)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertId((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public static CertId GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public virtual GeneralName Issuer
+ {
+ get { return issuer; }
+ }
+
+ public virtual DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ /**
+ * <pre>
+ * CertId ::= SEQUENCE {
+ * issuer GeneralName,
+ * serialNumber INTEGER }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(issuer, serialNumber);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/CertReqMessages.cs b/Crypto/src/asn1/crmf/CertReqMessages.cs
new file mode 100644
index 000000000..9247281e8
--- /dev/null
+++ b/Crypto/src/asn1/crmf/CertReqMessages.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertReqMessages
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private CertReqMessages(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertReqMessages GetInstance(object obj)
+ {
+ if (obj is CertReqMessages)
+ return (CertReqMessages)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertReqMessages((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertReqMessages(params CertReqMsg[] msgs)
+ {
+ content = new DerSequence(msgs);
+ }
+
+ public virtual CertReqMsg[] ToCertReqMsgArray()
+ {
+ CertReqMsg[] result = new CertReqMsg[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = CertReqMsg.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/CertReqMsg.cs b/Crypto/src/asn1/crmf/CertReqMsg.cs
new file mode 100644
index 000000000..2ca319a57
--- /dev/null
+++ b/Crypto/src/asn1/crmf/CertReqMsg.cs
@@ -0,0 +1,106 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertReqMsg
+ : Asn1Encodable
+ {
+ private readonly CertRequest certReq;
+ private readonly ProofOfPossession popo;
+ private readonly Asn1Sequence regInfo;
+
+ private CertReqMsg(Asn1Sequence seq)
+ {
+ certReq = CertRequest.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ object o = seq[pos];
+
+ if (o is Asn1TaggedObject || o is ProofOfPossession)
+ {
+ popo = ProofOfPossession.GetInstance(o);
+ }
+ else
+ {
+ regInfo = Asn1Sequence.GetInstance(o);
+ }
+ }
+ }
+
+ public static CertReqMsg GetInstance(object obj)
+ {
+ if (obj is CertReqMsg)
+ return (CertReqMsg)obj;
+
+ if (obj != null)
+ return new CertReqMsg(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ /**
+ * Creates a new CertReqMsg.
+ * @param certReq CertRequest
+ * @param popo may be null
+ * @param regInfo may be null
+ */
+ public CertReqMsg(
+ CertRequest certReq,
+ ProofOfPossession popo,
+ AttributeTypeAndValue[] regInfo)
+ {
+ if (certReq == null)
+ throw new ArgumentNullException("certReq");
+
+ this.certReq = certReq;
+ this.popo = popo;
+
+ if (regInfo != null)
+ {
+ this.regInfo = new DerSequence(regInfo);
+ }
+ }
+
+ public virtual CertRequest CertReq
+ {
+ get { return certReq; }
+ }
+
+ public virtual ProofOfPossession Popo
+ {
+ get { return popo; }
+ }
+
+ public virtual AttributeTypeAndValue[] GetRegInfo()
+ {
+ if (regInfo == null)
+ return null;
+
+ AttributeTypeAndValue[] results = new AttributeTypeAndValue[regInfo.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = AttributeTypeAndValue.GetInstance(regInfo[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * CertReqMsg ::= SEQUENCE {
+ * certReq CertRequest,
+ * pop ProofOfPossession OPTIONAL,
+ * -- content depends upon key type
+ * regInfo SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReq);
+ v.AddOptional(popo);
+ v.AddOptional(regInfo);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/CertRequest.cs b/Crypto/src/asn1/crmf/CertRequest.cs
new file mode 100644
index 000000000..625a9b519
--- /dev/null
+++ b/Crypto/src/asn1/crmf/CertRequest.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertRequest
+ : Asn1Encodable
+ {
+ private readonly DerInteger certReqId;
+ private readonly CertTemplate certTemplate;
+ private readonly Controls controls;
+
+ private CertRequest(Asn1Sequence seq)
+ {
+ certReqId = DerInteger.GetInstance(seq[0]);
+ certTemplate = CertTemplate.GetInstance(seq[1]);
+ if (seq.Count > 2)
+ {
+ controls = Controls.GetInstance(seq[2]);
+ }
+ }
+
+ public static CertRequest GetInstance(object obj)
+ {
+ if (obj is CertRequest)
+ return (CertRequest)obj;
+
+ if (obj != null)
+ return new CertRequest(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public CertRequest(
+ int certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ : this(new DerInteger(certReqId), certTemplate, controls)
+ {
+ }
+
+ public CertRequest(
+ DerInteger certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ {
+ this.certReqId = certReqId;
+ this.certTemplate = certTemplate;
+ this.controls = controls;
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual CertTemplate CertTemplate
+ {
+ get { return certTemplate; }
+ }
+
+ public virtual Controls Controls
+ {
+ get { return controls; }
+ }
+
+ /**
+ * <pre>
+ * CertRequest ::= SEQUENCE {
+ * certReqId INTEGER, -- ID for matching request and reply
+ * certTemplate CertTemplate, -- Selected fields of cert to be issued
+ * controls Controls OPTIONAL } -- Attributes affecting issuance
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReqId, certTemplate);
+ v.AddOptional(controls);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/CertTemplate.cs b/Crypto/src/asn1/crmf/CertTemplate.cs
new file mode 100644
index 000000000..3de9f1d5a
--- /dev/null
+++ b/Crypto/src/asn1/crmf/CertTemplate.cs
@@ -0,0 +1,149 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertTemplate
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence seq;
+
+ private readonly DerInteger version;
+ private readonly DerInteger serialNumber;
+ private readonly AlgorithmIdentifier signingAlg;
+ private readonly X509Name issuer;
+ private readonly OptionalValidity validity;
+ private readonly X509Name subject;
+ private readonly SubjectPublicKeyInfo publicKey;
+ private readonly DerBitString issuerUID;
+ private readonly DerBitString subjectUID;
+ private readonly X509Extensions extensions;
+
+ private CertTemplate(Asn1Sequence seq)
+ {
+ this.seq = seq;
+
+ foreach (Asn1TaggedObject tObj in seq)
+ {
+ switch (tObj.TagNo)
+ {
+ case 0:
+ version = DerInteger.GetInstance(tObj, false);
+ break;
+ case 1:
+ serialNumber = DerInteger.GetInstance(tObj, false);
+ break;
+ case 2:
+ signingAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 3:
+ issuer = X509Name.GetInstance(tObj, true); // CHOICE
+ break;
+ case 4:
+ validity = OptionalValidity.GetInstance(Asn1Sequence.GetInstance(tObj, false));
+ break;
+ case 5:
+ subject = X509Name.GetInstance(tObj, true); // CHOICE
+ break;
+ case 6:
+ publicKey = SubjectPublicKeyInfo.GetInstance(tObj, false);
+ break;
+ case 7:
+ issuerUID = DerBitString.GetInstance(tObj, false);
+ break;
+ case 8:
+ subjectUID = DerBitString.GetInstance(tObj, false);
+ break;
+ case 9:
+ extensions = X509Extensions.GetInstance(tObj, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag: " + tObj.TagNo, "seq");
+ }
+ }
+ }
+
+ public static CertTemplate GetInstance(object obj)
+ {
+ if (obj is CertTemplate)
+ return (CertTemplate)obj;
+
+ if (obj != null)
+ return new CertTemplate(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public virtual int Version
+ {
+ get { return version.Value.IntValue; }
+ }
+
+ public virtual DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ public virtual AlgorithmIdentifier SigningAlg
+ {
+ get { return signingAlg; }
+ }
+
+ public virtual X509Name Issuer
+ {
+ get { return issuer; }
+ }
+
+ public virtual OptionalValidity Validity
+ {
+ get { return validity; }
+ }
+
+ public virtual X509Name Subject
+ {
+ get { return subject; }
+ }
+
+ public virtual SubjectPublicKeyInfo PublicKey
+ {
+ get { return publicKey; }
+ }
+
+ public virtual DerBitString IssuerUID
+ {
+ get { return issuerUID; }
+ }
+
+ public virtual DerBitString SubjectUID
+ {
+ get { return subjectUID; }
+ }
+
+ public virtual X509Extensions Extensions
+ {
+ get { return extensions; }
+ }
+
+ /**
+ * <pre>
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/CertTemplateBuilder.cs b/Crypto/src/asn1/crmf/CertTemplateBuilder.cs
new file mode 100644
index 000000000..51c73c4e1
--- /dev/null
+++ b/Crypto/src/asn1/crmf/CertTemplateBuilder.cs
@@ -0,0 +1,125 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertTemplateBuilder
+ {
+ private DerInteger version;
+ private DerInteger serialNumber;
+ private AlgorithmIdentifier signingAlg;
+ private X509Name issuer;
+ private OptionalValidity validity;
+ private X509Name subject;
+ private SubjectPublicKeyInfo publicKey;
+ private DerBitString issuerUID;
+ private DerBitString subjectUID;
+ private X509Extensions extensions;
+
+ /** Sets the X.509 version. Note: for X509v3, use 2 here. */
+ public virtual CertTemplateBuilder SetVersion(int ver)
+ {
+ version = new DerInteger(ver);
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetSerialNumber(DerInteger ser)
+ {
+ serialNumber = ser;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetSigningAlg(AlgorithmIdentifier aid)
+ {
+ signingAlg = aid;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetIssuer(X509Name name)
+ {
+ issuer = name;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetValidity(OptionalValidity v)
+ {
+ validity = v;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetSubject(X509Name name)
+ {
+ subject = name;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetPublicKey(SubjectPublicKeyInfo spki)
+ {
+ publicKey = spki;
+ return this;
+ }
+
+ /** Sets the issuer unique ID (deprecated in X.509v3) */
+ public virtual CertTemplateBuilder SetIssuerUID(DerBitString uid)
+ {
+ issuerUID = uid;
+ return this;
+ }
+
+ /** Sets the subject unique ID (deprecated in X.509v3) */
+ public virtual CertTemplateBuilder SetSubjectUID(DerBitString uid)
+ {
+ subjectUID = uid;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetExtensions(X509Extensions extens)
+ {
+ extensions = extens;
+ return this;
+ }
+
+ /**
+ * <pre>
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public virtual CertTemplate Build()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ AddOptional(v, 0, false, version);
+ AddOptional(v, 1, false, serialNumber);
+ AddOptional(v, 2, false, signingAlg);
+ AddOptional(v, 3, true, issuer); // CHOICE
+ AddOptional(v, 4, false, validity);
+ AddOptional(v, 5, true, subject); // CHOICE
+ AddOptional(v, 6, false, publicKey);
+ AddOptional(v, 7, false, issuerUID);
+ AddOptional(v, 8, false, subjectUID);
+ AddOptional(v, 9, false, extensions);
+
+ return CertTemplate.GetInstance(new DerSequence(v));
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, bool isExplicit, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(isExplicit, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/Controls.cs b/Crypto/src/asn1/crmf/Controls.cs
new file mode 100644
index 000000000..cc52ea4bb
--- /dev/null
+++ b/Crypto/src/asn1/crmf/Controls.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class Controls
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private Controls(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static Controls GetInstance(object obj)
+ {
+ if (obj is Controls)
+ return (Controls)obj;
+
+ if (obj is Asn1Sequence)
+ return new Controls((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public Controls(params AttributeTypeAndValue[] atvs)
+ {
+ content = new DerSequence(atvs);
+ }
+
+ public virtual AttributeTypeAndValue[] ToAttributeTypeAndValueArray()
+ {
+ AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = AttributeTypeAndValue.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * Controls ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs b/Crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs
new file mode 100644
index 000000000..eaa1f7ba4
--- /dev/null
+++ b/Crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs
@@ -0,0 +1,23 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public abstract class CrmfObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier id_pkix = new DerObjectIdentifier("1.3.6.1.5.5.7");
+
+ // arc for Internet X.509 PKI protocols and their components
+
+ public static readonly DerObjectIdentifier id_pkip = id_pkix.Branch("5");
+
+ public static readonly DerObjectIdentifier id_regCtrl = id_pkip.Branch("1");
+ public static readonly DerObjectIdentifier id_regCtrl_regToken = id_regCtrl.Branch("1");
+ public static readonly DerObjectIdentifier id_regCtrl_authenticator = id_regCtrl.Branch("2");
+ public static readonly DerObjectIdentifier id_regCtrl_pkiPublicationInfo = id_regCtrl.Branch("3");
+ public static readonly DerObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.Branch("4");
+
+ public static readonly DerObjectIdentifier id_ct_encKeyWithID = new DerObjectIdentifier(PkcsObjectIdentifiers.IdCT + ".21");
+ }
+}
diff --git a/Crypto/src/asn1/crmf/EncKeyWithID.cs b/Crypto/src/asn1/crmf/EncKeyWithID.cs
new file mode 100644
index 000000000..6de56fa0b
--- /dev/null
+++ b/Crypto/src/asn1/crmf/EncKeyWithID.cs
@@ -0,0 +1,103 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class EncKeyWithID
+ : Asn1Encodable
+ {
+ private readonly PrivateKeyInfo privKeyInfo;
+ private readonly Asn1Encodable identifier;
+
+ public static EncKeyWithID GetInstance(object obj)
+ {
+ if (obj is EncKeyWithID)
+ return (EncKeyWithID)obj;
+
+ if (obj != null)
+ return new EncKeyWithID(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ private EncKeyWithID(Asn1Sequence seq)
+ {
+ this.privKeyInfo = PrivateKeyInfo.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ if (!(seq[1] is DerUtf8String))
+ {
+ this.identifier = GeneralName.GetInstance(seq[1]);
+ }
+ else
+ {
+ this.identifier = (Asn1Encodable)seq[1];
+ }
+ }
+ else
+ {
+ this.identifier = null;
+ }
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = null;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, DerUtf8String str)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = str;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, GeneralName generalName)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = generalName;
+ }
+
+ public virtual PrivateKeyInfo PrivateKey
+ {
+ get { return privKeyInfo; }
+ }
+
+ public virtual bool HasIdentifier
+ {
+ get { return identifier != null; }
+ }
+
+ public virtual bool IsIdentifierUtf8String
+ {
+ get { return identifier is DerUtf8String; }
+ }
+
+ public virtual Asn1Encodable Identifier
+ {
+ get { return identifier; }
+ }
+
+ /**
+ * <pre>
+ * EncKeyWithID ::= SEQUENCE {
+ * privateKey PrivateKeyInfo,
+ * identifier CHOICE {
+ * string UTF8String,
+ * generalName GeneralName
+ * } OPTIONAL
+ * }
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(privKeyInfo);
+ v.AddOptional(identifier);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/EncryptedKey.cs b/Crypto/src/asn1/crmf/EncryptedKey.cs
new file mode 100644
index 000000000..850fbd219
--- /dev/null
+++ b/Crypto/src/asn1/crmf/EncryptedKey.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class EncryptedKey
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly EnvelopedData envelopedData;
+ private readonly EncryptedValue encryptedValue;
+
+ public static EncryptedKey GetInstance(object o)
+ {
+ if (o is EncryptedKey)
+ {
+ return (EncryptedKey)o;
+ }
+ else if (o is Asn1TaggedObject)
+ {
+ return new EncryptedKey(EnvelopedData.GetInstance((Asn1TaggedObject)o, false));
+ }
+ else if (o is EncryptedValue)
+ {
+ return new EncryptedKey((EncryptedValue)o);
+ }
+ else
+ {
+ return new EncryptedKey(EncryptedValue.GetInstance(o));
+ }
+ }
+
+ public EncryptedKey(EnvelopedData envelopedData)
+ {
+ this.envelopedData = envelopedData;
+ }
+
+ public EncryptedKey(EncryptedValue encryptedValue)
+ {
+ this.encryptedValue = encryptedValue;
+ }
+
+ public virtual bool IsEncryptedValue
+ {
+ get { return encryptedValue != null; }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get
+ {
+ if (encryptedValue != null)
+ return encryptedValue;
+
+ return envelopedData;
+ }
+ }
+
+ /**
+ * <pre>
+ * EncryptedKey ::= CHOICE {
+ * encryptedValue EncryptedValue, -- deprecated
+ * envelopedData [0] EnvelopedData }
+ * -- The encrypted private key MUST be placed in the envelopedData
+ * -- encryptedContentInfo encryptedContent OCTET STRING.
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (encryptedValue != null)
+ {
+ return encryptedValue.ToAsn1Object();
+ }
+
+ return new DerTaggedObject(false, 0, envelopedData);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/EncryptedValue.cs b/Crypto/src/asn1/crmf/EncryptedValue.cs
new file mode 100644
index 000000000..83122e220
--- /dev/null
+++ b/Crypto/src/asn1/crmf/EncryptedValue.cs
@@ -0,0 +1,154 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class EncryptedValue
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier intendedAlg;
+ private readonly AlgorithmIdentifier symmAlg;
+ private readonly DerBitString encSymmKey;
+ private readonly AlgorithmIdentifier keyAlg;
+ private readonly Asn1OctetString valueHint;
+ private readonly DerBitString encValue;
+
+ private EncryptedValue(Asn1Sequence seq)
+ {
+ int index = 0;
+ while (seq[index] is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[index];
+
+ switch (tObj.TagNo)
+ {
+ case 0:
+ intendedAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 1:
+ symmAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 2:
+ encSymmKey = DerBitString.GetInstance(tObj, false);
+ break;
+ case 3:
+ keyAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 4:
+ valueHint = Asn1OctetString.GetInstance(tObj, false);
+ break;
+ }
+ ++index;
+ }
+
+ encValue = DerBitString.GetInstance(seq[index]);
+ }
+
+ public static EncryptedValue GetInstance(object obj)
+ {
+ if (obj is EncryptedValue)
+ return (EncryptedValue)obj;
+
+ if (obj != null)
+ return new EncryptedValue(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public EncryptedValue(
+ AlgorithmIdentifier intendedAlg,
+ AlgorithmIdentifier symmAlg,
+ DerBitString encSymmKey,
+ AlgorithmIdentifier keyAlg,
+ Asn1OctetString valueHint,
+ DerBitString encValue)
+ {
+ if (encValue == null)
+ {
+ throw new ArgumentNullException("encValue");
+ }
+
+ this.intendedAlg = intendedAlg;
+ this.symmAlg = symmAlg;
+ this.encSymmKey = encSymmKey;
+ this.keyAlg = keyAlg;
+ this.valueHint = valueHint;
+ this.encValue = encValue;
+ }
+
+ public virtual AlgorithmIdentifier IntendedAlg
+ {
+ get { return intendedAlg; }
+ }
+
+ public virtual AlgorithmIdentifier SymmAlg
+ {
+ get { return symmAlg; }
+ }
+
+ public virtual DerBitString EncSymmKey
+ {
+ get { return encSymmKey; }
+ }
+
+ public virtual AlgorithmIdentifier KeyAlg
+ {
+ get { return keyAlg; }
+ }
+
+ public virtual Asn1OctetString ValueHint
+ {
+ get { return valueHint; }
+ }
+
+ public virtual DerBitString EncValue
+ {
+ get { return encValue; }
+ }
+
+ /**
+ * <pre>
+ * EncryptedValue ::= SEQUENCE {
+ * intendedAlg [0] AlgorithmIdentifier OPTIONAL,
+ * -- the intended algorithm for which the value will be used
+ * symmAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- the symmetric algorithm used to encrypt the value
+ * encSymmKey [2] BIT STRING OPTIONAL,
+ * -- the (encrypted) symmetric key used to encrypt the value
+ * keyAlg [3] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used to encrypt the symmetric key
+ * valueHint [4] OCTET STRING OPTIONAL,
+ * -- a brief description or identifier of the encValue content
+ * -- (may be meaningful only to the sending entity, and used only
+ * -- if EncryptedValue might be re-examined by the sending entity
+ * -- in the future)
+ * encValue BIT STRING }
+ * -- the encrypted value itself
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ AddOptional(v, 0, intendedAlg);
+ AddOptional(v, 1, symmAlg);
+ AddOptional(v, 2, encSymmKey);
+ AddOptional(v, 3, keyAlg);
+ AddOptional(v, 4, valueHint);
+
+ v.Add(encValue);
+
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(false, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/OptionalValidity.cs b/Crypto/src/asn1/crmf/OptionalValidity.cs
new file mode 100644
index 000000000..c0037999a
--- /dev/null
+++ b/Crypto/src/asn1/crmf/OptionalValidity.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class OptionalValidity
+ : Asn1Encodable
+ {
+ private readonly Time notBefore;
+ private readonly Time notAfter;
+
+ private OptionalValidity(Asn1Sequence seq)
+ {
+ foreach (Asn1TaggedObject tObj in seq)
+ {
+ if (tObj.TagNo == 0)
+ {
+ notBefore = Time.GetInstance(tObj, true);
+ }
+ else
+ {
+ notAfter = Time.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static OptionalValidity GetInstance(object obj)
+ {
+ if (obj is OptionalValidity)
+ return (OptionalValidity)obj;
+
+ if (obj is Asn1Sequence)
+ return new OptionalValidity((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * <pre>
+ * OptionalValidity ::= SEQUENCE {
+ * notBefore [0] Time OPTIONAL,
+ * notAfter [1] Time OPTIONAL } --at least one MUST be present
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (notBefore != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, notBefore));
+ }
+
+ if (notAfter != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, notAfter));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/PKIArchiveOptions.cs b/Crypto/src/asn1/crmf/PKIArchiveOptions.cs
new file mode 100644
index 000000000..910f73b22
--- /dev/null
+++ b/Crypto/src/asn1/crmf/PKIArchiveOptions.cs
@@ -0,0 +1,105 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PkiArchiveOptions
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int encryptedPrivKey = 0;
+ public const int keyGenParameters = 1;
+ public const int archiveRemGenPrivKey = 2;
+
+ private readonly Asn1Encodable value;
+
+ public static PkiArchiveOptions GetInstance(object obj)
+ {
+ if (obj is PkiArchiveOptions)
+ return (PkiArchiveOptions)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new PkiArchiveOptions((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ private PkiArchiveOptions(Asn1TaggedObject tagged)
+ {
+ switch (tagged.TagNo)
+ {
+ case encryptedPrivKey:
+ value = EncryptedKey.GetInstance(tagged.GetObject());
+ break;
+ case keyGenParameters:
+ value = Asn1OctetString.GetInstance(tagged, false);
+ break;
+ case archiveRemGenPrivKey:
+ value = DerBoolean.GetInstance(tagged, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tagged.TagNo, "tagged");
+ }
+ }
+
+ public PkiArchiveOptions(EncryptedKey encKey)
+ {
+ this.value = encKey;
+ }
+
+ public PkiArchiveOptions(Asn1OctetString keyGenParameters)
+ {
+ this.value = keyGenParameters;
+ }
+
+ public PkiArchiveOptions(bool archiveRemGenPrivKey)
+ {
+ this.value = DerBoolean.GetInstance(archiveRemGenPrivKey);
+ }
+
+ public virtual int Type
+ {
+ get
+ {
+ if (value is EncryptedKey)
+ return encryptedPrivKey;
+
+ if (value is Asn1OctetString)
+ return keyGenParameters;
+
+ return archiveRemGenPrivKey;
+ }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get { return value; }
+ }
+
+ /**
+ * <pre>
+ * PkiArchiveOptions ::= CHOICE {
+ * encryptedPrivKey [0] EncryptedKey,
+ * -- the actual value of the private key
+ * keyGenParameters [1] KeyGenParameters,
+ * -- parameters which allow the private key to be re-generated
+ * archiveRemGenPrivKey [2] BOOLEAN }
+ * -- set to TRUE if sender wishes receiver to archive the private
+ * -- key of a key pair that the receiver generates in response to
+ * -- this request; set to FALSE if no archival is desired.
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (value is EncryptedKey)
+ {
+ return new DerTaggedObject(true, encryptedPrivKey, value); // choice
+ }
+
+ if (value is Asn1OctetString)
+ {
+ return new DerTaggedObject(false, keyGenParameters, value);
+ }
+
+ return new DerTaggedObject(false, archiveRemGenPrivKey, value);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/PKIPublicationInfo.cs b/Crypto/src/asn1/crmf/PKIPublicationInfo.cs
new file mode 100644
index 000000000..c8bc1403e
--- /dev/null
+++ b/Crypto/src/asn1/crmf/PKIPublicationInfo.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PkiPublicationInfo
+ : Asn1Encodable
+ {
+ private readonly DerInteger action;
+ private readonly Asn1Sequence pubInfos;
+
+ private PkiPublicationInfo(Asn1Sequence seq)
+ {
+ action = DerInteger.GetInstance(seq[0]);
+ pubInfos = Asn1Sequence.GetInstance(seq[1]);
+ }
+
+ public static PkiPublicationInfo GetInstance(object obj)
+ {
+ if (obj is PkiPublicationInfo)
+ return (PkiPublicationInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new PkiPublicationInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger Action
+ {
+ get { return action; }
+ }
+
+ public virtual SinglePubInfo[] GetPubInfos()
+ {
+ if (pubInfos == null)
+ return null;
+
+ SinglePubInfo[] results = new SinglePubInfo[pubInfos.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = SinglePubInfo.GetInstance(pubInfos[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PkiPublicationInfo ::= SEQUENCE {
+ * action INTEGER {
+ * dontPublish (0),
+ * pleasePublish (1) },
+ * pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+ * -- pubInfos MUST NOT be present if action is "dontPublish"
+ * -- (if action is "pleasePublish" and pubInfos is omitted,
+ * -- "dontCare" is assumed)
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(action, pubInfos);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/PKMacValue.cs b/Crypto/src/asn1/crmf/PKMacValue.cs
new file mode 100644
index 000000000..20a08fd1d
--- /dev/null
+++ b/Crypto/src/asn1/crmf/PKMacValue.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ /**
+ * Password-based MAC value for use with POPOSigningKeyInput.
+ */
+ public class PKMacValue
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier algID;
+ private readonly DerBitString macValue;
+
+ private PKMacValue(Asn1Sequence seq)
+ {
+ this.algID = AlgorithmIdentifier.GetInstance(seq[0]);
+ this.macValue = DerBitString.GetInstance(seq[1]);
+ }
+
+ public static PKMacValue GetInstance(object obj)
+ {
+ if (obj is PKMacValue)
+ return (PKMacValue)obj;
+
+ if (obj is Asn1Sequence)
+ return new PKMacValue((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public static PKMacValue GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param params parameters for password-based MAC
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMacValue(
+ PbmParameter pbmParams,
+ DerBitString macValue)
+ : this(new AlgorithmIdentifier(CmpObjectIdentifiers.passwordBasedMac, pbmParams), macValue)
+ {
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMacValue(
+ AlgorithmIdentifier algID,
+ DerBitString macValue)
+ {
+ this.algID = algID;
+ this.macValue = macValue;
+ }
+
+ public virtual AlgorithmIdentifier AlgID
+ {
+ get { return algID; }
+ }
+
+ public virtual DerBitString MacValue
+ {
+ get { return macValue; }
+ }
+
+ /**
+ * <pre>
+ * PKMACValue ::= SEQUENCE {
+ * algId AlgorithmIdentifier,
+ * -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+ * -- parameter value is PBMParameter
+ * value BIT STRING }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(algID, macValue);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/PopoPrivKey.cs b/Crypto/src/asn1/crmf/PopoPrivKey.cs
new file mode 100644
index 000000000..0cedc5127
--- /dev/null
+++ b/Crypto/src/asn1/crmf/PopoPrivKey.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PopoPrivKey
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int thisMessage = 0;
+ public const int subsequentMessage = 1;
+ public const int dhMAC = 2;
+ public const int agreeMAC = 3;
+ public const int encryptedKey = 4;
+
+ private readonly int tagNo;
+ private readonly Asn1Encodable obj;
+
+ private PopoPrivKey(Asn1TaggedObject obj)
+ {
+ this.tagNo = obj.TagNo;
+
+ switch (tagNo)
+ {
+ case thisMessage:
+ this.obj = DerBitString.GetInstance(obj, false);
+ break;
+ case subsequentMessage:
+ this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).Value.IntValue);
+ break;
+ case dhMAC:
+ this.obj = DerBitString.GetInstance(obj, false);
+ break;
+ case agreeMAC:
+ this.obj = PKMacValue.GetInstance(obj, false);
+ break;
+ case encryptedKey:
+ this.obj = EnvelopedData.GetInstance(obj, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag in PopoPrivKey", "obj");
+ }
+ }
+
+ public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit)
+ {
+ return new PopoPrivKey(Asn1TaggedObject.GetInstance(tagged.GetObject()));
+ }
+
+ public PopoPrivKey(SubsequentMessage msg)
+ {
+ this.tagNo = subsequentMessage;
+ this.obj = msg;
+ }
+
+ public virtual int Type
+ {
+ get { return tagNo; }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get { return obj; }
+ }
+
+ /**
+ * <pre>
+ * PopoPrivKey ::= CHOICE {
+ * thisMessage [0] BIT STRING, -- Deprecated
+ * -- possession is proven in this message (which contains the private
+ * -- key itself (encrypted for the CA))
+ * subsequentMessage [1] SubsequentMessage,
+ * -- possession will be proven in a subsequent message
+ * dhMAC [2] BIT STRING, -- Deprecated
+ * agreeMAC [3] PKMACValue,
+ * encryptedKey [4] EnvelopedData }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, tagNo, obj);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/PopoSigningKey.cs b/Crypto/src/asn1/crmf/PopoSigningKey.cs
new file mode 100644
index 000000000..614278eda
--- /dev/null
+++ b/Crypto/src/asn1/crmf/PopoSigningKey.cs
@@ -0,0 +1,115 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PopoSigningKey
+ : Asn1Encodable
+ {
+ private readonly PopoSigningKeyInput poposkInput;
+ private readonly AlgorithmIdentifier algorithmIdentifier;
+ private readonly DerBitString signature;
+
+ private PopoSigningKey(Asn1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq[index] is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagObj
+ = (Asn1TaggedObject) seq[index++];
+ if (tagObj.TagNo != 0)
+ {
+ throw new ArgumentException( "Unknown PopoSigningKeyInput tag: " + tagObj.TagNo, "seq");
+ }
+ poposkInput = PopoSigningKeyInput.GetInstance(tagObj.GetObject());
+ }
+ algorithmIdentifier = AlgorithmIdentifier.GetInstance(seq[index++]);
+ signature = DerBitString.GetInstance(seq[index]);
+ }
+
+ public static PopoSigningKey GetInstance(object obj)
+ {
+ if (obj is PopoSigningKey)
+ return (PopoSigningKey)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoSigningKey((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public static PopoSigningKey GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * Creates a new Proof of Possession object for a signing key.
+ * @param poposkIn the PopoSigningKeyInput structure, or null if the
+ * CertTemplate includes both subject and publicKey values.
+ * @param aid the AlgorithmIdentifier used to sign the proof of possession.
+ * @param signature a signature over the DER-encoded value of poposkIn,
+ * or the DER-encoded value of certReq if poposkIn is null.
+ */
+ public PopoSigningKey(
+ PopoSigningKeyInput poposkIn,
+ AlgorithmIdentifier aid,
+ DerBitString signature)
+ {
+ this.poposkInput = poposkIn;
+ this.algorithmIdentifier = aid;
+ this.signature = signature;
+ }
+
+ public virtual PopoSigningKeyInput PoposkInput
+ {
+ get { return poposkInput; }
+ }
+
+ public virtual AlgorithmIdentifier AlgorithmIdentifier
+ {
+ get { return algorithmIdentifier; }
+ }
+
+ public virtual DerBitString Signature
+ {
+ get { return signature; }
+ }
+
+ /**
+ * <pre>
+ * PopoSigningKey ::= SEQUENCE {
+ * poposkInput [0] PopoSigningKeyInput OPTIONAL,
+ * algorithmIdentifier AlgorithmIdentifier,
+ * signature BIT STRING }
+ * -- The signature (using "algorithmIdentifier") is on the
+ * -- DER-encoded value of poposkInput. NOTE: If the CertReqMsg
+ * -- certReq CertTemplate contains the subject and publicKey values,
+ * -- then poposkInput MUST be omitted and the signature MUST be
+ * -- computed on the DER-encoded value of CertReqMsg certReq. If
+ * -- the CertReqMsg certReq CertTemplate does not contain the public
+ * -- key and subject values, then poposkInput MUST be present and
+ * -- MUST be signed. This strategy ensures that the public key is
+ * -- not present in both the poposkInput and CertReqMsg certReq
+ * -- CertTemplate fields.
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (poposkInput != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, poposkInput));
+ }
+
+ v.Add(algorithmIdentifier);
+ v.Add(signature);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/PopoSigningKeyInput.cs b/Crypto/src/asn1/crmf/PopoSigningKeyInput.cs
new file mode 100644
index 000000000..63695262f
--- /dev/null
+++ b/Crypto/src/asn1/crmf/PopoSigningKeyInput.cs
@@ -0,0 +1,115 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PopoSigningKeyInput
+ : Asn1Encodable
+ {
+ private readonly GeneralName sender;
+ private readonly PKMacValue publicKeyMac;
+ private readonly SubjectPublicKeyInfo publicKey;
+
+ private PopoSigningKeyInput(Asn1Sequence seq)
+ {
+ Asn1Encodable authInfo = (Asn1Encodable)seq[0];
+
+ if (authInfo is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagObj = (Asn1TaggedObject)authInfo;
+ if (tagObj.TagNo != 0)
+ {
+ throw new ArgumentException("Unknown authInfo tag: " + tagObj.TagNo, "seq");
+ }
+ sender = GeneralName.GetInstance(tagObj.GetObject());
+ }
+ else
+ {
+ publicKeyMac = PKMacValue.GetInstance(authInfo);
+ }
+
+ publicKey = SubjectPublicKeyInfo.GetInstance(seq[1]);
+ }
+
+ public static PopoSigningKeyInput GetInstance(object obj)
+ {
+ if (obj is PopoSigningKeyInput)
+ return (PopoSigningKeyInput)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoSigningKeyInput((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ /** Creates a new PopoSigningKeyInput with sender name as authInfo. */
+ public PopoSigningKeyInput(
+ GeneralName sender,
+ SubjectPublicKeyInfo spki)
+ {
+ this.sender = sender;
+ this.publicKey = spki;
+ }
+
+ /** Creates a new PopoSigningKeyInput using password-based MAC. */
+ public PopoSigningKeyInput(
+ PKMacValue pkmac,
+ SubjectPublicKeyInfo spki)
+ {
+ this.publicKeyMac = pkmac;
+ this.publicKey = spki;
+ }
+
+ /** Returns the sender field, or null if authInfo is publicKeyMac */
+ public virtual GeneralName Sender
+ {
+ get { return sender; }
+ }
+
+ /** Returns the publicKeyMac field, or null if authInfo is sender */
+ public virtual PKMacValue PublicKeyMac
+ {
+ get { return publicKeyMac; }
+ }
+
+ public virtual SubjectPublicKeyInfo PublicKey
+ {
+ get { return publicKey; }
+ }
+
+ /**
+ * <pre>
+ * PopoSigningKeyInput ::= SEQUENCE {
+ * authInfo CHOICE {
+ * sender [0] GeneralName,
+ * -- used only if an authenticated identity has been
+ * -- established for the sender (e.g., a DN from a
+ * -- previously-issued and currently-valid certificate
+ * publicKeyMac PKMacValue },
+ * -- used if no authenticated GeneralName currently exists for
+ * -- the sender; publicKeyMac contains a password-based MAC
+ * -- on the DER-encoded value of publicKey
+ * publicKey SubjectPublicKeyInfo } -- from CertTemplate
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (sender != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, sender));
+ }
+ else
+ {
+ v.Add(publicKeyMac);
+ }
+
+ v.Add(publicKey);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/ProofOfPossession.cs b/Crypto/src/asn1/crmf/ProofOfPossession.cs
new file mode 100644
index 000000000..fc00edb32
--- /dev/null
+++ b/Crypto/src/asn1/crmf/ProofOfPossession.cs
@@ -0,0 +1,98 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class ProofOfPossession
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int TYPE_RA_VERIFIED = 0;
+ public const int TYPE_SIGNING_KEY = 1;
+ public const int TYPE_KEY_ENCIPHERMENT = 2;
+ public const int TYPE_KEY_AGREEMENT = 3;
+
+ private readonly int tagNo;
+ private readonly Asn1Encodable obj;
+
+ private ProofOfPossession(Asn1TaggedObject tagged)
+ {
+ tagNo = tagged.TagNo;
+ switch (tagNo)
+ {
+ case 0:
+ obj = DerNull.Instance;
+ break;
+ case 1:
+ obj = PopoSigningKey.GetInstance(tagged, false);
+ break;
+ case 2:
+ case 3:
+ obj = PopoPrivKey.GetInstance(tagged, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag: " + tagNo, "tagged");
+ }
+ }
+
+ public static ProofOfPossession GetInstance(object obj)
+ {
+ if (obj is ProofOfPossession)
+ return (ProofOfPossession)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new ProofOfPossession((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ /** Creates a ProofOfPossession with type raVerified. */
+ public ProofOfPossession()
+ {
+ tagNo = TYPE_RA_VERIFIED;
+ obj = DerNull.Instance;
+ }
+
+ /** Creates a ProofOfPossession for a signing key. */
+ public ProofOfPossession(PopoSigningKey Poposk)
+ {
+ tagNo = TYPE_SIGNING_KEY;
+ obj = Poposk;
+ }
+
+ /**
+ * Creates a ProofOfPossession for key encipherment or agreement.
+ * @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
+ */
+ public ProofOfPossession(int type, PopoPrivKey privkey)
+ {
+ tagNo = type;
+ obj = privkey;
+ }
+
+ public virtual int Type
+ {
+ get { return tagNo; }
+ }
+
+ public virtual Asn1Encodable Object
+ {
+ get { return obj; }
+ }
+
+ /**
+ * <pre>
+ * ProofOfPossession ::= CHOICE {
+ * raVerified [0] NULL,
+ * -- used if the RA has already verified that the requester is in
+ * -- possession of the private key
+ * signature [1] PopoSigningKey,
+ * keyEncipherment [2] PopoPrivKey,
+ * keyAgreement [3] PopoPrivKey }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, tagNo, obj);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/SinglePubInfo.cs b/Crypto/src/asn1/crmf/SinglePubInfo.cs
new file mode 100644
index 000000000..eaf8a3efd
--- /dev/null
+++ b/Crypto/src/asn1/crmf/SinglePubInfo.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class SinglePubInfo
+ : Asn1Encodable
+ {
+ private readonly DerInteger pubMethod;
+ private readonly GeneralName pubLocation;
+
+ private SinglePubInfo(Asn1Sequence seq)
+ {
+ pubMethod = DerInteger.GetInstance(seq[0]);
+
+ if (seq.Count == 2)
+ {
+ pubLocation = GeneralName.GetInstance(seq[1]);
+ }
+ }
+
+ public static SinglePubInfo GetInstance(object obj)
+ {
+ if (obj is SinglePubInfo)
+ return (SinglePubInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new SinglePubInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual GeneralName PubLocation
+ {
+ get { return pubLocation; }
+ }
+
+ /**
+ * <pre>
+ * SinglePubInfo ::= SEQUENCE {
+ * pubMethod INTEGER {
+ * dontCare (0),
+ * x500 (1),
+ * web (2),
+ * ldap (3) },
+ * pubLocation GeneralName OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pubMethod);
+ v.AddOptional(pubLocation);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/crmf/SubsequentMessage.cs b/Crypto/src/asn1/crmf/SubsequentMessage.cs
new file mode 100644
index 000000000..cc1c16492
--- /dev/null
+++ b/Crypto/src/asn1/crmf/SubsequentMessage.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class SubsequentMessage
+ : DerInteger
+ {
+ public static readonly SubsequentMessage encrCert = new SubsequentMessage(0);
+ public static readonly SubsequentMessage challengeResp = new SubsequentMessage(1);
+
+ private SubsequentMessage(int value)
+ : base(value)
+ {
+ }
+
+ public static SubsequentMessage ValueOf(int value)
+ {
+ if (value == 0)
+ return encrCert;
+
+ if (value == 1)
+ return challengeResp;
+
+ throw new ArgumentException("unknown value: " + value, "value");
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs b/Crypto/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs
new file mode 100644
index 000000000..6e0e023b9
--- /dev/null
+++ b/Crypto/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs
@@ -0,0 +1,48 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+ public abstract class CryptoProObjectIdentifiers
+ {
+ // GOST Algorithms OBJECT IDENTIFIERS :
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
+ public const string GostID = "1.2.643.2.2";
+
+ public static readonly DerObjectIdentifier GostR3411 = new DerObjectIdentifier(GostID + ".9");
+
+ public static readonly DerObjectIdentifier GostR28147Cbc = new DerObjectIdentifier(GostID + ".21");
+
+ public static readonly DerObjectIdentifier GostR3410x94 = new DerObjectIdentifier(GostID + ".20");
+ public static readonly DerObjectIdentifier GostR3410x2001 = new DerObjectIdentifier(GostID + ".19");
+ public static readonly DerObjectIdentifier GostR3411x94WithGostR3410x94 = new DerObjectIdentifier(GostID + ".4");
+ public static readonly DerObjectIdentifier GostR3411x94WithGostR3410x2001 = new DerObjectIdentifier(GostID + ".3");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
+ public static readonly DerObjectIdentifier GostR3411x94CryptoProParamSet = new DerObjectIdentifier(GostID + ".30.1");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
+ public static readonly DerObjectIdentifier GostR3410x94CryptoProA = new DerObjectIdentifier(GostID + ".32.2");
+ public static readonly DerObjectIdentifier GostR3410x94CryptoProB = new DerObjectIdentifier(GostID + ".32.3");
+ public static readonly DerObjectIdentifier GostR3410x94CryptoProC = new DerObjectIdentifier(GostID + ".32.4");
+ public static readonly DerObjectIdentifier GostR3410x94CryptoProD = new DerObjectIdentifier(GostID + ".32.5");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
+ public static readonly DerObjectIdentifier GostR3410x94CryptoProXchA = new DerObjectIdentifier(GostID + ".33.1");
+ public static readonly DerObjectIdentifier GostR3410x94CryptoProXchB = new DerObjectIdentifier(GostID + ".33.2");
+ public static readonly DerObjectIdentifier GostR3410x94CryptoProXchC = new DerObjectIdentifier(GostID + ".33.3");
+
+ //{ iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
+ public static readonly DerObjectIdentifier GostR3410x2001CryptoProA = new DerObjectIdentifier(GostID + ".35.1");
+ public static readonly DerObjectIdentifier GostR3410x2001CryptoProB = new DerObjectIdentifier(GostID + ".35.2");
+ public static readonly DerObjectIdentifier GostR3410x2001CryptoProC = new DerObjectIdentifier(GostID + ".35.3");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
+ public static readonly DerObjectIdentifier GostR3410x2001CryptoProXchA = new DerObjectIdentifier(GostID + ".36.0");
+ public static readonly DerObjectIdentifier GostR3410x2001CryptoProXchB = new DerObjectIdentifier(GostID + ".36.1");
+
+ public static readonly DerObjectIdentifier GostElSgDH3410Default = new DerObjectIdentifier(GostID + ".36.0");
+ public static readonly DerObjectIdentifier GostElSgDH3410x1 = new DerObjectIdentifier(GostID + ".36.1");
+ }
+}
diff --git a/Crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs b/Crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
new file mode 100644
index 000000000..998e0e06f
--- /dev/null
+++ b/Crypto/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+ /**
+ * table of the available named parameters for GOST 3410-2001.
+ */
+ public sealed class ECGost3410NamedCurves
+ {
+ private ECGost3410NamedCurves()
+ {
+ }
+
+ internal static readonly IDictionary objIds = Platform.CreateHashtable();
+ internal static readonly IDictionary parameters = Platform.CreateHashtable();
+ internal static readonly IDictionary names = Platform.CreateHashtable();
+
+ static ECGost3410NamedCurves()
+ {
+ BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
+ BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+ FpCurve curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
+ new BigInteger("166")); // b
+
+ ECDomainParameters ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ BigInteger.One, // x
+ new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"), // y
+ false),
+ mod_q);
+
+ parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProA] = ecParams;
+
+ mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
+ mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"),
+ new BigInteger("166"));
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ BigInteger.One, // x
+ new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"), // y
+ false),
+ mod_q);
+
+ parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA] = ecParams;
+
+ mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
+ mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703"); //q
+
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
+ new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595")); // b
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ BigInteger.One, // x
+ new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124"), // y
+ false),
+ mod_q); // q
+
+ parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProB] = ecParams;
+
+ mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619");
+ mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
+
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"),
+ new BigInteger("32858"));
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ BigInteger.Zero, // x
+ new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"), // y
+ false),
+ mod_q);
+
+ parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB] = ecParams;
+
+ mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
+ mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601"); //q
+ curve = new FpCurve(
+ mod_p, // p
+ new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
+ new BigInteger("32858")); // b
+
+ ecParams = new ECDomainParameters(
+ curve,
+ curve.CreatePoint(
+ BigInteger.Zero, // x
+ new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"), // y
+ false),
+ mod_q); // q
+
+ parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = ecParams;
+
+ objIds["GostR3410-2001-CryptoPro-A"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProA;
+ objIds["GostR3410-2001-CryptoPro-B"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProB;
+ objIds["GostR3410-2001-CryptoPro-C"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProC;
+ objIds["GostR3410-2001-CryptoPro-XchA"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA;
+ objIds["GostR3410-2001-CryptoPro-XchB"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB;
+
+ names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProA] = "GostR3410-2001-CryptoPro-A";
+ names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProB] = "GostR3410-2001-CryptoPro-B";
+ names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = "GostR3410-2001-CryptoPro-C";
+ names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA] = "GostR3410-2001-CryptoPro-XchA";
+ names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB] = "GostR3410-2001-CryptoPro-XchB";
+ }
+
+ /**
+ * return the ECDomainParameters object for the given OID, null if it
+ * isn't present.
+ *
+ * @param oid an object identifier representing a named parameters, if present.
+ */
+ public static ECDomainParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ return (ECDomainParameters) parameters[oid];
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(objIds.Keys); }
+ }
+
+ public static ECDomainParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name];
+
+ if (oid != null)
+ {
+ return (ECDomainParameters) parameters[oid];
+ }
+
+ return null;
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static string GetName(
+ DerObjectIdentifier oid)
+ {
+ return (string) names[oid];
+ }
+
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier) objIds[name];
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs b/Crypto/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs
new file mode 100644
index 000000000..6f4435d7b
--- /dev/null
+++ b/Crypto/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+ public class ECGost3410ParamSetParameters
+ : Asn1Encodable
+ {
+ internal readonly DerInteger p, q, a, b, x, y;
+
+ public static ECGost3410ParamSetParameters GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static ECGost3410ParamSetParameters GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ECGost3410ParamSetParameters)
+ {
+ return (ECGost3410ParamSetParameters) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ECGost3410ParamSetParameters((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+ }
+
+ public ECGost3410ParamSetParameters(
+ BigInteger a,
+ BigInteger b,
+ BigInteger p,
+ BigInteger q,
+ int x,
+ BigInteger y)
+ {
+ this.a = new DerInteger(a);
+ this.b = new DerInteger(b);
+ this.p = new DerInteger(p);
+ this.q = new DerInteger(q);
+ this.x = new DerInteger(x);
+ this.y = new DerInteger(y);
+ }
+
+ public ECGost3410ParamSetParameters(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 6)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.a = DerInteger.GetInstance(seq[0]);
+ this.b = DerInteger.GetInstance(seq[1]);
+ this.p = DerInteger.GetInstance(seq[2]);
+ this.q = DerInteger.GetInstance(seq[3]);
+ this.x = DerInteger.GetInstance(seq[4]);
+ this.y = DerInteger.GetInstance(seq[5]);
+ }
+
+ public BigInteger P
+ {
+ get { return p.PositiveValue; }
+ }
+
+ public BigInteger Q
+ {
+ get { return q.PositiveValue; }
+ }
+
+ public BigInteger A
+ {
+ get { return a.PositiveValue; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(a, b, p, q, x, y);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cryptopro/GOST28147Parameters.cs b/Crypto/src/asn1/cryptopro/GOST28147Parameters.cs
new file mode 100644
index 000000000..eb7e0e3f6
--- /dev/null
+++ b/Crypto/src/asn1/cryptopro/GOST28147Parameters.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+ public class Gost28147Parameters
+ : Asn1Encodable
+ {
+ private readonly Asn1OctetString iv;
+ private readonly DerObjectIdentifier paramSet;
+
+ public static Gost28147Parameters GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static Gost28147Parameters GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Gost28147Parameters)
+ {
+ return (Gost28147Parameters) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Gost28147Parameters((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+ }
+
+ private Gost28147Parameters(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.iv = Asn1OctetString.GetInstance(seq[0]);
+ this.paramSet = DerObjectIdentifier.GetInstance(seq[1]);
+ }
+
+ /**
+ * <pre>
+ * Gost28147-89-Parameters ::=
+ * SEQUENCE {
+ * iv Gost28147-89-IV,
+ * encryptionParamSet OBJECT IDENTIFIER
+ * }
+ *
+ * Gost28147-89-IV ::= OCTET STRING (SIZE (8))
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(iv, paramSet);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cryptopro/GOST3410NamedParameters.cs b/Crypto/src/asn1/cryptopro/GOST3410NamedParameters.cs
new file mode 100644
index 000000000..66dba51d7
--- /dev/null
+++ b/Crypto/src/asn1/cryptopro/GOST3410NamedParameters.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+ /**
+ * table of the available named parameters for GOST 3410-94.
+ */
+ public sealed class Gost3410NamedParameters
+ {
+ private Gost3410NamedParameters()
+ {
+ }
+
+ private static readonly IDictionary objIds = Platform.CreateHashtable();
+ private static readonly IDictionary parameters = Platform.CreateHashtable();
+
+ private static readonly Gost3410ParamSetParameters cryptoProA = new Gost3410ParamSetParameters(
+ 1024,
+ new BigInteger("127021248288932417465907042777176443525787653508916535812817507265705031260985098497423188333483401180925999995120988934130659205614996724254121049274349357074920312769561451689224110579311248812610229678534638401693520013288995000362260684222750813532307004517341633685004541062586971416883686778842537820383"),
+ new BigInteger("68363196144955700784444165611827252895102170888761442055095051287550314083023"),
+ new BigInteger("100997906755055304772081815535925224869841082572053457874823515875577147990529272777244152852699298796483356699682842027972896052747173175480590485607134746852141928680912561502802222185647539190902656116367847270145019066794290930185446216399730872221732889830323194097355403213400972588322876850946740663962")
+ // validationAlgorithm {
+ // algorithm
+ // id-GostR3410-94-bBis,
+ // parameters
+ // GostR3410-94-ValidationBisParameters: {
+ // x0 1376285941,
+ // c 3996757427
+ // }
+ // }
+
+ );
+
+ private static readonly Gost3410ParamSetParameters cryptoProB = new Gost3410ParamSetParameters(
+ 1024,
+ new BigInteger("139454871199115825601409655107690713107041707059928031797758001454375765357722984094124368522288239833039114681648076688236921220737322672160740747771700911134550432053804647694904686120113087816240740184800477047157336662926249423571248823968542221753660143391485680840520336859458494803187341288580489525163"),
+ new BigInteger("79885141663410976897627118935756323747307951916507639758300472692338873533959"),
+ new BigInteger("42941826148615804143873447737955502392672345968607143066798112994089471231420027060385216699563848719957657284814898909770759462613437669456364882730370838934791080835932647976778601915343474400961034231316672578686920482194932878633360203384797092684342247621055760235016132614780652761028509445403338652341")
+ // validationAlgorithm {
+ // algorithm
+ // id-GostR3410-94-bBis,
+ // parameters
+ // GostR3410-94-ValidationBisParameters: {
+ // x0 1536654555,
+ // c 1855361757,
+ // d 14408629386140014567655
+ //4902939282056547857802241461782996702017713059974755104394739915140
+ //6115284791024439062735788342744854120601660303926203867703556828005
+ //8957203818114895398976594425537561271800850306
+ // }
+ // }
+ //}
+ );
+
+ private static readonly Gost3410ParamSetParameters cryptoProXchA = new Gost3410ParamSetParameters(
+ 1024,
+ new BigInteger("142011741597563481196368286022318089743276138395243738762872573441927459393512718973631166078467600360848946623567625795282774719212241929071046134208380636394084512691828894000571524625445295769349356752728956831541775441763139384457191755096847107846595662547942312293338483924514339614727760681880609734239"),
+ new BigInteger("91771529896554605945588149018382750217296858393520724172743325725474374979801"),
+ new BigInteger("133531813272720673433859519948319001217942375967847486899482359599369642528734712461590403327731821410328012529253871914788598993103310567744136196364803064721377826656898686468463277710150809401182608770201615324990468332931294920912776241137878030224355746606283971659376426832674269780880061631528163475887")
+ );
+
+ static Gost3410NamedParameters()
+ {
+ parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProA] = cryptoProA;
+ parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProB] = cryptoProB;
+ //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProC] = cryptoProC;
+ //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProD] = cryptoProD;
+ parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchA] = cryptoProXchA;
+ //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchB] = cryptoProXchA;
+ //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchC] = cryptoProXchA;
+
+ objIds["GostR3410-94-CryptoPro-A"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProA;
+ objIds["GostR3410-94-CryptoPro-B"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProB;
+ objIds["GostR3410-94-CryptoPro-XchA"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProXchA;
+ }
+
+ /**
+ * return the GOST3410ParamSetParameters object for the given OID, null if it
+ * isn't present.
+ *
+ * @param oid an object identifier representing a named parameters, if present.
+ */
+ public static Gost3410ParamSetParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ return (Gost3410ParamSetParameters) parameters[oid];
+ }
+
+ /**
+ * returns an enumeration containing the name strings for parameters
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(objIds.Keys); }
+ }
+
+ public static Gost3410ParamSetParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name];
+
+ if (oid != null)
+ {
+ return (Gost3410ParamSetParameters) parameters[oid];
+ }
+
+ return null;
+ }
+
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier) objIds[name];
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs b/Crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs
new file mode 100644
index 000000000..f133cdf1b
--- /dev/null
+++ b/Crypto/src/asn1/cryptopro/GOST3410ParamSetParameters.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+ public class Gost3410ParamSetParameters
+ : Asn1Encodable
+ {
+ private readonly int keySize;
+ private readonly DerInteger p, q, a;
+
+ public static Gost3410ParamSetParameters GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static Gost3410ParamSetParameters GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Gost3410ParamSetParameters)
+ {
+ return (Gost3410ParamSetParameters) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Gost3410ParamSetParameters((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+ }
+
+ public Gost3410ParamSetParameters(
+ int keySize,
+ BigInteger p,
+ BigInteger q,
+ BigInteger a)
+ {
+ this.keySize = keySize;
+ this.p = new DerInteger(p);
+ this.q = new DerInteger(q);
+ this.a = new DerInteger(a);
+ }
+
+ private Gost3410ParamSetParameters(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 4)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.keySize = DerInteger.GetInstance(seq[0]).Value.IntValue;
+ this.p = DerInteger.GetInstance(seq[1]);
+ this.q = DerInteger.GetInstance(seq[2]);
+ this.a = DerInteger.GetInstance(seq[3]);
+ }
+
+ public int KeySize
+ {
+ get { return keySize; }
+ }
+
+ public BigInteger P
+ {
+ get { return p.PositiveValue; }
+ }
+
+ public BigInteger Q
+ {
+ get { return q.PositiveValue; }
+ }
+
+ public BigInteger A
+ {
+ get { return a.PositiveValue; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(new DerInteger(keySize), p, q, a);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs b/Crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs
new file mode 100644
index 000000000..8bc1460af
--- /dev/null
+++ b/Crypto/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs
@@ -0,0 +1,99 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+ public class Gost3410PublicKeyAlgParameters
+ : Asn1Encodable
+ {
+ private DerObjectIdentifier publicKeyParamSet;
+ private DerObjectIdentifier digestParamSet;
+ private DerObjectIdentifier encryptionParamSet;
+
+ public static Gost3410PublicKeyAlgParameters GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static Gost3410PublicKeyAlgParameters GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Gost3410PublicKeyAlgParameters)
+ {
+ return (Gost3410PublicKeyAlgParameters) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Gost3410PublicKeyAlgParameters((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+ }
+
+ public Gost3410PublicKeyAlgParameters(
+ DerObjectIdentifier publicKeyParamSet,
+ DerObjectIdentifier digestParamSet)
+ : this (publicKeyParamSet, digestParamSet, null)
+ {
+ }
+
+ public Gost3410PublicKeyAlgParameters(
+ DerObjectIdentifier publicKeyParamSet,
+ DerObjectIdentifier digestParamSet,
+ DerObjectIdentifier encryptionParamSet)
+ {
+ if (publicKeyParamSet == null)
+ throw new ArgumentNullException("publicKeyParamSet");
+ if (digestParamSet == null)
+ throw new ArgumentNullException("digestParamSet");
+
+ this.publicKeyParamSet = publicKeyParamSet;
+ this.digestParamSet = digestParamSet;
+ this.encryptionParamSet = encryptionParamSet;
+ }
+
+ public Gost3410PublicKeyAlgParameters(
+ Asn1Sequence seq)
+ {
+ this.publicKeyParamSet = (DerObjectIdentifier) seq[0];
+ this.digestParamSet = (DerObjectIdentifier) seq[1];
+
+ if (seq.Count > 2)
+ {
+ this.encryptionParamSet = (DerObjectIdentifier) seq[2];
+ }
+ }
+
+ public DerObjectIdentifier PublicKeyParamSet
+ {
+ get { return publicKeyParamSet; }
+ }
+
+ public DerObjectIdentifier DigestParamSet
+ {
+ get { return digestParamSet; }
+ }
+
+ public DerObjectIdentifier EncryptionParamSet
+ {
+ get { return encryptionParamSet; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ publicKeyParamSet, digestParamSet);
+
+ if (encryptionParamSet != null)
+ {
+ v.Add(encryptionParamSet);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/eac/EACObjectIdentifiers.cs b/Crypto/src/asn1/eac/EACObjectIdentifiers.cs
new file mode 100644
index 000000000..d54ef0eba
--- /dev/null
+++ b/Crypto/src/asn1/eac/EACObjectIdentifiers.cs
@@ -0,0 +1,50 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Eac
+{
+ public abstract class EacObjectIdentifiers
+ {
+ // bsi-de OBJECT IDENTIFIER ::= {
+ // itu-t(0) identified-organization(4) etsi(0)
+ // reserved(127) etsi-identified-organization(0) 7
+ // }
+ public static readonly DerObjectIdentifier bsi_de = new DerObjectIdentifier("0.4.0.127.0.7");
+
+ // id-PK OBJECT IDENTIFIER ::= {
+ // bsi-de protocols(2) smartcard(2) 1
+ // }
+ public static readonly DerObjectIdentifier id_PK = new DerObjectIdentifier(bsi_de + ".2.2.1");
+
+ public static readonly DerObjectIdentifier id_PK_DH = new DerObjectIdentifier(id_PK + ".1");
+ public static readonly DerObjectIdentifier id_PK_ECDH = new DerObjectIdentifier(id_PK + ".2");
+
+ // id-CA OBJECT IDENTIFIER ::= {
+ // bsi-de protocols(2) smartcard(2) 3
+ // }
+ public static readonly DerObjectIdentifier id_CA = new DerObjectIdentifier(bsi_de + ".2.2.3");
+ public static readonly DerObjectIdentifier id_CA_DH = new DerObjectIdentifier(id_CA + ".1");
+ public static readonly DerObjectIdentifier id_CA_DH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_DH + ".1");
+ public static readonly DerObjectIdentifier id_CA_ECDH = new DerObjectIdentifier(id_CA + ".2");
+ public static readonly DerObjectIdentifier id_CA_ECDH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_ECDH + ".1");
+
+ //
+ // id-TA OBJECT IDENTIFIER ::= {
+ // bsi-de protocols(2) smartcard(2) 2
+ // }
+ public static readonly DerObjectIdentifier id_TA = new DerObjectIdentifier(bsi_de + ".2.2.2");
+
+ public static readonly DerObjectIdentifier id_TA_RSA = new DerObjectIdentifier(id_TA + ".1");
+ public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".1");
+ public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".2");
+ public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".3");
+ public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".4");
+ public static readonly DerObjectIdentifier id_TA_ECDSA = new DerObjectIdentifier(id_TA + ".2");
+ public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_1 = new DerObjectIdentifier(id_TA_ECDSA + ".1");
+ public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_224 = new DerObjectIdentifier(id_TA_ECDSA + ".2");
+ public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_256 = new DerObjectIdentifier(id_TA_ECDSA + ".3");
+ public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_384 = new DerObjectIdentifier(id_TA_ECDSA + ".4");
+ public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_512 = new DerObjectIdentifier(id_TA_ECDSA + ".5");
+ }
+}
diff --git a/Crypto/src/asn1/esf/CertificateValues.cs b/Crypto/src/asn1/esf/CertificateValues.cs
new file mode 100644
index 000000000..e0fb39b83
--- /dev/null
+++ b/Crypto/src/asn1/esf/CertificateValues.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.3.1 Certificate Values Attribute Definition
+ /// <code>
+ /// CertificateValues ::= SEQUENCE OF Certificate
+ /// </code>
+ /// </remarks>
+ public class CertificateValues
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence certificates;
+
+ public static CertificateValues GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CertificateValues)
+ return (CertificateValues) obj;
+
+ if (obj is Asn1Sequence)
+ return new CertificateValues((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CertificateValues' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private CertificateValues(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+
+ foreach (Asn1Encodable ae in seq)
+ {
+ X509CertificateStructure.GetInstance(ae.ToAsn1Object());
+ }
+
+ this.certificates = seq;
+ }
+
+ public CertificateValues(
+ params X509CertificateStructure[] certificates)
+ {
+ if (certificates == null)
+ throw new ArgumentNullException("certificates");
+
+ this.certificates = new DerSequence(certificates);
+ }
+
+ public CertificateValues(
+ IEnumerable certificates)
+ {
+ if (certificates == null)
+ throw new ArgumentNullException("certificates");
+ if (!CollectionUtilities.CheckElementsAreOfType(certificates, typeof(X509CertificateStructure)))
+ throw new ArgumentException("Must contain only 'X509CertificateStructure' objects", "certificates");
+
+ this.certificates = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(certificates));
+ }
+
+ public X509CertificateStructure[] GetCertificates()
+ {
+ X509CertificateStructure[] result = new X509CertificateStructure[certificates.Count];
+ for (int i = 0; i < certificates.Count; ++i)
+ {
+ result[i] = X509CertificateStructure.GetInstance(certificates[i]);
+ }
+ return result;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return certificates;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CommitmentTypeIdentifier.cs b/Crypto/src/asn1/esf/CommitmentTypeIdentifier.cs
new file mode 100644
index 000000000..65cd45b4a
--- /dev/null
+++ b/Crypto/src/asn1/esf/CommitmentTypeIdentifier.cs
@@ -0,0 +1,17 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ public abstract class CommitmentTypeIdentifier
+ {
+ public static readonly DerObjectIdentifier ProofOfOrigin = PkcsObjectIdentifiers.IdCtiEtsProofOfOrigin;
+ public static readonly DerObjectIdentifier ProofOfReceipt = PkcsObjectIdentifiers.IdCtiEtsProofOfReceipt;
+ public static readonly DerObjectIdentifier ProofOfDelivery = PkcsObjectIdentifiers.IdCtiEtsProofOfDelivery;
+ public static readonly DerObjectIdentifier ProofOfSender = PkcsObjectIdentifiers.IdCtiEtsProofOfSender;
+ public static readonly DerObjectIdentifier ProofOfApproval = PkcsObjectIdentifiers.IdCtiEtsProofOfApproval;
+ public static readonly DerObjectIdentifier ProofOfCreation = PkcsObjectIdentifiers.IdCtiEtsProofOfCreation;
+ }
+}
diff --git a/Crypto/src/asn1/esf/CommitmentTypeIndication.cs b/Crypto/src/asn1/esf/CommitmentTypeIndication.cs
new file mode 100644
index 000000000..8342cbf8d
--- /dev/null
+++ b/Crypto/src/asn1/esf/CommitmentTypeIndication.cs
@@ -0,0 +1,95 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ public class CommitmentTypeIndication
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier commitmentTypeId;
+ private readonly Asn1Sequence commitmentTypeQualifier;
+
+ public static CommitmentTypeIndication GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CommitmentTypeIndication)
+ return (CommitmentTypeIndication) obj;
+
+ if (obj is Asn1Sequence)
+ return new CommitmentTypeIndication((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CommitmentTypeIndication' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ public CommitmentTypeIndication(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.commitmentTypeId = (DerObjectIdentifier) seq[0].ToAsn1Object();
+
+ if (seq.Count > 1)
+ {
+ this.commitmentTypeQualifier = (Asn1Sequence) seq[1].ToAsn1Object();
+ }
+ }
+
+ public CommitmentTypeIndication(
+ DerObjectIdentifier commitmentTypeId)
+ : this(commitmentTypeId, null)
+ {
+ }
+
+ public CommitmentTypeIndication(
+ DerObjectIdentifier commitmentTypeId,
+ Asn1Sequence commitmentTypeQualifier)
+ {
+ if (commitmentTypeId == null)
+ throw new ArgumentNullException("commitmentTypeId");
+
+ this.commitmentTypeId = commitmentTypeId;
+
+ if (commitmentTypeQualifier != null)
+ {
+ this.commitmentTypeQualifier = commitmentTypeQualifier;
+ }
+ }
+
+ public DerObjectIdentifier CommitmentTypeID
+ {
+ get { return commitmentTypeId; }
+ }
+
+ public Asn1Sequence CommitmentTypeQualifier
+ {
+ get { return commitmentTypeQualifier; }
+ }
+
+ /**
+ * <pre>
+ * CommitmentTypeIndication ::= SEQUENCE {
+ * commitmentTypeId CommitmentTypeIdentifier,
+ * commitmentTypeQualifier SEQUENCE SIZE (1..MAX) OF
+ * CommitmentTypeQualifier OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(commitmentTypeId);
+
+ if (commitmentTypeQualifier != null)
+ {
+ v.Add(commitmentTypeQualifier);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CommitmentTypeQualifier.cs b/Crypto/src/asn1/esf/CommitmentTypeQualifier.cs
new file mode 100644
index 000000000..09ff70714
--- /dev/null
+++ b/Crypto/src/asn1/esf/CommitmentTypeQualifier.cs
@@ -0,0 +1,119 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /**
+ * Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126).
+ *
+ * <pre>
+ * CommitmentTypeQualifier ::= SEQUENCE {
+ * commitmentTypeIdentifier CommitmentTypeIdentifier,
+ * qualifier ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
+ * </pre>
+ */
+ public class CommitmentTypeQualifier
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier commitmentTypeIdentifier;
+ private readonly Asn1Object qualifier;
+
+ /**
+ * Creates a new <code>CommitmentTypeQualifier</code> instance.
+ *
+ * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+ */
+ public CommitmentTypeQualifier(
+ DerObjectIdentifier commitmentTypeIdentifier)
+ : this(commitmentTypeIdentifier, null)
+ {
+ }
+
+ /**
+ * Creates a new <code>CommitmentTypeQualifier</code> instance.
+ *
+ * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+ * @param qualifier the qualifier, defined by the above field.
+ */
+ public CommitmentTypeQualifier(
+ DerObjectIdentifier commitmentTypeIdentifier,
+ Asn1Encodable qualifier)
+ {
+ if (commitmentTypeIdentifier == null)
+ throw new ArgumentNullException("commitmentTypeIdentifier");
+
+ this.commitmentTypeIdentifier = commitmentTypeIdentifier;
+
+ if (qualifier != null)
+ {
+ this.qualifier = qualifier.ToAsn1Object();
+ }
+ }
+
+ /**
+ * Creates a new <code>CommitmentTypeQualifier</code> instance.
+ *
+ * @param as <code>CommitmentTypeQualifier</code> structure
+ * encoded as an Asn1Sequence.
+ */
+ public CommitmentTypeQualifier(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ commitmentTypeIdentifier = (DerObjectIdentifier) seq[0].ToAsn1Object();
+
+ if (seq.Count > 1)
+ {
+ qualifier = seq[1].ToAsn1Object();
+ }
+ }
+
+ public static CommitmentTypeQualifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CommitmentTypeQualifier)
+ return (CommitmentTypeQualifier) obj;
+
+ if (obj is Asn1Sequence)
+ return new CommitmentTypeQualifier((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CommitmentTypeQualifier' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ public DerObjectIdentifier CommitmentTypeIdentifier
+ {
+ get { return commitmentTypeIdentifier; }
+ }
+
+ public Asn1Object Qualifier
+ {
+ get { return qualifier; }
+ }
+
+ /**
+ * Returns a DER-encodable representation of this instance.
+ *
+ * @return a <code>Asn1Object</code> value
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ commitmentTypeIdentifier);
+
+ if (qualifier != null)
+ {
+ v.Add(qualifier);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CompleteCertificateRefs.cs b/Crypto/src/asn1/esf/CompleteCertificateRefs.cs
new file mode 100644
index 000000000..7f1c835c9
--- /dev/null
+++ b/Crypto/src/asn1/esf/CompleteCertificateRefs.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.1 Complete Certificate Refs Attribute Definition
+ /// <code>
+ /// CompleteCertificateRefs ::= SEQUENCE OF OtherCertID
+ /// </code>
+ /// </remarks>
+ public class CompleteCertificateRefs
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence otherCertIDs;
+
+ public static CompleteCertificateRefs GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CompleteCertificateRefs)
+ return (CompleteCertificateRefs) obj;
+
+ if (obj is Asn1Sequence)
+ return new CompleteCertificateRefs((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CompleteCertificateRefs' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private CompleteCertificateRefs(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+
+ foreach (Asn1Encodable ae in seq)
+ {
+ OtherCertID.GetInstance(ae.ToAsn1Object());
+ }
+
+ this.otherCertIDs = seq;
+ }
+
+ public CompleteCertificateRefs(
+ params OtherCertID[] otherCertIDs)
+ {
+ if (otherCertIDs == null)
+ throw new ArgumentNullException("otherCertIDs");
+
+ this.otherCertIDs = new DerSequence(otherCertIDs);
+ }
+
+ public CompleteCertificateRefs(
+ IEnumerable otherCertIDs)
+ {
+ if (otherCertIDs == null)
+ throw new ArgumentNullException("otherCertIDs");
+ if (!CollectionUtilities.CheckElementsAreOfType(otherCertIDs, typeof(OtherCertID)))
+ throw new ArgumentException("Must contain only 'OtherCertID' objects", "otherCertIDs");
+
+ this.otherCertIDs = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(otherCertIDs));
+ }
+
+ public OtherCertID[] GetOtherCertIDs()
+ {
+ OtherCertID[] result = new OtherCertID[otherCertIDs.Count];
+ for (int i = 0; i < otherCertIDs.Count; ++i)
+ {
+ result[i] = OtherCertID.GetInstance(otherCertIDs[i].ToAsn1Object());
+ }
+ return result;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return otherCertIDs;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CompleteRevocationRefs.cs b/Crypto/src/asn1/esf/CompleteRevocationRefs.cs
new file mode 100644
index 000000000..4e1fb403d
--- /dev/null
+++ b/Crypto/src/asn1/esf/CompleteRevocationRefs.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef
+ /// </code>
+ /// </remarks>
+ public class CompleteRevocationRefs
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence crlOcspRefs;
+
+ public static CompleteRevocationRefs GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CompleteRevocationRefs)
+ return (CompleteRevocationRefs) obj;
+
+ if (obj is Asn1Sequence)
+ return new CompleteRevocationRefs((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CompleteRevocationRefs' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private CompleteRevocationRefs(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+
+ foreach (Asn1Encodable ae in seq)
+ {
+ CrlOcspRef.GetInstance(ae.ToAsn1Object());
+ }
+
+ this.crlOcspRefs = seq;
+ }
+
+ public CompleteRevocationRefs(
+ params CrlOcspRef[] crlOcspRefs)
+ {
+ if (crlOcspRefs == null)
+ throw new ArgumentNullException("crlOcspRefs");
+
+ this.crlOcspRefs = new DerSequence(crlOcspRefs);
+ }
+
+ public CompleteRevocationRefs(
+ IEnumerable crlOcspRefs)
+ {
+ if (crlOcspRefs == null)
+ throw new ArgumentNullException("crlOcspRefs");
+ if (!CollectionUtilities.CheckElementsAreOfType(crlOcspRefs, typeof(CrlOcspRef)))
+ throw new ArgumentException("Must contain only 'CrlOcspRef' objects", "crlOcspRefs");
+
+ this.crlOcspRefs = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(crlOcspRefs));
+ }
+
+ public CrlOcspRef[] GetCrlOcspRefs()
+ {
+ CrlOcspRef[] result = new CrlOcspRef[crlOcspRefs.Count];
+ for (int i = 0; i < crlOcspRefs.Count; ++i)
+ {
+ result[i] = CrlOcspRef.GetInstance(crlOcspRefs[i].ToAsn1Object());
+ }
+ return result;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return crlOcspRefs;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CrlIdentifier.cs b/Crypto/src/asn1/esf/CrlIdentifier.cs
new file mode 100644
index 000000000..dfff7d838
--- /dev/null
+++ b/Crypto/src/asn1/esf/CrlIdentifier.cs
@@ -0,0 +1,110 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// CrlIdentifier ::= SEQUENCE
+ /// {
+ /// crlissuer Name,
+ /// crlIssuedTime UTCTime,
+ /// crlNumber INTEGER OPTIONAL
+ /// }
+ /// </code>
+ /// </remarks>
+ public class CrlIdentifier
+ : Asn1Encodable
+ {
+ private readonly X509Name crlIssuer;
+ private readonly DerUtcTime crlIssuedTime;
+ private readonly DerInteger crlNumber;
+
+ public static CrlIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CrlIdentifier)
+ return (CrlIdentifier) obj;
+
+ if (obj is Asn1Sequence)
+ return new CrlIdentifier((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CrlIdentifier' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private CrlIdentifier(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 2 || seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.crlIssuer = X509Name.GetInstance(seq[0]);
+ this.crlIssuedTime = DerUtcTime.GetInstance(seq[1]);
+
+ if (seq.Count > 2)
+ {
+ this.crlNumber = DerInteger.GetInstance(seq[2]);
+ }
+ }
+
+ public CrlIdentifier(
+ X509Name crlIssuer,
+ DateTime crlIssuedTime)
+ : this(crlIssuer, crlIssuedTime, null)
+ {
+ }
+
+ public CrlIdentifier(
+ X509Name crlIssuer,
+ DateTime crlIssuedTime,
+ BigInteger crlNumber)
+ {
+ if (crlIssuer == null)
+ throw new ArgumentNullException("crlIssuer");
+
+ this.crlIssuer = crlIssuer;
+ this.crlIssuedTime = new DerUtcTime(crlIssuedTime);
+
+ if (crlNumber != null)
+ {
+ this.crlNumber = new DerInteger(crlNumber);
+ }
+ }
+
+ public X509Name CrlIssuer
+ {
+ get { return crlIssuer; }
+ }
+
+ public DateTime CrlIssuedTime
+ {
+ get { return crlIssuedTime.ToAdjustedDateTime(); }
+ }
+
+ public BigInteger CrlNumber
+ {
+ get { return crlNumber == null ? null : crlNumber.Value; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ crlIssuer.ToAsn1Object(), crlIssuedTime);
+
+ if (crlNumber != null)
+ {
+ v.Add(crlNumber);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CrlListID.cs b/Crypto/src/asn1/esf/CrlListID.cs
new file mode 100644
index 000000000..2aae9b965
--- /dev/null
+++ b/Crypto/src/asn1/esf/CrlListID.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// CRLListID ::= SEQUENCE
+ /// {
+ /// crls SEQUENCE OF CrlValidatedID
+ /// }
+ /// </code>
+ /// </remarks>
+ public class CrlListID
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence crls;
+
+ public static CrlListID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CrlListID)
+ return (CrlListID) obj;
+
+ if (obj is Asn1Sequence)
+ return new CrlListID((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CrlListID' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private CrlListID(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count != 1)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.crls = (Asn1Sequence) seq[0].ToAsn1Object();
+
+ foreach (Asn1Encodable ae in this.crls)
+ {
+ CrlValidatedID.GetInstance(ae.ToAsn1Object());
+ }
+ }
+
+ public CrlListID(
+ params CrlValidatedID[] crls)
+ {
+ if (crls == null)
+ throw new ArgumentNullException("crls");
+
+ this.crls = new DerSequence(crls);
+ }
+
+ public CrlListID(
+ IEnumerable crls)
+ {
+ if (crls == null)
+ throw new ArgumentNullException("crls");
+ if (!CollectionUtilities.CheckElementsAreOfType(crls, typeof(CrlValidatedID)))
+ throw new ArgumentException("Must contain only 'CrlValidatedID' objects", "crls");
+
+ this.crls = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(crls));
+ }
+
+ public CrlValidatedID[] GetCrls()
+ {
+ CrlValidatedID[] result = new CrlValidatedID[crls.Count];
+ for (int i = 0; i < crls.Count; ++i)
+ {
+ result[i] = CrlValidatedID.GetInstance(crls[i].ToAsn1Object());
+ }
+ return result;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(crls);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CrlOcspRef.cs b/Crypto/src/asn1/esf/CrlOcspRef.cs
new file mode 100644
index 000000000..c8e10d504
--- /dev/null
+++ b/Crypto/src/asn1/esf/CrlOcspRef.cs
@@ -0,0 +1,111 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// CrlOcspRef ::= SEQUENCE {
+ /// crlids [0] CRLListID OPTIONAL,
+ /// ocspids [1] OcspListID OPTIONAL,
+ /// otherRev [2] OtherRevRefs OPTIONAL
+ /// }
+ /// </code>
+ /// </remarks>
+ public class CrlOcspRef
+ : Asn1Encodable
+ {
+ private readonly CrlListID crlids;
+ private readonly OcspListID ocspids;
+ private readonly OtherRevRefs otherRev;
+
+ public static CrlOcspRef GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CrlOcspRef)
+ return (CrlOcspRef) obj;
+
+ if (obj is Asn1Sequence)
+ return new CrlOcspRef((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CrlOcspRef' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private CrlOcspRef(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+
+ foreach (Asn1TaggedObject taggedObj in seq)
+ {
+ Asn1Object asn1Obj = taggedObj.GetObject();
+
+ switch (taggedObj.TagNo)
+ {
+ case 0:
+ this.crlids = CrlListID.GetInstance(asn1Obj);
+ break;
+ case 1:
+ this.ocspids = OcspListID.GetInstance(asn1Obj);
+ break;
+ case 2:
+ this.otherRev = OtherRevRefs.GetInstance(asn1Obj);
+ break;
+ default:
+ throw new ArgumentException("Illegal tag in CrlOcspRef", "seq");
+ }
+ }
+ }
+
+ public CrlOcspRef(
+ CrlListID crlids,
+ OcspListID ocspids,
+ OtherRevRefs otherRev)
+ {
+ this.crlids = crlids;
+ this.ocspids = ocspids;
+ this.otherRev = otherRev;
+ }
+
+ public CrlListID CrlIDs
+ {
+ get { return crlids; }
+ }
+
+ public OcspListID OcspIDs
+ {
+ get { return ocspids; }
+ }
+
+ public OtherRevRefs OtherRev
+ {
+ get { return otherRev; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (crlids != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, crlids.ToAsn1Object()));
+ }
+
+ if (ocspids != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, ocspids.ToAsn1Object()));
+ }
+
+ if (otherRev != null)
+ {
+ v.Add(new DerTaggedObject(true, 2, otherRev.ToAsn1Object()));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/CrlValidatedID.cs b/Crypto/src/asn1/esf/CrlValidatedID.cs
new file mode 100644
index 000000000..165f547a8
--- /dev/null
+++ b/Crypto/src/asn1/esf/CrlValidatedID.cs
@@ -0,0 +1,89 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// CrlValidatedID ::= SEQUENCE {
+ /// crlHash OtherHash,
+ /// crlIdentifier CrlIdentifier OPTIONAL}
+ /// </code>
+ /// </remarks>
+ public class CrlValidatedID
+ : Asn1Encodable
+ {
+ private readonly OtherHash crlHash;
+ private readonly CrlIdentifier crlIdentifier;
+
+ public static CrlValidatedID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CrlValidatedID)
+ return (CrlValidatedID) obj;
+
+ if (obj is Asn1Sequence)
+ return new CrlValidatedID((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'CrlValidatedID' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private CrlValidatedID(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.crlHash = OtherHash.GetInstance(seq[0].ToAsn1Object());
+
+ if (seq.Count > 1)
+ {
+ this.crlIdentifier = CrlIdentifier.GetInstance(seq[1].ToAsn1Object());
+ }
+ }
+
+ public CrlValidatedID(
+ OtherHash crlHash)
+ : this(crlHash, null)
+ {
+ }
+
+ public CrlValidatedID(
+ OtherHash crlHash,
+ CrlIdentifier crlIdentifier)
+ {
+ if (crlHash == null)
+ throw new ArgumentNullException("crlHash");
+
+ this.crlHash = crlHash;
+ this.crlIdentifier = crlIdentifier;
+ }
+
+ public OtherHash CrlHash
+ {
+ get { return crlHash; }
+ }
+
+ public CrlIdentifier CrlIdentifier
+ {
+ get { return crlIdentifier; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(crlHash.ToAsn1Object());
+
+ if (crlIdentifier != null)
+ {
+ v.Add(crlIdentifier.ToAsn1Object());
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/ESFAttributes.cs b/Crypto/src/asn1/esf/ESFAttributes.cs
new file mode 100644
index 000000000..9401ffb8e
--- /dev/null
+++ b/Crypto/src/asn1/esf/ESFAttributes.cs
@@ -0,0 +1,25 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ public abstract class EsfAttributes
+ {
+ public static readonly DerObjectIdentifier SigPolicyId = PkcsObjectIdentifiers.IdAAEtsSigPolicyID;
+ public static readonly DerObjectIdentifier CommitmentType = PkcsObjectIdentifiers.IdAAEtsCommitmentType;
+ public static readonly DerObjectIdentifier SignerLocation = PkcsObjectIdentifiers.IdAAEtsSignerLocation;
+ public static readonly DerObjectIdentifier SignerAttr = PkcsObjectIdentifiers.IdAAEtsSignerAttr;
+ public static readonly DerObjectIdentifier OtherSigCert = PkcsObjectIdentifiers.IdAAEtsOtherSigCert;
+ public static readonly DerObjectIdentifier ContentTimestamp = PkcsObjectIdentifiers.IdAAEtsContentTimestamp;
+ public static readonly DerObjectIdentifier CertificateRefs = PkcsObjectIdentifiers.IdAAEtsCertificateRefs;
+ public static readonly DerObjectIdentifier RevocationRefs = PkcsObjectIdentifiers.IdAAEtsRevocationRefs;
+ public static readonly DerObjectIdentifier CertValues = PkcsObjectIdentifiers.IdAAEtsCertValues;
+ public static readonly DerObjectIdentifier RevocationValues = PkcsObjectIdentifiers.IdAAEtsRevocationValues;
+ public static readonly DerObjectIdentifier EscTimeStamp = PkcsObjectIdentifiers.IdAAEtsEscTimeStamp;
+ public static readonly DerObjectIdentifier CertCrlTimestamp = PkcsObjectIdentifiers.IdAAEtsCertCrlTimestamp;
+ public static readonly DerObjectIdentifier ArchiveTimestamp = PkcsObjectIdentifiers.IdAAEtsArchiveTimestamp;
+ public static readonly DerObjectIdentifier ArchiveTimestampV2 = new DerObjectIdentifier(PkcsObjectIdentifiers.IdAA + ".48");
+ }
+}
diff --git a/Crypto/src/asn1/esf/OcspIdentifier.cs b/Crypto/src/asn1/esf/OcspIdentifier.cs
new file mode 100644
index 000000000..949b68243
--- /dev/null
+++ b/Crypto/src/asn1/esf/OcspIdentifier.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Ocsp;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// OcspIdentifier ::= SEQUENCE {
+ /// ocspResponderID ResponderID,
+ /// -- As in OCSP response data
+ /// producedAt GeneralizedTime
+ /// -- As in OCSP response data
+ /// }
+ /// </code>
+ /// </remarks>
+ public class OcspIdentifier
+ : Asn1Encodable
+ {
+ private readonly ResponderID ocspResponderID;
+ private readonly DerGeneralizedTime producedAt;
+
+ public static OcspIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OcspIdentifier)
+ return (OcspIdentifier) obj;
+
+ if (obj is Asn1Sequence)
+ return new OcspIdentifier((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OcspIdentifier' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OcspIdentifier(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.ocspResponderID = ResponderID.GetInstance(seq[0].ToAsn1Object());
+ this.producedAt = (DerGeneralizedTime) seq[1].ToAsn1Object();
+ }
+
+ public OcspIdentifier(
+ ResponderID ocspResponderID,
+ DateTime producedAt)
+ {
+ if (ocspResponderID == null)
+ throw new ArgumentNullException();
+
+ this.ocspResponderID = ocspResponderID;
+ this.producedAt = new DerGeneralizedTime(producedAt);
+ }
+
+ public ResponderID OcspResponderID
+ {
+ get { return ocspResponderID; }
+ }
+
+ public DateTime ProducedAt
+ {
+ get { return producedAt.ToDateTime(); }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(ocspResponderID, producedAt);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/OcspListID.cs b/Crypto/src/asn1/esf/OcspListID.cs
new file mode 100644
index 000000000..1f3f3a337
--- /dev/null
+++ b/Crypto/src/asn1/esf/OcspListID.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// OcspListID ::= SEQUENCE {
+ /// ocspResponses SEQUENCE OF OcspResponsesID
+ /// }
+ /// </code>
+ /// </remarks>
+ public class OcspListID
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence ocspResponses;
+
+ public static OcspListID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OcspListID)
+ return (OcspListID) obj;
+
+ if (obj is Asn1Sequence)
+ return new OcspListID((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OcspListID' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OcspListID(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count != 1)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.ocspResponses = (Asn1Sequence) seq[0].ToAsn1Object();
+
+ foreach (Asn1Encodable ae in this.ocspResponses)
+ {
+ OcspResponsesID.GetInstance(ae.ToAsn1Object());
+ }
+ }
+
+ public OcspListID(
+ params OcspResponsesID[] ocspResponses)
+ {
+ if (ocspResponses == null)
+ throw new ArgumentNullException("ocspResponses");
+
+ this.ocspResponses = new DerSequence(ocspResponses);
+ }
+
+ public OcspListID(
+ IEnumerable ocspResponses)
+ {
+ if (ocspResponses == null)
+ throw new ArgumentNullException("ocspResponses");
+ if (!CollectionUtilities.CheckElementsAreOfType(ocspResponses, typeof(OcspResponsesID)))
+ throw new ArgumentException("Must contain only 'OcspResponsesID' objects", "ocspResponses");
+
+ this.ocspResponses = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(ocspResponses));
+ }
+
+ public OcspResponsesID[] GetOcspResponses()
+ {
+ OcspResponsesID[] result = new OcspResponsesID[ocspResponses.Count];
+ for (int i = 0; i < ocspResponses.Count; ++i)
+ {
+ result[i] = OcspResponsesID.GetInstance(ocspResponses[i].ToAsn1Object());
+ }
+ return result;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(ocspResponses);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/OcspResponsesID.cs b/Crypto/src/asn1/esf/OcspResponsesID.cs
new file mode 100644
index 000000000..e09508a01
--- /dev/null
+++ b/Crypto/src/asn1/esf/OcspResponsesID.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// OcspResponsesID ::= SEQUENCE {
+ /// ocspIdentifier OcspIdentifier,
+ /// ocspRepHash OtherHash OPTIONAL
+ /// }
+ /// </code>
+ /// </remarks>
+ public class OcspResponsesID
+ : Asn1Encodable
+ {
+ private readonly OcspIdentifier ocspIdentifier;
+ private readonly OtherHash ocspRepHash;
+
+ public static OcspResponsesID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OcspResponsesID)
+ return (OcspResponsesID) obj;
+
+ if (obj is Asn1Sequence)
+ return new OcspResponsesID((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OcspResponsesID' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OcspResponsesID(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.ocspIdentifier = OcspIdentifier.GetInstance(seq[0].ToAsn1Object());
+
+ if (seq.Count > 1)
+ {
+ this.ocspRepHash = OtherHash.GetInstance(seq[1].ToAsn1Object());
+ }
+ }
+
+ public OcspResponsesID(
+ OcspIdentifier ocspIdentifier)
+ : this(ocspIdentifier, null)
+ {
+ }
+
+ public OcspResponsesID(
+ OcspIdentifier ocspIdentifier,
+ OtherHash ocspRepHash)
+ {
+ if (ocspIdentifier == null)
+ throw new ArgumentNullException("ocspIdentifier");
+
+ this.ocspIdentifier = ocspIdentifier;
+ this.ocspRepHash = ocspRepHash;
+ }
+
+ public OcspIdentifier OcspIdentifier
+ {
+ get { return ocspIdentifier; }
+ }
+
+ public OtherHash OcspRepHash
+ {
+ get { return ocspRepHash; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ ocspIdentifier.ToAsn1Object());
+
+ if (ocspRepHash != null)
+ {
+ v.Add(ocspRepHash.ToAsn1Object());
+ }
+
+ return new DerSequence(v);
+ }
+
+ }
+}
diff --git a/Crypto/src/asn1/esf/OtherCertID.cs b/Crypto/src/asn1/esf/OtherCertID.cs
new file mode 100644
index 000000000..6d1255535
--- /dev/null
+++ b/Crypto/src/asn1/esf/OtherCertID.cs
@@ -0,0 +1,93 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// <code>
+ /// OtherCertID ::= SEQUENCE {
+ /// otherCertHash OtherHash,
+ /// issuerSerial IssuerSerial OPTIONAL
+ /// }
+ /// </code>
+ /// </remarks>
+ public class OtherCertID
+ : Asn1Encodable
+ {
+ private readonly OtherHash otherCertHash;
+ private readonly IssuerSerial issuerSerial;
+
+ public static OtherCertID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherCertID)
+ return (OtherCertID) obj;
+
+ if (obj is Asn1Sequence)
+ return new OtherCertID((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OtherCertID' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OtherCertID(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.otherCertHash = OtherHash.GetInstance(seq[0].ToAsn1Object());
+
+ if (seq.Count > 1)
+ {
+ this.issuerSerial = IssuerSerial.GetInstance(seq[1].ToAsn1Object());
+ }
+ }
+
+ public OtherCertID(
+ OtherHash otherCertHash)
+ : this(otherCertHash, null)
+ {
+ }
+
+ public OtherCertID(
+ OtherHash otherCertHash,
+ IssuerSerial issuerSerial)
+ {
+ if (otherCertHash == null)
+ throw new ArgumentNullException("otherCertHash");
+
+ this.otherCertHash = otherCertHash;
+ this.issuerSerial = issuerSerial;
+ }
+
+ public OtherHash OtherCertHash
+ {
+ get { return otherCertHash; }
+ }
+
+ public IssuerSerial IssuerSerial
+ {
+ get { return issuerSerial; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ otherCertHash.ToAsn1Object());
+
+ if (issuerSerial != null)
+ {
+ v.Add(issuerSerial.ToAsn1Object());
+ }
+
+ return new DerSequence(v);
+ }
+
+ }
+}
diff --git a/Crypto/src/asn1/esf/OtherHash.cs b/Crypto/src/asn1/esf/OtherHash.cs
new file mode 100644
index 000000000..2ee162478
--- /dev/null
+++ b/Crypto/src/asn1/esf/OtherHash.cs
@@ -0,0 +1,88 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// <code>
+ /// OtherHash ::= CHOICE {
+ /// sha1Hash OtherHashValue, -- This contains a SHA-1 hash
+ /// otherHash OtherHashAlgAndValue
+ /// }
+ ///
+ /// OtherHashValue ::= OCTET STRING
+ /// </code>
+ /// </remarks>
+ public class OtherHash
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly Asn1OctetString sha1Hash;
+ private readonly OtherHashAlgAndValue otherHash;
+
+ public static OtherHash GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherHash)
+ return (OtherHash) obj;
+
+ if (obj is Asn1OctetString)
+ return new OtherHash((Asn1OctetString) obj);
+
+ return new OtherHash(
+ OtherHashAlgAndValue.GetInstance(obj));
+ }
+
+ public OtherHash(
+ byte[] sha1Hash)
+ {
+ if (sha1Hash == null)
+ throw new ArgumentNullException("sha1Hash");
+
+ this.sha1Hash = new DerOctetString(sha1Hash);
+ }
+
+ public OtherHash(
+ Asn1OctetString sha1Hash)
+ {
+ if (sha1Hash == null)
+ throw new ArgumentNullException("sha1Hash");
+
+ this.sha1Hash = sha1Hash;
+ }
+
+ public OtherHash(
+ OtherHashAlgAndValue otherHash)
+ {
+ if (otherHash == null)
+ throw new ArgumentNullException("otherHash");
+
+ this.otherHash = otherHash;
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get
+ {
+ return otherHash == null
+ ? new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1)
+ : otherHash.HashAlgorithm;
+ }
+ }
+
+ public byte[] GetHashValue()
+ {
+ return otherHash == null
+ ? sha1Hash.GetOctets()
+ : otherHash.GetHashValue();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return otherHash == null
+ ? sha1Hash
+ : otherHash.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/OtherHashAlgAndValue.cs b/Crypto/src/asn1/esf/OtherHashAlgAndValue.cs
new file mode 100644
index 000000000..b6bd4f498
--- /dev/null
+++ b/Crypto/src/asn1/esf/OtherHashAlgAndValue.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <summary>
+ /// Summary description for OtherHashAlgAndValue.
+ /// </summary>
+ /// <remarks>
+ /// <code>
+ /// OtherHashAlgAndValue ::= SEQUENCE {
+ /// hashAlgorithm AlgorithmIdentifier,
+ /// hashValue OtherHashValue
+ /// }
+ ///
+ /// OtherHashValue ::= OCTET STRING
+ /// </code>
+ /// </remarks>
+ public class OtherHashAlgAndValue
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlgorithm;
+ private readonly Asn1OctetString hashValue;
+
+ public static OtherHashAlgAndValue GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherHashAlgAndValue)
+ return (OtherHashAlgAndValue) obj;
+
+ if (obj is Asn1Sequence)
+ return new OtherHashAlgAndValue((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OtherHashAlgAndValue' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OtherHashAlgAndValue(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0].ToAsn1Object());
+ this.hashValue = (Asn1OctetString) seq[1].ToAsn1Object();
+ }
+
+ public OtherHashAlgAndValue(
+ AlgorithmIdentifier hashAlgorithm,
+ byte[] hashValue)
+ {
+ if (hashAlgorithm == null)
+ throw new ArgumentNullException("hashAlgorithm");
+ if (hashValue == null)
+ throw new ArgumentNullException("hashValue");
+
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashValue = new DerOctetString(hashValue);
+ }
+
+ public OtherHashAlgAndValue(
+ AlgorithmIdentifier hashAlgorithm,
+ Asn1OctetString hashValue)
+ {
+ if (hashAlgorithm == null)
+ throw new ArgumentNullException("hashAlgorithm");
+ if (hashValue == null)
+ throw new ArgumentNullException("hashValue");
+
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashValue = hashValue;
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return hashAlgorithm; }
+ }
+
+ public byte[] GetHashValue()
+ {
+ return hashValue.GetOctets();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(hashAlgorithm, hashValue);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/OtherRevRefs.cs b/Crypto/src/asn1/esf/OtherRevRefs.cs
new file mode 100644
index 000000000..56713e3f2
--- /dev/null
+++ b/Crypto/src/asn1/esf/OtherRevRefs.cs
@@ -0,0 +1,78 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+ /// <code>
+ /// OtherRevRefs ::= SEQUENCE
+ /// {
+ /// otherRevRefType OtherRevRefType,
+ /// otherRevRefs ANY DEFINED BY otherRevRefType
+ /// }
+ ///
+ /// OtherRevRefType ::= OBJECT IDENTIFIER
+ /// </code>
+ /// </remarks>
+ public class OtherRevRefs
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier otherRevRefType;
+ private readonly Asn1Object otherRevRefs;
+
+ public static OtherRevRefs GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherRevRefs)
+ return (OtherRevRefs) obj;
+
+ if (obj is Asn1Sequence)
+ return new OtherRevRefs((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OtherRevRefs' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OtherRevRefs(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.otherRevRefType = (DerObjectIdentifier) seq[0].ToAsn1Object();
+ this.otherRevRefs = seq[1].ToAsn1Object();
+ }
+
+ public OtherRevRefs(
+ DerObjectIdentifier otherRevRefType,
+ Asn1Encodable otherRevRefs)
+ {
+ if (otherRevRefType == null)
+ throw new ArgumentNullException("otherRevRefType");
+ if (otherRevRefs == null)
+ throw new ArgumentNullException("otherRevRefs");
+
+ this.otherRevRefType = otherRevRefType;
+ this.otherRevRefs = otherRevRefs.ToAsn1Object();
+ }
+
+ public DerObjectIdentifier OtherRevRefType
+ {
+ get { return otherRevRefType; }
+ }
+
+ public Asn1Object OtherRevRefsObject
+ {
+ get { return otherRevRefs; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(otherRevRefType, otherRevRefs);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/OtherRevVals.cs b/Crypto/src/asn1/esf/OtherRevVals.cs
new file mode 100644
index 000000000..b88a1a72a
--- /dev/null
+++ b/Crypto/src/asn1/esf/OtherRevVals.cs
@@ -0,0 +1,78 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 3126: 4.3.2 Revocation Values Attribute Definition
+ /// <code>
+ /// OtherRevVals ::= SEQUENCE
+ /// {
+ /// otherRevValType OtherRevValType,
+ /// otherRevVals ANY DEFINED BY otherRevValType
+ /// }
+ ///
+ /// OtherRevValType ::= OBJECT IDENTIFIER
+ /// </code>
+ /// </remarks>
+ public class OtherRevVals
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier otherRevValType;
+ private readonly Asn1Object otherRevVals;
+
+ public static OtherRevVals GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherRevVals)
+ return (OtherRevVals) obj;
+
+ if (obj is Asn1Sequence)
+ return new OtherRevVals((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OtherRevVals' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OtherRevVals(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.otherRevValType = (DerObjectIdentifier) seq[0].ToAsn1Object();
+ this.otherRevVals = seq[1].ToAsn1Object();
+ }
+
+ public OtherRevVals(
+ DerObjectIdentifier otherRevValType,
+ Asn1Encodable otherRevVals)
+ {
+ if (otherRevValType == null)
+ throw new ArgumentNullException("otherRevValType");
+ if (otherRevVals == null)
+ throw new ArgumentNullException("otherRevVals");
+
+ this.otherRevValType = otherRevValType;
+ this.otherRevVals = otherRevVals.ToAsn1Object();
+ }
+
+ public DerObjectIdentifier OtherRevValType
+ {
+ get { return otherRevValType; }
+ }
+
+ public Asn1Object OtherRevValsObject
+ {
+ get { return otherRevVals; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(otherRevValType, otherRevVals);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/OtherSigningCertificate.cs b/Crypto/src/asn1/esf/OtherSigningCertificate.cs
new file mode 100644
index 000000000..90e385a33
--- /dev/null
+++ b/Crypto/src/asn1/esf/OtherSigningCertificate.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// <code>
+ /// OtherSigningCertificate ::= SEQUENCE {
+ /// certs SEQUENCE OF OtherCertID,
+ /// policies SEQUENCE OF PolicyInformation OPTIONAL
+ /// }
+ /// </code>
+ /// </remarks>
+ public class OtherSigningCertificate
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence certs;
+ private readonly Asn1Sequence policies;
+
+ public static OtherSigningCertificate GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OtherSigningCertificate)
+ return (OtherSigningCertificate) obj;
+
+ if (obj is Asn1Sequence)
+ return new OtherSigningCertificate((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'OtherSigningCertificate' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private OtherSigningCertificate(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.certs = Asn1Sequence.GetInstance(seq[0].ToAsn1Object());
+
+ if (seq.Count > 1)
+ {
+ this.policies = Asn1Sequence.GetInstance(seq[1].ToAsn1Object());
+ }
+ }
+
+ public OtherSigningCertificate(
+ params OtherCertID[] certs)
+ : this(certs, null)
+ {
+ }
+
+ public OtherSigningCertificate(
+ OtherCertID[] certs,
+ params PolicyInformation[] policies)
+ {
+ if (certs == null)
+ throw new ArgumentNullException("certs");
+
+ this.certs = new DerSequence(certs);
+
+ if (policies != null)
+ {
+ this.policies = new DerSequence(policies);
+ }
+ }
+
+ public OtherSigningCertificate(
+ IEnumerable certs)
+ : this(certs, null)
+ {
+ }
+
+ public OtherSigningCertificate(
+ IEnumerable certs,
+ IEnumerable policies)
+ {
+ if (certs == null)
+ throw new ArgumentNullException("certs");
+ if (!CollectionUtilities.CheckElementsAreOfType(certs, typeof(OtherCertID)))
+ throw new ArgumentException("Must contain only 'OtherCertID' objects", "certs");
+
+ this.certs = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(certs));
+
+ if (policies != null)
+ {
+ if (!CollectionUtilities.CheckElementsAreOfType(policies, typeof(PolicyInformation)))
+ throw new ArgumentException("Must contain only 'PolicyInformation' objects", "policies");
+
+ this.policies = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(policies));
+ }
+ }
+
+ public OtherCertID[] GetCerts()
+ {
+ OtherCertID[] cs = new OtherCertID[certs.Count];
+ for (int i = 0; i < certs.Count; ++i)
+ {
+ cs[i] = OtherCertID.GetInstance(certs[i].ToAsn1Object());
+ }
+ return cs;
+ }
+
+ public PolicyInformation[] GetPolicies()
+ {
+ if (policies == null)
+ return null;
+
+ PolicyInformation[] ps = new PolicyInformation[policies.Count];
+ for (int i = 0; i < policies.Count; ++i)
+ {
+ ps[i] = PolicyInformation.GetInstance(policies[i].ToAsn1Object());
+ }
+ return ps;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+ if (policies != null)
+ {
+ v.Add(policies);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/RevocationValues.cs b/Crypto/src/asn1/esf/RevocationValues.cs
new file mode 100644
index 000000000..a7b47b47a
--- /dev/null
+++ b/Crypto/src/asn1/esf/RevocationValues.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// RFC 5126: 6.3.4. revocation-values Attribute Definition
+ /// <code>
+ /// RevocationValues ::= SEQUENCE {
+ /// crlVals [0] SEQUENCE OF CertificateList OPTIONAL,
+ /// ocspVals [1] SEQUENCE OF BasicOCSPResponse OPTIONAL,
+ /// otherRevVals [2] OtherRevVals OPTIONAL
+ /// }
+ /// </code>
+ /// </remarks>
+ public class RevocationValues
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence crlVals;
+ private readonly Asn1Sequence ocspVals;
+ private readonly OtherRevVals otherRevVals;
+
+ public static RevocationValues GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RevocationValues)
+ return (RevocationValues) obj;
+
+ return new RevocationValues(Asn1Sequence.GetInstance(obj));
+ }
+
+ private RevocationValues(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ foreach (Asn1TaggedObject taggedObj in seq)
+ {
+ Asn1Object asn1Obj = taggedObj.GetObject();
+ switch (taggedObj.TagNo)
+ {
+ case 0:
+ Asn1Sequence crlValsSeq = (Asn1Sequence) asn1Obj;
+ foreach (Asn1Encodable ae in crlValsSeq)
+ {
+ CertificateList.GetInstance(ae.ToAsn1Object());
+ }
+ this.crlVals = crlValsSeq;
+ break;
+ case 1:
+ Asn1Sequence ocspValsSeq = (Asn1Sequence) asn1Obj;
+ foreach (Asn1Encodable ae in ocspValsSeq)
+ {
+ BasicOcspResponse.GetInstance(ae.ToAsn1Object());
+ }
+ this.ocspVals = ocspValsSeq;
+ break;
+ case 2:
+ this.otherRevVals = OtherRevVals.GetInstance(asn1Obj);
+ break;
+ default:
+ throw new ArgumentException("Illegal tag in RevocationValues", "seq");
+ }
+ }
+ }
+
+ public RevocationValues(
+ CertificateList[] crlVals,
+ BasicOcspResponse[] ocspVals,
+ OtherRevVals otherRevVals)
+ {
+ if (crlVals != null)
+ {
+ this.crlVals = new DerSequence(crlVals);
+ }
+
+ if (ocspVals != null)
+ {
+ this.ocspVals = new DerSequence(ocspVals);
+ }
+
+ this.otherRevVals = otherRevVals;
+ }
+
+ public RevocationValues(
+ IEnumerable crlVals,
+ IEnumerable ocspVals,
+ OtherRevVals otherRevVals)
+ {
+ if (crlVals != null)
+ {
+ if (!CollectionUtilities.CheckElementsAreOfType(crlVals, typeof(CertificateList)))
+ throw new ArgumentException("Must contain only 'CertificateList' objects", "crlVals");
+
+ this.crlVals = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(crlVals));
+ }
+
+ if (ocspVals != null)
+ {
+ if (!CollectionUtilities.CheckElementsAreOfType(ocspVals, typeof(BasicOcspResponse)))
+ throw new ArgumentException("Must contain only 'BasicOcspResponse' objects", "ocspVals");
+
+ this.ocspVals = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(ocspVals));
+ }
+
+ this.otherRevVals = otherRevVals;
+ }
+
+ public CertificateList[] GetCrlVals()
+ {
+ CertificateList[] result = new CertificateList[crlVals.Count];
+ for (int i = 0; i < crlVals.Count; ++i)
+ {
+ result[i] = CertificateList.GetInstance(crlVals[i].ToAsn1Object());
+ }
+ return result;
+ }
+
+ public BasicOcspResponse[] GetOcspVals()
+ {
+ BasicOcspResponse[] result = new BasicOcspResponse[ocspVals.Count];
+ for (int i = 0; i < ocspVals.Count; ++i)
+ {
+ result[i] = BasicOcspResponse.GetInstance(ocspVals[i].ToAsn1Object());
+ }
+ return result;
+ }
+
+ public OtherRevVals OtherRevVals
+ {
+ get { return otherRevVals; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (crlVals != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, crlVals));
+ }
+
+ if (ocspVals != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, ocspVals));
+ }
+
+ if (otherRevVals != null)
+ {
+ v.Add(new DerTaggedObject(true, 2, otherRevVals.ToAsn1Object()));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/SigPolicyQualifierInfo.cs b/Crypto/src/asn1/esf/SigPolicyQualifierInfo.cs
new file mode 100644
index 000000000..2d36bc751
--- /dev/null
+++ b/Crypto/src/asn1/esf/SigPolicyQualifierInfo.cs
@@ -0,0 +1,71 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// <code>
+ /// SigPolicyQualifierInfo ::= SEQUENCE {
+ /// sigPolicyQualifierId SigPolicyQualifierId,
+ /// sigQualifier ANY DEFINED BY sigPolicyQualifierId
+ /// }
+ ///
+ /// SigPolicyQualifierId ::= OBJECT IDENTIFIER
+ /// </code>
+ /// </remarks>
+ public class SigPolicyQualifierInfo
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier sigPolicyQualifierId;
+ private readonly Asn1Object sigQualifier;
+
+ public static SigPolicyQualifierInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SigPolicyQualifierInfo)
+ return (SigPolicyQualifierInfo) obj;
+
+ if (obj is Asn1Sequence)
+ return new SigPolicyQualifierInfo((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'SigPolicyQualifierInfo' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private SigPolicyQualifierInfo(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.sigPolicyQualifierId = (DerObjectIdentifier) seq[0].ToAsn1Object();
+ this.sigQualifier = seq[1].ToAsn1Object();
+ }
+
+ public SigPolicyQualifierInfo(
+ DerObjectIdentifier sigPolicyQualifierId,
+ Asn1Encodable sigQualifier)
+ {
+ this.sigPolicyQualifierId = sigPolicyQualifierId;
+ this.sigQualifier = sigQualifier.ToAsn1Object();
+ }
+
+ public DerObjectIdentifier SigPolicyQualifierId
+ {
+ get { return sigPolicyQualifierId; }
+ }
+
+ public Asn1Object SigQualifier
+ {
+ get { return sigQualifier; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(sigPolicyQualifierId, sigQualifier);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/SignaturePolicyId.cs b/Crypto/src/asn1/esf/SignaturePolicyId.cs
new file mode 100644
index 000000000..545be2cf4
--- /dev/null
+++ b/Crypto/src/asn1/esf/SignaturePolicyId.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// <code>
+ /// SignaturePolicyId ::= SEQUENCE {
+ /// sigPolicyIdentifier SigPolicyId,
+ /// sigPolicyHash SigPolicyHash,
+ /// sigPolicyQualifiers SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL
+ /// }
+ ///
+ /// SigPolicyId ::= OBJECT IDENTIFIER
+ ///
+ /// SigPolicyHash ::= OtherHashAlgAndValue
+ /// </code>
+ /// </remarks>
+ public class SignaturePolicyId
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier sigPolicyIdentifier;
+ private readonly OtherHashAlgAndValue sigPolicyHash;
+ private readonly Asn1Sequence sigPolicyQualifiers;
+
+ public static SignaturePolicyId GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SignaturePolicyId)
+ return (SignaturePolicyId) obj;
+
+ if (obj is Asn1Sequence)
+ return new SignaturePolicyId((Asn1Sequence) obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'SignaturePolicyId' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private SignaturePolicyId(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+ if (seq.Count < 2 || seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.sigPolicyIdentifier = (DerObjectIdentifier) seq[0].ToAsn1Object();
+ this.sigPolicyHash = OtherHashAlgAndValue.GetInstance(seq[1].ToAsn1Object());
+
+ if (seq.Count > 2)
+ {
+ this.sigPolicyQualifiers = (Asn1Sequence) seq[2].ToAsn1Object();
+ }
+ }
+
+ public SignaturePolicyId(
+ DerObjectIdentifier sigPolicyIdentifier,
+ OtherHashAlgAndValue sigPolicyHash)
+ : this(sigPolicyIdentifier, sigPolicyHash, null)
+ {
+ }
+
+ public SignaturePolicyId(
+ DerObjectIdentifier sigPolicyIdentifier,
+ OtherHashAlgAndValue sigPolicyHash,
+ params SigPolicyQualifierInfo[] sigPolicyQualifiers)
+ {
+ if (sigPolicyIdentifier == null)
+ throw new ArgumentNullException("sigPolicyIdentifier");
+ if (sigPolicyHash == null)
+ throw new ArgumentNullException("sigPolicyHash");
+
+ this.sigPolicyIdentifier = sigPolicyIdentifier;
+ this.sigPolicyHash = sigPolicyHash;
+
+ if (sigPolicyQualifiers != null)
+ {
+ this.sigPolicyQualifiers = new DerSequence(sigPolicyQualifiers);
+ }
+ }
+
+ public SignaturePolicyId(
+ DerObjectIdentifier sigPolicyIdentifier,
+ OtherHashAlgAndValue sigPolicyHash,
+ IEnumerable sigPolicyQualifiers)
+ {
+ if (sigPolicyIdentifier == null)
+ throw new ArgumentNullException("sigPolicyIdentifier");
+ if (sigPolicyHash == null)
+ throw new ArgumentNullException("sigPolicyHash");
+
+ this.sigPolicyIdentifier = sigPolicyIdentifier;
+ this.sigPolicyHash = sigPolicyHash;
+
+ if (sigPolicyQualifiers != null)
+ {
+ if (!CollectionUtilities.CheckElementsAreOfType(sigPolicyQualifiers, typeof(SigPolicyQualifierInfo)))
+ throw new ArgumentException("Must contain only 'SigPolicyQualifierInfo' objects", "sigPolicyQualifiers");
+
+ this.sigPolicyQualifiers = new DerSequence(
+ Asn1EncodableVector.FromEnumerable(sigPolicyQualifiers));
+ }
+ }
+
+ public DerObjectIdentifier SigPolicyIdentifier
+ {
+ get { return sigPolicyIdentifier; }
+ }
+
+ public OtherHashAlgAndValue SigPolicyHash
+ {
+ get { return sigPolicyHash; }
+ }
+
+ public SigPolicyQualifierInfo[] GetSigPolicyQualifiers()
+ {
+ if (sigPolicyQualifiers == null)
+ return null;
+
+ SigPolicyQualifierInfo[] infos = new SigPolicyQualifierInfo[sigPolicyQualifiers.Count];
+ for (int i = 0; i < sigPolicyQualifiers.Count; ++i)
+ {
+ infos[i] = SigPolicyQualifierInfo.GetInstance(sigPolicyQualifiers[i]);
+ }
+ return infos;
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ sigPolicyIdentifier, sigPolicyHash.ToAsn1Object());
+
+ if (sigPolicyQualifiers != null)
+ {
+ v.Add(sigPolicyQualifiers.ToAsn1Object());
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/SignaturePolicyIdentifier.cs b/Crypto/src/asn1/esf/SignaturePolicyIdentifier.cs
new file mode 100644
index 000000000..3a639f444
--- /dev/null
+++ b/Crypto/src/asn1/esf/SignaturePolicyIdentifier.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /// <remarks>
+ /// <code>
+ /// SignaturePolicyIdentifier ::= CHOICE {
+ /// SignaturePolicyId SignaturePolicyId,
+ /// SignaturePolicyImplied SignaturePolicyImplied
+ /// }
+ ///
+ /// SignaturePolicyImplied ::= NULL
+ /// </code>
+ /// </remarks>
+ public class SignaturePolicyIdentifier
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly SignaturePolicyId sigPolicy;
+
+ public static SignaturePolicyIdentifier GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SignaturePolicyIdentifier)
+ return (SignaturePolicyIdentifier) obj;
+
+ if (obj is SignaturePolicyId)
+ return new SignaturePolicyIdentifier((SignaturePolicyId) obj);
+
+ if (obj is Asn1Null)
+ return new SignaturePolicyIdentifier();
+
+ throw new ArgumentException(
+ "Unknown object in 'SignaturePolicyIdentifier' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ public SignaturePolicyIdentifier()
+ {
+ this.sigPolicy = null;
+ }
+
+ public SignaturePolicyIdentifier(
+ SignaturePolicyId signaturePolicyId)
+ {
+ if (signaturePolicyId == null)
+ throw new ArgumentNullException("signaturePolicyId");
+
+ this.sigPolicy = signaturePolicyId;
+ }
+
+ public SignaturePolicyId SignaturePolicyId
+ {
+ get { return sigPolicy; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return sigPolicy == null
+ ? DerNull.Instance
+ : sigPolicy.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/SignerAttribute.cs b/Crypto/src/asn1/esf/SignerAttribute.cs
new file mode 100644
index 000000000..ddee53c69
--- /dev/null
+++ b/Crypto/src/asn1/esf/SignerAttribute.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ public class SignerAttribute
+ : Asn1Encodable
+ {
+ private Asn1Sequence claimedAttributes;
+ private AttributeCertificate certifiedAttributes;
+
+ public static SignerAttribute GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SignerAttribute)
+ return (SignerAttribute) obj;
+
+ if (obj is Asn1Sequence)
+ return new SignerAttribute(obj);
+
+ throw new ArgumentException(
+ "Unknown object in 'SignerAttribute' factory: "
+ + obj.GetType().Name,
+ "obj");
+ }
+
+ private SignerAttribute(
+ object obj)
+ {
+ Asn1Sequence seq = (Asn1Sequence) obj;
+ DerTaggedObject taggedObject = (DerTaggedObject) seq[0];
+ if (taggedObject.TagNo == 0)
+ {
+ claimedAttributes = Asn1Sequence.GetInstance(taggedObject, true);
+ }
+ else if (taggedObject.TagNo == 1)
+ {
+ certifiedAttributes = AttributeCertificate.GetInstance(taggedObject);
+ }
+ else
+ {
+ throw new ArgumentException("illegal tag.", "obj");
+ }
+ }
+
+ public SignerAttribute(
+ Asn1Sequence claimedAttributes)
+ {
+ this.claimedAttributes = claimedAttributes;
+ }
+
+ public SignerAttribute(
+ AttributeCertificate certifiedAttributes)
+ {
+ this.certifiedAttributes = certifiedAttributes;
+ }
+
+ public virtual Asn1Sequence ClaimedAttributes
+ {
+ get { return claimedAttributes; }
+ }
+
+ public virtual AttributeCertificate CertifiedAttributes
+ {
+ get { return certifiedAttributes; }
+ }
+
+ /**
+ *
+ * <pre>
+ * SignerAttribute ::= SEQUENCE OF CHOICE {
+ * claimedAttributes [0] ClaimedAttributes,
+ * certifiedAttributes [1] CertifiedAttributes }
+ *
+ * ClaimedAttributes ::= SEQUENCE OF Attribute
+ * CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (claimedAttributes != null)
+ {
+ v.Add(new DerTaggedObject(0, claimedAttributes));
+ }
+ else
+ {
+ v.Add(new DerTaggedObject(1, certifiedAttributes));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/esf/SignerLocation.cs b/Crypto/src/asn1/esf/SignerLocation.cs
new file mode 100644
index 000000000..d2cef51bb
--- /dev/null
+++ b/Crypto/src/asn1/esf/SignerLocation.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+ /**
+ * Signer-Location attribute (RFC3126).
+ *
+ * <pre>
+ * SignerLocation ::= SEQUENCE {
+ * countryName [0] DirectoryString OPTIONAL,
+ * localityName [1] DirectoryString OPTIONAL,
+ * postalAddress [2] PostalAddress OPTIONAL }
+ *
+ * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+ * </pre>
+ */
+ public class SignerLocation
+ : Asn1Encodable
+ {
+ // TODO Should these be using DirectoryString?
+ private DerUtf8String countryName;
+ private DerUtf8String localityName;
+ private Asn1Sequence postalAddress;
+
+ public SignerLocation(
+ Asn1Sequence seq)
+ {
+ foreach (Asn1TaggedObject obj in seq)
+ {
+ switch (obj.TagNo)
+ {
+ case 0:
+ this.countryName = DerUtf8String.GetInstance(obj, true);
+ break;
+ case 1:
+ this.localityName = DerUtf8String.GetInstance(obj, true);
+ break;
+ case 2:
+ bool isExplicit = obj.IsExplicit(); // handle erroneous implicitly tagged sequences
+ this.postalAddress = Asn1Sequence.GetInstance(obj, isExplicit);
+ if (postalAddress != null && postalAddress.Count > 6)
+ throw new ArgumentException("postal address must contain less than 6 strings");
+ break;
+ default:
+ throw new ArgumentException("illegal tag");
+ }
+ }
+ }
+
+ public SignerLocation(
+ DerUtf8String countryName,
+ DerUtf8String localityName,
+ Asn1Sequence postalAddress)
+ {
+ if (postalAddress != null && postalAddress.Count > 6)
+ {
+ throw new ArgumentException("postal address must contain less than 6 strings");
+ }
+
+ if (countryName != null)
+ {
+ this.countryName = DerUtf8String.GetInstance(countryName.ToAsn1Object());
+ }
+
+ if (localityName != null)
+ {
+ this.localityName = DerUtf8String.GetInstance(localityName.ToAsn1Object());
+ }
+
+ if (postalAddress != null)
+ {
+ this.postalAddress = (Asn1Sequence) postalAddress.ToAsn1Object();
+ }
+ }
+
+ public static SignerLocation GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SignerLocation)
+ {
+ return (SignerLocation) obj;
+ }
+
+ return new SignerLocation(Asn1Sequence.GetInstance(obj));
+ }
+
+ public DerUtf8String CountryName
+ {
+ get { return countryName; }
+ }
+
+ public DerUtf8String LocalityName
+ {
+ get { return localityName; }
+ }
+
+ public Asn1Sequence PostalAddress
+ {
+ get { return postalAddress; }
+ }
+
+ /**
+ * <pre>
+ * SignerLocation ::= SEQUENCE {
+ * countryName [0] DirectoryString OPTIONAL,
+ * localityName [1] DirectoryString OPTIONAL,
+ * postalAddress [2] PostalAddress OPTIONAL }
+ *
+ * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+ *
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1.. MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (countryName != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, countryName));
+ }
+
+ if (localityName != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, localityName));
+ }
+
+ if (postalAddress != null)
+ {
+ v.Add(new DerTaggedObject(true, 2, postalAddress));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ess/ContentHints.cs b/Crypto/src/asn1/ess/ContentHints.cs
new file mode 100644
index 000000000..a430fea8d
--- /dev/null
+++ b/Crypto/src/asn1/ess/ContentHints.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ public class ContentHints
+ : Asn1Encodable
+ {
+ private readonly DerUtf8String contentDescription;
+ private readonly DerObjectIdentifier contentType;
+
+ public static ContentHints GetInstance(
+ object o)
+ {
+ if (o == null || o is ContentHints)
+ {
+ return (ContentHints)o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new ContentHints((Asn1Sequence)o);
+ }
+
+ throw new ArgumentException("unknown object in 'ContentHints' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ /**
+ * constructor
+ */
+ private ContentHints(
+ Asn1Sequence seq)
+ {
+ IAsn1Convertible field = seq[0];
+ if (field.ToAsn1Object() is DerUtf8String)
+ {
+ contentDescription = DerUtf8String.GetInstance(field);
+ contentType = DerObjectIdentifier.GetInstance(seq[1]);
+ }
+ else
+ {
+ contentType = DerObjectIdentifier.GetInstance(seq[0]);
+ }
+ }
+
+ public ContentHints(
+ DerObjectIdentifier contentType)
+ {
+ this.contentType = contentType;
+ this.contentDescription = null;
+ }
+
+ public ContentHints(
+ DerObjectIdentifier contentType,
+ DerUtf8String contentDescription)
+ {
+ this.contentType = contentType;
+ this.contentDescription = contentDescription;
+ }
+
+ public DerObjectIdentifier ContentType
+ {
+ get { return contentType; }
+ }
+
+ public DerUtf8String ContentDescription
+ {
+ get { return contentDescription; }
+ }
+
+ /**
+ * <pre>
+ * ContentHints ::= SEQUENCE {
+ * contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
+ * contentType ContentType }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (contentDescription != null)
+ {
+ v.Add(contentDescription);
+ }
+
+ v.Add(contentType);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ess/ContentIdentifier.cs b/Crypto/src/asn1/ess/ContentIdentifier.cs
new file mode 100644
index 000000000..8058dcc53
--- /dev/null
+++ b/Crypto/src/asn1/ess/ContentIdentifier.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ public class ContentIdentifier
+ : Asn1Encodable
+ {
+ private Asn1OctetString value;
+
+ public static ContentIdentifier GetInstance(
+ object o)
+ {
+ if (o == null || o is ContentIdentifier)
+ {
+ return (ContentIdentifier) o;
+ }
+
+ if (o is Asn1OctetString)
+ {
+ return new ContentIdentifier((Asn1OctetString) o);
+ }
+
+ throw new ArgumentException(
+ "unknown object in 'ContentIdentifier' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ /**
+ * Create from OCTET STRING whose octets represent the identifier.
+ */
+ public ContentIdentifier(
+ Asn1OctetString value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create from byte array representing the identifier.
+ */
+ public ContentIdentifier(
+ byte[] value)
+ : this(new DerOctetString(value))
+ {
+ }
+
+ public Asn1OctetString Value
+ {
+ get { return value; }
+ }
+
+ /**
+ * The definition of ContentIdentifier is
+ * <pre>
+ * ContentIdentifier ::= OCTET STRING
+ * </pre>
+ * id-aa-contentIdentifier OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 7 }
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return value;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ess/ESSCertID.cs b/Crypto/src/asn1/ess/ESSCertID.cs
new file mode 100644
index 000000000..4d449a746
--- /dev/null
+++ b/Crypto/src/asn1/ess/ESSCertID.cs
@@ -0,0 +1,93 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ public class EssCertID
+ : Asn1Encodable
+ {
+ private Asn1OctetString certHash;
+ private IssuerSerial issuerSerial;
+
+ public static EssCertID GetInstance(
+ object o)
+ {
+ if (o == null || o is EssCertID)
+ {
+ return (EssCertID) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new EssCertID((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "unknown object in 'EssCertID' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ /**
+ * constructor
+ */
+ public EssCertID(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ this.certHash = Asn1OctetString.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ issuerSerial = IssuerSerial.GetInstance(seq[1]);
+ }
+ }
+
+ public EssCertID(
+ byte[] hash)
+ {
+ certHash = new DerOctetString(hash);
+ }
+
+ public EssCertID(
+ byte[] hash,
+ IssuerSerial issuerSerial)
+ {
+ this.certHash = new DerOctetString(hash);
+ this.issuerSerial = issuerSerial;
+ }
+
+ public byte[] GetCertHash()
+ {
+ return certHash.GetOctets();
+ }
+
+ public IssuerSerial IssuerSerial
+ {
+ get { return issuerSerial; }
+ }
+
+ /**
+ * <pre>
+ * EssCertID ::= SEQUENCE {
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certHash);
+
+ if (issuerSerial != null)
+ {
+ v.Add(issuerSerial);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ess/ESSCertIDv2.cs b/Crypto/src/asn1/ess/ESSCertIDv2.cs
new file mode 100644
index 000000000..1d154cd27
--- /dev/null
+++ b/Crypto/src/asn1/ess/ESSCertIDv2.cs
@@ -0,0 +1,138 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ public class EssCertIDv2
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlgorithm;
+ private readonly byte[] certHash;
+ private readonly IssuerSerial issuerSerial;
+
+ private static readonly AlgorithmIdentifier DefaultAlgID = new AlgorithmIdentifier(
+ NistObjectIdentifiers.IdSha256);
+
+ public static EssCertIDv2 GetInstance(
+ object o)
+ {
+ if (o == null || o is EssCertIDv2)
+ return (EssCertIDv2) o;
+
+ if (o is Asn1Sequence)
+ return new EssCertIDv2((Asn1Sequence) o);
+
+ throw new ArgumentException(
+ "unknown object in 'EssCertIDv2' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ private EssCertIDv2(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ int count = 0;
+
+ if (seq[0] is Asn1OctetString)
+ {
+ // Default value
+ this.hashAlgorithm = DefaultAlgID;
+ }
+ else
+ {
+ this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[count++].ToAsn1Object());
+ }
+
+ this.certHash = Asn1OctetString.GetInstance(seq[count++].ToAsn1Object()).GetOctets();
+
+ if (seq.Count > count)
+ {
+ this.issuerSerial = IssuerSerial.GetInstance(
+ Asn1Sequence.GetInstance(seq[count].ToAsn1Object()));
+ }
+ }
+
+ public EssCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash)
+ : this(algId, certHash, null)
+ {
+ }
+
+ public EssCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash,
+ IssuerSerial issuerSerial)
+ {
+ if (algId == null)
+ {
+ // Default value
+ this.hashAlgorithm = DefaultAlgID;
+ }
+ else
+ {
+ this.hashAlgorithm = algId;
+ }
+
+ this.certHash = certHash;
+ this.issuerSerial = issuerSerial;
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return this.hashAlgorithm; }
+ }
+
+ public byte[] GetCertHash()
+ {
+ return Arrays.Clone(certHash);
+ }
+
+ public IssuerSerial IssuerSerial
+ {
+ get { return issuerSerial; }
+ }
+
+ /**
+ * <pre>
+ * EssCertIDv2 ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier
+ * DEFAULT {algorithm id-sha256},
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ *
+ * Hash ::= OCTET STRING
+ *
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serialNumber CertificateSerialNumber
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (!hashAlgorithm.Equals(DefaultAlgID))
+ {
+ v.Add(hashAlgorithm);
+ }
+
+ v.Add(new DerOctetString(certHash).ToAsn1Object());
+
+ if (issuerSerial != null)
+ {
+ v.Add(issuerSerial);
+ }
+
+ return new DerSequence(v);
+ }
+
+ }
+}
diff --git a/Crypto/src/asn1/ess/OtherCertID.cs b/Crypto/src/asn1/ess/OtherCertID.cs
new file mode 100644
index 000000000..972ef8c6b
--- /dev/null
+++ b/Crypto/src/asn1/ess/OtherCertID.cs
@@ -0,0 +1,132 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ [Obsolete("Use version in Asn1.Esf instead")]
+ public class OtherCertID
+ : Asn1Encodable
+ {
+ private Asn1Encodable otherCertHash;
+ private IssuerSerial issuerSerial;
+
+ public static OtherCertID GetInstance(
+ object o)
+ {
+ if (o == null || o is OtherCertID)
+ {
+ return (OtherCertID) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new OtherCertID((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "unknown object in 'OtherCertID' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ /**
+ * constructor
+ */
+ public OtherCertID(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ if (seq[0].ToAsn1Object() is Asn1OctetString)
+ {
+ otherCertHash = Asn1OctetString.GetInstance(seq[0]);
+ }
+ else
+ {
+ otherCertHash = DigestInfo.GetInstance(seq[0]);
+ }
+
+ if (seq.Count > 1)
+ {
+ issuerSerial = IssuerSerial.GetInstance(Asn1Sequence.GetInstance(seq[1]));
+ }
+ }
+
+ public OtherCertID(
+ AlgorithmIdentifier algId,
+ byte[] digest)
+ {
+ this.otherCertHash = new DigestInfo(algId, digest);
+ }
+
+ public OtherCertID(
+ AlgorithmIdentifier algId,
+ byte[] digest,
+ IssuerSerial issuerSerial)
+ {
+ this.otherCertHash = new DigestInfo(algId, digest);
+ this.issuerSerial = issuerSerial;
+ }
+
+ public AlgorithmIdentifier AlgorithmHash
+ {
+ get
+ {
+ if (otherCertHash.ToAsn1Object() is Asn1OctetString)
+ {
+ // SHA-1
+ return new AlgorithmIdentifier("1.3.14.3.2.26");
+ }
+
+ return DigestInfo.GetInstance(otherCertHash).AlgorithmID;
+ }
+ }
+
+ public byte[] GetCertHash()
+ {
+ if (otherCertHash.ToAsn1Object() is Asn1OctetString)
+ {
+ // SHA-1
+ return ((Asn1OctetString) otherCertHash.ToAsn1Object()).GetOctets();
+ }
+
+ return DigestInfo.GetInstance(otherCertHash).GetDigest();
+ }
+
+ public IssuerSerial IssuerSerial
+ {
+ get { return issuerSerial; }
+ }
+
+ /**
+ * <pre>
+ * OtherCertID ::= SEQUENCE {
+ * otherCertHash OtherHash,
+ * issuerSerial IssuerSerial OPTIONAL }
+ *
+ * OtherHash ::= CHOICE {
+ * sha1Hash OCTET STRING,
+ * otherHash OtherHashAlgAndValue }
+ *
+ * OtherHashAlgAndValue ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashValue OCTET STRING }
+ *
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(otherCertHash);
+
+ if (issuerSerial != null)
+ {
+ v.Add(issuerSerial);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ess/OtherSigningCertificate.cs b/Crypto/src/asn1/ess/OtherSigningCertificate.cs
new file mode 100644
index 000000000..c165fecea
--- /dev/null
+++ b/Crypto/src/asn1/ess/OtherSigningCertificate.cs
@@ -0,0 +1,109 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ [Obsolete("Use version in Asn1.Esf instead")]
+ public class OtherSigningCertificate
+ : Asn1Encodable
+ {
+ private Asn1Sequence certs, policies;
+
+ public static OtherSigningCertificate GetInstance(
+ object o)
+ {
+ if (o == null || o is OtherSigningCertificate)
+ {
+ return (OtherSigningCertificate) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new OtherSigningCertificate((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "unknown object in 'OtherSigningCertificate' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ /**
+ * constructors
+ */
+ public OtherSigningCertificate(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ this.certs = Asn1Sequence.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ this.policies = Asn1Sequence.GetInstance(seq[1]);
+ }
+ }
+
+ public OtherSigningCertificate(
+ OtherCertID otherCertID)
+ {
+ certs = new DerSequence(otherCertID);
+ }
+
+ public OtherCertID[] GetCerts()
+ {
+ OtherCertID[] cs = new OtherCertID[certs.Count];
+
+ for (int i = 0; i != certs.Count; ++i)
+ {
+ cs[i] = OtherCertID.GetInstance(certs[i]);
+ }
+
+ return cs;
+ }
+
+ public PolicyInformation[] GetPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] ps = new PolicyInformation[policies.Count];
+
+ for (int i = 0; i != policies.Count; i++)
+ {
+ ps[i] = PolicyInformation.GetInstance(policies[i]);
+ }
+
+ return ps;
+ }
+
+ /**
+ * The definition of OtherSigningCertificate is
+ * <pre>
+ * OtherSigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF OtherCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ * </pre>
+ * id-aa-ets-otherSigCert OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 19 }
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+ if (policies != null)
+ {
+ v.Add(policies);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ess/SigningCertificate.cs b/Crypto/src/asn1/ess/SigningCertificate.cs
new file mode 100644
index 000000000..366749bc3
--- /dev/null
+++ b/Crypto/src/asn1/ess/SigningCertificate.cs
@@ -0,0 +1,108 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ public class SigningCertificate
+ : Asn1Encodable
+ {
+ private Asn1Sequence certs, policies;
+
+ public static SigningCertificate GetInstance(
+ object o)
+ {
+ if (o == null || o is SigningCertificate)
+ {
+ return (SigningCertificate) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new SigningCertificate((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "unknown object in 'SigningCertificate' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ /**
+ * constructors
+ */
+ public SigningCertificate(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+ }
+
+ this.certs = Asn1Sequence.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ this.policies = Asn1Sequence.GetInstance(seq[1]);
+ }
+ }
+
+ public SigningCertificate(
+ EssCertID essCertID)
+ {
+ certs = new DerSequence(essCertID);
+ }
+
+ public EssCertID[] GetCerts()
+ {
+ EssCertID[] cs = new EssCertID[certs.Count];
+
+ for (int i = 0; i != certs.Count; i++)
+ {
+ cs[i] = EssCertID.GetInstance(certs[i]);
+ }
+
+ return cs;
+ }
+
+ public PolicyInformation[] GetPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] ps = new PolicyInformation[policies.Count];
+
+ for (int i = 0; i != policies.Count; i++)
+ {
+ ps[i] = PolicyInformation.GetInstance(policies[i]);
+ }
+
+ return ps;
+ }
+
+ /**
+ * The definition of SigningCertificate is
+ * <pre>
+ * SigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF EssCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ * </pre>
+ * id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 12 }
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+ if (policies != null)
+ {
+ v.Add(policies);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ess/SigningCertificateV2.cs b/Crypto/src/asn1/ess/SigningCertificateV2.cs
new file mode 100644
index 000000000..a2aff4866
--- /dev/null
+++ b/Crypto/src/asn1/ess/SigningCertificateV2.cs
@@ -0,0 +1,106 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+ public class SigningCertificateV2
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence certs;
+ private readonly Asn1Sequence policies;
+
+ public static SigningCertificateV2 GetInstance(
+ object o)
+ {
+ if (o == null || o is SigningCertificateV2)
+ return (SigningCertificateV2) o;
+
+ if (o is Asn1Sequence)
+ return new SigningCertificateV2((Asn1Sequence) o);
+
+ throw new ArgumentException(
+ "unknown object in 'SigningCertificateV2' factory : "
+ + o.GetType().Name + ".");
+ }
+
+ private SigningCertificateV2(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.certs = Asn1Sequence.GetInstance(seq[0].ToAsn1Object());
+
+ if (seq.Count > 1)
+ {
+ this.policies = Asn1Sequence.GetInstance(seq[1].ToAsn1Object());
+ }
+ }
+
+ public SigningCertificateV2(
+ EssCertIDv2[] certs)
+ {
+ this.certs = new DerSequence(certs);
+ }
+
+ public SigningCertificateV2(
+ EssCertIDv2[] certs,
+ PolicyInformation[] policies)
+ {
+ this.certs = new DerSequence(certs);
+
+ if (policies != null)
+ {
+ this.policies = new DerSequence(policies);
+ }
+ }
+
+ public EssCertIDv2[] GetCerts()
+ {
+ EssCertIDv2[] certIds = new EssCertIDv2[certs.Count];
+ for (int i = 0; i != certs.Count; i++)
+ {
+ certIds[i] = EssCertIDv2.GetInstance(certs[i]);
+ }
+ return certIds;
+ }
+
+ public PolicyInformation[] GetPolicies()
+ {
+ if (policies == null)
+ return null;
+
+ PolicyInformation[] policyInformations = new PolicyInformation[policies.Count];
+ for (int i = 0; i != policies.Count; i++)
+ {
+ policyInformations[i] = PolicyInformation.GetInstance(policies[i]);
+ }
+ return policyInformations;
+ }
+
+ /**
+ * The definition of SigningCertificateV2 is
+ * <pre>
+ * SigningCertificateV2 ::= SEQUENCE {
+ * certs SEQUENCE OF EssCertIDv2,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ * </pre>
+ * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 47 }
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+ if (policies != null)
+ {
+ v.Add(policies);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/gnu/GNUObjectIdentifiers.cs b/Crypto/src/asn1/gnu/GNUObjectIdentifiers.cs
new file mode 100644
index 000000000..9311a3ac1
--- /dev/null
+++ b/Crypto/src/asn1/gnu/GNUObjectIdentifiers.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Gnu
+{
+ public abstract class GnuObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier Gnu = new DerObjectIdentifier("1.3.6.1.4.1.11591.1"); // GNU Radius
+ public static readonly DerObjectIdentifier GnuPG = new DerObjectIdentifier("1.3.6.1.4.1.11591.2"); // GnuPG (Ägypten)
+ public static readonly DerObjectIdentifier Notation = new DerObjectIdentifier("1.3.6.1.4.1.11591.2.1"); // notation
+ public static readonly DerObjectIdentifier PkaAddress = new DerObjectIdentifier("1.3.6.1.4.1.11591.2.1.1"); // pkaAddress
+ public static readonly DerObjectIdentifier GnuRadar = new DerObjectIdentifier("1.3.6.1.4.1.11591.3"); // GNU Radar
+ public static readonly DerObjectIdentifier DigestAlgorithm = new DerObjectIdentifier("1.3.6.1.4.1.11591.12"); // digestAlgorithm
+ public static readonly DerObjectIdentifier Tiger192 = new DerObjectIdentifier("1.3.6.1.4.1.11591.12.2"); // TIGER/192
+ public static readonly DerObjectIdentifier EncryptionAlgorithm = new DerObjectIdentifier("1.3.6.1.4.1.11591.13"); // encryptionAlgorithm
+ public static readonly DerObjectIdentifier Serpent = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2"); // Serpent
+ public static readonly DerObjectIdentifier Serpent128Ecb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.1"); // Serpent-128-ECB
+ public static readonly DerObjectIdentifier Serpent128Cbc = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.2"); // Serpent-128-CBC
+ public static readonly DerObjectIdentifier Serpent128Ofb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.3"); // Serpent-128-OFB
+ public static readonly DerObjectIdentifier Serpent128Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.4"); // Serpent-128-CFB
+ public static readonly DerObjectIdentifier Serpent192Ecb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.21"); // Serpent-192-ECB
+ public static readonly DerObjectIdentifier Serpent192Cbc = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.22"); // Serpent-192-CBC
+ public static readonly DerObjectIdentifier Serpent192Ofb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.23"); // Serpent-192-OFB
+ public static readonly DerObjectIdentifier Serpent192Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.24"); // Serpent-192-CFB
+ public static readonly DerObjectIdentifier Serpent256Ecb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.41"); // Serpent-256-ECB
+ public static readonly DerObjectIdentifier Serpent256Cbc = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.42"); // Serpent-256-CBC
+ public static readonly DerObjectIdentifier Serpent256Ofb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.43"); // Serpent-256-OFB
+ public static readonly DerObjectIdentifier Serpent256Cfb = new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.44"); // Serpent-256-CFB
+ public static readonly DerObjectIdentifier Crc = new DerObjectIdentifier("1.3.6.1.4.1.11591.14"); // CRC algorithms
+ public static readonly DerObjectIdentifier Crc32 = new DerObjectIdentifier("1.3.6.1.4.1.11591.14.1"); // CRC 32
+ }
+}
diff --git a/Crypto/src/asn1/iana/IANAObjectIdentifiers.cs b/Crypto/src/asn1/iana/IANAObjectIdentifiers.cs
new file mode 100644
index 000000000..63343f5ce
--- /dev/null
+++ b/Crypto/src/asn1/iana/IANAObjectIdentifiers.cs
@@ -0,0 +1,18 @@
+namespace Org.BouncyCastle.Asn1.Iana
+{
+ public abstract class IanaObjectIdentifiers
+ {
+ // id-SHA1 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)}
+ //
+
+ public static readonly DerObjectIdentifier IsakmpOakley = new DerObjectIdentifier("1.3.6.1.5.5.8.1");
+
+ public static readonly DerObjectIdentifier HmacMD5 = new DerObjectIdentifier(IsakmpOakley + ".1");
+ public static readonly DerObjectIdentifier HmacSha1 = new DerObjectIdentifier(IsakmpOakley + ".2");
+
+ public static readonly DerObjectIdentifier HmacTiger = new DerObjectIdentifier(IsakmpOakley + ".3");
+
+ public static readonly DerObjectIdentifier HmacRipeMD160 = new DerObjectIdentifier(IsakmpOakley + ".4");
+ }
+}
diff --git a/Crypto/src/asn1/icao/CscaMasterList.cs b/Crypto/src/asn1/icao/CscaMasterList.cs
new file mode 100644
index 000000000..6890d8a2e
--- /dev/null
+++ b/Crypto/src/asn1/icao/CscaMasterList.cs
@@ -0,0 +1,83 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+ /**
+ * The CscaMasterList object. This object can be wrapped in a
+ * CMSSignedData to be published in LDAP.
+ *
+ * <pre>
+ * CscaMasterList ::= SEQUENCE {
+ * version CscaMasterListVersion,
+ * certList SET OF Certificate }
+ *
+ * CscaMasterListVersion :: INTEGER {v0(0)}
+ * </pre>
+ */
+ public class CscaMasterList
+ : Asn1Encodable
+ {
+ private DerInteger version = new DerInteger(0);
+ private X509CertificateStructure[] certList;
+
+ public static CscaMasterList GetInstance(
+ object obj)
+ {
+ if (obj is CscaMasterList)
+ return (CscaMasterList)obj;
+
+ if (obj != null)
+ return new CscaMasterList(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ private CscaMasterList(
+ Asn1Sequence seq)
+ {
+ if (seq == null || seq.Count == 0)
+ throw new ArgumentException("null or empty sequence passed.");
+
+ if (seq.Count != 2)
+ throw new ArgumentException("Incorrect sequence size: " + seq.Count);
+
+ this.version = DerInteger.GetInstance(seq[0]);
+
+ Asn1Set certSet = Asn1Set.GetInstance(seq[1]);
+
+ this.certList = new X509CertificateStructure[certSet.Count];
+ for (int i = 0; i < certList.Length; i++)
+ {
+ certList[i] = X509CertificateStructure.GetInstance(certSet[i]);
+ }
+ }
+
+ public CscaMasterList(
+ X509CertificateStructure[] certStructs)
+ {
+ certList = CopyCertList(certStructs);
+ }
+
+ public virtual int Version
+ {
+ get { return version.Value.IntValue; }
+ }
+
+ public X509CertificateStructure[] GetCertStructs()
+ {
+ return CopyCertList(certList);
+ }
+
+ private static X509CertificateStructure[] CopyCertList(X509CertificateStructure[] orig)
+ {
+ return (X509CertificateStructure[])orig.Clone();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(version, new DerSet(certList));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/icao/DataGroupHash.cs b/Crypto/src/asn1/icao/DataGroupHash.cs
new file mode 100644
index 000000000..e0d7eee7b
--- /dev/null
+++ b/Crypto/src/asn1/icao/DataGroupHash.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+ /**
+ * The DataGroupHash object.
+ * <pre>
+ * DataGroupHash ::= SEQUENCE {
+ * dataGroupNumber DataGroupNumber,
+ * dataGroupHashValue OCTET STRING }
+ *
+ * DataGroupNumber ::= INTEGER {
+ * dataGroup1 (1),
+ * dataGroup1 (2),
+ * dataGroup1 (3),
+ * dataGroup1 (4),
+ * dataGroup1 (5),
+ * dataGroup1 (6),
+ * dataGroup1 (7),
+ * dataGroup1 (8),
+ * dataGroup1 (9),
+ * dataGroup1 (10),
+ * dataGroup1 (11),
+ * dataGroup1 (12),
+ * dataGroup1 (13),
+ * dataGroup1 (14),
+ * dataGroup1 (15),
+ * dataGroup1 (16) }
+ *
+ * </pre>
+ */
+ public class DataGroupHash
+ : Asn1Encodable
+ {
+ private readonly DerInteger dataGroupNumber;
+ private readonly Asn1OctetString dataGroupHashValue;
+
+ public static DataGroupHash GetInstance(
+ object obj)
+ {
+ if (obj is DataGroupHash)
+ return (DataGroupHash)obj;
+
+ if (obj != null)
+ return new DataGroupHash(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ private DataGroupHash(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.dataGroupNumber = DerInteger.GetInstance(seq[0]);
+ this.dataGroupHashValue = Asn1OctetString.GetInstance(seq[1]);
+ }
+
+ public DataGroupHash(
+ int dataGroupNumber,
+ Asn1OctetString dataGroupHashValue)
+ {
+ this.dataGroupNumber = new DerInteger(dataGroupNumber);
+ this.dataGroupHashValue = dataGroupHashValue;
+ }
+
+ public int DataGroupNumber
+ {
+ get { return dataGroupNumber.Value.IntValue; }
+ }
+
+ public Asn1OctetString DataGroupHashValue
+ {
+ get { return dataGroupHashValue; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(dataGroupNumber, dataGroupHashValue);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/icao/ICAOObjectIdentifiers.cs b/Crypto/src/asn1/icao/ICAOObjectIdentifiers.cs
new file mode 100644
index 000000000..389d4dacd
--- /dev/null
+++ b/Crypto/src/asn1/icao/ICAOObjectIdentifiers.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+ public abstract class IcaoObjectIdentifiers
+ {
+ //
+ // base id
+ //
+ public static readonly DerObjectIdentifier IdIcao = new DerObjectIdentifier("2.23.136");
+
+ public static readonly DerObjectIdentifier IdIcaoMrtd = IdIcao.Branch("1");
+ public static readonly DerObjectIdentifier IdIcaoMrtdSecurity = IdIcaoMrtd.Branch("1");
+
+ // LDS security object, see ICAO Doc 9303-Volume 2-Section IV-A3.2
+ public static readonly DerObjectIdentifier IdIcaoLdsSecurityObject = IdIcaoMrtdSecurity.Branch("1");
+
+ // CSCA master list, see TR CSCA Countersigning and Master List issuance
+ public static readonly DerObjectIdentifier IdIcaoCscaMasterList = IdIcaoMrtdSecurity.Branch("2");
+ public static readonly DerObjectIdentifier IdIcaoCscaMasterListSigningKey = IdIcaoMrtdSecurity.Branch("3");
+
+ // document type list, see draft TR LDS and PKI Maintenance, par. 3.2.1
+ public static readonly DerObjectIdentifier IdIcaoDocumentTypeList = IdIcaoMrtdSecurity.Branch("4");
+
+ // Active Authentication protocol, see draft TR LDS and PKI Maintenance,
+ // par. 5.2.2
+ public static readonly DerObjectIdentifier IdIcaoAAProtocolObject = IdIcaoMrtdSecurity.Branch("5");
+
+ // CSCA name change and key reoll-over, see draft TR LDS and PKI
+ // Maintenance, par. 3.2.1
+ public static readonly DerObjectIdentifier IdIcaoExtensions = IdIcaoMrtdSecurity.Branch("6");
+ public static readonly DerObjectIdentifier IdIcaoExtensionsNamechangekeyrollover = IdIcaoExtensions.Branch("1");
+ }
+}
diff --git a/Crypto/src/asn1/icao/LDSSecurityObject.cs b/Crypto/src/asn1/icao/LDSSecurityObject.cs
new file mode 100644
index 000000000..c33ca6877
--- /dev/null
+++ b/Crypto/src/asn1/icao/LDSSecurityObject.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+ /**
+ * The LDSSecurityObject object (V1.8).
+ * <pre>
+ * LDSSecurityObject ::= SEQUENCE {
+ * version LDSSecurityObjectVersion,
+ * hashAlgorithm DigestAlgorithmIdentifier,
+ * dataGroupHashValues SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup,
+ * ldsVersionInfo LDSVersionInfo OPTIONAL
+ * -- if present, version MUST be v1 }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier,
+ *
+ * LDSSecurityObjectVersion :: INTEGER {V0(0)}
+ * </pre>
+ */
+ public class LdsSecurityObject
+ : Asn1Encodable
+ {
+ public const int UBDataGroups = 16;
+
+ private DerInteger version = new DerInteger(0);
+ private AlgorithmIdentifier digestAlgorithmIdentifier;
+ private DataGroupHash[] datagroupHash;
+ private LdsVersionInfo versionInfo;
+
+ public static LdsSecurityObject GetInstance(
+ object obj)
+ {
+ if (obj is LdsSecurityObject)
+ return (LdsSecurityObject)obj;
+
+ if (obj != null)
+ return new LdsSecurityObject(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ private LdsSecurityObject(
+ Asn1Sequence seq)
+ {
+ if (seq == null || seq.Count == 0)
+ throw new ArgumentException("null or empty sequence passed.");
+
+ IEnumerator e = seq.GetEnumerator();
+
+ // version
+ e.MoveNext();
+ version = DerInteger.GetInstance(e.Current);
+ // digestAlgorithmIdentifier
+ e.MoveNext();
+ digestAlgorithmIdentifier = AlgorithmIdentifier.GetInstance(e.Current);
+
+ e.MoveNext();
+ Asn1Sequence datagroupHashSeq = Asn1Sequence.GetInstance(e.Current);
+
+ if (version.Value.Equals(BigInteger.One))
+ {
+ e.MoveNext();
+ versionInfo = LdsVersionInfo.GetInstance(e.Current);
+ }
+
+ CheckDatagroupHashSeqSize(datagroupHashSeq.Count);
+
+ datagroupHash = new DataGroupHash[datagroupHashSeq.Count];
+ for (int i= 0; i< datagroupHashSeq.Count; i++)
+ {
+ datagroupHash[i] = DataGroupHash.GetInstance(datagroupHashSeq[i]);
+ }
+ }
+
+ public LdsSecurityObject(
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash)
+ {
+ this.version = new DerInteger(0);
+ this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+ this.datagroupHash = datagroupHash;
+
+ CheckDatagroupHashSeqSize(datagroupHash.Length);
+ }
+
+
+ public LdsSecurityObject(
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash,
+ LdsVersionInfo versionInfo)
+ {
+ this.version = new DerInteger(1);
+ this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+ this.datagroupHash = datagroupHash;
+ this.versionInfo = versionInfo;
+
+ CheckDatagroupHashSeqSize(datagroupHash.Length);
+ }
+
+ private void CheckDatagroupHashSeqSize(int size)
+ {
+ if (size < 2 || size > UBDataGroups)
+ throw new ArgumentException("wrong size in DataGroupHashValues : not in (2.."+ UBDataGroups +")");
+ }
+
+ public BigInteger Version
+ {
+ get { return version.Value; }
+ }
+
+ public AlgorithmIdentifier DigestAlgorithmIdentifier
+ {
+ get { return digestAlgorithmIdentifier; }
+ }
+
+ public DataGroupHash[] GetDatagroupHash()
+ {
+ return datagroupHash;
+ }
+
+ public LdsVersionInfo VersionInfo
+ {
+ get { return versionInfo; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ DerSequence hashSeq = new DerSequence(datagroupHash);
+
+ Asn1EncodableVector v = new Asn1EncodableVector(version, digestAlgorithmIdentifier, hashSeq);
+
+ if (versionInfo != null)
+ {
+ v.Add(versionInfo);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/icao/LDSVersionInfo.cs b/Crypto/src/asn1/icao/LDSVersionInfo.cs
new file mode 100644
index 000000000..2cdcad2db
--- /dev/null
+++ b/Crypto/src/asn1/icao/LDSVersionInfo.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+ public class LdsVersionInfo
+ : Asn1Encodable
+ {
+ private DerPrintableString ldsVersion;
+ private DerPrintableString unicodeVersion;
+
+ public LdsVersionInfo(string ldsVersion, string unicodeVersion)
+ {
+ this.ldsVersion = new DerPrintableString(ldsVersion);
+ this.unicodeVersion = new DerPrintableString(unicodeVersion);
+ }
+
+ private LdsVersionInfo(Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("sequence wrong size for LDSVersionInfo", "seq");
+
+ this.ldsVersion = DerPrintableString.GetInstance(seq[0]);
+ this.unicodeVersion = DerPrintableString.GetInstance(seq[1]);
+ }
+
+ public static LdsVersionInfo GetInstance(object obj)
+ {
+ if (obj is LdsVersionInfo)
+ return (LdsVersionInfo)obj;
+
+ if (obj != null)
+ return new LdsVersionInfo(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public virtual string GetLdsVersion()
+ {
+ return ldsVersion.GetString();
+ }
+
+ public virtual string GetUnicodeVersion()
+ {
+ return unicodeVersion.GetString();
+ }
+
+ /**
+ * <pre>
+ * LDSVersionInfo ::= SEQUENCE {
+ * ldsVersion PRINTABLE STRING
+ * unicodeVersion PRINTABLE STRING
+ * }
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(ldsVersion, unicodeVersion);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs b/Crypto/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs
new file mode 100644
index 000000000..af60b030a
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs
@@ -0,0 +1,177 @@
+namespace Org.BouncyCastle.Asn1.IsisMtt
+{
+ public abstract class IsisMttObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier IdIsisMtt = new DerObjectIdentifier("1.3.36.8");
+
+ public static readonly DerObjectIdentifier IdIsisMttCP = new DerObjectIdentifier(IdIsisMtt + ".1");
+
+ /**
+ * The id-isismtt-cp-accredited OID indicates that the certificate is a
+ * qualified certificate according to Directive 1999/93/EC of the European
+ * Parliament and of the Council of 13 December 1999 on a Community
+ * Framework for Electronic Signatures, which additionally conforms the
+ * special requirements of the SigG and has been issued by an accredited CA.
+ */
+ public static readonly DerObjectIdentifier IdIsisMttCPAccredited = new DerObjectIdentifier(IdIsisMttCP + ".1");
+
+ public static readonly DerObjectIdentifier IdIsisMttAT = new DerObjectIdentifier(IdIsisMtt + ".3");
+
+ /**
+ * Certificate extensionDate of certificate generation
+ *
+ * <pre>
+ * DateOfCertGenSyntax ::= GeneralizedTime
+ * </pre>
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATDateOfCertGen = new DerObjectIdentifier(IdIsisMttAT + ".1");
+
+ /**
+ * Attribute to indicate that the certificate holder may sign in the name of
+ * a third person. May also be used as extension in a certificate.
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATProcuration = new DerObjectIdentifier(IdIsisMttAT + ".2");
+
+ /**
+ * Attribute to indicate admissions to certain professions. May be used as
+ * attribute in attribute certificate or as extension in a certificate
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATAdmission = new DerObjectIdentifier(IdIsisMttAT + ".3");
+
+ /**
+ * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST
+ * be used in new certificates in place of the extension/attribute
+ * MonetaryLimit since January 1, 2004. For the sake of backward
+ * compatibility with certificates already in use, SigG conforming
+ * components MUST support MonetaryLimit (as well as QcEuLimitValue).
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATMonetaryLimit = new DerObjectIdentifier(IdIsisMttAT + ".4");
+
+ /**
+ * A declaration of majority. May be used as attribute in attribute
+ * certificate or as extension in a certificate
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATDeclarationOfMajority = new DerObjectIdentifier(IdIsisMttAT + ".5");
+
+ /**
+ *
+ * Serial number of the smart card containing the corresponding private key
+ *
+ * <pre>
+ * ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+ * </pre>
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATIccsn = new DerObjectIdentifier(IdIsisMttAT + ".6");
+
+ /**
+ *
+ * Reference for a file of a smartcard that stores the public key of this
+ * certificate and that is used as �security anchor�.
+ *
+ * <pre>
+ * PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+ * </pre>
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATPKReference = new DerObjectIdentifier(IdIsisMttAT + ".7");
+
+ /**
+ * Some other restriction regarding the usage of this certificate. May be
+ * used as attribute in attribute certificate or as extension in a
+ * certificate.
+ *
+ * <pre>
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * </pre>
+ *
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATRestriction = new DerObjectIdentifier(IdIsisMttAT + ".8");
+
+ /**
+ *
+ * (Single)Request extension: Clients may include this extension in a
+ * (single) Request to request the responder to send the certificate in the
+ * response message along with the status information. Besides the LDAP
+ * service, this extension provides another mechanism for the distribution
+ * of certificates, which MAY optionally be provided by certificate
+ * repositories.
+ *
+ * <pre>
+ * RetrieveIfAllowed ::= BOOLEAN
+ * </pre>
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATRetrieveIfAllowed = new DerObjectIdentifier(IdIsisMttAT + ".9");
+
+ /**
+ * SingleOCSPResponse extension: The certificate requested by the client by
+ * inserting the RetrieveIfAllowed extension in the request, will be
+ * returned in this extension.
+ *
+ * @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATRequestedCertificate = new DerObjectIdentifier(IdIsisMttAT + ".10");
+
+ /**
+ * Base ObjectIdentifier for naming authorities
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATNamingAuthorities = new DerObjectIdentifier(IdIsisMttAT + ".11");
+
+ /**
+ * SingleOCSPResponse extension: Date, when certificate has been published
+ * in the directory and status information has become available. Currently,
+ * accrediting authorities enforce that SigG-conforming OCSP servers include
+ * this extension in the responses.
+ *
+ * <pre>
+ * CertInDirSince ::= GeneralizedTime
+ * </pre>
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATCertInDirSince = new DerObjectIdentifier(IdIsisMttAT + ".12");
+
+ /**
+ * Hash of a certificate in OCSP.
+ *
+ * @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATCertHash = new DerObjectIdentifier(IdIsisMttAT + ".13");
+
+ /**
+ * <pre>
+ * NameAtBirth ::= DirectoryString(SIZE(1..64)
+ * </pre>
+ *
+ * Used in
+ * {@link Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATNameAtBirth = new DerObjectIdentifier(IdIsisMttAT + ".14");
+
+ /**
+ * Some other information of non-restrictive nature regarding the usage of
+ * this certificate. May be used as attribute in atribute certificate or as
+ * extension in a certificate.
+ *
+ * <pre>
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * </pre>
+ *
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATAdditionalInformation = new DerObjectIdentifier(IdIsisMttAT + ".15");
+
+ /**
+ * Indicates that an attribute certificate exists, which limits the
+ * usability of this public key certificate. Whenever verifying a signature
+ * with the help of this certificate, the content of the corresponding
+ * attribute certificate should be concerned. This extension MUST be
+ * included in a PKC, if a corresponding attribute certificate (having the
+ * PKC as base certificate) contains some attribute that restricts the
+ * usability of the PKC too. Attribute certificates with restricting content
+ * MUST always be included in the signed document.
+ *
+ * <pre>
+ * LiabilityLimitationFlagSyntax ::= BOOLEAN
+ * </pre>
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATLiabilityLimitationFlag = new DerObjectIdentifier("0.2.262.1.10.12.0");
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/ocsp/CertHash.cs b/Crypto/src/asn1/isismtt/ocsp/CertHash.cs
new file mode 100644
index 000000000..da5b530e4
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/ocsp/CertHash.cs
@@ -0,0 +1,121 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
+{
+ /**
+ * ISIS-MTT PROFILE: The responder may include this extension in a response to
+ * send the hash of the requested certificate to the responder. This hash is
+ * cryptographically bound to the certificate and serves as evidence that the
+ * certificate is known to the responder (i.e. it has been issued and is present
+ * in the directory). Hence, this extension is a means to provide a positive
+ * statement of availability as described in T8.[8]. As explained in T13.[1],
+ * clients may rely on this information to be able to validate signatures after
+ * the expiry of the corresponding certificate. Hence, clients MUST support this
+ * extension. If a positive statement of availability is to be delivered, this
+ * extension syntax and OID MUST be used.
+ * <p/>
+ * <p/>
+ * <pre>
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ * </pre>
+ */
+ public class CertHash
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlgorithm;
+ private readonly byte[] certificateHash;
+
+ public static CertHash GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CertHash)
+ {
+ return (CertHash) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new CertHash((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * The sequence is of type CertHash:
+ * <p/>
+ * <pre>
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private CertHash(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+ this.certificateHash = DerOctetString.GetInstance(seq[1]).GetOctets();
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param hashAlgorithm The hash algorithm identifier.
+ * @param certificateHash The hash of the whole DER encoding of the certificate.
+ */
+ public CertHash(
+ AlgorithmIdentifier hashAlgorithm,
+ byte[] certificateHash)
+ {
+ if (hashAlgorithm == null)
+ throw new ArgumentNullException("hashAlgorithm");
+ if (certificateHash == null)
+ throw new ArgumentNullException("certificateHash");
+
+ this.hashAlgorithm = hashAlgorithm;
+ this.certificateHash = (byte[]) certificateHash.Clone();
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return hashAlgorithm; }
+ }
+
+ public byte[] CertificateHash
+ {
+ get { return (byte[]) certificateHash.Clone(); }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(hashAlgorithm, new DerOctetString(certificateHash));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs b/Crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
new file mode 100644
index 000000000..7724bfed6
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/ocsp/RequestedCertificate.cs
@@ -0,0 +1,186 @@
+using System;
+using System.IO;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
+{
+ /**
+ * ISIS-MTT-Optional: The certificate requested by the client by inserting the
+ * RetrieveIfAllowed extension in the request, will be returned in this
+ * extension.
+ * <p/>
+ * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
+ * when the certificate owner gives his isExplicit permission. Accordingly, there
+ * may be �nondownloadable� certificates, about which the responder must provide
+ * status information, but MUST NOT include them in the response. Clients may
+ * get therefore the following three kind of answers on a single request
+ * including the RetrieveIfAllowed extension:
+ * <ul>
+ * <li> a) the responder supports the extension and is allowed to publish the
+ * certificate: RequestedCertificate returned including the requested
+ * certificate</li>
+ * <li>b) the responder supports the extension but is NOT allowed to publish
+ * the certificate: RequestedCertificate returned including an empty OCTET
+ * STRING</li>
+ * <li>c) the responder does not support the extension: RequestedCertificate is
+ * not included in the response</li>
+ * </ul>
+ * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
+ * any of the OCTET STRING options is used, it MUST contain the DER encoding of
+ * the requested certificate.
+ * <p/>
+ * <pre>
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ * </pre>
+ */
+ public class RequestedCertificate
+ : Asn1Encodable, IAsn1Choice
+ {
+ public enum Choice
+ {
+ Certificate = -1,
+ PublicKeyCertificate = 0,
+ AttributeCertificate = 1
+ }
+
+ private readonly X509CertificateStructure cert;
+ private readonly byte[] publicKeyCert;
+ private readonly byte[] attributeCert;
+
+ public static RequestedCertificate GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RequestedCertificate)
+ {
+ return (RequestedCertificate) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new RequestedCertificate(X509CertificateStructure.GetInstance(obj));
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new RequestedCertificate((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static RequestedCertificate GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ if (!isExplicit)
+ throw new ArgumentException("choice item must be explicitly tagged");
+
+ return GetInstance(obj.GetObject());
+ }
+
+ private RequestedCertificate(
+ Asn1TaggedObject tagged)
+ {
+ switch ((Choice) tagged.TagNo)
+ {
+ case Choice.AttributeCertificate:
+ this.attributeCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
+ break;
+ case Choice.PublicKeyCertificate:
+ this.publicKeyCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tagged.TagNo);
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p/>
+ * Only one parameter can be given. All other must be <code>null</code>.
+ *
+ * @param certificate Given as Certificate
+ */
+ public RequestedCertificate(
+ X509CertificateStructure certificate)
+ {
+ this.cert = certificate;
+ }
+
+ public RequestedCertificate(
+ Choice type,
+ byte[] certificateOctets)
+ : this(new DerTaggedObject((int) type, new DerOctetString(certificateOctets)))
+ {
+ }
+
+ public Choice Type
+ {
+ get
+ {
+ if (cert != null)
+ return Choice.Certificate;
+
+ if (publicKeyCert != null)
+ return Choice.PublicKeyCertificate;
+
+ return Choice.AttributeCertificate;
+ }
+ }
+
+ public byte[] GetCertificateBytes()
+ {
+ if (cert != null)
+ {
+ try
+ {
+ return cert.GetEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new InvalidOperationException("can't decode certificate: " + e);
+ }
+ }
+
+ if (publicKeyCert != null)
+ return publicKeyCert;
+
+ return attributeCert;
+ }
+
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (publicKeyCert != null)
+ {
+ return new DerTaggedObject(0, new DerOctetString(publicKeyCert));
+ }
+
+ if (attributeCert != null)
+ {
+ return new DerTaggedObject(1, new DerOctetString(attributeCert));
+ }
+
+ return cert.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs b/Crypto/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs
new file mode 100644
index 000000000..f81d459c6
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * Some other information of non-restrictive nature regarding the usage of this
+ * certificate.
+ *
+ * <pre>
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * </pre>
+ */
+ public class AdditionalInformationSyntax
+ : Asn1Encodable
+ {
+ private readonly DirectoryString information;
+
+ public static AdditionalInformationSyntax GetInstance(
+ object obj)
+ {
+ if (obj is AdditionalInformationSyntax)
+ return (AdditionalInformationSyntax) obj;
+
+ if (obj is IAsn1String)
+ return new AdditionalInformationSyntax(DirectoryString.GetInstance(obj));
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().Name, "obj");
+ }
+
+ private AdditionalInformationSyntax(
+ DirectoryString information)
+ {
+ this.information = information;
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param information The describtion of the information.
+ */
+ public AdditionalInformationSyntax(
+ string information)
+ {
+ this.information = new DirectoryString(information);
+ }
+
+ public virtual DirectoryString Information
+ {
+ get { return information; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return information.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs b/Crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs
new file mode 100644
index 000000000..f322ef88f
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/AdmissionSyntax.cs
Binary files differdiff --git a/Crypto/src/asn1/isismtt/x509/Admissions.cs b/Crypto/src/asn1/isismtt/x509/Admissions.cs
new file mode 100644
index 000000000..40290c608
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/Admissions.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * An Admissions structure.
+ * <p/>
+ * <pre>
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ * <p/>
+ * </pre>
+ *
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority
+ */
+ public class Admissions
+ : Asn1Encodable
+ {
+ private readonly GeneralName admissionAuthority;
+ private readonly NamingAuthority namingAuthority;
+ private readonly Asn1Sequence professionInfos;
+
+ public static Admissions GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Admissions)
+ {
+ return (Admissions) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Admissions((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * The sequence is of type ProcurationSyntax:
+ * <p/>
+ * <pre>
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private Admissions(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ Asn1Encodable o = (Asn1Encodable) e.Current;
+ if (o is Asn1TaggedObject)
+ {
+ switch (((Asn1TaggedObject)o).TagNo)
+ {
+ case 0:
+ admissionAuthority = GeneralName.GetInstance((Asn1TaggedObject)o, true);
+ break;
+ case 1:
+ namingAuthority = NamingAuthority.GetInstance((Asn1TaggedObject)o, true);
+ break;
+ default:
+ throw new ArgumentException("Bad tag number: " + ((Asn1TaggedObject)o).TagNo);
+ }
+ e.MoveNext();
+ o = (Asn1Encodable) e.Current;
+ }
+ if (o is Asn1TaggedObject)
+ {
+ switch (((Asn1TaggedObject)o).TagNo)
+ {
+ case 1:
+ namingAuthority = NamingAuthority.GetInstance((Asn1TaggedObject)o, true);
+ break;
+ default:
+ throw new ArgumentException("Bad tag number: " + ((Asn1TaggedObject)o).TagNo);
+ }
+ e.MoveNext();
+ o = (Asn1Encodable) e.Current;
+ }
+ professionInfos = Asn1Sequence.GetInstance(o);
+ if (e.MoveNext())
+ {
+ throw new ArgumentException("Bad object encountered: " + e.Current.GetType().Name);
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p/>
+ * Parameter <code>professionInfos</code> is mandatory.
+ *
+ * @param admissionAuthority The admission authority.
+ * @param namingAuthority The naming authority.
+ * @param professionInfos The profession infos.
+ */
+ public Admissions(
+ GeneralName admissionAuthority,
+ NamingAuthority namingAuthority,
+ ProfessionInfo[] professionInfos)
+ {
+ this.admissionAuthority = admissionAuthority;
+ this.namingAuthority = namingAuthority;
+ this.professionInfos = new DerSequence(professionInfos);
+ }
+
+ public virtual GeneralName AdmissionAuthority
+ {
+ get { return admissionAuthority; }
+ }
+
+ public virtual NamingAuthority NamingAuthority
+ {
+ get { return namingAuthority; }
+ }
+
+ public ProfessionInfo[] GetProfessionInfos()
+ {
+ ProfessionInfo[] infos = new ProfessionInfo[professionInfos.Count];
+ int count = 0;
+ foreach (Asn1Encodable ae in professionInfos)
+ {
+ infos[count++] = ProfessionInfo.GetInstance(ae);
+ }
+ return infos;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ * <p/>
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+
+ if (admissionAuthority != null)
+ {
+ vec.Add(new DerTaggedObject(true, 0, admissionAuthority));
+ }
+
+ if (namingAuthority != null)
+ {
+ vec.Add(new DerTaggedObject(true, 1, namingAuthority));
+ }
+
+ vec.Add(professionInfos);
+
+ return new DerSequence(vec);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs b/Crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
new file mode 100644
index 000000000..dfac65040
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/DeclarationOfMajority.cs
@@ -0,0 +1,170 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * A declaration of majority.
+ * <p/>
+ * <pre>
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ * </pre>
+ * <p/>
+ * fullAgeAtCountry indicates the majority of the owner with respect to the laws
+ * of a specific country.
+ */
+ public class DeclarationOfMajority
+ : Asn1Encodable, IAsn1Choice
+ {
+ public enum Choice
+ {
+ NotYoungerThan = 0,
+ FullAgeAtCountry = 1,
+ DateOfBirth = 2
+ };
+
+ private readonly Asn1TaggedObject declaration;
+
+ public DeclarationOfMajority(
+ int notYoungerThan)
+ {
+ declaration = new DerTaggedObject(false, 0, new DerInteger(notYoungerThan));
+ }
+
+ public DeclarationOfMajority(
+ bool fullAge,
+ string country)
+ {
+ if (country.Length > 2)
+ throw new ArgumentException("country can only be 2 characters");
+
+ DerPrintableString countryString = new DerPrintableString(country, true);
+
+ DerSequence seq;
+ if (fullAge)
+ {
+ seq = new DerSequence(countryString);
+ }
+ else
+ {
+ seq = new DerSequence(DerBoolean.False, countryString);
+ }
+
+ this.declaration = new DerTaggedObject(false, 1, seq);
+ }
+
+ public DeclarationOfMajority(
+ DerGeneralizedTime dateOfBirth)
+ {
+ this.declaration = new DerTaggedObject(false, 2, dateOfBirth);
+ }
+
+ public static DeclarationOfMajority GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is DeclarationOfMajority)
+ {
+ return (DeclarationOfMajority) obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new DeclarationOfMajority((Asn1TaggedObject) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private DeclarationOfMajority(
+ Asn1TaggedObject o)
+ {
+ if (o.TagNo > 2)
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+
+ this.declaration = o;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return declaration;
+ }
+
+ public Choice Type
+ {
+ get { return (Choice) declaration.TagNo; }
+ }
+
+ /**
+ * @return notYoungerThan if that's what we are, -1 otherwise
+ */
+ public virtual int NotYoungerThan
+ {
+ get
+ {
+ switch ((Choice) declaration.TagNo)
+ {
+ case Choice.NotYoungerThan:
+ return DerInteger.GetInstance(declaration, false).Value.IntValue;
+ default:
+ return -1;
+ }
+ }
+ }
+
+ public virtual Asn1Sequence FullAgeAtCountry
+ {
+ get
+ {
+ switch ((Choice) declaration.TagNo)
+ {
+ case Choice.FullAgeAtCountry:
+ return Asn1Sequence.GetInstance(declaration, false);
+ default:
+ return null;
+ }
+ }
+ }
+
+ public virtual DerGeneralizedTime DateOfBirth
+ {
+ get
+ {
+ switch ((Choice) declaration.TagNo)
+ {
+ case Choice.DateOfBirth:
+ return DerGeneralizedTime.GetInstance(declaration, false);
+ default:
+ return null;
+ }
+ }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/MonetaryLimit.cs b/Crypto/src/asn1/isismtt/x509/MonetaryLimit.cs
new file mode 100644
index 000000000..80b6b684b
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/MonetaryLimit.cs
@@ -0,0 +1,121 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST be
+ * used in new certificates in place of the extension/attribute MonetaryLimit
+ * since January 1, 2004. For the sake of backward compatibility with
+ * certificates already in use, components SHOULD support MonetaryLimit (as well
+ * as QcEuLimitValue).
+ * <p/>
+ * Indicates a monetary limit within which the certificate holder is authorized
+ * to act. (This value DOES NOT express a limit on the liability of the
+ * certification authority).
+ * <p/>
+ * <pre>
+ * MonetaryLimitSyntax ::= SEQUENCE
+ * {
+ * currency PrintableString (SIZE(3)),
+ * amount INTEGER,
+ * exponent INTEGER
+ * }
+ * </pre>
+ * <p/>
+ * currency must be the ISO code.
+ * <p/>
+ * value = amount�10*exponent
+ */
+ public class MonetaryLimit
+ : Asn1Encodable
+ {
+ private readonly DerPrintableString currency;
+ private readonly DerInteger amount;
+ private readonly DerInteger exponent;
+
+ public static MonetaryLimit GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is MonetaryLimit)
+ {
+ return (MonetaryLimit) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new MonetaryLimit(Asn1Sequence.GetInstance(obj));
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ private MonetaryLimit(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ currency = DerPrintableString.GetInstance(seq[0]);
+ amount = DerInteger.GetInstance(seq[1]);
+ exponent = DerInteger.GetInstance(seq[2]);
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p/>
+ * <p/>
+ * value = amount�10^exponent
+ *
+ * @param currency The currency. Must be the ISO code.
+ * @param amount The amount
+ * @param exponent The exponent
+ */
+ public MonetaryLimit(
+ string currency,
+ int amount,
+ int exponent)
+ {
+ this.currency = new DerPrintableString(currency, true);
+ this.amount = new DerInteger(amount);
+ this.exponent = new DerInteger(exponent);
+ }
+
+ public virtual string Currency
+ {
+ get { return currency.GetString(); }
+ }
+
+ public virtual BigInteger Amount
+ {
+ get { return amount.Value; }
+ }
+
+ public virtual BigInteger Exponent
+ {
+ get { return exponent.Value; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * MonetaryLimitSyntax ::= SEQUENCE
+ * {
+ * currency PrintableString (SIZE(3)),
+ * amount INTEGER,
+ * exponent INTEGER
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(currency, amount, exponent);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/NamingAuthority.cs b/Crypto/src/asn1/isismtt/x509/NamingAuthority.cs
new file mode 100644
index 000000000..4262fd0f4
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/NamingAuthority.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * Names of authorities which are responsible for the administration of title
+ * registers.
+ *
+ * <pre>
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ * </pre>
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+ *
+ */
+ public class NamingAuthority
+ : Asn1Encodable
+ {
+ /**
+ * Profession OIDs should always be defined under the OID branch of the
+ * responsible naming authority. At the time of this writing, the work group
+ * �Recht, Wirtschaft, Steuern� (�Law, Economy, Taxes�) is registered as the
+ * first naming authority under the OID id-isismtt-at-namingAuthorities.
+ */
+ public static readonly DerObjectIdentifier IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern
+ = new DerObjectIdentifier(IsisMttObjectIdentifiers.IdIsisMttATNamingAuthorities + ".1");
+
+ private readonly DerObjectIdentifier namingAuthorityID;
+ private readonly string namingAuthorityUrl;
+ private readonly DirectoryString namingAuthorityText;
+
+ public static NamingAuthority GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is NamingAuthority)
+ {
+ return (NamingAuthority) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new NamingAuthority((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static NamingAuthority GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * <p/>
+ * <pre>
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private NamingAuthority(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ IEnumerator e = seq.GetEnumerator();
+
+ if (e.MoveNext())
+ {
+ Asn1Encodable o = (Asn1Encodable) e.Current;
+ if (o is DerObjectIdentifier)
+ {
+ namingAuthorityID = (DerObjectIdentifier) o;
+ }
+ else if (o is DerIA5String)
+ {
+ namingAuthorityUrl = DerIA5String.GetInstance(o).GetString();
+ }
+ else if (o is IAsn1String)
+ {
+ namingAuthorityText = DirectoryString.GetInstance(o);
+ }
+ else
+ {
+ throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+ }
+ }
+
+ if (e.MoveNext())
+ {
+ Asn1Encodable o = (Asn1Encodable) e.Current;
+ if (o is DerIA5String)
+ {
+ namingAuthorityUrl = DerIA5String.GetInstance(o).GetString();
+ }
+ else if (o is IAsn1String)
+ {
+ namingAuthorityText = DirectoryString.GetInstance(o);
+ }
+ else
+ {
+ throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+ }
+ }
+
+ if (e.MoveNext())
+ {
+ Asn1Encodable o = (Asn1Encodable) e.Current;
+ if (o is IAsn1String)
+ {
+ namingAuthorityText = DirectoryString.GetInstance(o);
+ }
+ else
+ {
+ throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+ }
+ }
+ }
+
+ /**
+ * @return Returns the namingAuthorityID.
+ */
+ public virtual DerObjectIdentifier NamingAuthorityID
+ {
+ get { return namingAuthorityID; }
+ }
+
+ /**
+ * @return Returns the namingAuthorityText.
+ */
+ public virtual DirectoryString NamingAuthorityText
+ {
+ get { return namingAuthorityText; }
+ }
+
+ /**
+ * @return Returns the namingAuthorityUrl.
+ */
+ public virtual string NamingAuthorityUrl
+ {
+ get { return namingAuthorityUrl; }
+ }
+
+ /**
+ * Constructor from given details.
+ * <p/>
+ * All parameters can be combined.
+ *
+ * @param namingAuthorityID ObjectIdentifier for naming authority.
+ * @param namingAuthorityUrl URL for naming authority.
+ * @param namingAuthorityText Textual representation of naming authority.
+ */
+ public NamingAuthority(
+ DerObjectIdentifier namingAuthorityID,
+ string namingAuthorityUrl,
+ DirectoryString namingAuthorityText)
+ {
+ this.namingAuthorityID = namingAuthorityID;
+ this.namingAuthorityUrl = namingAuthorityUrl;
+ this.namingAuthorityText = namingAuthorityText;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+ if (namingAuthorityID != null)
+ {
+ vec.Add(namingAuthorityID);
+ }
+ if (namingAuthorityUrl != null)
+ {
+ vec.Add(new DerIA5String(namingAuthorityUrl, true));
+ }
+ if (namingAuthorityText != null)
+ {
+ vec.Add(namingAuthorityText);
+ }
+ return new DerSequence(vec);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs b/Crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs
new file mode 100644
index 000000000..a25df225e
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/ProcurationSyntax.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * Attribute to indicate that the certificate holder may sign in the name of a
+ * third person.
+ * <p>
+ * ISIS-MTT PROFILE: The corresponding ProcurationSyntax contains either the
+ * name of the person who is represented (subcomponent thirdPerson) or a
+ * reference to his/her base certificate (in the component signingFor,
+ * subcomponent certRef), furthermore the optional components country and
+ * typeSubstitution to indicate the country whose laws apply, and respectively
+ * the type of procuration (e.g. manager, procuration, custody).
+ * </p>
+ * <p>
+ * ISIS-MTT PROFILE: The GeneralName MUST be of type directoryName and MAY only
+ * contain: - RFC3039 attributes, except pseudonym (countryName, commonName,
+ * surname, givenName, serialNumber, organizationName, organizationalUnitName,
+ * stateOrProvincename, localityName, postalAddress) and - SubjectDirectoryName
+ * attributes (title, dateOfBirth, placeOfBirth, gender, countryOfCitizenship,
+ * countryOfResidence and NameAtBirth).
+ * </p>
+ * <pre>
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ *
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ * </pre>
+ *
+ */
+ public class ProcurationSyntax
+ : Asn1Encodable
+ {
+ private readonly string country;
+ private readonly DirectoryString typeOfSubstitution;
+ private readonly GeneralName thirdPerson;
+ private readonly IssuerSerial certRef;
+
+ public static ProcurationSyntax GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ProcurationSyntax)
+ {
+ return (ProcurationSyntax) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ProcurationSyntax((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * The sequence is of type ProcurationSyntax:
+ * <p/>
+ * <pre>
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ * <p/>
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private ProcurationSyntax(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 1 || seq.Count > 3)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ IEnumerator e = seq.GetEnumerator();
+
+ while (e.MoveNext())
+ {
+ Asn1TaggedObject o = Asn1TaggedObject.GetInstance(e.Current);
+ switch (o.TagNo)
+ {
+ case 1:
+ country = DerPrintableString.GetInstance(o, true).GetString();
+ break;
+ case 2:
+ typeOfSubstitution = DirectoryString.GetInstance(o, true);
+ break;
+ case 3:
+ Asn1Object signingFor = o.GetObject();
+ if (signingFor is Asn1TaggedObject)
+ {
+ thirdPerson = GeneralName.GetInstance(signingFor);
+ }
+ else
+ {
+ certRef = IssuerSerial.GetInstance(signingFor);
+ }
+ break;
+ default:
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p/>
+ * <p/>
+ * Either <code>generalName</code> or <code>certRef</code> MUST be
+ * <code>null</code>.
+ *
+ * @param country The country code whose laws apply.
+ * @param typeOfSubstitution The type of procuration.
+ * @param certRef Reference to certificate of the person who is represented.
+ */
+ public ProcurationSyntax(
+ string country,
+ DirectoryString typeOfSubstitution,
+ IssuerSerial certRef)
+ {
+ this.country = country;
+ this.typeOfSubstitution = typeOfSubstitution;
+ this.thirdPerson = null;
+ this.certRef = certRef;
+ }
+
+ /**
+ * Constructor from a given details.
+ * <p/>
+ * <p/>
+ * Either <code>generalName</code> or <code>certRef</code> MUST be
+ * <code>null</code>.
+ *
+ * @param country The country code whose laws apply.
+ * @param typeOfSubstitution The type of procuration.
+ * @param thirdPerson The GeneralName of the person who is represented.
+ */
+ public ProcurationSyntax(
+ string country,
+ DirectoryString typeOfSubstitution,
+ GeneralName thirdPerson)
+ {
+ this.country = country;
+ this.typeOfSubstitution = typeOfSubstitution;
+ this.thirdPerson = thirdPerson;
+ this.certRef = null;
+ }
+
+ public virtual string Country
+ {
+ get { return country; }
+ }
+
+ public virtual DirectoryString TypeOfSubstitution
+ {
+ get { return typeOfSubstitution; }
+ }
+
+ public virtual GeneralName ThirdPerson
+ {
+ get { return thirdPerson; }
+ }
+
+ public virtual IssuerSerial CertRef
+ {
+ get { return certRef; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ * <p/>
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+ if (country != null)
+ {
+ vec.Add(new DerTaggedObject(true, 1, new DerPrintableString(country, true)));
+ }
+ if (typeOfSubstitution != null)
+ {
+ vec.Add(new DerTaggedObject(true, 2, typeOfSubstitution));
+ }
+ if (thirdPerson != null)
+ {
+ vec.Add(new DerTaggedObject(true, 3, thirdPerson));
+ }
+ else
+ {
+ vec.Add(new DerTaggedObject(true, 3, certRef));
+ }
+
+ return new DerSequence(vec);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/ProfessionInfo.cs b/Crypto/src/asn1/isismtt/x509/ProfessionInfo.cs
new file mode 100644
index 000000000..3bad2cbc4
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/ProfessionInfo.cs
@@ -0,0 +1,386 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * Professions, specializations, disciplines, fields of activity, etc.
+ *
+ * <pre>
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+ */
+ public class ProfessionInfo
+ : Asn1Encodable
+ {
+ /**
+ * Rechtsanw�ltin
+ */
+ public static readonly DerObjectIdentifier Rechtsanwltin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".1");
+
+ /**
+ * Rechtsanwalt
+ */
+ public static readonly DerObjectIdentifier Rechtsanwalt = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".2");
+
+ /**
+ * Rechtsbeistand
+ */
+ public static readonly DerObjectIdentifier Rechtsbeistand = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".3");
+
+ /**
+ * Steuerberaterin
+ */
+ public static readonly DerObjectIdentifier Steuerberaterin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".4");
+
+ /**
+ * Steuerberater
+ */
+ public static readonly DerObjectIdentifier Steuerberater = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".5");
+
+ /**
+ * Steuerbevollm�chtigte
+ */
+ public static readonly DerObjectIdentifier Steuerbevollmchtigte = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".6");
+
+ /**
+ * Steuerbevollm�chtigter
+ */
+ public static readonly DerObjectIdentifier Steuerbevollmchtigter = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".7");
+
+ /**
+ * Notarin
+ */
+ public static readonly DerObjectIdentifier Notarin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".8");
+
+ /**
+ * Notar
+ */
+ public static readonly DerObjectIdentifier Notar = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".9");
+
+ /**
+ * Notarvertreterin
+ */
+ public static readonly DerObjectIdentifier Notarvertreterin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".10");
+
+ /**
+ * Notarvertreter
+ */
+ public static readonly DerObjectIdentifier Notarvertreter = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".11");
+
+ /**
+ * Notariatsverwalterin
+ */
+ public static readonly DerObjectIdentifier Notariatsverwalterin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".12");
+
+ /**
+ * Notariatsverwalter
+ */
+ public static readonly DerObjectIdentifier Notariatsverwalter = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".13");
+
+ /**
+ * Wirtschaftspr�ferin
+ */
+ public static readonly DerObjectIdentifier Wirtschaftsprferin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".14");
+
+ /**
+ * Wirtschaftspr�fer
+ */
+ public static readonly DerObjectIdentifier Wirtschaftsprfer = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".15");
+
+ /**
+ * Vereidigte Buchpr�ferin
+ */
+ public static readonly DerObjectIdentifier VereidigteBuchprferin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".16");
+
+ /**
+ * Vereidigter Buchpr�fer
+ */
+ public static readonly DerObjectIdentifier VereidigterBuchprfer = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".17");
+
+ /**
+ * Patentanw�ltin
+ */
+ public static readonly DerObjectIdentifier Patentanwltin = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".18");
+
+ /**
+ * Patentanwalt
+ */
+ public static readonly DerObjectIdentifier Patentanwalt = new DerObjectIdentifier(
+ NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".19");
+
+ private readonly NamingAuthority namingAuthority;
+ private readonly Asn1Sequence professionItems;
+ private readonly Asn1Sequence professionOids;
+ private readonly string registrationNumber;
+ private readonly Asn1OctetString addProfessionInfo;
+
+ public static ProfessionInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ProfessionInfo)
+ {
+ return (ProfessionInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ProfessionInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * <p/>
+ * <pre>
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private ProfessionInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count > 5)
+ throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ Asn1Encodable o = (Asn1Encodable) e.Current;
+
+ if (o is Asn1TaggedObject)
+ {
+ Asn1TaggedObject ato = (Asn1TaggedObject) o;
+ if (ato.TagNo != 0)
+ throw new ArgumentException("Bad tag number: " + ato.TagNo);
+
+ namingAuthority = NamingAuthority.GetInstance(ato, true);
+ e.MoveNext();
+ o = (Asn1Encodable) e.Current;
+ }
+
+ professionItems = Asn1Sequence.GetInstance(o);
+
+ if (e.MoveNext())
+ {
+ o = (Asn1Encodable) e.Current;
+ if (o is Asn1Sequence)
+ {
+ professionOids = Asn1Sequence.GetInstance(o);
+ }
+ else if (o is DerPrintableString)
+ {
+ registrationNumber = DerPrintableString.GetInstance(o).GetString();
+ }
+ else if (o is Asn1OctetString)
+ {
+ addProfessionInfo = Asn1OctetString.GetInstance(o);
+ }
+ else
+ {
+ throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+ }
+ }
+
+ if (e.MoveNext())
+ {
+ o = (Asn1Encodable) e.Current;
+ if (o is DerPrintableString)
+ {
+ registrationNumber = DerPrintableString.GetInstance(o).GetString();
+ }
+ else if (o is DerOctetString)
+ {
+ addProfessionInfo = (DerOctetString) o;
+ }
+ else
+ {
+ throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+ }
+ }
+
+ if (e.MoveNext())
+ {
+ o = (Asn1Encodable) e.Current;
+ if (o is DerOctetString)
+ {
+ addProfessionInfo = (DerOctetString) o;
+ }
+ else
+ {
+ throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+ }
+ }
+ }
+
+ /**
+ * Constructor from given details.
+ * <p/>
+ * <code>professionItems</code> is mandatory, all other parameters are
+ * optional.
+ *
+ * @param namingAuthority The naming authority.
+ * @param professionItems Directory strings of the profession.
+ * @param professionOids DERObjectIdentfier objects for the
+ * profession.
+ * @param registrationNumber Registration number.
+ * @param addProfessionInfo Additional infos in encoded form.
+ */
+ public ProfessionInfo(
+ NamingAuthority namingAuthority,
+ DirectoryString[] professionItems,
+ DerObjectIdentifier[] professionOids,
+ string registrationNumber,
+ Asn1OctetString addProfessionInfo)
+ {
+ this.namingAuthority = namingAuthority;
+ this.professionItems = new DerSequence(professionItems);
+ if (professionOids != null)
+ {
+ this.professionOids = new DerSequence(professionOids);
+ }
+ this.registrationNumber = registrationNumber;
+ this.addProfessionInfo = addProfessionInfo;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+ if (namingAuthority != null)
+ {
+ vec.Add(new DerTaggedObject(true, 0, namingAuthority));
+ }
+ vec.Add(professionItems);
+ if (professionOids != null)
+ {
+ vec.Add(professionOids);
+ }
+ if (registrationNumber != null)
+ {
+ vec.Add(new DerPrintableString(registrationNumber, true));
+ }
+ if (addProfessionInfo != null)
+ {
+ vec.Add(addProfessionInfo);
+ }
+ return new DerSequence(vec);
+ }
+
+ /**
+ * @return Returns the addProfessionInfo.
+ */
+ public virtual Asn1OctetString AddProfessionInfo
+ {
+ get { return addProfessionInfo; }
+ }
+
+ /**
+ * @return Returns the namingAuthority.
+ */
+ public virtual NamingAuthority NamingAuthority
+ {
+ get { return namingAuthority; }
+ }
+
+ /**
+ * @return Returns the professionItems.
+ */
+ public virtual DirectoryString[] GetProfessionItems()
+ {
+ DirectoryString[] result = new DirectoryString[professionItems.Count];
+
+ for (int i = 0; i < professionItems.Count; ++i)
+ {
+ result[i] = DirectoryString.GetInstance(professionItems[i]);
+ }
+
+ return result;
+ }
+
+ /**
+ * @return Returns the professionOids.
+ */
+ public virtual DerObjectIdentifier[] GetProfessionOids()
+ {
+ if (professionOids == null)
+ {
+ return new DerObjectIdentifier[0];
+ }
+
+ DerObjectIdentifier[] result = new DerObjectIdentifier[professionOids.Count];
+
+ for (int i = 0; i < professionOids.Count; ++i)
+ {
+ result[i] = DerObjectIdentifier.GetInstance(professionOids[i]);
+ }
+
+ return result;
+ }
+
+ /**
+ * @return Returns the registrationNumber.
+ */
+ public virtual string RegistrationNumber
+ {
+ get { return registrationNumber; }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/isismtt/x509/Restriction.cs b/Crypto/src/asn1/isismtt/x509/Restriction.cs
new file mode 100644
index 000000000..c97766999
--- /dev/null
+++ b/Crypto/src/asn1/isismtt/x509/Restriction.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+ /**
+ * Some other restriction regarding the usage of this certificate.
+ * <p/>
+ * <pre>
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * </pre>
+ */
+ public class Restriction
+ : Asn1Encodable
+ {
+ private readonly DirectoryString restriction;
+
+ public static Restriction GetInstance(
+ object obj)
+ {
+ if (obj is Restriction)
+ return (Restriction) obj;
+
+ if (obj is IAsn1String)
+ return new Restriction(DirectoryString.GetInstance(obj));
+
+ throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from DirectoryString.
+ * <p/>
+ * The DirectoryString is of type RestrictionSyntax:
+ * <p/>
+ * <pre>
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * </pre>
+ *
+ * @param restriction A IAsn1String.
+ */
+ private Restriction(
+ DirectoryString restriction)
+ {
+ this.restriction = restriction;
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param restriction The description of the restriction.
+ */
+ public Restriction(
+ string restriction)
+ {
+ this.restriction = new DirectoryString(restriction);
+ }
+
+ public virtual DirectoryString RestrictionString
+ {
+ get { return restriction; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ * <p/>
+ * </pre>
+ *
+ * @return an Asn1Object
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return restriction.ToAsn1Object();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/kisa/KISAObjectIdentifiers.cs b/Crypto/src/asn1/kisa/KISAObjectIdentifiers.cs
new file mode 100644
index 000000000..05351ec75
--- /dev/null
+++ b/Crypto/src/asn1/kisa/KISAObjectIdentifiers.cs
@@ -0,0 +1,8 @@
+namespace Org.BouncyCastle.Asn1.Kisa
+{
+ public abstract class KisaObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier IdSeedCbc = new DerObjectIdentifier("1.2.410.200004.1.4");
+ public static readonly DerObjectIdentifier IdNpkiAppCmsSeedWrap = new DerObjectIdentifier("1.2.410.200004.7.1.1.1");
+ }
+}
diff --git a/Crypto/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs b/Crypto/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs
new file mode 100644
index 000000000..b8aba7ee9
--- /dev/null
+++ b/Crypto/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Microsoft
+{
+ public abstract class MicrosoftObjectIdentifiers
+ {
+ //
+ // Microsoft
+ // iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) Microsoft(311)
+ //
+ public static readonly DerObjectIdentifier Microsoft = new DerObjectIdentifier("1.3.6.1.4.1.311");
+ public static readonly DerObjectIdentifier MicrosoftCertTemplateV1 = new DerObjectIdentifier(Microsoft + ".20.2");
+ public static readonly DerObjectIdentifier MicrosoftCAVersion = new DerObjectIdentifier(Microsoft + ".21.1");
+ public static readonly DerObjectIdentifier MicrosoftPrevCACertHash = new DerObjectIdentifier(Microsoft + ".21.2");
+ public static readonly DerObjectIdentifier MicrosoftCertTemplateV2 = new DerObjectIdentifier(Microsoft + ".21.7");
+ public static readonly DerObjectIdentifier MicrosoftAppPolicies = new DerObjectIdentifier(Microsoft + ".21.10");
+ }
+}
diff --git a/Crypto/src/asn1/misc/CAST5CBCParameters.cs b/Crypto/src/asn1/misc/CAST5CBCParameters.cs
new file mode 100644
index 000000000..51fd6607a
--- /dev/null
+++ b/Crypto/src/asn1/misc/CAST5CBCParameters.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+ public class Cast5CbcParameters
+ : Asn1Encodable
+ {
+ private readonly DerInteger keyLength;
+ private readonly Asn1OctetString iv;
+
+ public static Cast5CbcParameters GetInstance(
+ object o)
+ {
+ if (o is Cast5CbcParameters)
+ {
+ return (Cast5CbcParameters) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new Cast5CbcParameters((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException("unknown object in Cast5CbcParameters factory");
+ }
+
+ public Cast5CbcParameters(
+ byte[] iv,
+ int keyLength)
+ {
+ this.iv = new DerOctetString(iv);
+ this.keyLength = new DerInteger(keyLength);
+ }
+
+ private Cast5CbcParameters(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ iv = (Asn1OctetString) seq[0];
+ keyLength = (DerInteger) seq[1];
+ }
+
+ public byte[] GetIV()
+ {
+ return Arrays.Clone(iv.GetOctets());
+ }
+
+ public int KeyLength
+ {
+ get { return keyLength.Value.IntValue; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * cast5CBCParameters ::= Sequence {
+ * iv OCTET STRING DEFAULT 0,
+ * -- Initialization vector
+ * keyLength Integer
+ * -- Key length, in bits
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(iv, keyLength);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/misc/IDEACBCPar.cs b/Crypto/src/asn1/misc/IDEACBCPar.cs
new file mode 100644
index 000000000..72a60b9dc
--- /dev/null
+++ b/Crypto/src/asn1/misc/IDEACBCPar.cs
@@ -0,0 +1,68 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+ public class IdeaCbcPar
+ : Asn1Encodable
+ {
+ internal Asn1OctetString iv;
+
+ public static IdeaCbcPar GetInstance(
+ object o)
+ {
+ if (o is IdeaCbcPar)
+ {
+ return (IdeaCbcPar) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new IdeaCbcPar((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException("unknown object in IDEACBCPar factory");
+ }
+
+ public IdeaCbcPar(
+ byte[] iv)
+ {
+ this.iv = new DerOctetString(iv);
+ }
+
+ private IdeaCbcPar(
+ Asn1Sequence seq)
+ {
+ if (seq.Count == 1)
+ {
+ iv = (Asn1OctetString) seq[0];
+ }
+ }
+
+ public byte[] GetIV()
+ {
+ return iv == null ? null : iv.GetOctets();
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * IDEA-CBCPar ::= Sequence {
+ * iv OCTET STRING OPTIONAL -- exactly 8 octets
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (iv != null)
+ {
+ v.Add(iv);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/misc/MiscObjectIdentifiers.cs b/Crypto/src/asn1/misc/MiscObjectIdentifiers.cs
new file mode 100644
index 000000000..01004d889
--- /dev/null
+++ b/Crypto/src/asn1/misc/MiscObjectIdentifiers.cs
@@ -0,0 +1,48 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+ public abstract class MiscObjectIdentifiers
+ {
+ //
+ // Netscape
+ // iso/itu(2) joint-assign(16) us(840) uscompany(1) Netscape(113730) cert-extensions(1) }
+ //
+ public static readonly DerObjectIdentifier Netscape = new DerObjectIdentifier("2.16.840.1.113730.1");
+ public static readonly DerObjectIdentifier NetscapeCertType = new DerObjectIdentifier(Netscape + ".1");
+ public static readonly DerObjectIdentifier NetscapeBaseUrl = new DerObjectIdentifier(Netscape + ".2");
+ public static readonly DerObjectIdentifier NetscapeRevocationUrl = new DerObjectIdentifier(Netscape + ".3");
+ public static readonly DerObjectIdentifier NetscapeCARevocationUrl = new DerObjectIdentifier(Netscape + ".4");
+ public static readonly DerObjectIdentifier NetscapeRenewalUrl = new DerObjectIdentifier(Netscape + ".7");
+ public static readonly DerObjectIdentifier NetscapeCAPolicyUrl = new DerObjectIdentifier(Netscape + ".8");
+ public static readonly DerObjectIdentifier NetscapeSslServerName = new DerObjectIdentifier(Netscape + ".12");
+ public static readonly DerObjectIdentifier NetscapeCertComment = new DerObjectIdentifier(Netscape + ".13");
+ //
+ // Verisign
+ // iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) }
+ //
+ internal const string Verisign = "2.16.840.1.113733.1";
+
+ //
+ // CZAG - country, zip, age, and gender
+ //
+ public static readonly DerObjectIdentifier VerisignCzagExtension = new DerObjectIdentifier(Verisign + ".6.3");
+
+ // D&B D-U-N-S number
+ public static readonly DerObjectIdentifier VerisignDnbDunsNumber = new DerObjectIdentifier(Verisign + ".6.15");
+
+ //
+ // Novell
+ // iso/itu(2) country(16) us(840) organization(1) novell(113719)
+ //
+ public static readonly string Novell = "2.16.840.1.113719";
+ public static readonly DerObjectIdentifier NovellSecurityAttribs = new DerObjectIdentifier(Novell + ".1.9.4.1");
+
+ //
+ // Entrust
+ // iso(1) member-body(16) us(840) nortelnetworks(113533) entrust(7)
+ //
+ public static readonly string Entrust = "1.2.840.113533.7";
+ public static readonly DerObjectIdentifier EntrustVersionExtension = new DerObjectIdentifier(Entrust + ".65.0");
+ }
+}
diff --git a/Crypto/src/asn1/misc/NetscapeCertType.cs b/Crypto/src/asn1/misc/NetscapeCertType.cs
new file mode 100644
index 000000000..d5db6523d
--- /dev/null
+++ b/Crypto/src/asn1/misc/NetscapeCertType.cs
@@ -0,0 +1,54 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+ /**
+ * The NetscapeCertType object.
+ * <pre>
+ * NetscapeCertType ::= BIT STRING {
+ * SSLClient (0),
+ * SSLServer (1),
+ * S/MIME (2),
+ * Object Signing (3),
+ * Reserved (4),
+ * SSL CA (5),
+ * S/MIME CA (6),
+ * Object Signing CA (7) }
+ * </pre>
+ */
+ public class NetscapeCertType
+ : DerBitString
+ {
+ public const int SslClient = (1 << 7);
+ public const int SslServer = (1 << 6);
+ public const int Smime = (1 << 5);
+ public const int ObjectSigning = (1 << 4);
+ public const int Reserved = (1 << 3);
+ public const int SslCA = (1 << 2);
+ public const int SmimeCA = (1 << 1);
+ public const int ObjectSigningCA = (1 << 0);
+
+ /**
+ * Basic constructor.
+ *
+ * @param usage - the bitwise OR of the Key Usage flags giving the
+ * allowed uses for the key.
+ * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
+ */
+ public NetscapeCertType(int usage)
+ : base(GetBytes(usage), GetPadBits(usage))
+ {
+ }
+
+ public NetscapeCertType(DerBitString usage)
+ : base(usage.GetBytes(), usage.PadBits)
+ {
+ }
+
+ public override string ToString()
+ {
+ byte[] data = GetBytes();
+ return "NetscapeCertType: 0x" + (data[0] & 0xff).ToString("X");
+ }
+ }
+}
diff --git a/Crypto/src/asn1/misc/NetscapeRevocationURL.cs b/Crypto/src/asn1/misc/NetscapeRevocationURL.cs
new file mode 100644
index 000000000..6cac031f2
--- /dev/null
+++ b/Crypto/src/asn1/misc/NetscapeRevocationURL.cs
@@ -0,0 +1,18 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+ public class NetscapeRevocationUrl
+ : DerIA5String
+ {
+ public NetscapeRevocationUrl(DerIA5String str)
+ : base(str.GetString())
+ {
+ }
+
+ public override string ToString()
+ {
+ return "NetscapeRevocationUrl: " + this.GetString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/misc/VerisignCzagExtension.cs b/Crypto/src/asn1/misc/VerisignCzagExtension.cs
new file mode 100644
index 000000000..1c3054b32
--- /dev/null
+++ b/Crypto/src/asn1/misc/VerisignCzagExtension.cs
@@ -0,0 +1,18 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+ public class VerisignCzagExtension
+ : DerIA5String
+ {
+ public VerisignCzagExtension(DerIA5String str)
+ : base(str.GetString())
+ {
+ }
+
+ public override string ToString()
+ {
+ return "VerisignCzagExtension: " + this.GetString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs b/Crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs
new file mode 100644
index 000000000..1e08b809d
--- /dev/null
+++ b/Crypto/src/asn1/mozilla/PublicKeyAndChallenge.cs
@@ -0,0 +1,67 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Mozilla
+{
+ /**
+ * This is designed to parse
+ * the PublicKeyAndChallenge created by the KEYGEN tag included by
+ * Mozilla based browsers.
+ * <pre>
+ * PublicKeyAndChallenge ::= SEQUENCE {
+ * spki SubjectPublicKeyInfo,
+ * challenge IA5STRING
+ * }
+ *
+ * </pre>
+ */
+ public class PublicKeyAndChallenge
+ : Asn1Encodable
+ {
+ private Asn1Sequence pkacSeq;
+ private SubjectPublicKeyInfo spki;
+ private DerIA5String challenge;
+
+ public static PublicKeyAndChallenge GetInstance(
+ object obj)
+ {
+ if (obj is PublicKeyAndChallenge)
+ {
+ return (PublicKeyAndChallenge) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new PublicKeyAndChallenge((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException(
+ "unknown object in 'PublicKeyAndChallenge' factory : "
+ + obj.GetType().Name + ".");
+ }
+
+ public PublicKeyAndChallenge(
+ Asn1Sequence seq)
+ {
+ pkacSeq = seq;
+ spki = SubjectPublicKeyInfo.GetInstance(seq[0]);
+ challenge = DerIA5String.GetInstance(seq[1]);
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return pkacSeq;
+ }
+
+ public SubjectPublicKeyInfo SubjectPublicKeyInfo
+ {
+ get { return spki; }
+ }
+
+ public DerIA5String Challenge
+ {
+ get { return challenge; }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/nist/NISTNamedCurves.cs b/Crypto/src/asn1/nist/NISTNamedCurves.cs
new file mode 100644
index 000000000..3b4c59df2
--- /dev/null
+++ b/Crypto/src/asn1/nist/NISTNamedCurves.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Nist
+{
+ /**
+ * Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-2
+ */
+ public sealed class NistNamedCurves
+ {
+ private NistNamedCurves()
+ {
+ }
+
+ private static readonly IDictionary objIds = Platform.CreateHashtable();
+ private static readonly IDictionary names = Platform.CreateHashtable();
+
+ private static void DefineCurve(
+ string name,
+ DerObjectIdentifier oid)
+ {
+ objIds.Add(name, oid);
+ names.Add(oid, name);
+ }
+
+ static NistNamedCurves()
+ {
+ DefineCurve("B-571", SecObjectIdentifiers.SecT571r1);
+ DefineCurve("B-409", SecObjectIdentifiers.SecT409r1);
+ DefineCurve("B-283", SecObjectIdentifiers.SecT283r1);
+ DefineCurve("B-233", SecObjectIdentifiers.SecT233r1);
+ DefineCurve("B-163", SecObjectIdentifiers.SecT163r2);
+ DefineCurve("P-521", SecObjectIdentifiers.SecP521r1);
+ DefineCurve("P-384", SecObjectIdentifiers.SecP384r1);
+ DefineCurve("P-256", SecObjectIdentifiers.SecP256r1);
+ DefineCurve("P-224", SecObjectIdentifiers.SecP224r1);
+ DefineCurve("P-192", SecObjectIdentifiers.SecP192r1);
+ }
+
+ public static X9ECParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name.ToUpperInvariant()];
+
+ if (oid != null)
+ {
+ return GetByOid(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ return SecNamedCurves.GetByOid(oid);
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier) objIds[name.ToUpperInvariant()];
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static string GetName(
+ DerObjectIdentifier oid)
+ {
+ return (string) names[oid];
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(objIds.Keys); }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/nist/NISTObjectIdentifiers.cs b/Crypto/src/asn1/nist/NISTObjectIdentifiers.cs
new file mode 100644
index 000000000..f3957062f
--- /dev/null
+++ b/Crypto/src/asn1/nist/NISTObjectIdentifiers.cs
@@ -0,0 +1,61 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Nist
+{
+ public sealed class NistObjectIdentifiers
+ {
+ private NistObjectIdentifiers()
+ {
+ }
+
+ //
+ // NIST
+ // iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
+
+ //
+ // nistalgorithms(4)
+ //
+ public static readonly DerObjectIdentifier NistAlgorithm = new DerObjectIdentifier("2.16.840.1.101.3.4");
+
+ public static readonly DerObjectIdentifier IdSha256 = new DerObjectIdentifier(NistAlgorithm + ".2.1");
+ public static readonly DerObjectIdentifier IdSha384 = new DerObjectIdentifier(NistAlgorithm + ".2.2");
+ public static readonly DerObjectIdentifier IdSha512 = new DerObjectIdentifier(NistAlgorithm + ".2.3");
+ public static readonly DerObjectIdentifier IdSha224 = new DerObjectIdentifier(NistAlgorithm + ".2.4");
+
+ public static readonly DerObjectIdentifier Aes = new DerObjectIdentifier(NistAlgorithm + ".1");
+
+ public static readonly DerObjectIdentifier IdAes128Ecb = new DerObjectIdentifier(Aes + ".1");
+ public static readonly DerObjectIdentifier IdAes128Cbc = new DerObjectIdentifier(Aes + ".2");
+ public static readonly DerObjectIdentifier IdAes128Ofb = new DerObjectIdentifier(Aes + ".3");
+ public static readonly DerObjectIdentifier IdAes128Cfb = new DerObjectIdentifier(Aes + ".4");
+ public static readonly DerObjectIdentifier IdAes128Wrap = new DerObjectIdentifier(Aes + ".5");
+ public static readonly DerObjectIdentifier IdAes128Gcm = new DerObjectIdentifier(Aes + ".6");
+ public static readonly DerObjectIdentifier IdAes128Ccm = new DerObjectIdentifier(Aes + ".7");
+
+ public static readonly DerObjectIdentifier IdAes192Ecb = new DerObjectIdentifier(Aes + ".21");
+ public static readonly DerObjectIdentifier IdAes192Cbc = new DerObjectIdentifier(Aes + ".22");
+ public static readonly DerObjectIdentifier IdAes192Ofb = new DerObjectIdentifier(Aes + ".23");
+ public static readonly DerObjectIdentifier IdAes192Cfb = new DerObjectIdentifier(Aes + ".24");
+ public static readonly DerObjectIdentifier IdAes192Wrap = new DerObjectIdentifier(Aes + ".25");
+ public static readonly DerObjectIdentifier IdAes192Gcm = new DerObjectIdentifier(Aes + ".26");
+ public static readonly DerObjectIdentifier IdAes192Ccm = new DerObjectIdentifier(Aes + ".27");
+
+ public static readonly DerObjectIdentifier IdAes256Ecb = new DerObjectIdentifier(Aes + ".41");
+ public static readonly DerObjectIdentifier IdAes256Cbc = new DerObjectIdentifier(Aes + ".42");
+ public static readonly DerObjectIdentifier IdAes256Ofb = new DerObjectIdentifier(Aes + ".43");
+ public static readonly DerObjectIdentifier IdAes256Cfb = new DerObjectIdentifier(Aes + ".44");
+ public static readonly DerObjectIdentifier IdAes256Wrap = new DerObjectIdentifier(Aes + ".45");
+ public static readonly DerObjectIdentifier IdAes256Gcm = new DerObjectIdentifier(Aes + ".46");
+ public static readonly DerObjectIdentifier IdAes256Ccm = new DerObjectIdentifier(Aes + ".47");
+
+ //
+ // signatures
+ //
+ public static readonly DerObjectIdentifier IdDsaWithSha2 = new DerObjectIdentifier(NistAlgorithm + ".3");
+
+ public static readonly DerObjectIdentifier DsaWithSha224 = new DerObjectIdentifier(IdDsaWithSha2 + ".1");
+ public static readonly DerObjectIdentifier DsaWithSha256 = new DerObjectIdentifier(IdDsaWithSha2 + ".2");
+ public static readonly DerObjectIdentifier DsaWithSha384 = new DerObjectIdentifier(IdDsaWithSha2 + ".3");
+ public static readonly DerObjectIdentifier DsaWithSha512 = new DerObjectIdentifier(IdDsaWithSha2 + ".4");
+ }
+}
diff --git a/Crypto/src/asn1/ntt/NTTObjectIdentifiers.cs b/Crypto/src/asn1/ntt/NTTObjectIdentifiers.cs
new file mode 100644
index 000000000..cd2595600
--- /dev/null
+++ b/Crypto/src/asn1/ntt/NTTObjectIdentifiers.cs
@@ -0,0 +1,14 @@
+namespace Org.BouncyCastle.Asn1.Ntt
+{
+ /// <summary>From RFC 3657</summary>
+ public abstract class NttObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier IdCamellia128Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.2");
+ public static readonly DerObjectIdentifier IdCamellia192Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.3");
+ public static readonly DerObjectIdentifier IdCamellia256Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.4");
+
+ public static readonly DerObjectIdentifier IdCamellia128Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.2");
+ public static readonly DerObjectIdentifier IdCamellia192Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.3");
+ public static readonly DerObjectIdentifier IdCamellia256Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.4");
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/BasicOCSPResponse.cs b/Crypto/src/asn1/ocsp/BasicOCSPResponse.cs
new file mode 100644
index 000000000..dd666addf
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/BasicOCSPResponse.cs
@@ -0,0 +1,131 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class BasicOcspResponse
+ : Asn1Encodable
+ {
+ private readonly ResponseData tbsResponseData;
+ private readonly AlgorithmIdentifier signatureAlgorithm;
+ private readonly DerBitString signature;
+ private readonly Asn1Sequence certs;
+
+ public static BasicOcspResponse GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static BasicOcspResponse GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is BasicOcspResponse)
+ {
+ return (BasicOcspResponse)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new BasicOcspResponse((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public BasicOcspResponse(
+ ResponseData tbsResponseData,
+ AlgorithmIdentifier signatureAlgorithm,
+ DerBitString signature,
+ Asn1Sequence certs)
+ {
+ this.tbsResponseData = tbsResponseData;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signature = signature;
+ this.certs = certs;
+ }
+
+ private BasicOcspResponse(
+ Asn1Sequence seq)
+ {
+ this.tbsResponseData = ResponseData.GetInstance(seq[0]);
+ this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+ this.signature = (DerBitString)seq[2];
+
+ if (seq.Count > 3)
+ {
+ this.certs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[3], true);
+ }
+ }
+
+ [Obsolete("Use TbsResponseData property instead")]
+ public ResponseData GetTbsResponseData()
+ {
+ return tbsResponseData;
+ }
+
+ public ResponseData TbsResponseData
+ {
+ get { return tbsResponseData; }
+ }
+
+ [Obsolete("Use SignatureAlgorithm property instead")]
+ public AlgorithmIdentifier GetSignatureAlgorithm()
+ {
+ return signatureAlgorithm;
+ }
+
+ public AlgorithmIdentifier SignatureAlgorithm
+ {
+ get { return signatureAlgorithm; }
+ }
+
+ [Obsolete("Use Signature property instead")]
+ public DerBitString GetSignature()
+ {
+ return signature;
+ }
+
+ public DerBitString Signature
+ {
+ get { return signature; }
+ }
+
+ [Obsolete("Use Certs property instead")]
+ public Asn1Sequence GetCerts()
+ {
+ return certs;
+ }
+
+ public Asn1Sequence Certs
+ {
+ get { return certs; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * BasicOcspResponse ::= Sequence {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT Sequence OF Certificate OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ tbsResponseData, signatureAlgorithm, signature);
+
+ if (certs != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, certs));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/CertID.cs b/Crypto/src/asn1/ocsp/CertID.cs
new file mode 100644
index 000000000..4b251095b
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/CertID.cs
@@ -0,0 +1,98 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class CertID
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlgorithm;
+ private readonly Asn1OctetString issuerNameHash;
+ private readonly Asn1OctetString issuerKeyHash;
+ private readonly DerInteger serialNumber;
+
+ public static CertID GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static CertID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CertID)
+ {
+ return (CertID)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new CertID((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public CertID(
+ AlgorithmIdentifier hashAlgorithm,
+ Asn1OctetString issuerNameHash,
+ Asn1OctetString issuerKeyHash,
+ DerInteger serialNumber)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.issuerNameHash = issuerNameHash;
+ this.issuerKeyHash = issuerKeyHash;
+ this.serialNumber = serialNumber;
+ }
+
+ private CertID(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 4)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+ this.issuerNameHash = Asn1OctetString.GetInstance(seq[1]);
+ this.issuerKeyHash = Asn1OctetString.GetInstance(seq[2]);
+ this.serialNumber = DerInteger.GetInstance(seq[3]);
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return hashAlgorithm; }
+ }
+
+ public Asn1OctetString IssuerNameHash
+ {
+ get { return issuerNameHash; }
+ }
+
+ public Asn1OctetString IssuerKeyHash
+ {
+ get { return issuerKeyHash; }
+ }
+
+ public DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * CertID ::= Sequence {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
+ * serialNumber CertificateSerialNumber }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(hashAlgorithm, issuerNameHash, issuerKeyHash, serialNumber);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/CertStatus.cs b/Crypto/src/asn1/ocsp/CertStatus.cs
new file mode 100644
index 000000000..d5b1a94a2
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/CertStatus.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class CertStatus
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly int tagNo;
+ private readonly Asn1Encodable value;
+
+ /**
+ * create a CertStatus object with a tag of zero.
+ */
+ public CertStatus()
+ {
+ tagNo = 0;
+ value = DerNull.Instance;
+ }
+
+ public CertStatus(
+ RevokedInfo info)
+ {
+ tagNo = 1;
+ value = info;
+ }
+
+ public CertStatus(
+ int tagNo,
+ Asn1Encodable value)
+ {
+ this.tagNo = tagNo;
+ this.value = value;
+ }
+
+ public CertStatus(
+ Asn1TaggedObject choice)
+ {
+ this.tagNo = choice.TagNo;
+
+ switch (choice.TagNo)
+ {
+ case 1:
+ value = RevokedInfo.GetInstance(choice, false);
+ break;
+ case 0:
+ case 2:
+ value = DerNull.Instance;
+ break;
+ }
+ }
+
+ public static CertStatus GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CertStatus)
+ {
+ return (CertStatus)obj;
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ return new CertStatus((Asn1TaggedObject)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public int TagNo
+ {
+ get { return tagNo; }
+ }
+
+ public Asn1Encodable Status
+ {
+ get { return value; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * CertStatus ::= CHOICE {
+ * good [0] IMPLICIT Null,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, tagNo, value);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/CrlID.cs b/Crypto/src/asn1/ocsp/CrlID.cs
new file mode 100644
index 000000000..cfb3d6fcb
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/CrlID.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class CrlID
+ : Asn1Encodable
+ {
+ private readonly DerIA5String crlUrl;
+ private readonly DerInteger crlNum;
+ private readonly DerGeneralizedTime crlTime;
+
+ // TODO Add GetInstance method(s) and amke this private?
+ public CrlID(
+ Asn1Sequence seq)
+ {
+ foreach (Asn1TaggedObject o in seq)
+ {
+ switch (o.TagNo)
+ {
+ case 0:
+ crlUrl = DerIA5String.GetInstance(o, true);
+ break;
+ case 1:
+ crlNum = DerInteger.GetInstance(o, true);
+ break;
+ case 2:
+ crlTime = DerGeneralizedTime.GetInstance(o, true);
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + o.TagNo);
+ }
+ }
+ }
+
+ public DerIA5String CrlUrl
+ {
+ get { return crlUrl; }
+ }
+
+ public DerInteger CrlNum
+ {
+ get { return crlNum; }
+ }
+
+ public DerGeneralizedTime CrlTime
+ {
+ get { return crlTime; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * CrlID ::= Sequence {
+ * crlUrl [0] EXPLICIT IA5String OPTIONAL,
+ * crlNum [1] EXPLICIT Integer OPTIONAL,
+ * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (crlUrl != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, crlUrl));
+ }
+
+ if (crlNum != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, crlNum));
+ }
+
+ if (crlTime != null)
+ {
+ v.Add(new DerTaggedObject(true, 2, crlTime));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs b/Crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs
new file mode 100644
index 000000000..a37c8552d
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPObjectIdentifiers.cs
@@ -0,0 +1,23 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public abstract class OcspObjectIdentifiers
+ {
+ internal const string PkixOcspId = "1.3.6.1.5.5.7.48.1";
+
+ public static readonly DerObjectIdentifier PkixOcsp = new DerObjectIdentifier(PkixOcspId);
+ public static readonly DerObjectIdentifier PkixOcspBasic = new DerObjectIdentifier(PkixOcspId + ".1");
+
+ //
+ // extensions
+ //
+ public static readonly DerObjectIdentifier PkixOcspNonce = new DerObjectIdentifier(PkixOcsp + ".2");
+ public static readonly DerObjectIdentifier PkixOcspCrl = new DerObjectIdentifier(PkixOcsp + ".3");
+
+ public static readonly DerObjectIdentifier PkixOcspResponse = new DerObjectIdentifier(PkixOcsp + ".4");
+ public static readonly DerObjectIdentifier PkixOcspNocheck = new DerObjectIdentifier(PkixOcsp + ".5");
+ public static readonly DerObjectIdentifier PkixOcspArchiveCutoff = new DerObjectIdentifier(PkixOcsp + ".6");
+ public static readonly DerObjectIdentifier PkixOcspServiceLocator = new DerObjectIdentifier(PkixOcsp + ".7");
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPRequest.cs b/Crypto/src/asn1/ocsp/OCSPRequest.cs
new file mode 100644
index 000000000..1e804d78e
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPRequest.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class OcspRequest
+ : Asn1Encodable
+ {
+ private readonly TbsRequest tbsRequest;
+ private readonly Signature optionalSignature;
+
+ public static OcspRequest GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static OcspRequest GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OcspRequest)
+ {
+ return (OcspRequest)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new OcspRequest((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public OcspRequest(
+ TbsRequest tbsRequest,
+ Signature optionalSignature)
+ {
+ if (tbsRequest == null)
+ throw new ArgumentNullException("tbsRequest");
+
+ this.tbsRequest = tbsRequest;
+ this.optionalSignature = optionalSignature;
+ }
+
+ private OcspRequest(
+ Asn1Sequence seq)
+ {
+ tbsRequest = TbsRequest.GetInstance(seq[0]);
+
+ if (seq.Count == 2)
+ {
+ optionalSignature = Signature.GetInstance(
+ (Asn1TaggedObject)seq[1], true);
+ }
+ }
+
+ public TbsRequest TbsRequest
+ {
+ get { return tbsRequest; }
+ }
+
+ public Signature OptionalSignature
+ {
+ get { return optionalSignature; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OcspRequest ::= Sequence {
+ * tbsRequest TBSRequest,
+ * optionalSignature [0] EXPLICIT Signature OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(tbsRequest);
+
+ if (optionalSignature != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, optionalSignature));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPResponse.cs b/Crypto/src/asn1/ocsp/OCSPResponse.cs
new file mode 100644
index 000000000..e9aad8100
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPResponse.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class OcspResponse
+ : Asn1Encodable
+ {
+ private readonly OcspResponseStatus responseStatus;
+ private readonly ResponseBytes responseBytes;
+
+ public static OcspResponse GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static OcspResponse GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is OcspResponse)
+ {
+ return (OcspResponse)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new OcspResponse((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public OcspResponse(
+ OcspResponseStatus responseStatus,
+ ResponseBytes responseBytes)
+ {
+ if (responseStatus == null)
+ throw new ArgumentNullException("responseStatus");
+
+ this.responseStatus = responseStatus;
+ this.responseBytes = responseBytes;
+ }
+
+ private OcspResponse(
+ Asn1Sequence seq)
+ {
+ responseStatus = new OcspResponseStatus(
+ DerEnumerated.GetInstance(seq[0]));
+
+ if (seq.Count == 2)
+ {
+ responseBytes = ResponseBytes.GetInstance(
+ (Asn1TaggedObject)seq[1], true);
+ }
+ }
+
+ public OcspResponseStatus ResponseStatus
+ {
+ get { return responseStatus; }
+ }
+
+ public ResponseBytes ResponseBytes
+ {
+ get { return responseBytes; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OcspResponse ::= Sequence {
+ * responseStatus OcspResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(responseStatus);
+
+ if (responseBytes != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, responseBytes));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/OCSPResponseStatus.cs b/Crypto/src/asn1/ocsp/OCSPResponseStatus.cs
new file mode 100644
index 000000000..653317e33
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/OCSPResponseStatus.cs
@@ -0,0 +1,41 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class OcspResponseStatus
+ : DerEnumerated
+ {
+ public const int Successful = 0;
+ public const int MalformedRequest = 1;
+ public const int InternalError = 2;
+ public const int TryLater = 3;
+ public const int SignatureRequired = 5;
+ public const int Unauthorized = 6;
+
+ /**
+ * The OcspResponseStatus enumeration.
+ * <pre>
+ * OcspResponseStatus ::= Enumerated {
+ * successful (0), --Response has valid confirmations
+ * malformedRequest (1), --Illegal confirmation request
+ * internalError (2), --Internal error in issuer
+ * tryLater (3), --Try again later
+ * --(4) is not used
+ * sigRequired (5), --Must sign the request
+ * unauthorized (6) --Request unauthorized
+ * }
+ * </pre>
+ */
+ public OcspResponseStatus(int value)
+ : base(value)
+ {
+ }
+
+ public OcspResponseStatus(DerEnumerated value)
+ : base(value.Value.IntValue)
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/Request.cs b/Crypto/src/asn1/ocsp/Request.cs
new file mode 100644
index 000000000..116c15e73
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/Request.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class Request
+ : Asn1Encodable
+ {
+ private readonly CertID reqCert;
+ private readonly X509Extensions singleRequestExtensions;
+
+ public static Request GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static Request GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Request)
+ {
+ return (Request)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Request((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public Request(
+ CertID reqCert,
+ X509Extensions singleRequestExtensions)
+ {
+ if (reqCert == null)
+ throw new ArgumentNullException("reqCert");
+
+ this.reqCert = reqCert;
+ this.singleRequestExtensions = singleRequestExtensions;
+ }
+
+ private Request(
+ Asn1Sequence seq)
+ {
+ reqCert = CertID.GetInstance(seq[0]);
+
+ if (seq.Count == 2)
+ {
+ singleRequestExtensions = X509Extensions.GetInstance(
+ (Asn1TaggedObject)seq[1], true);
+ }
+ }
+
+ public CertID ReqCert
+ {
+ get { return reqCert; }
+ }
+
+ public X509Extensions SingleRequestExtensions
+ {
+ get { return singleRequestExtensions; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * Request ::= Sequence {
+ * reqCert CertID,
+ * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(reqCert);
+
+ if (singleRequestExtensions != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, singleRequestExtensions));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/ResponderID.cs b/Crypto/src/asn1/ocsp/ResponderID.cs
new file mode 100644
index 000000000..143b17339
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ResponderID.cs
@@ -0,0 +1,107 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class ResponderID
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly Asn1Encodable id;
+
+ public static ResponderID GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ResponderID)
+ {
+ return (ResponderID)obj;
+ }
+
+ if (obj is DerOctetString)
+ {
+ return new ResponderID((DerOctetString)obj);
+ }
+
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject)obj;
+
+ if (o.TagNo == 1)
+ {
+ return new ResponderID(X509Name.GetInstance(o, true));
+ }
+
+ return new ResponderID(Asn1OctetString.GetInstance(o, true));
+ }
+
+ return new ResponderID(X509Name.GetInstance(obj));
+ }
+
+ public ResponderID(
+ Asn1OctetString id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+
+ this.id = id;
+ }
+
+ public ResponderID(
+ X509Name id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+
+ this.id = id;
+ }
+
+ public static ResponderID GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ return GetInstance(obj.GetObject()); // must be explicitly tagged
+ }
+
+ public virtual byte[] GetKeyHash()
+ {
+ if (id is Asn1OctetString)
+ {
+ return ((Asn1OctetString)id).GetOctets();
+ }
+
+ return null;
+ }
+
+ public virtual X509Name Name
+ {
+ get
+ {
+ if (id is Asn1OctetString)
+ {
+ return null;
+ }
+
+ return X509Name.GetInstance(id);
+ }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (id is Asn1OctetString)
+ {
+ return new DerTaggedObject(true, 2, id);
+ }
+
+ return new DerTaggedObject(true, 1, id);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/ResponseBytes.cs b/Crypto/src/asn1/ocsp/ResponseBytes.cs
new file mode 100644
index 000000000..2ce59faea
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ResponseBytes.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class ResponseBytes
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier responseType;
+ private readonly Asn1OctetString response;
+
+ public static ResponseBytes GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static ResponseBytes GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ResponseBytes)
+ {
+ return (ResponseBytes)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ResponseBytes((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public ResponseBytes(
+ DerObjectIdentifier responseType,
+ Asn1OctetString response)
+ {
+ if (responseType == null)
+ throw new ArgumentNullException("responseType");
+ if (response == null)
+ throw new ArgumentNullException("response");
+
+ this.responseType = responseType;
+ this.response = response;
+ }
+
+ private ResponseBytes(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.responseType = DerObjectIdentifier.GetInstance(seq[0]);
+ this.response = Asn1OctetString.GetInstance(seq[1]);
+ }
+
+ public DerObjectIdentifier ResponseType
+ {
+ get { return responseType; }
+ }
+
+ public Asn1OctetString Response
+ {
+ get { return response; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ResponseBytes ::= Sequence {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(responseType, response);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/ResponseData.cs b/Crypto/src/asn1/ocsp/ResponseData.cs
new file mode 100644
index 000000000..173829db8
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ResponseData.cs
@@ -0,0 +1,158 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class ResponseData
+ : Asn1Encodable
+ {
+ private static readonly DerInteger V1 = new DerInteger(0);
+
+ private readonly bool versionPresent;
+ private readonly DerInteger version;
+ private readonly ResponderID responderID;
+ private readonly DerGeneralizedTime producedAt;
+ private readonly Asn1Sequence responses;
+ private readonly X509Extensions responseExtensions;
+
+ public static ResponseData GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static ResponseData GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ResponseData)
+ {
+ return (ResponseData)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ResponseData((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public ResponseData(
+ DerInteger version,
+ ResponderID responderID,
+ DerGeneralizedTime producedAt,
+ Asn1Sequence responses,
+ X509Extensions responseExtensions)
+ {
+ this.version = version;
+ this.responderID = responderID;
+ this.producedAt = producedAt;
+ this.responses = responses;
+ this.responseExtensions = responseExtensions;
+ }
+
+ public ResponseData(
+ ResponderID responderID,
+ DerGeneralizedTime producedAt,
+ Asn1Sequence responses,
+ X509Extensions responseExtensions)
+ : this(V1, responderID, producedAt, responses, responseExtensions)
+ {
+ }
+
+ private ResponseData(
+ Asn1Sequence seq)
+ {
+ int index = 0;
+
+ Asn1Encodable enc = seq[0];
+ if (enc is Asn1TaggedObject)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject)enc;
+
+ if (o.TagNo == 0)
+ {
+ this.versionPresent = true;
+ this.version = DerInteger.GetInstance(o, true);
+ index++;
+ }
+ else
+ {
+ this.version = V1;
+ }
+ }
+ else
+ {
+ this.version = V1;
+ }
+
+ this.responderID = ResponderID.GetInstance(seq[index++]);
+ this.producedAt = (DerGeneralizedTime)seq[index++];
+ this.responses = (Asn1Sequence)seq[index++];
+
+ if (seq.Count > index)
+ {
+ this.responseExtensions = X509Extensions.GetInstance(
+ (Asn1TaggedObject)seq[index], true);
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public ResponderID ResponderID
+ {
+ get { return responderID; }
+ }
+
+ public DerGeneralizedTime ProducedAt
+ {
+ get { return producedAt; }
+ }
+
+ public Asn1Sequence Responses
+ {
+ get { return responses; }
+ }
+
+ public X509Extensions ResponseExtensions
+ {
+ get { return responseExtensions; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ResponseData ::= Sequence {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses Sequence OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (versionPresent || !version.Equals(V1))
+ {
+ v.Add(new DerTaggedObject(true, 0, version));
+ }
+
+ v.Add(responderID, producedAt, responses);
+
+ if (responseExtensions != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, responseExtensions));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/RevokedInfo.cs b/Crypto/src/asn1/ocsp/RevokedInfo.cs
new file mode 100644
index 000000000..7d9d590e3
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/RevokedInfo.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class RevokedInfo
+ : Asn1Encodable
+ {
+ private readonly DerGeneralizedTime revocationTime;
+ private readonly CrlReason revocationReason;
+
+ public static RevokedInfo GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static RevokedInfo GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RevokedInfo)
+ {
+ return (RevokedInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new RevokedInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public RevokedInfo(
+ DerGeneralizedTime revocationTime)
+ : this(revocationTime, null)
+ {
+ }
+
+ public RevokedInfo(
+ DerGeneralizedTime revocationTime,
+ CrlReason revocationReason)
+ {
+ if (revocationTime == null)
+ throw new ArgumentNullException("revocationTime");
+
+ this.revocationTime = revocationTime;
+ this.revocationReason = revocationReason;
+ }
+
+ private RevokedInfo(
+ Asn1Sequence seq)
+ {
+ this.revocationTime = (DerGeneralizedTime) seq[0];
+
+ if (seq.Count > 1)
+ {
+ this.revocationReason = new CrlReason(
+ DerEnumerated.GetInstance((Asn1TaggedObject) seq[1], true));
+ }
+ }
+
+ public DerGeneralizedTime RevocationTime
+ {
+ get { return revocationTime; }
+ }
+
+ public CrlReason RevocationReason
+ {
+ get { return revocationReason; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * RevokedInfo ::= Sequence {
+ * revocationTime GeneralizedTime,
+ * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(revocationTime);
+
+ if (revocationReason != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, revocationReason));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/ServiceLocator.cs b/Crypto/src/asn1/ocsp/ServiceLocator.cs
new file mode 100644
index 000000000..56bc49ded
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/ServiceLocator.cs
@@ -0,0 +1,95 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class ServiceLocator
+ : Asn1Encodable
+ {
+ private readonly X509Name issuer;
+ private readonly Asn1Object locator;
+
+ public static ServiceLocator GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static ServiceLocator GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is ServiceLocator)
+ {
+ return (ServiceLocator) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ServiceLocator((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public ServiceLocator(
+ X509Name issuer)
+ : this(issuer, null)
+ {
+ }
+
+ public ServiceLocator(
+ X509Name issuer,
+ Asn1Object locator)
+ {
+ if (issuer == null)
+ throw new ArgumentNullException("issuer");
+
+ this.issuer = issuer;
+ this.locator = locator;
+ }
+
+ private ServiceLocator(
+ Asn1Sequence seq)
+ {
+ this.issuer = X509Name.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ this.locator = seq[1].ToAsn1Object();
+ }
+ }
+
+ public X509Name Issuer
+ {
+ get { return issuer; }
+ }
+
+ public Asn1Object Locator
+ {
+ get { return locator; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ServiceLocator ::= Sequence {
+ * issuer Name,
+ * locator AuthorityInfoAccessSyntax OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(issuer);
+
+ if (locator != null)
+ {
+ v.Add(locator);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/Signature.cs b/Crypto/src/asn1/ocsp/Signature.cs
new file mode 100644
index 000000000..a07e7a709
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/Signature.cs
@@ -0,0 +1,110 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class Signature
+ : Asn1Encodable
+ {
+ internal AlgorithmIdentifier signatureAlgorithm;
+ internal DerBitString signatureValue;
+ internal Asn1Sequence certs;
+
+ public static Signature GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static Signature GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Signature)
+ {
+ return (Signature)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Signature((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public Signature(
+ AlgorithmIdentifier signatureAlgorithm,
+ DerBitString signatureValue)
+ : this(signatureAlgorithm, signatureValue, null)
+ {
+ }
+
+ public Signature(
+ AlgorithmIdentifier signatureAlgorithm,
+ DerBitString signatureValue,
+ Asn1Sequence certs)
+ {
+ if (signatureAlgorithm == null)
+ throw new ArgumentException("signatureAlgorithm");
+ if (signatureValue == null)
+ throw new ArgumentException("signatureValue");
+
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signatureValue = signatureValue;
+ this.certs = certs;
+ }
+
+ private Signature(
+ Asn1Sequence seq)
+ {
+ signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+ signatureValue = (DerBitString)seq[1];
+
+ if (seq.Count == 3)
+ {
+ certs = Asn1Sequence.GetInstance(
+ (Asn1TaggedObject)seq[2], true);
+ }
+ }
+
+ public AlgorithmIdentifier SignatureAlgorithm
+ {
+ get { return signatureAlgorithm; }
+ }
+
+ public DerBitString SignatureValue
+ {
+ get { return signatureValue; }
+ }
+
+ public Asn1Sequence Certs
+ {
+ get { return certs; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * Signature ::= Sequence {
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT Sequence OF Certificate OPTIONAL}
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ signatureAlgorithm, signatureValue);
+
+ if (certs != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, certs));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/SingleResponse.cs b/Crypto/src/asn1/ocsp/SingleResponse.cs
new file mode 100644
index 000000000..93d4c21d6
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/SingleResponse.cs
@@ -0,0 +1,137 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class SingleResponse
+ : Asn1Encodable
+ {
+ private readonly CertID certID;
+ private readonly CertStatus certStatus;
+ private readonly DerGeneralizedTime thisUpdate;
+ private readonly DerGeneralizedTime nextUpdate;
+ private readonly X509Extensions singleExtensions;
+
+ public SingleResponse(
+ CertID certID,
+ CertStatus certStatus,
+ DerGeneralizedTime thisUpdate,
+ DerGeneralizedTime nextUpdate,
+ X509Extensions singleExtensions)
+ {
+ this.certID = certID;
+ this.certStatus = certStatus;
+ this.thisUpdate = thisUpdate;
+ this.nextUpdate = nextUpdate;
+ this.singleExtensions = singleExtensions;
+ }
+
+ public SingleResponse(
+ Asn1Sequence seq)
+ {
+ this.certID = CertID.GetInstance(seq[0]);
+ this.certStatus = CertStatus.GetInstance(seq[1]);
+ this.thisUpdate = (DerGeneralizedTime)seq[2];
+
+ if (seq.Count > 4)
+ {
+ this.nextUpdate = DerGeneralizedTime.GetInstance(
+ (Asn1TaggedObject) seq[3], true);
+ this.singleExtensions = X509Extensions.GetInstance(
+ (Asn1TaggedObject) seq[4], true);
+ }
+ else if (seq.Count > 3)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject) seq[3];
+
+ if (o.TagNo == 0)
+ {
+ this.nextUpdate = DerGeneralizedTime.GetInstance(o, true);
+ }
+ else
+ {
+ this.singleExtensions = X509Extensions.GetInstance(o, true);
+ }
+ }
+ }
+
+ public static SingleResponse GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static SingleResponse GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SingleResponse)
+ {
+ return (SingleResponse)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new SingleResponse((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public CertID CertId
+ {
+ get { return certID; }
+ }
+
+ public CertStatus CertStatus
+ {
+ get { return certStatus; }
+ }
+
+ public DerGeneralizedTime ThisUpdate
+ {
+ get { return thisUpdate; }
+ }
+
+ public DerGeneralizedTime NextUpdate
+ {
+ get { return nextUpdate; }
+ }
+
+ public X509Extensions SingleExtensions
+ {
+ get { return singleExtensions; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SingleResponse ::= Sequence {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ certID, certStatus, thisUpdate);
+
+ if (nextUpdate != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, nextUpdate));
+ }
+
+ if (singleExtensions != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, singleExtensions));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/ocsp/TBSRequest.cs b/Crypto/src/asn1/ocsp/TBSRequest.cs
new file mode 100644
index 000000000..6bf75eb96
--- /dev/null
+++ b/Crypto/src/asn1/ocsp/TBSRequest.cs
@@ -0,0 +1,151 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+ public class TbsRequest
+ : Asn1Encodable
+ {
+ private static readonly DerInteger V1 = new DerInteger(0);
+
+ private readonly DerInteger version;
+ private readonly GeneralName requestorName;
+ private readonly Asn1Sequence requestList;
+ private readonly X509Extensions requestExtensions;
+
+ private bool versionSet;
+
+ public static TbsRequest GetInstance(
+ Asn1TaggedObject obj,
+ bool explicitly)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+ }
+
+ public static TbsRequest GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is TbsRequest)
+ {
+ return (TbsRequest)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new TbsRequest((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public TbsRequest(
+ GeneralName requestorName,
+ Asn1Sequence requestList,
+ X509Extensions requestExtensions)
+ {
+ this.version = V1;
+ this.requestorName = requestorName;
+ this.requestList = requestList;
+ this.requestExtensions = requestExtensions;
+ }
+
+ private TbsRequest(
+ Asn1Sequence seq)
+ {
+ int index = 0;
+
+ Asn1Encodable enc = seq[0];
+ if (enc is Asn1TaggedObject)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject) enc;
+
+ if (o.TagNo == 0)
+ {
+ versionSet = true;
+ version = DerInteger.GetInstance(o, true);
+ index++;
+ }
+ else
+ {
+ version = V1;
+ }
+ }
+ else
+ {
+ version = V1;
+ }
+
+ if (seq[index] is Asn1TaggedObject)
+ {
+ requestorName = GeneralName.GetInstance((Asn1TaggedObject) seq[index++], true);
+ }
+
+ requestList = (Asn1Sequence) seq[index++];
+
+ if (seq.Count == (index + 1))
+ {
+ requestExtensions = X509Extensions.GetInstance((Asn1TaggedObject) seq[index], true);
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public GeneralName RequestorName
+ {
+ get { return requestorName; }
+ }
+
+ public Asn1Sequence RequestList
+ {
+ get { return requestList; }
+ }
+
+ public X509Extensions RequestExtensions
+ {
+ get { return requestExtensions; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * TBSRequest ::= Sequence {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ * requestList Sequence OF Request,
+ * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ //
+ // if default don't include - unless explicitly provided. Not strictly correct
+ // but required for some requests
+ //
+ if (!version.Equals(V1) || versionSet)
+ {
+ v.Add(new DerTaggedObject(true, 0, version));
+ }
+
+ if (requestorName != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, requestorName));
+ }
+
+ v.Add(requestList);
+
+ if (requestExtensions != null)
+ {
+ v.Add(new DerTaggedObject(true, 2, requestExtensions));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/oiw/ElGamalParameter.cs b/Crypto/src/asn1/oiw/ElGamalParameter.cs
new file mode 100644
index 000000000..3e020f059
--- /dev/null
+++ b/Crypto/src/asn1/oiw/ElGamalParameter.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Oiw
+{
+ public class ElGamalParameter
+ : Asn1Encodable
+ {
+ internal DerInteger p, g;
+
+ public ElGamalParameter(
+ BigInteger p,
+ BigInteger g)
+ {
+ this.p = new DerInteger(p);
+ this.g = new DerInteger(g);
+ }
+
+ public ElGamalParameter(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ p = DerInteger.GetInstance(seq[0]);
+ g = DerInteger.GetInstance(seq[1]);
+ }
+
+ public BigInteger P
+ {
+ get { return p.PositiveValue; }
+ }
+
+ public BigInteger G
+ {
+ get { return g.PositiveValue; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(p, g);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/oiw/OIWObjectIdentifiers.cs b/Crypto/src/asn1/oiw/OIWObjectIdentifiers.cs
new file mode 100644
index 000000000..3da226301
--- /dev/null
+++ b/Crypto/src/asn1/oiw/OIWObjectIdentifiers.cs
@@ -0,0 +1,29 @@
+namespace Org.BouncyCastle.Asn1.Oiw
+{
+ public abstract class OiwObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier MD4WithRsa = new DerObjectIdentifier("1.3.14.3.2.2");
+ public static readonly DerObjectIdentifier MD5WithRsa = new DerObjectIdentifier("1.3.14.3.2.3");
+ public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier("1.3.14.3.2.4");
+
+ public static readonly DerObjectIdentifier DesEcb = new DerObjectIdentifier("1.3.14.3.2.6");
+ public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7");
+ public static readonly DerObjectIdentifier DesOfb = new DerObjectIdentifier("1.3.14.3.2.8");
+ public static readonly DerObjectIdentifier DesCfb = new DerObjectIdentifier("1.3.14.3.2.9");
+
+ public static readonly DerObjectIdentifier DesEde = new DerObjectIdentifier("1.3.14.3.2.17");
+
+ // 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");
+
+ public static readonly DerObjectIdentifier DsaWithSha1 = new DerObjectIdentifier("1.3.14.3.2.27");
+
+ public static readonly DerObjectIdentifier Sha1WithRsa = new DerObjectIdentifier("1.3.14.3.2.29");
+
+ // ElGamal Algorithm OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
+ //
+ public static readonly DerObjectIdentifier ElGamalAlgorithm = new DerObjectIdentifier("1.3.14.7.2.1.1");
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/Attribute.cs b/Crypto/src/asn1/pkcs/Attribute.cs
new file mode 100644
index 000000000..ceec115bd
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/Attribute.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class AttributePkcs
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier attrType;
+ private readonly Asn1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception ArgumentException if the object cannot be converted.
+ */
+ public static AttributePkcs GetInstance(
+ object obj)
+ {
+ AttributePkcs attr = obj as AttributePkcs;
+ if (obj == null || attr != null)
+ {
+ return attr;
+ }
+
+ Asn1Sequence seq = obj as Asn1Sequence;
+ if (seq != null)
+ {
+ return new AttributePkcs(seq);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ private AttributePkcs(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ attrType = DerObjectIdentifier.GetInstance(seq[0]);
+ attrValues = Asn1Set.GetInstance(seq[1]);
+ }
+
+ public AttributePkcs(
+ DerObjectIdentifier attrType,
+ Asn1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public DerObjectIdentifier AttrType
+ {
+ get { return attrType; }
+ }
+
+ 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/pkcs/AuthenticatedSafe.cs b/Crypto/src/asn1/pkcs/AuthenticatedSafe.cs
new file mode 100644
index 000000000..f3dabb89c
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/AuthenticatedSafe.cs
@@ -0,0 +1,37 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class AuthenticatedSafe
+ : Asn1Encodable
+ {
+ private readonly ContentInfo[] info;
+
+ public AuthenticatedSafe(
+ Asn1Sequence seq)
+ {
+ info = new ContentInfo[seq.Count];
+
+ for (int i = 0; i != info.Length; i++)
+ {
+ info[i] = ContentInfo.GetInstance(seq[i]);
+ }
+ }
+
+ public AuthenticatedSafe(
+ ContentInfo[] info)
+ {
+ this.info = (ContentInfo[]) info.Clone();
+ }
+
+ public ContentInfo[] GetContentInfo()
+ {
+ return (ContentInfo[]) info.Clone();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new BerSequence(info);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/CertBag.cs b/Crypto/src/asn1/pkcs/CertBag.cs
new file mode 100644
index 000000000..b6f4c8a30
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/CertBag.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class CertBag
+ : Asn1Encodable
+ {
+// private readonly Asn1Sequence seq;
+ private readonly DerObjectIdentifier certID;
+ private readonly Asn1Object certValue;
+
+ public CertBag(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+// this.seq = seq;
+ this.certID = DerObjectIdentifier.GetInstance(seq[0]);
+ this.certValue = DerTaggedObject.GetInstance(seq[1]).GetObject();
+ }
+
+ public CertBag(
+ DerObjectIdentifier certID,
+ Asn1Object certValue)
+ {
+ this.certID = certID;
+ this.certValue = certValue;
+ }
+
+ public DerObjectIdentifier CertID
+ {
+ get { return certID; }
+ }
+
+ public Asn1Object CertValue
+ {
+ get { return certValue; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(certID, new DerTaggedObject(0, certValue));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/CertificationRequest.cs b/Crypto/src/asn1/pkcs/CertificationRequest.cs
new file mode 100644
index 000000000..32b1612d2
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/CertificationRequest.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ /**
+ * Pkcs10 Certfication request object.
+ * <pre>
+ * CertificationRequest ::= Sequence {
+ * certificationRequestInfo CertificationRequestInfo,
+ * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
+ * signature BIT STRING
+ * }
+ * </pre>
+ */
+ public class CertificationRequest
+ : Asn1Encodable
+ {
+ protected CertificationRequestInfo reqInfo;
+ protected AlgorithmIdentifier sigAlgId;
+ protected DerBitString sigBits;
+
+ public static CertificationRequest GetInstance(
+ object obj)
+ {
+ if (obj is CertificationRequest)
+ return (CertificationRequest)obj;
+
+ if (obj != null)
+ return new CertificationRequest((Asn1Sequence)obj);
+
+ return null;
+ }
+
+ protected CertificationRequest()
+ {
+ }
+
+ public CertificationRequest(
+ CertificationRequestInfo requestInfo,
+ AlgorithmIdentifier algorithm,
+ DerBitString signature)
+ {
+ this.reqInfo = requestInfo;
+ this.sigAlgId = algorithm;
+ this.sigBits = signature;
+ }
+
+ public CertificationRequest(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ reqInfo = CertificationRequestInfo.GetInstance(seq[0]);
+ sigAlgId = AlgorithmIdentifier.GetInstance(seq[1]);
+ sigBits = DerBitString.GetInstance(seq[2]);
+ }
+
+ public CertificationRequestInfo GetCertificationRequestInfo()
+ {
+ return reqInfo;
+ }
+
+ public AlgorithmIdentifier SignatureAlgorithm
+ {
+ get { return sigAlgId; }
+ }
+
+ public DerBitString Signature
+ {
+ get { return sigBits; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(reqInfo, sigAlgId, sigBits);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/CertificationRequestInfo.cs b/Crypto/src/asn1/pkcs/CertificationRequestInfo.cs
new file mode 100644
index 000000000..690d06878
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/CertificationRequestInfo.cs
@@ -0,0 +1,123 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ /**
+ * Pkcs10 CertificationRequestInfo object.
+ * <pre>
+ * CertificationRequestInfo ::= Sequence {
+ * version Integer { v1(0) } (v1,...),
+ * subject Name,
+ * subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+ * attributes [0] Attributes{{ CRIAttributes }}
+ * }
+ *
+ * Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+ *
+ * Attr { ATTRIBUTE:IOSet } ::= Sequence {
+ * type ATTRIBUTE.&id({IOSet}),
+ * values Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+ * }
+ * </pre>
+ */
+ public class CertificationRequestInfo
+ : Asn1Encodable
+ {
+ internal DerInteger version = new DerInteger(0);
+ internal X509Name subject;
+ internal SubjectPublicKeyInfo subjectPKInfo;
+ internal Asn1Set attributes;
+
+ public static CertificationRequestInfo GetInstance(
+ object obj)
+ {
+ if (obj is CertificationRequestInfo)
+ {
+ return (CertificationRequestInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new CertificationRequestInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public CertificationRequestInfo(
+ X509Name subject,
+ SubjectPublicKeyInfo pkInfo,
+ Asn1Set attributes)
+ {
+ this.subject = subject;
+ this.subjectPKInfo = pkInfo;
+ this.attributes = attributes;
+
+ if (subject == null || version == null || subjectPKInfo == null)
+ {
+ throw new ArgumentException(
+ "Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ private CertificationRequestInfo(
+ Asn1Sequence seq)
+ {
+ version = (DerInteger) seq[0];
+
+ subject = X509Name.GetInstance(seq[1]);
+ subjectPKInfo = SubjectPublicKeyInfo.GetInstance(seq[2]);
+
+ //
+ // some CertificationRequestInfo objects seem to treat this field
+ // as optional.
+ //
+ if (seq.Count > 3)
+ {
+ DerTaggedObject tagobj = (DerTaggedObject) seq[3];
+ attributes = Asn1Set.GetInstance(tagobj, false);
+ }
+
+ if (subject == null || version == null || subjectPKInfo == null)
+ {
+ throw new ArgumentException(
+ "Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public X509Name Subject
+ {
+ get { return subject; }
+ }
+
+ public SubjectPublicKeyInfo SubjectPublicKeyInfo
+ {
+ get { return subjectPKInfo; }
+ }
+
+ public Asn1Set Attributes
+ {
+ get { return attributes; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, subject, subjectPKInfo);
+
+ if (attributes != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, attributes));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/ContentInfo.cs b/Crypto/src/asn1/pkcs/ContentInfo.cs
new file mode 100644
index 000000000..78213c138
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/ContentInfo.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class ContentInfo
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier contentType;
+ private readonly Asn1Encodable content;
+
+ public static ContentInfo GetInstance(
+ object obj)
+ {
+ if (obj is ContentInfo)
+ {
+ return (ContentInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new ContentInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ private ContentInfo(
+ Asn1Sequence seq)
+ {
+ contentType = (DerObjectIdentifier) seq[0];
+
+ if (seq.Count > 1)
+ {
+ content = ((Asn1TaggedObject) seq[1]).GetObject();
+ }
+ }
+
+ public ContentInfo(
+ DerObjectIdentifier contentType,
+ Asn1Encodable content)
+ {
+ this.contentType = contentType;
+ this.content = content;
+ }
+
+ public DerObjectIdentifier ContentType
+ {
+ get { return contentType; }
+ }
+
+ public Asn1Encodable Content
+ {
+ get { return content; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ContentInfo ::= Sequence {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(contentType);
+
+ if (content != null)
+ {
+ v.Add(new BerTaggedObject(0, content));
+ }
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/DHParameter.cs b/Crypto/src/asn1/pkcs/DHParameter.cs
new file mode 100644
index 000000000..25a091a97
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/DHParameter.cs
@@ -0,0 +1,72 @@
+using Org.BouncyCastle.Asn1;
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class DHParameter
+ : Asn1Encodable
+ {
+ internal DerInteger p, g, l;
+
+ public DHParameter(
+ BigInteger p,
+ BigInteger g,
+ int l)
+ {
+ this.p = new DerInteger(p);
+ this.g = new DerInteger(g);
+
+ if (l != 0)
+ {
+ this.l = new DerInteger(l);
+ }
+ }
+
+ public DHParameter(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ p = (DerInteger)e.Current;
+
+ e.MoveNext();
+ g = (DerInteger)e.Current;
+
+ if (e.MoveNext())
+ {
+ l = (DerInteger) e.Current;
+ }
+ }
+
+ public BigInteger P
+ {
+ get { return p.PositiveValue; }
+ }
+
+ public BigInteger G
+ {
+ get { return g.PositiveValue; }
+ }
+
+ public BigInteger L
+ {
+ get { return l == null ? null : l.PositiveValue; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(p, g);
+
+ if (this.l != null)
+ {
+ v.Add(l);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/EncryptedData.cs b/Crypto/src/asn1/pkcs/EncryptedData.cs
new file mode 100644
index 000000000..912064ace
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/EncryptedData.cs
@@ -0,0 +1,104 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ /**
+ * The EncryptedData object.
+ * <pre>
+ * EncryptedData ::= Sequence {
+ * version Version,
+ * encryptedContentInfo EncryptedContentInfo
+ * }
+ *
+ *
+ * EncryptedContentInfo ::= Sequence {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ *
+ * EncryptedContent ::= OCTET STRING
+ * </pre>
+ */
+ public class EncryptedData
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence data;
+// private readonly DerObjectIdentifier bagId;
+// private readonly Asn1Object bagValue;
+
+ public static EncryptedData GetInstance(
+ object obj)
+ {
+ if (obj is EncryptedData)
+ {
+ return (EncryptedData) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new EncryptedData((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ private EncryptedData(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ int version = ((DerInteger) seq[0]).Value.IntValue;
+ if (version != 0)
+ {
+ throw new ArgumentException("sequence not version 0");
+ }
+
+ this.data = (Asn1Sequence) seq[1];
+ }
+
+ public EncryptedData(
+ DerObjectIdentifier contentType,
+ AlgorithmIdentifier encryptionAlgorithm,
+ Asn1Encodable content)
+ {
+ data = new BerSequence(
+ contentType,
+ encryptionAlgorithm.ToAsn1Object(),
+ new BerTaggedObject(false, 0, content));
+ }
+
+ public DerObjectIdentifier ContentType
+ {
+ get { return (DerObjectIdentifier) data[0]; }
+ }
+
+ public AlgorithmIdentifier EncryptionAlgorithm
+ {
+ get { return AlgorithmIdentifier.GetInstance(data[1]); }
+ }
+
+ public Asn1OctetString Content
+ {
+ get
+ {
+ if (data.Count == 3)
+ {
+ DerTaggedObject o = (DerTaggedObject) data[2];
+
+ return Asn1OctetString.GetInstance(o, false);
+ }
+
+ return null;
+ }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new BerSequence(new DerInteger(0), data);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs b/Crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs
new file mode 100644
index 000000000..b97b8f5ea
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class EncryptedPrivateKeyInfo
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier algId;
+ private readonly Asn1OctetString data;
+
+ private EncryptedPrivateKeyInfo(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ algId = AlgorithmIdentifier.GetInstance(seq[0]);
+ data = Asn1OctetString.GetInstance(seq[1]);
+ }
+
+ public EncryptedPrivateKeyInfo(
+ AlgorithmIdentifier algId,
+ byte[] encoding)
+ {
+ this.algId = algId;
+ this.data = new DerOctetString(encoding);
+ }
+
+ public static EncryptedPrivateKeyInfo GetInstance(
+ object obj)
+ {
+ if (obj is EncryptedPrivateKeyInfo)
+ {
+ return (EncryptedPrivateKeyInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new EncryptedPrivateKeyInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public AlgorithmIdentifier EncryptionAlgorithm
+ {
+ get { return algId; }
+ }
+
+ public byte[] GetEncryptedData()
+ {
+ return data.GetOctets();
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * EncryptedPrivateKeyInfo ::= Sequence {
+ * encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+ * encryptedData EncryptedData
+ * }
+ *
+ * EncryptedData ::= OCTET STRING
+ *
+ * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * ... -- For local profiles
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(algId, data);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/EncryptionScheme.cs b/Crypto/src/asn1/pkcs/EncryptionScheme.cs
new file mode 100644
index 000000000..5b64d6f67
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/EncryptionScheme.cs
@@ -0,0 +1,49 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class EncryptionScheme
+ : AlgorithmIdentifier
+ {
+ public EncryptionScheme(
+ DerObjectIdentifier objectID,
+ Asn1Encodable parameters)
+ : base(objectID, parameters)
+ {
+ }
+
+ internal EncryptionScheme(
+ Asn1Sequence seq)
+ : this((DerObjectIdentifier)seq[0], seq[1])
+ {
+ }
+
+ public new static EncryptionScheme GetInstance(object obj)
+ {
+ if (obj is EncryptionScheme)
+ {
+ return (EncryptionScheme)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new EncryptionScheme((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public Asn1Object Asn1Object
+ {
+ get { return Parameters.ToAsn1Object(); }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(ObjectID, Parameters);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs b/Crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs
new file mode 100644
index 000000000..ff608f15b
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/IssuerAndSerialNumber.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class IssuerAndSerialNumber
+ : Asn1Encodable
+ {
+ private readonly X509Name name;
+ private readonly DerInteger certSerialNumber;
+
+ public static IssuerAndSerialNumber GetInstance(
+ object obj)
+ {
+ if (obj is IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new IssuerAndSerialNumber((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ private IssuerAndSerialNumber(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.name = X509Name.GetInstance(seq[0]);
+ this.certSerialNumber = DerInteger.GetInstance(seq[1]);
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ BigInteger certSerialNumber)
+ {
+ this.name = name;
+ this.certSerialNumber = new DerInteger(certSerialNumber);
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ DerInteger certSerialNumber)
+ {
+ this.name = name;
+ this.certSerialNumber = certSerialNumber;
+ }
+
+ public X509Name Name
+ {
+ get { return name; }
+ }
+
+ public DerInteger CertificateSerialNumber
+ {
+ get { return certSerialNumber; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(name, certSerialNumber);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/KeyDerivationFunc.cs b/Crypto/src/asn1/pkcs/KeyDerivationFunc.cs
new file mode 100644
index 000000000..9fc89853b
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/KeyDerivationFunc.cs
@@ -0,0 +1,21 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class KeyDerivationFunc
+ : AlgorithmIdentifier
+ {
+ internal KeyDerivationFunc(Asn1Sequence seq)
+ : base(seq)
+ {
+ }
+
+ public KeyDerivationFunc(
+ DerObjectIdentifier id,
+ Asn1Encodable parameters)
+ : base(id, parameters)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/Crypto/src/asn1/pkcs/MacData.cs b/Crypto/src/asn1/pkcs/MacData.cs
new file mode 100644
index 000000000..780b24153
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/MacData.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class MacData
+ : Asn1Encodable
+ {
+ internal DigestInfo digInfo;
+ internal byte[] salt;
+ internal BigInteger iterationCount;
+
+ public static MacData GetInstance(
+ object obj)
+ {
+ if (obj is MacData)
+ {
+ return (MacData) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new MacData((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ private MacData(
+ Asn1Sequence seq)
+ {
+ this.digInfo = DigestInfo.GetInstance(seq[0]);
+ this.salt = ((Asn1OctetString) seq[1]).GetOctets();
+
+ if (seq.Count == 3)
+ {
+ this.iterationCount = ((DerInteger) seq[2]).Value;
+ }
+ else
+ {
+ this.iterationCount = BigInteger.One;
+ }
+ }
+
+ public MacData(
+ DigestInfo digInfo,
+ byte[] salt,
+ int iterationCount)
+ {
+ this.digInfo = digInfo;
+ this.salt = (byte[]) salt.Clone();
+ this.iterationCount = BigInteger.ValueOf(iterationCount);
+ }
+
+ public DigestInfo Mac
+ {
+ get { return digInfo; }
+ }
+
+ public byte[] GetSalt()
+ {
+ return (byte[]) salt.Clone();
+ }
+
+ public BigInteger IterationCount
+ {
+ get { return iterationCount; }
+ }
+
+ /**
+ * <pre>
+ * MacData ::= SEQUENCE {
+ * mac DigestInfo,
+ * macSalt OCTET STRING,
+ * iterations INTEGER DEFAULT 1
+ * -- Note: The default is for historic reasons and its use is deprecated. A
+ * -- higher value, like 1024 is recommended.
+ * </pre>
+ * @return the basic DERObject construction.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(digInfo, new DerOctetString(salt));
+
+ if (!iterationCount.Equals(BigInteger.One))
+ {
+ v.Add(new DerInteger(iterationCount));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/PBEParameter.cs b/Crypto/src/asn1/pkcs/PBEParameter.cs
new file mode 100644
index 000000000..80d5ec3e1
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/PBEParameter.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class PbeParameter
+ : Asn1Encodable
+ {
+ private readonly Asn1OctetString salt;
+ private readonly DerInteger iterationCount;
+
+ public static PbeParameter GetInstance(object obj)
+ {
+ if (obj is PbeParameter || obj == null)
+ {
+ return (PbeParameter) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new PbeParameter((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ private PbeParameter(Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ salt = Asn1OctetString.GetInstance(seq[0]);
+ iterationCount = DerInteger.GetInstance(seq[1]);
+ }
+
+ public PbeParameter(byte[] salt, int iterationCount)
+ {
+ this.salt = new DerOctetString(salt);
+ this.iterationCount = new DerInteger(iterationCount);
+ }
+
+ public byte[] GetSalt()
+ {
+ return salt.GetOctets();
+ }
+
+ public BigInteger IterationCount
+ {
+ get { return iterationCount.Value; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(salt, iterationCount);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/PBES2Parameters.cs b/Crypto/src/asn1/pkcs/PBES2Parameters.cs
new file mode 100644
index 000000000..645bb867c
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/PBES2Parameters.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class PbeS2Parameters
+ : Asn1Encodable
+ {
+ private readonly KeyDerivationFunc func;
+ private readonly EncryptionScheme scheme;
+
+ public static PbeS2Parameters GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is PbeS2Parameters)
+ return (PbeS2Parameters) obj;
+
+ if (obj is Asn1Sequence)
+ return new PbeS2Parameters((Asn1Sequence) obj);
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public PbeS2Parameters(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ Asn1Sequence funcSeq = (Asn1Sequence)seq[0].ToAsn1Object();
+
+ // TODO Not sure if this special case is really necessary/appropriate
+ if (funcSeq[0].Equals(PkcsObjectIdentifiers.IdPbkdf2))
+ {
+ func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2,
+ Pbkdf2Params.GetInstance(funcSeq[1]));
+ }
+ else
+ {
+ func = new KeyDerivationFunc(funcSeq);
+ }
+
+ scheme = EncryptionScheme.GetInstance(seq[1].ToAsn1Object());
+ }
+
+ public KeyDerivationFunc KeyDerivationFunc
+ {
+ get { return func; }
+ }
+
+ public EncryptionScheme EncryptionScheme
+ {
+ get { return scheme; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(func, scheme);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/PBKDF2Params.cs b/Crypto/src/asn1/pkcs/PBKDF2Params.cs
new file mode 100644
index 000000000..1351b94cf
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/PBKDF2Params.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class Pbkdf2Params
+ : Asn1Encodable
+ {
+ private readonly Asn1OctetString octStr;
+ private readonly DerInteger iterationCount;
+ private readonly DerInteger keyLength;
+
+ public static Pbkdf2Params GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is Pbkdf2Params)
+ return (Pbkdf2Params)obj;
+
+ if (obj is Asn1Sequence)
+ return new Pbkdf2Params((Asn1Sequence)obj);
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public Pbkdf2Params(
+ Asn1Sequence seq)
+ {
+ if (seq.Count < 2 || seq.Count > 3)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ octStr = (Asn1OctetString)seq[0];
+ iterationCount = (DerInteger)seq[1];
+
+ if (seq.Count > 2)
+ {
+ keyLength = (DerInteger)seq[2];
+ }
+ }
+
+ public Pbkdf2Params(
+ byte[] salt,
+ int iterationCount)
+ {
+ this.octStr = new DerOctetString(salt);
+ this.iterationCount = new DerInteger(iterationCount);
+ }
+
+ public Pbkdf2Params(
+ byte[] salt,
+ int iterationCount,
+ int keyLength)
+ : this(salt, iterationCount)
+ {
+ this.keyLength = new DerInteger(keyLength);
+ }
+
+ public byte[] GetSalt()
+ {
+ return octStr.GetOctets();
+ }
+
+ public BigInteger IterationCount
+ {
+ get { return iterationCount.Value; }
+ }
+
+ public BigInteger KeyLength
+ {
+ get { return keyLength == null ? null : keyLength.Value; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ octStr, iterationCount);
+
+ if (keyLength != null)
+ {
+ v.Add(keyLength);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/PKCS12PBEParams.cs b/Crypto/src/asn1/pkcs/PKCS12PBEParams.cs
new file mode 100644
index 000000000..7521f93ea
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/PKCS12PBEParams.cs
@@ -0,0 +1,63 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class Pkcs12PbeParams
+ : Asn1Encodable
+ {
+ private readonly DerInteger iterations;
+ private readonly Asn1OctetString iv;
+
+ public Pkcs12PbeParams(
+ byte[] salt,
+ int iterations)
+ {
+ this.iv = new DerOctetString(salt);
+ this.iterations = new DerInteger(iterations);
+ }
+
+ private Pkcs12PbeParams(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ iv = Asn1OctetString.GetInstance(seq[0]);
+ iterations = DerInteger.GetInstance(seq[1]);
+ }
+
+ public static Pkcs12PbeParams GetInstance(
+ object obj)
+ {
+ if (obj is Pkcs12PbeParams)
+ {
+ return (Pkcs12PbeParams) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new Pkcs12PbeParams((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public BigInteger Iterations
+ {
+ get { return iterations.Value; }
+ }
+
+ public byte[] GetIV()
+ {
+ return iv.GetOctets();
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(iv, iterations);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/Crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
new file mode 100644
index 000000000..0b2ffa0d1
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/PKCSObjectIdentifiers.cs
@@ -0,0 +1,256 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public abstract class PkcsObjectIdentifiers
+ {
+ //
+ // pkcs-1 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+ //
+ public const string Pkcs1 = "1.2.840.113549.1.1";
+
+ public static readonly DerObjectIdentifier RsaEncryption = new DerObjectIdentifier(Pkcs1 + ".1");
+ public static readonly DerObjectIdentifier MD2WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".2");
+ public static readonly DerObjectIdentifier MD4WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".3");
+ public static readonly DerObjectIdentifier MD5WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".4");
+ public static readonly DerObjectIdentifier Sha1WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".5");
+ public static readonly DerObjectIdentifier SrsaOaepEncryptionSet = new DerObjectIdentifier(Pkcs1 + ".6");
+ public static readonly DerObjectIdentifier IdRsaesOaep = new DerObjectIdentifier(Pkcs1 + ".7");
+ public static readonly DerObjectIdentifier IdMgf1 = new DerObjectIdentifier(Pkcs1 + ".8");
+ public static readonly DerObjectIdentifier IdPSpecified = new DerObjectIdentifier(Pkcs1 + ".9");
+ public static readonly DerObjectIdentifier IdRsassaPss = new DerObjectIdentifier(Pkcs1 + ".10");
+ public static readonly DerObjectIdentifier Sha256WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".11");
+ public static readonly DerObjectIdentifier Sha384WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".12");
+ public static readonly DerObjectIdentifier Sha512WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".13");
+ public static readonly DerObjectIdentifier Sha224WithRsaEncryption = new DerObjectIdentifier(Pkcs1 + ".14");
+
+ //
+ // pkcs-3 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
+ //
+ public const string Pkcs3 = "1.2.840.113549.1.3";
+
+ public static readonly DerObjectIdentifier DhKeyAgreement = new DerObjectIdentifier(Pkcs3 + ".1");
+
+ //
+ // pkcs-5 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
+ //
+ public const string Pkcs5 = "1.2.840.113549.1.5";
+
+ public static readonly DerObjectIdentifier PbeWithMD2AndDesCbc = new DerObjectIdentifier(Pkcs5 + ".1");
+ public static readonly DerObjectIdentifier PbeWithMD2AndRC2Cbc = new DerObjectIdentifier(Pkcs5 + ".4");
+ public static readonly DerObjectIdentifier PbeWithMD5AndDesCbc = new DerObjectIdentifier(Pkcs5 + ".3");
+ public static readonly DerObjectIdentifier PbeWithMD5AndRC2Cbc = new DerObjectIdentifier(Pkcs5 + ".6");
+ public static readonly DerObjectIdentifier PbeWithSha1AndDesCbc = new DerObjectIdentifier(Pkcs5 + ".10");
+ public static readonly DerObjectIdentifier PbeWithSha1AndRC2Cbc = new DerObjectIdentifier(Pkcs5 + ".11");
+
+ public static readonly DerObjectIdentifier IdPbeS2 = new DerObjectIdentifier(Pkcs5 + ".13");
+ public static readonly DerObjectIdentifier IdPbkdf2 = new DerObjectIdentifier(Pkcs5 + ".12");
+
+ //
+ // encryptionAlgorithm OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) 3 }
+ //
+ public const string EncryptionAlgorithm = "1.2.840.113549.3";
+
+ public static readonly DerObjectIdentifier DesEde3Cbc = new DerObjectIdentifier(EncryptionAlgorithm + ".7");
+ public static readonly DerObjectIdentifier RC2Cbc = new DerObjectIdentifier(EncryptionAlgorithm + ".2");
+
+ //
+ // object identifiers for digests
+ //
+ public const string DigestAlgorithm = "1.2.840.113549.2";
+
+ //
+ // md2 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 2}
+ //
+ public static readonly DerObjectIdentifier MD2 = new DerObjectIdentifier(DigestAlgorithm + ".2");
+
+ //
+ // md4 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 4}
+ //
+ public static readonly DerObjectIdentifier MD4 = new DerObjectIdentifier(DigestAlgorithm + ".4");
+
+ //
+ // md5 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 5}
+ //
+ public static readonly DerObjectIdentifier MD5 = new DerObjectIdentifier(DigestAlgorithm + ".5");
+
+ public static readonly DerObjectIdentifier IdHmacWithSha1 = new DerObjectIdentifier(DigestAlgorithm + ".7");
+ public static readonly DerObjectIdentifier IdHmacWithSha224 = new DerObjectIdentifier(DigestAlgorithm + ".8");
+ public static readonly DerObjectIdentifier IdHmacWithSha256 = new DerObjectIdentifier(DigestAlgorithm + ".9");
+ public static readonly DerObjectIdentifier IdHmacWithSha384 = new DerObjectIdentifier(DigestAlgorithm + ".10");
+ public static readonly DerObjectIdentifier IdHmacWithSha512 = new DerObjectIdentifier(DigestAlgorithm + ".11");
+
+ //
+ // pkcs-7 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
+ //
+ public const string Pkcs7 = "1.2.840.113549.1.7";
+
+ public static readonly DerObjectIdentifier Data = new DerObjectIdentifier(Pkcs7 + ".1");
+ public static readonly DerObjectIdentifier SignedData = new DerObjectIdentifier(Pkcs7 + ".2");
+ public static readonly DerObjectIdentifier EnvelopedData = new DerObjectIdentifier(Pkcs7 + ".3");
+ public static readonly DerObjectIdentifier SignedAndEnvelopedData = new DerObjectIdentifier(Pkcs7 + ".4");
+ public static readonly DerObjectIdentifier DigestedData = new DerObjectIdentifier(Pkcs7 + ".5");
+ public static readonly DerObjectIdentifier EncryptedData = new DerObjectIdentifier(Pkcs7 + ".6");
+
+ //
+ // pkcs-9 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
+ //
+ public const string Pkcs9 = "1.2.840.113549.1.9";
+
+ public static readonly DerObjectIdentifier Pkcs9AtEmailAddress = new DerObjectIdentifier(Pkcs9 + ".1");
+ public static readonly DerObjectIdentifier Pkcs9AtUnstructuredName = new DerObjectIdentifier(Pkcs9 + ".2");
+ public static readonly DerObjectIdentifier Pkcs9AtContentType = new DerObjectIdentifier(Pkcs9 + ".3");
+ public static readonly DerObjectIdentifier Pkcs9AtMessageDigest = new DerObjectIdentifier(Pkcs9 + ".4");
+ public static readonly DerObjectIdentifier Pkcs9AtSigningTime = new DerObjectIdentifier(Pkcs9 + ".5");
+ public static readonly DerObjectIdentifier Pkcs9AtCounterSignature = new DerObjectIdentifier(Pkcs9 + ".6");
+ public static readonly DerObjectIdentifier Pkcs9AtChallengePassword = new DerObjectIdentifier(Pkcs9 + ".7");
+ public static readonly DerObjectIdentifier Pkcs9AtUnstructuredAddress = new DerObjectIdentifier(Pkcs9 + ".8");
+ public static readonly DerObjectIdentifier Pkcs9AtExtendedCertificateAttributes = new DerObjectIdentifier(Pkcs9 + ".9");
+ public static readonly DerObjectIdentifier Pkcs9AtSigningDescription = new DerObjectIdentifier(Pkcs9 + ".13");
+ public static readonly DerObjectIdentifier Pkcs9AtExtensionRequest = new DerObjectIdentifier(Pkcs9 + ".14");
+ public static readonly DerObjectIdentifier Pkcs9AtSmimeCapabilities = new DerObjectIdentifier(Pkcs9 + ".15");
+ public static readonly DerObjectIdentifier Pkcs9AtFriendlyName = new DerObjectIdentifier(Pkcs9 + ".20");
+ public static readonly DerObjectIdentifier Pkcs9AtLocalKeyID = new DerObjectIdentifier(Pkcs9 + ".21");
+
+ [Obsolete("Use X509Certificate instead")]
+ public static readonly DerObjectIdentifier X509CertType = new DerObjectIdentifier(Pkcs9 + ".22.1");
+
+ public const string CertTypes = Pkcs9 + ".22";
+ public static readonly DerObjectIdentifier X509Certificate = new DerObjectIdentifier(CertTypes + ".1");
+ public static readonly DerObjectIdentifier SdsiCertificate = new DerObjectIdentifier(CertTypes + ".2");
+
+ public const string CrlTypes = Pkcs9 + ".23";
+ public static readonly DerObjectIdentifier X509Crl = new DerObjectIdentifier(CrlTypes + ".1");
+
+ public static readonly DerObjectIdentifier IdAlgPwriKek = new DerObjectIdentifier(Pkcs9 + ".16.3.9");
+
+ //
+ // SMIME capability sub oids.
+ //
+ public static readonly DerObjectIdentifier PreferSignedData = new DerObjectIdentifier(Pkcs9 + ".15.1");
+ public static readonly DerObjectIdentifier CannotDecryptAny = new DerObjectIdentifier(Pkcs9 + ".15.2");
+ public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = new DerObjectIdentifier(Pkcs9 + ".15.3");
+
+ //
+ // other SMIME attributes
+ //
+ public static readonly DerObjectIdentifier IdAAReceiptRequest = new DerObjectIdentifier(Pkcs9 + ".16.2.1");
+
+ //
+ // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)}
+ //
+ public const string IdCT = "1.2.840.113549.1.9.16.1";
+
+ public static readonly DerObjectIdentifier IdCTAuthData = new DerObjectIdentifier(IdCT + ".2");
+ public static readonly DerObjectIdentifier IdCTTstInfo = new DerObjectIdentifier(IdCT + ".4");
+ public static readonly DerObjectIdentifier IdCTCompressedData = new DerObjectIdentifier(IdCT + ".9");
+ public static readonly DerObjectIdentifier IdCTAuthEnvelopedData = new DerObjectIdentifier(IdCT + ".23");
+ public static readonly DerObjectIdentifier IdCTTimestampedData = new DerObjectIdentifier(IdCT + ".31");
+
+ //
+ // id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) cti(6)}
+ //
+ public const string IdCti = "1.2.840.113549.1.9.16.6";
+
+ public static readonly DerObjectIdentifier IdCtiEtsProofOfOrigin = new DerObjectIdentifier(IdCti + ".1");
+ public static readonly DerObjectIdentifier IdCtiEtsProofOfReceipt = new DerObjectIdentifier(IdCti + ".2");
+ public static readonly DerObjectIdentifier IdCtiEtsProofOfDelivery = new DerObjectIdentifier(IdCti + ".3");
+ public static readonly DerObjectIdentifier IdCtiEtsProofOfSender = new DerObjectIdentifier(IdCti + ".4");
+ public static readonly DerObjectIdentifier IdCtiEtsProofOfApproval = new DerObjectIdentifier(IdCti + ".5");
+ public static readonly DerObjectIdentifier IdCtiEtsProofOfCreation = new DerObjectIdentifier(IdCti + ".6");
+
+ //
+ // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
+ //
+ public const string IdAA = "1.2.840.113549.1.9.16.2";
+
+ public static readonly DerObjectIdentifier IdAAContentHint = new DerObjectIdentifier(IdAA + ".4"); // See RFC 2634
+ public static readonly DerObjectIdentifier IdAAMsgSigDigest = new DerObjectIdentifier(IdAA + ".5");
+ public static readonly DerObjectIdentifier IdAAContentReference = new DerObjectIdentifier(IdAA + ".10");
+
+ /*
+ * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
+ *
+ */
+ public static readonly DerObjectIdentifier IdAAEncrypKeyPref = new DerObjectIdentifier(IdAA + ".11");
+ public static readonly DerObjectIdentifier IdAASigningCertificate = new DerObjectIdentifier(IdAA + ".12");
+ public static readonly DerObjectIdentifier IdAASigningCertificateV2 = new DerObjectIdentifier(IdAA + ".47");
+
+ public static readonly DerObjectIdentifier IdAAContentIdentifier = new DerObjectIdentifier(IdAA + ".7"); // See RFC 2634
+
+ /*
+ * RFC 3126
+ */
+ public static readonly DerObjectIdentifier IdAASignatureTimeStampToken = new DerObjectIdentifier(IdAA + ".14");
+
+ public static readonly DerObjectIdentifier IdAAEtsSigPolicyID = new DerObjectIdentifier(IdAA + ".15");
+ public static readonly DerObjectIdentifier IdAAEtsCommitmentType = new DerObjectIdentifier(IdAA + ".16");
+ public static readonly DerObjectIdentifier IdAAEtsSignerLocation = new DerObjectIdentifier(IdAA + ".17");
+ public static readonly DerObjectIdentifier IdAAEtsSignerAttr = new DerObjectIdentifier(IdAA + ".18");
+ public static readonly DerObjectIdentifier IdAAEtsOtherSigCert = new DerObjectIdentifier(IdAA + ".19");
+ public static readonly DerObjectIdentifier IdAAEtsContentTimestamp = new DerObjectIdentifier(IdAA + ".20");
+ public static readonly DerObjectIdentifier IdAAEtsCertificateRefs = new DerObjectIdentifier(IdAA + ".21");
+ public static readonly DerObjectIdentifier IdAAEtsRevocationRefs = new DerObjectIdentifier(IdAA + ".22");
+ public static readonly DerObjectIdentifier IdAAEtsCertValues = new DerObjectIdentifier(IdAA + ".23");
+ public static readonly DerObjectIdentifier IdAAEtsRevocationValues = new DerObjectIdentifier(IdAA + ".24");
+ public static readonly DerObjectIdentifier IdAAEtsEscTimeStamp = new DerObjectIdentifier(IdAA + ".25");
+ public static readonly DerObjectIdentifier IdAAEtsCertCrlTimestamp = new DerObjectIdentifier(IdAA + ".26");
+ public static readonly DerObjectIdentifier IdAAEtsArchiveTimestamp = new DerObjectIdentifier(IdAA + ".27");
+
+ [Obsolete("Use 'IdAAEtsSigPolicyID' instead")]
+ public static readonly DerObjectIdentifier IdAASigPolicyID = IdAAEtsSigPolicyID;
+ [Obsolete("Use 'IdAAEtsCommitmentType' instead")]
+ public static readonly DerObjectIdentifier IdAACommitmentType = IdAAEtsCommitmentType;
+ [Obsolete("Use 'IdAAEtsSignerLocation' instead")]
+ public static readonly DerObjectIdentifier IdAASignerLocation = IdAAEtsSignerLocation;
+ [Obsolete("Use 'IdAAEtsOtherSigCert' instead")]
+ public static readonly DerObjectIdentifier IdAAOtherSigCert = IdAAEtsOtherSigCert;
+
+ //
+ // id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}
+ //
+ public const string IdSpq = "1.2.840.113549.1.9.16.5";
+
+ public static readonly DerObjectIdentifier IdSpqEtsUri = new DerObjectIdentifier(IdSpq + ".1");
+ public static readonly DerObjectIdentifier IdSpqEtsUNotice = new DerObjectIdentifier(IdSpq + ".2");
+
+ //
+ // pkcs-12 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
+ //
+ public const string Pkcs12 = "1.2.840.113549.1.12";
+ public const string BagTypes = Pkcs12 + ".10.1";
+
+ public static readonly DerObjectIdentifier KeyBag = new DerObjectIdentifier(BagTypes + ".1");
+ public static readonly DerObjectIdentifier Pkcs8ShroudedKeyBag = new DerObjectIdentifier(BagTypes + ".2");
+ public static readonly DerObjectIdentifier CertBag = new DerObjectIdentifier(BagTypes + ".3");
+ public static readonly DerObjectIdentifier CrlBag = new DerObjectIdentifier(BagTypes + ".4");
+ public static readonly DerObjectIdentifier SecretBag = new DerObjectIdentifier(BagTypes + ".5");
+ public static readonly DerObjectIdentifier SafeContentsBag = new DerObjectIdentifier(BagTypes + ".6");
+
+ public const string Pkcs12PbeIds = Pkcs12 + ".1";
+
+ public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC4 = new DerObjectIdentifier(Pkcs12PbeIds + ".1");
+ public static readonly DerObjectIdentifier PbeWithShaAnd40BitRC4 = new DerObjectIdentifier(Pkcs12PbeIds + ".2");
+ public static readonly DerObjectIdentifier PbeWithShaAnd3KeyTripleDesCbc = new DerObjectIdentifier(Pkcs12PbeIds + ".3");
+ public static readonly DerObjectIdentifier PbeWithShaAnd2KeyTripleDesCbc = new DerObjectIdentifier(Pkcs12PbeIds + ".4");
+ public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC2Cbc = new DerObjectIdentifier(Pkcs12PbeIds + ".5");
+ public static readonly DerObjectIdentifier PbewithShaAnd40BitRC2Cbc = new DerObjectIdentifier(Pkcs12PbeIds + ".6");
+
+ public static readonly DerObjectIdentifier IdAlgCms3DesWrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6");
+ public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7");
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/Pfx.cs b/Crypto/src/asn1/pkcs/Pfx.cs
new file mode 100644
index 000000000..9676f64fc
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/Pfx.cs
@@ -0,0 +1,65 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ /**
+ * the infamous Pfx from Pkcs12
+ */
+ public class Pfx
+ : Asn1Encodable
+ {
+ private ContentInfo contentInfo;
+ private MacData macData;
+
+ public Pfx(
+ Asn1Sequence seq)
+ {
+ BigInteger version = ((DerInteger) seq[0]).Value;
+ if (version.IntValue != 3)
+ {
+ throw new ArgumentException("wrong version for PFX PDU");
+ }
+
+ contentInfo = ContentInfo.GetInstance(seq[1]);
+
+ if (seq.Count == 3)
+ {
+ macData = MacData.GetInstance(seq[2]);
+ }
+ }
+
+ public Pfx(
+ ContentInfo contentInfo,
+ MacData macData)
+ {
+ this.contentInfo = contentInfo;
+ this.macData = macData;
+ }
+
+ public ContentInfo AuthSafe
+ {
+ get { return contentInfo; }
+ }
+
+ public MacData MacData
+ {
+ get { return macData; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ new DerInteger(3), contentInfo);
+
+ if (macData != null)
+ {
+ v.Add(macData);
+ }
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/PrivateKeyInfo.cs b/Crypto/src/asn1/pkcs/PrivateKeyInfo.cs
new file mode 100644
index 000000000..bd0ef7d1e
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/PrivateKeyInfo.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class PrivateKeyInfo
+ : Asn1Encodable
+ {
+ private readonly Asn1Object privKey;
+ private readonly AlgorithmIdentifier algID;
+ private readonly Asn1Set attributes;
+
+ public static PrivateKeyInfo GetInstance(
+ object obj)
+ {
+ if (obj is PrivateKeyInfo)
+ return (PrivateKeyInfo) obj;
+
+ if (obj != null)
+ return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public PrivateKeyInfo(
+ AlgorithmIdentifier algID,
+ Asn1Object privateKey)
+ : this(algID, privateKey, null)
+ {
+ }
+
+ public PrivateKeyInfo(
+ AlgorithmIdentifier algID,
+ Asn1Object privateKey,
+ Asn1Set attributes)
+ {
+ this.privKey = privateKey;
+ this.algID = algID;
+ this.attributes = attributes;
+ }
+
+ private PrivateKeyInfo(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ BigInteger version = ((DerInteger) e.Current).Value;
+ if (version.IntValue != 0)
+ {
+ throw new ArgumentException("wrong version for private key info");
+ }
+
+ e.MoveNext();
+ algID = AlgorithmIdentifier.GetInstance(e.Current);
+
+ try
+ {
+ e.MoveNext();
+ Asn1OctetString data = (Asn1OctetString) e.Current;
+
+ privKey = Asn1Object.FromByteArray(data.GetOctets());
+ }
+ catch (IOException)
+ {
+ throw new ArgumentException("Error recoverying private key from sequence");
+ }
+
+ if (e.MoveNext())
+ {
+ attributes = Asn1Set.GetInstance((Asn1TaggedObject) e.Current, false);
+ }
+ }
+
+ public AlgorithmIdentifier AlgorithmID
+ {
+ get { return algID; }
+ }
+
+ public Asn1Object PrivateKey
+ {
+ get { return privKey; }
+ }
+
+ public Asn1Set Attributes
+ {
+ get { return attributes; }
+ }
+
+ /**
+ * write out an RSA private key with its associated information
+ * as described in Pkcs8.
+ * <pre>
+ * PrivateKeyInfo ::= Sequence {
+ * version Version,
+ * privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL
+ * }
+ * Version ::= Integer {v1(0)} (v1,...)
+ *
+ * PrivateKey ::= OCTET STRING
+ *
+ * Attributes ::= Set OF Attr
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ new DerInteger(0),
+ algID,
+ new DerOctetString(privKey));
+
+ if (attributes != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, attributes));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/RC2CBCParameter.cs b/Crypto/src/asn1/pkcs/RC2CBCParameter.cs
new file mode 100644
index 000000000..f5355d012
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/RC2CBCParameter.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class RC2CbcParameter
+ : Asn1Encodable
+ {
+ internal DerInteger version;
+ internal Asn1OctetString iv;
+
+ public static RC2CbcParameter GetInstance(
+ object obj)
+ {
+ if (obj is Asn1Sequence)
+ {
+ return new RC2CbcParameter((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public RC2CbcParameter(
+ byte[] iv)
+ {
+ this.iv = new DerOctetString(iv);
+ }
+
+ public RC2CbcParameter(
+ int parameterVersion,
+ byte[] iv)
+ {
+ this.version = new DerInteger(parameterVersion);
+ this.iv = new DerOctetString(iv);
+ }
+
+ private RC2CbcParameter(
+ Asn1Sequence seq)
+ {
+ if (seq.Count == 1)
+ {
+ iv = (Asn1OctetString)seq[0];
+ }
+ else
+ {
+ version = (DerInteger)seq[0];
+ iv = (Asn1OctetString)seq[1];
+ }
+ }
+
+ public BigInteger RC2ParameterVersion
+ {
+ get
+ {
+ return version == null ? null : version.Value;
+ }
+ }
+
+ public byte[] GetIV()
+ {
+ return Arrays.Clone(iv.GetOctets());
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (version != null)
+ {
+ v.Add(version);
+ }
+
+ v.Add(iv);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/RSAESOAEPparams.cs b/Crypto/src/asn1/pkcs/RSAESOAEPparams.cs
new file mode 100644
index 000000000..5ecb394fd
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/RSAESOAEPparams.cs
@@ -0,0 +1,145 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class RsaesOaepParameters
+ : Asn1Encodable
+ {
+ private AlgorithmIdentifier hashAlgorithm;
+ private AlgorithmIdentifier maskGenAlgorithm;
+ private AlgorithmIdentifier pSourceAlgorithm;
+
+ public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+ public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
+ public readonly static AlgorithmIdentifier DefaultPSourceAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]));
+
+ public static RsaesOaepParameters GetInstance(
+ object obj)
+ {
+ if (obj is RsaesOaepParameters)
+ {
+ return (RsaesOaepParameters)obj;
+ }
+ else if (obj is Asn1Sequence)
+ {
+ return new RsaesOaepParameters((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * The default version
+ */
+ public RsaesOaepParameters()
+ {
+ hashAlgorithm = DefaultHashAlgorithm;
+ maskGenAlgorithm = DefaultMaskGenFunction;
+ pSourceAlgorithm = DefaultPSourceAlgorithm;
+ }
+
+ public RsaesOaepParameters(
+ AlgorithmIdentifier hashAlgorithm,
+ AlgorithmIdentifier maskGenAlgorithm,
+ AlgorithmIdentifier pSourceAlgorithm)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.maskGenAlgorithm = maskGenAlgorithm;
+ this.pSourceAlgorithm = pSourceAlgorithm;
+ }
+
+ public RsaesOaepParameters(
+ Asn1Sequence seq)
+ {
+ hashAlgorithm = DefaultHashAlgorithm;
+ maskGenAlgorithm = DefaultMaskGenFunction;
+ pSourceAlgorithm = DefaultPSourceAlgorithm;
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject)seq[i];
+
+ switch (o.TagNo)
+ {
+ case 0:
+ hashAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+ break;
+ case 1:
+ maskGenAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+ break;
+ case 2:
+ pSourceAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+ break;
+ default:
+ throw new ArgumentException("unknown tag");
+ }
+ }
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return hashAlgorithm; }
+ }
+
+ public AlgorithmIdentifier MaskGenAlgorithm
+ {
+ get { return maskGenAlgorithm; }
+ }
+
+ public AlgorithmIdentifier PSourceAlgorithm
+ {
+ get { return pSourceAlgorithm; }
+ }
+
+ /**
+ * <pre>
+ * RSAES-OAEP-params ::= SEQUENCE {
+ * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
+ * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * pSourceAlgorithm [2] PKCS1PSourceAlgorithms DEFAULT pSpecifiedEmpty
+ * }
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+ * ... -- Allows for future expansion --
+ * }
+ * PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-pSpecified PARAMETERS OCTET STRING },
+ * ... -- Allows for future expansion --
+ * }
+ * </pre>
+ * @return the asn1 primitive representing the parameters.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (!hashAlgorithm.Equals(DefaultHashAlgorithm))
+ {
+ v.Add(new DerTaggedObject(true, 0, hashAlgorithm));
+ }
+
+ if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction))
+ {
+ v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm));
+ }
+
+ if (!pSourceAlgorithm.Equals(DefaultPSourceAlgorithm))
+ {
+ v.Add(new DerTaggedObject(true, 2, pSourceAlgorithm));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs b/Crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
new file mode 100644
index 000000000..dbb07c744
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/RSAPrivateKeyStructure.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class RsaPrivateKeyStructure
+ : Asn1Encodable
+ {
+ private readonly BigInteger modulus;
+ private readonly BigInteger publicExponent;
+ private readonly BigInteger privateExponent;
+ private readonly BigInteger prime1;
+ private readonly BigInteger prime2;
+ private readonly BigInteger exponent1;
+ private readonly BigInteger exponent2;
+ private readonly BigInteger coefficient;
+
+ public RsaPrivateKeyStructure(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger prime1,
+ BigInteger prime2,
+ BigInteger exponent1,
+ BigInteger exponent2,
+ BigInteger coefficient)
+ {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ this.privateExponent = privateExponent;
+ this.prime1 = prime1;
+ this.prime2 = prime2;
+ this.exponent1 = exponent1;
+ this.exponent2 = exponent2;
+ this.coefficient = coefficient;
+ }
+
+ public RsaPrivateKeyStructure(
+ Asn1Sequence seq)
+ {
+ BigInteger version = ((DerInteger) seq[0]).Value;
+ if (version.IntValue != 0)
+ throw new ArgumentException("wrong version for RSA private key");
+
+ modulus = ((DerInteger) seq[1]).Value;
+ publicExponent = ((DerInteger) seq[2]).Value;
+ privateExponent = ((DerInteger) seq[3]).Value;
+ prime1 = ((DerInteger) seq[4]).Value;
+ prime2 = ((DerInteger) seq[5]).Value;
+ exponent1 = ((DerInteger) seq[6]).Value;
+ exponent2 = ((DerInteger) seq[7]).Value;
+ coefficient = ((DerInteger) seq[8]).Value;
+ }
+
+ public BigInteger Modulus
+ {
+ get { return modulus; }
+ }
+
+ public BigInteger PublicExponent
+ {
+ get { return publicExponent; }
+ }
+
+ public BigInteger PrivateExponent
+ {
+ get { return privateExponent; }
+ }
+
+ public BigInteger Prime1
+ {
+ get { return prime1; }
+ }
+
+ public BigInteger Prime2
+ {
+ get { return prime2; }
+ }
+
+ public BigInteger Exponent1
+ {
+ get { return exponent1; }
+ }
+
+ public BigInteger Exponent2
+ {
+ get { return exponent2; }
+ }
+
+ public BigInteger Coefficient
+ {
+ get { return coefficient; }
+ }
+
+ /**
+ * This outputs the key in Pkcs1v2 format.
+ * <pre>
+ * RsaPrivateKey ::= Sequence {
+ * version Version,
+ * modulus Integer, -- n
+ * publicExponent Integer, -- e
+ * privateExponent Integer, -- d
+ * prime1 Integer, -- p
+ * prime2 Integer, -- q
+ * exponent1 Integer, -- d mod (p-1)
+ * exponent2 Integer, -- d mod (q-1)
+ * coefficient Integer -- (inverse of q) mod p
+ * }
+ *
+ * Version ::= Integer
+ * </pre>
+ * <p>This routine is written to output Pkcs1 version 0, private keys.</p>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(
+ new DerInteger(0), // version
+ new DerInteger(Modulus),
+ new DerInteger(PublicExponent),
+ new DerInteger(PrivateExponent),
+ new DerInteger(Prime1),
+ new DerInteger(Prime2),
+ new DerInteger(Exponent1),
+ new DerInteger(Exponent2),
+ new DerInteger(Coefficient));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/RSASSAPSSparams.cs b/Crypto/src/asn1/pkcs/RSASSAPSSparams.cs
new file mode 100644
index 000000000..941620761
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/RSASSAPSSparams.cs
@@ -0,0 +1,165 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class RsassaPssParameters
+ : Asn1Encodable
+ {
+ private AlgorithmIdentifier hashAlgorithm;
+ private AlgorithmIdentifier maskGenAlgorithm;
+ private DerInteger saltLength;
+ private DerInteger trailerField;
+
+ public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+ public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
+ public readonly static DerInteger DefaultSaltLength = new DerInteger(20);
+ public readonly static DerInteger DefaultTrailerField = new DerInteger(1);
+
+ public static RsassaPssParameters GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is RsassaPssParameters)
+ {
+ return (RsassaPssParameters)obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new RsassaPssParameters((Asn1Sequence)obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ /**
+ * The default version
+ */
+ public RsassaPssParameters()
+ {
+ hashAlgorithm = DefaultHashAlgorithm;
+ maskGenAlgorithm = DefaultMaskGenFunction;
+ saltLength = DefaultSaltLength;
+ trailerField = DefaultTrailerField;
+ }
+
+ public RsassaPssParameters(
+ AlgorithmIdentifier hashAlgorithm,
+ AlgorithmIdentifier maskGenAlgorithm,
+ DerInteger saltLength,
+ DerInteger trailerField)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.maskGenAlgorithm = maskGenAlgorithm;
+ this.saltLength = saltLength;
+ this.trailerField = trailerField;
+ }
+
+ public RsassaPssParameters(
+ Asn1Sequence seq)
+ {
+ hashAlgorithm = DefaultHashAlgorithm;
+ maskGenAlgorithm = DefaultMaskGenFunction;
+ saltLength = DefaultSaltLength;
+ trailerField = DefaultTrailerField;
+
+ for (int i = 0; i != seq.Count; i++)
+ {
+ Asn1TaggedObject o = (Asn1TaggedObject)seq[i];
+
+ switch (o.TagNo)
+ {
+ case 0:
+ hashAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+ break;
+ case 1:
+ maskGenAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+ break;
+ case 2:
+ saltLength = DerInteger.GetInstance(o, true);
+ break;
+ case 3:
+ trailerField = DerInteger.GetInstance(o, true);
+ break;
+ default:
+ throw new ArgumentException("unknown tag");
+ }
+ }
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return hashAlgorithm; }
+ }
+
+ public AlgorithmIdentifier MaskGenAlgorithm
+ {
+ get { return maskGenAlgorithm; }
+ }
+
+ public DerInteger SaltLength
+ {
+ get { return saltLength; }
+ }
+
+ public DerInteger TrailerField
+ {
+ get { return trailerField; }
+ }
+
+ /**
+ * <pre>
+ * RSASSA-PSS-params ::= SEQUENCE {
+ * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
+ * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * saltLength [2] INTEGER DEFAULT 20,
+ * trailerField [3] TrailerField DEFAULT trailerFieldBC
+ * }
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * TrailerField ::= INTEGER { trailerFieldBC(1) }
+ * </pre>
+ * @return the asn1 primitive representing the parameters.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (!hashAlgorithm.Equals(DefaultHashAlgorithm))
+ {
+ v.Add(new DerTaggedObject(true, 0, hashAlgorithm));
+ }
+
+ if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction))
+ {
+ v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm));
+ }
+
+ if (!saltLength.Equals(DefaultSaltLength))
+ {
+ v.Add(new DerTaggedObject(true, 2, saltLength));
+ }
+
+ if (!trailerField.Equals(DefaultTrailerField))
+ {
+ v.Add(new DerTaggedObject(true, 3, trailerField));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/SafeBag.cs b/Crypto/src/asn1/pkcs/SafeBag.cs
new file mode 100644
index 000000000..4b9350bac
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/SafeBag.cs
@@ -0,0 +1,70 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ public class SafeBag
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier bagID;
+ private readonly Asn1Object bagValue;
+ private readonly Asn1Set bagAttributes;
+
+ public SafeBag(
+ DerObjectIdentifier oid,
+ Asn1Object obj)
+ {
+ this.bagID = oid;
+ this.bagValue = obj;
+ this.bagAttributes = null;
+ }
+
+ public SafeBag(
+ DerObjectIdentifier oid,
+ Asn1Object obj,
+ Asn1Set bagAttributes)
+ {
+ this.bagID = oid;
+ this.bagValue = obj;
+ this.bagAttributes = bagAttributes;
+ }
+
+ public SafeBag(
+ Asn1Sequence seq)
+ {
+ this.bagID = (DerObjectIdentifier) seq[0];
+ this.bagValue = ((DerTaggedObject) seq[1]).GetObject();
+ if (seq.Count == 3)
+ {
+ this.bagAttributes = (Asn1Set) seq[2];
+ }
+ }
+
+ public DerObjectIdentifier BagID
+ {
+ get { return bagID; }
+ }
+
+ public Asn1Object BagValue
+ {
+ get { return bagValue; }
+ }
+
+ public Asn1Set BagAttributes
+ {
+ get { return bagAttributes; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ bagID, new DerTaggedObject(0, bagValue));
+
+ if (bagAttributes != null)
+ {
+ v.Add(bagAttributes);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/SignedData.cs b/Crypto/src/asn1/pkcs/SignedData.cs
new file mode 100644
index 000000000..10951d37a
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/SignedData.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ /**
+ * a Pkcs#7 signed data object.
+ */
+ public class SignedData
+ : Asn1Encodable
+ {
+ private readonly DerInteger version;
+ private readonly Asn1Set digestAlgorithms;
+ private readonly ContentInfo contentInfo;
+ private readonly Asn1Set certificates;
+ private readonly Asn1Set crls;
+ private readonly Asn1Set signerInfos;
+
+ public static SignedData GetInstance(
+ object obj)
+ {
+ if (obj is SignedData)
+ {
+ return (SignedData) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new SignedData((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public SignedData(
+ DerInteger _version,
+ Asn1Set _digestAlgorithms,
+ ContentInfo _contentInfo,
+ Asn1Set _certificates,
+ Asn1Set _crls,
+ Asn1Set _signerInfos)
+ {
+ version = _version;
+ digestAlgorithms = _digestAlgorithms;
+ contentInfo = _contentInfo;
+ certificates = _certificates;
+ crls = _crls;
+ signerInfos = _signerInfos;
+ }
+
+ private SignedData(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ version = (DerInteger) e.Current;
+
+ e.MoveNext();
+ digestAlgorithms = (Asn1Set) e.Current;
+
+ e.MoveNext();
+ contentInfo = ContentInfo.GetInstance(e.Current);
+
+ while (e.MoveNext())
+ {
+ Asn1Object o = (Asn1Object) e.Current;
+
+ //
+ // an interesting feature of SignedData is that there appear to be varying implementations...
+ // for the moment we ignore anything which doesn't fit.
+ //
+ if (o is DerTaggedObject)
+ {
+ DerTaggedObject tagged = (DerTaggedObject) o;
+
+ switch (tagged.TagNo)
+ {
+ case 0:
+ certificates = Asn1Set.GetInstance(tagged, false);
+ break;
+ case 1:
+ crls = Asn1Set.GetInstance(tagged, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag value " + tagged.TagNo);
+ }
+ }
+ else
+ {
+ signerInfos = (Asn1Set) o;
+ }
+ }
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public Asn1Set DigestAlgorithms
+ {
+ get { return digestAlgorithms; }
+ }
+
+ public ContentInfo ContentInfo
+ {
+ get { return contentInfo; }
+ }
+
+ public Asn1Set Certificates
+ {
+ get { return certificates; }
+ }
+
+ public Asn1Set Crls
+ {
+ get { return crls; }
+ }
+
+ public Asn1Set SignerInfos
+ {
+ get { return signerInfos; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SignedData ::= Sequence {
+ * version Version,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * contentInfo ContentInfo,
+ * certificates
+ * [0] IMPLICIT ExtendedCertificatesAndCertificates
+ * OPTIONAL,
+ * crls
+ * [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, digestAlgorithms, contentInfo);
+
+ if (certificates != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, certificates));
+ }
+
+ if (crls != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, crls));
+ }
+
+ v.Add(signerInfos);
+
+ return new BerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/pkcs/SignerInfo.cs b/Crypto/src/asn1/pkcs/SignerInfo.cs
new file mode 100644
index 000000000..1e4694547
--- /dev/null
+++ b/Crypto/src/asn1/pkcs/SignerInfo.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+ /**
+ * a Pkcs#7 signer info object.
+ */
+ public class SignerInfo
+ : Asn1Encodable
+ {
+ private DerInteger version;
+ private IssuerAndSerialNumber issuerAndSerialNumber;
+ private AlgorithmIdentifier digAlgorithm;
+ private Asn1Set authenticatedAttributes;
+ private AlgorithmIdentifier digEncryptionAlgorithm;
+ private Asn1OctetString encryptedDigest;
+ private Asn1Set unauthenticatedAttributes;
+
+ public static SignerInfo GetInstance(
+ object obj)
+ {
+ if (obj is SignerInfo)
+ {
+ return (SignerInfo) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new SignerInfo((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+ }
+
+ public SignerInfo(
+ DerInteger version,
+ IssuerAndSerialNumber issuerAndSerialNumber,
+ AlgorithmIdentifier digAlgorithm,
+ Asn1Set authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ Asn1OctetString encryptedDigest,
+ Asn1Set unauthenticatedAttributes)
+ {
+ this.version = version;
+ this.issuerAndSerialNumber = issuerAndSerialNumber;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = unauthenticatedAttributes;
+ }
+
+ public SignerInfo(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ version = (DerInteger) e.Current;
+
+ e.MoveNext();
+ issuerAndSerialNumber = IssuerAndSerialNumber.GetInstance(e.Current);
+
+ e.MoveNext();
+ digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+
+ e.MoveNext();
+ object obj = e.Current;
+
+ if (obj is Asn1TaggedObject)
+ {
+ authenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) obj, false);
+
+ e.MoveNext();
+ digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+ }
+ else
+ {
+ authenticatedAttributes = null;
+ digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj);
+ }
+
+ e.MoveNext();
+ encryptedDigest = DerOctetString.GetInstance(e.Current);
+
+ if (e.MoveNext())
+ {
+ unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current, false);
+ }
+ else
+ {
+ unauthenticatedAttributes = null;
+ }
+ }
+
+ public DerInteger Version { get { return version; } }
+
+ public IssuerAndSerialNumber IssuerAndSerialNumber { get { return issuerAndSerialNumber; } }
+
+ public Asn1Set AuthenticatedAttributes { get { return authenticatedAttributes; } }
+
+ public AlgorithmIdentifier DigestAlgorithm { get { return digAlgorithm; } }
+
+ public Asn1OctetString EncryptedDigest { get { return encryptedDigest; } }
+
+ public AlgorithmIdentifier DigestEncryptionAlgorithm { get { return digEncryptionAlgorithm; } }
+
+ public Asn1Set UnauthenticatedAttributes { get { return unauthenticatedAttributes; } }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SignerInfo ::= Sequence {
+ * version Version,
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+ * }
+ *
+ * EncryptedDigest ::= OCTET STRING
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, issuerAndSerialNumber, digAlgorithm);
+
+ if (authenticatedAttributes != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, authenticatedAttributes));
+ }
+
+ v.Add(digEncryptionAlgorithm, encryptedDigest);
+
+ if (unauthenticatedAttributes != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, unauthenticatedAttributes));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/sec/ECPrivateKeyStructure.cs b/Crypto/src/asn1/sec/ECPrivateKeyStructure.cs
new file mode 100644
index 000000000..2e9c27fd2
--- /dev/null
+++ b/Crypto/src/asn1/sec/ECPrivateKeyStructure.cs
@@ -0,0 +1,118 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Sec
+{
+ /**
+ * the elliptic curve private key object from SEC 1
+ */
+ public class ECPrivateKeyStructure
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence seq;
+
+ public ECPrivateKeyStructure(
+ Asn1Sequence seq)
+ {
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+
+ this.seq = seq;
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ this.seq = new DerSequence(
+ new DerInteger(1),
+ new DerOctetString(key.ToByteArrayUnsigned()));
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key,
+ Asn1Encodable parameters)
+ : this(key, null, parameters)
+ {
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key,
+ DerBitString publicKey,
+ Asn1Encodable parameters)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ new DerInteger(1),
+ new DerOctetString(key.ToByteArrayUnsigned()));
+
+ if (parameters != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, parameters));
+ }
+
+ if (publicKey != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, publicKey));
+ }
+
+ this.seq = new DerSequence(v);
+ }
+
+ public BigInteger GetKey()
+ {
+ Asn1OctetString octs = (Asn1OctetString) seq[1];
+
+ return new BigInteger(1, octs.GetOctets());
+ }
+
+ public DerBitString GetPublicKey()
+ {
+ return (DerBitString) GetObjectInTag(1);
+ }
+
+ public Asn1Object GetParameters()
+ {
+ return GetObjectInTag(0);
+ }
+
+ private Asn1Object GetObjectInTag(
+ int tagNo)
+ {
+ foreach (Asn1Encodable ae in seq)
+ {
+ Asn1Object obj = ae.ToAsn1Object();
+
+ if (obj is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tag = (Asn1TaggedObject) obj;
+ if (tag.TagNo == tagNo)
+ {
+ return tag.GetObject();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] Parameters OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL }
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/sec/SECNamedCurves.cs b/Crypto/src/asn1/sec/SECNamedCurves.cs
new file mode 100644
index 000000000..c7503144f
--- /dev/null
+++ b/Crypto/src/asn1/sec/SECNamedCurves.cs
@@ -0,0 +1,1192 @@
+using System;
+using System.Collections;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Sec
+{
+ public sealed class SecNamedCurves
+ {
+ private SecNamedCurves()
+ {
+ }
+
+ private static BigInteger FromHex(
+ string hex)
+ {
+ return new BigInteger(1, Hex.Decode(hex));
+ }
+
+ /*
+ * secp112r1
+ */
+ internal class Secp112r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp112r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp112r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = (2^128 - 3) / 76439
+ BigInteger p = FromHex("DB7C2ABF62E35E668076BEAD208B");
+ BigInteger a = FromHex("DB7C2ABF62E35E668076BEAD2088");
+ BigInteger b = FromHex("659EF8BA043916EEDE8911702B22");
+ byte[] S = Hex.Decode("00F50B028E4D696E676875615175290472783FB1");
+ BigInteger n = FromHex("DB7C2ABF62E35E7628DFAC6561C5");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "09487239995A5EE76B55F9C2F098"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "09487239995A5EE76B55F9C2F098"
+ + "A89CE5AF8724C0A23E0E0FF77500"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp112r2
+ */
+ internal class Secp112r2Holder
+ : X9ECParametersHolder
+ {
+ private Secp112r2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp112r2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = (2^128 - 3) / 76439
+ BigInteger p = FromHex("DB7C2ABF62E35E668076BEAD208B");
+ BigInteger a = FromHex("6127C24C05F38A0AAAF65C0EF02C");
+ BigInteger b = FromHex("51DEF1815DB5ED74FCC34C85D709");
+ byte[] S = Hex.Decode("002757A1114D696E6768756151755316C05E0BD4");
+ BigInteger n = FromHex("36DF0AAFD8B8D7597CA10520D04B");
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "4BA30AB5E892B4E1649DD0928643"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "4BA30AB5E892B4E1649DD0928643"
+ + "ADCD46F5882E3747DEF36E956E97"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp128r1
+ */
+ internal class Secp128r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp128r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp128r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^128 - 2^97 - 1
+ BigInteger p = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = FromHex("E87579C11079F43DD824993C2CEE5ED3");
+ byte[] S = Hex.Decode("000E0D4D696E6768756151750CC03A4473D03679");
+ BigInteger n = FromHex("FFFFFFFE0000000075A30D1B9038A115");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "161FF7528B899B2D0C28607CA52C5B86"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "161FF7528B899B2D0C28607CA52C5B86"
+ + "CF5AC8395BAFEB13C02DA292DDED7A83"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp128r2
+ */
+ internal class Secp128r2Holder
+ : X9ECParametersHolder
+ {
+ private Secp128r2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp128r2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^128 - 2^97 - 1
+ BigInteger p = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = FromHex("D6031998D1B3BBFEBF59CC9BBFF9AEE1");
+ BigInteger b = FromHex("5EEEFCA380D02919DC2C6558BB6D8A5D");
+ byte[] S = Hex.Decode("004D696E67687561517512D8F03431FCE63B88F4");
+ BigInteger n = FromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "7B6AA5D85E572983E6FB32A7CDEBC140"
+ + "27B6916A894D3AEE7106FE805FC34B44"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp160k1
+ */
+ internal class Secp160k1Holder
+ : X9ECParametersHolder
+ {
+ private Secp160k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp160k1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(7);
+ byte[] S = null;
+ BigInteger n = FromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+ + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp160r1
+ */
+ internal class Secp160r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp160r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp160r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^160 - 2^31 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF");
+ BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC");
+ BigInteger b = FromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45");
+ byte[] S = Hex.Decode("1053CDE42C14D696E67687561517533BF3F83345");
+ BigInteger n = FromHex("0100000000000000000001F4C8F927AED3CA752257");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "4A96B5688EF573284664698968C38BB913CBFC82"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "4A96B5688EF573284664698968C38BB913CBFC82"
+ + "23A628553168947D59DCC912042351377AC5FB32"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp160r2
+ */
+ internal class Secp160r2Holder
+ : X9ECParametersHolder
+ {
+ private Secp160r2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp160r2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+ BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70");
+ BigInteger b = FromHex("B4E134D3FB59EB8BAB57274904664D5AF50388BA");
+ byte[] S = Hex.Decode("B99B99B099B323E02709A4D696E6768756151751");
+ BigInteger n = FromHex("0100000000000000000000351EE786A818F3A1A16B");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
+ + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp192k1
+ */
+ internal class Secp192k1Holder
+ : X9ECParametersHolder
+ {
+ private Secp192k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp192k1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37");
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(3);
+ byte[] S = null;
+ BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp192r1
+ */
+ internal class Secp192r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp192r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp192r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^192 - 2^64 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
+ BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
+ BigInteger b = FromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1");
+ byte[] S = Hex.Decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+ BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp224k1
+ */
+ internal class Secp224k1Holder
+ : X9ECParametersHolder
+ {
+ private Secp224k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp224k1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D");
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(5);
+ byte[] S = null;
+ BigInteger n = FromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp224r1
+ */
+ internal class Secp224r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp224r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp224r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^224 - 2^96 + 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
+ BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE");
+ BigInteger b = FromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4");
+ byte[] S = Hex.Decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+ BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp256k1
+ */
+ internal class Secp256k1Holder
+ : X9ECParametersHolder
+ {
+ private Secp256k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp256k1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(7);
+ byte[] S = null;
+ BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp256r1
+ */
+ internal class Secp256r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp256r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp256r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
+ BigInteger p = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = FromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
+ byte[] S = Hex.Decode("C49D360886E704936A6678E1139D26B7819F7E90");
+ BigInteger n = FromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp384r1
+ */
+ internal class Secp384r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp384r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp384r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^384 - 2^128 - 2^96 + 2^32 - 1
+ BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF");
+ BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC");
+ BigInteger b = FromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF");
+ byte[] S = Hex.Decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
+ BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * secp521r1
+ */
+ internal class Secp521r1Holder
+ : X9ECParametersHolder
+ {
+ private Secp521r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Secp521r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ // p = 2^521 - 1
+ BigInteger p = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = FromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00");
+ byte[] S = Hex.Decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
+ BigInteger n = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
+ BigInteger h = BigInteger.ValueOf(1);
+
+ ECCurve curve = new FpCurve(p, a, b);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect113r1
+ */
+ internal class Sect113r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect113r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect113r1Holder();
+
+ private const int m = 113;
+ private const int k = 9;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = FromHex("003088250CA6E7C7FE649CE85820F7");
+ BigInteger b = FromHex("00E8BEE4D3E2260744188BE0E9C723");
+ byte[] S = Hex.Decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
+ BigInteger n = FromHex("0100000000000000D9CCEC8A39E56F");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "009D73616F35F4AB1407D73562C10F"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "009D73616F35F4AB1407D73562C10F"
+ + "00A52830277958EE84D1315ED31886"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect113r2
+ */
+ internal class Sect113r2Holder
+ : X9ECParametersHolder
+ {
+ private Sect113r2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect113r2Holder();
+
+ private const int m = 113;
+ private const int k = 9;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = FromHex("00689918DBEC7E5A0DD6DFC0AA55C7");
+ BigInteger b = FromHex("0095E9A9EC9B297BD4BF36E059184F");
+ byte[] S = Hex.Decode("10C0FB15760860DEF1EEF4D696E676875615175D");
+ BigInteger n = FromHex("010000000000000108789B2496AF93");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "01A57A6A7B26CA5EF52FCDB8164797"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "01A57A6A7B26CA5EF52FCDB8164797"
+ + "00B3ADC94ED1FE674C06E695BABA1D"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect131r1
+ */
+ internal class Sect131r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect131r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect131r1Holder();
+
+ private const int m = 131;
+ private const int k1 = 2;
+ private const int k2 = 3;
+ private const int k3 = 8;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = FromHex("07A11B09A76B562144418FF3FF8C2570B8");
+ BigInteger b = FromHex("0217C05610884B63B9C6C7291678F9D341");
+ byte[] S = Hex.Decode("4D696E676875615175985BD3ADBADA21B43A97E2");
+ BigInteger n = FromHex("0400000000000000023123953A9464B54D");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "0081BAF91FDF9833C40F9C181343638399"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0081BAF91FDF9833C40F9C181343638399"
+ + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect131r2
+ */
+ internal class Sect131r2Holder
+ : X9ECParametersHolder
+ {
+ private Sect131r2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect131r2Holder();
+
+ private const int m = 131;
+ private const int k1 = 2;
+ private const int k2 = 3;
+ private const int k3 = 8;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = FromHex("03E5A88919D7CAFCBF415F07C2176573B2");
+ BigInteger b = FromHex("04B8266A46C55657AC734CE38F018F2192");
+ byte[] S = Hex.Decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
+ BigInteger n = FromHex("0400000000000000016954A233049BA98F");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "0356DCD8F2F95031AD652D23951BB366A8"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0356DCD8F2F95031AD652D23951BB366A8"
+ + "0648F06D867940A5366D9E265DE9EB240F"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect163k1
+ */
+ internal class Sect163k1Holder
+ : X9ECParametersHolder
+ {
+ private Sect163k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect163k1Holder();
+
+ private const int m = 163;
+ private const int k1 = 3;
+ private const int k2 = 6;
+ private const int k3 = 7;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.ValueOf(1);
+ BigInteger b = BigInteger.ValueOf(1);
+ byte[] S = null;
+ BigInteger n = FromHex("04000000000000000000020108A2E0CC0D99F8A5EF");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+ + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect163r1
+ */
+ internal class Sect163r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect163r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect163r1Holder();
+
+ private const int m = 163;
+ private const int k1 = 3;
+ private const int k2 = 6;
+ private const int k3 = 7;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = FromHex("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2");
+ BigInteger b = FromHex("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9");
+ byte[] S = Hex.Decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
+ BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "0369979697AB43897789566789567F787A7876A654"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0369979697AB43897789566789567F787A7876A654"
+ + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect163r2
+ */
+ internal class Sect163r2Holder
+ : X9ECParametersHolder
+ {
+ private Sect163r2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect163r2Holder();
+
+ private const int m = 163;
+ private const int k1 = 3;
+ private const int k2 = 6;
+ private const int k3 = 7;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.ValueOf(1);
+ BigInteger b = FromHex("020A601907B8C953CA1481EB10512F78744A3205FD");
+ byte[] S = Hex.Decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
+ BigInteger n = FromHex("040000000000000000000292FE77E70C12A4234C33");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+ + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect193r1
+ */
+ internal class Sect193r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect193r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect193r1Holder();
+
+ private const int m = 193;
+ private const int k = 15;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = FromHex("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01");
+ BigInteger b = FromHex("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814");
+ byte[] S = Hex.Decode("103FAEC74D696E676875615175777FC5B191EF30");
+ BigInteger n = FromHex("01000000000000000000000000C7F34A778F443ACC920EBA49");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+ + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect193r2
+ */
+ internal class Sect193r2Holder
+ : X9ECParametersHolder
+ {
+ private Sect193r2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect193r2Holder();
+
+ private const int m = 193;
+ private const int k = 15;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = FromHex("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B");
+ BigInteger b = FromHex("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE");
+ byte[] S = Hex.Decode("10B7B4D696E676875615175137C8A16FD0DA2211");
+ BigInteger n = FromHex("010000000000000000000000015AAB561B005413CCD4EE99D5");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+ + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect233k1
+ */
+ internal class Sect233k1Holder
+ : X9ECParametersHolder
+ {
+ private Sect233k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect233k1Holder();
+
+ private const int m = 233;
+ private const int k = 74;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(1);
+ byte[] S = null;
+ BigInteger n = FromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF");
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+ + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect233r1
+ */
+ internal class Sect233r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect233r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect233r1Holder();
+
+ private const int m = 233;
+ private const int k = 74;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.ValueOf(1);
+ BigInteger b = FromHex("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD");
+ byte[] S = Hex.Decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
+ BigInteger n = FromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+ + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect239k1
+ */
+ internal class Sect239k1Holder
+ : X9ECParametersHolder
+ {
+ private Sect239k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect239k1Holder();
+
+ private const int m = 239;
+ private const int k = 158;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(1);
+ byte[] S = null;
+ BigInteger n = FromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5");
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+ + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect283k1
+ */
+ internal class Sect283k1Holder
+ : X9ECParametersHolder
+ {
+ private Sect283k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect283k1Holder();
+
+ private const int m = 283;
+ private const int k1 = 5;
+ private const int k2 = 7;
+ private const int k3 = 12;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(1);
+ byte[] S = null;
+ BigInteger n = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61");
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+ + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect283r1
+ */
+ internal class Sect283r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect283r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect283r1Holder();
+
+ private const int m = 283;
+ private const int k1 = 5;
+ private const int k2 = 7;
+ private const int k3 = 12;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.ValueOf(1);
+ BigInteger b = FromHex("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5");
+ byte[] S = Hex.Decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
+ BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+ + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect409k1
+ */
+ internal class Sect409k1Holder
+ : X9ECParametersHolder
+ {
+ private Sect409k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect409k1Holder();
+
+ private const int m = 409;
+ private const int k = 87;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(1);
+ byte[] S = null;
+ BigInteger n = FromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF");
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+ + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect409r1
+ */
+ internal class Sect409r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect409r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect409r1Holder();
+
+ private const int m = 409;
+ private const int k = 87;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.ValueOf(1);
+ BigInteger b = FromHex("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F");
+ byte[] S = Hex.Decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
+ BigInteger n = FromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+ + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect571k1
+ */
+ internal class Sect571k1Holder
+ : X9ECParametersHolder
+ {
+ private Sect571k1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect571k1Holder();
+
+ private const int m = 571;
+ private const int k1 = 2;
+ private const int k2 = 5;
+ private const int k3 = 10;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.Zero;
+ BigInteger b = BigInteger.ValueOf(1);
+ byte[] S = null;
+ BigInteger n = FromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001");
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+ //+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+ + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+ /*
+ * sect571r1
+ */
+ internal class Sect571r1Holder
+ : X9ECParametersHolder
+ {
+ private Sect571r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Sect571r1Holder();
+
+ private const int m = 571;
+ private const int k1 = 2;
+ private const int k2 = 5;
+ private const int k3 = 10;
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger a = BigInteger.ValueOf(1);
+ BigInteger b = FromHex("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A");
+ byte[] S = Hex.Decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
+ BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47");
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+ //+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"));
+ ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+ + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ }
+
+
+ private static readonly IDictionary objIds = Platform.CreateHashtable();
+ private static readonly IDictionary curves = Platform.CreateHashtable();
+ private static readonly IDictionary names = Platform.CreateHashtable();
+
+ private static void DefineCurve(
+ string name,
+ DerObjectIdentifier oid,
+ X9ECParametersHolder holder)
+ {
+ objIds.Add(name, oid);
+ names.Add(oid, name);
+ curves.Add(oid, holder);
+ }
+
+ static SecNamedCurves()
+ {
+ DefineCurve("secp112r1", SecObjectIdentifiers.SecP112r1, Secp112r1Holder.Instance);
+ DefineCurve("secp112r2", SecObjectIdentifiers.SecP112r2, Secp112r2Holder.Instance);
+ DefineCurve("secp128r1", SecObjectIdentifiers.SecP128r1, Secp128r1Holder.Instance);
+ DefineCurve("secp128r2", SecObjectIdentifiers.SecP128r2, Secp128r2Holder.Instance);
+ DefineCurve("secp160k1", SecObjectIdentifiers.SecP160k1, Secp160k1Holder.Instance);
+ DefineCurve("secp160r1", SecObjectIdentifiers.SecP160r1, Secp160r1Holder.Instance);
+ DefineCurve("secp160r2", SecObjectIdentifiers.SecP160r2, Secp160r2Holder.Instance);
+ DefineCurve("secp192k1", SecObjectIdentifiers.SecP192k1, Secp192k1Holder.Instance);
+ DefineCurve("secp192r1", SecObjectIdentifiers.SecP192r1, Secp192r1Holder.Instance);
+ DefineCurve("secp224k1", SecObjectIdentifiers.SecP224k1, Secp224k1Holder.Instance);
+ DefineCurve("secp224r1", SecObjectIdentifiers.SecP224r1, Secp224r1Holder.Instance);
+ DefineCurve("secp256k1", SecObjectIdentifiers.SecP256k1, Secp256k1Holder.Instance);
+ DefineCurve("secp256r1", SecObjectIdentifiers.SecP256r1, Secp256r1Holder.Instance);
+ DefineCurve("secp384r1", SecObjectIdentifiers.SecP384r1, Secp384r1Holder.Instance);
+ DefineCurve("secp521r1", SecObjectIdentifiers.SecP521r1, Secp521r1Holder.Instance);
+
+ DefineCurve("sect113r1", SecObjectIdentifiers.SecT113r1, Sect113r1Holder.Instance);
+ DefineCurve("sect113r2", SecObjectIdentifiers.SecT113r2, Sect113r2Holder.Instance);
+ DefineCurve("sect131r1", SecObjectIdentifiers.SecT131r1, Sect131r1Holder.Instance);
+ DefineCurve("sect131r2", SecObjectIdentifiers.SecT131r2, Sect131r2Holder.Instance);
+ DefineCurve("sect163k1", SecObjectIdentifiers.SecT163k1, Sect163k1Holder.Instance);
+ DefineCurve("sect163r1", SecObjectIdentifiers.SecT163r1, Sect163r1Holder.Instance);
+ DefineCurve("sect163r2", SecObjectIdentifiers.SecT163r2, Sect163r2Holder.Instance);
+ DefineCurve("sect193r1", SecObjectIdentifiers.SecT193r1, Sect193r1Holder.Instance);
+ DefineCurve("sect193r2", SecObjectIdentifiers.SecT193r2, Sect193r2Holder.Instance);
+ DefineCurve("sect233k1", SecObjectIdentifiers.SecT233k1, Sect233k1Holder.Instance);
+ DefineCurve("sect233r1", SecObjectIdentifiers.SecT233r1, Sect233r1Holder.Instance);
+ DefineCurve("sect239k1", SecObjectIdentifiers.SecT239k1, Sect239k1Holder.Instance);
+ DefineCurve("sect283k1", SecObjectIdentifiers.SecT283k1, Sect283k1Holder.Instance);
+ DefineCurve("sect283r1", SecObjectIdentifiers.SecT283r1, Sect283r1Holder.Instance);
+ DefineCurve("sect409k1", SecObjectIdentifiers.SecT409k1, Sect409k1Holder.Instance);
+ DefineCurve("sect409r1", SecObjectIdentifiers.SecT409r1, Sect409r1Holder.Instance);
+ DefineCurve("sect571k1", SecObjectIdentifiers.SecT571k1, Sect571k1Holder.Instance);
+ DefineCurve("sect571r1", SecObjectIdentifiers.SecT571r1, Sect571r1Holder.Instance);
+ }
+
+ public static X9ECParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier)
+ objIds[name.ToLowerInvariant()];
+
+ return oid == null ? null : GetByOid(oid);
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid];
+
+ return holder == null ? null : holder.Parameters;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier) objIds[name.ToLowerInvariant()];
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static string GetName(
+ DerObjectIdentifier oid)
+ {
+ return (string) names[oid];
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(objIds.Keys); }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/sec/SECObjectIdentifiers.cs b/Crypto/src/asn1/sec/SECObjectIdentifiers.cs
new file mode 100644
index 000000000..afc10e1d6
--- /dev/null
+++ b/Crypto/src/asn1/sec/SECObjectIdentifiers.cs
@@ -0,0 +1,52 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+
+namespace Org.BouncyCastle.Asn1.Sec
+{
+ public abstract class SecObjectIdentifiers
+ {
+ /**
+ * EllipticCurve OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0)
+ * }
+ */
+ public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier("1.3.132.0");
+
+ public static readonly DerObjectIdentifier SecT163k1 = new DerObjectIdentifier(EllipticCurve + ".1");
+ public static readonly DerObjectIdentifier SecT163r1 = new DerObjectIdentifier(EllipticCurve + ".2");
+ public static readonly DerObjectIdentifier SecT239k1 = new DerObjectIdentifier(EllipticCurve + ".3");
+ public static readonly DerObjectIdentifier SecT113r1 = new DerObjectIdentifier(EllipticCurve + ".4");
+ public static readonly DerObjectIdentifier SecT113r2 = new DerObjectIdentifier(EllipticCurve + ".5");
+ public static readonly DerObjectIdentifier SecP112r1 = new DerObjectIdentifier(EllipticCurve + ".6");
+ public static readonly DerObjectIdentifier SecP112r2 = new DerObjectIdentifier(EllipticCurve + ".7");
+ public static readonly DerObjectIdentifier SecP160r1 = new DerObjectIdentifier(EllipticCurve + ".8");
+ public static readonly DerObjectIdentifier SecP160k1 = new DerObjectIdentifier(EllipticCurve + ".9");
+ public static readonly DerObjectIdentifier SecP256k1 = new DerObjectIdentifier(EllipticCurve + ".10");
+ public static readonly DerObjectIdentifier SecT163r2 = new DerObjectIdentifier(EllipticCurve + ".15");
+ public static readonly DerObjectIdentifier SecT283k1 = new DerObjectIdentifier(EllipticCurve + ".16");
+ public static readonly DerObjectIdentifier SecT283r1 = new DerObjectIdentifier(EllipticCurve + ".17");
+ public static readonly DerObjectIdentifier SecT131r1 = new DerObjectIdentifier(EllipticCurve + ".22");
+ public static readonly DerObjectIdentifier SecT131r2 = new DerObjectIdentifier(EllipticCurve + ".23");
+ public static readonly DerObjectIdentifier SecT193r1 = new DerObjectIdentifier(EllipticCurve + ".24");
+ public static readonly DerObjectIdentifier SecT193r2 = new DerObjectIdentifier(EllipticCurve + ".25");
+ public static readonly DerObjectIdentifier SecT233k1 = new DerObjectIdentifier(EllipticCurve + ".26");
+ public static readonly DerObjectIdentifier SecT233r1 = new DerObjectIdentifier(EllipticCurve + ".27");
+ public static readonly DerObjectIdentifier SecP128r1 = new DerObjectIdentifier(EllipticCurve + ".28");
+ public static readonly DerObjectIdentifier SecP128r2 = new DerObjectIdentifier(EllipticCurve + ".29");
+ public static readonly DerObjectIdentifier SecP160r2 = new DerObjectIdentifier(EllipticCurve + ".30");
+ public static readonly DerObjectIdentifier SecP192k1 = new DerObjectIdentifier(EllipticCurve + ".31");
+ public static readonly DerObjectIdentifier SecP224k1 = new DerObjectIdentifier(EllipticCurve + ".32");
+ public static readonly DerObjectIdentifier SecP224r1 = new DerObjectIdentifier(EllipticCurve + ".33");
+ public static readonly DerObjectIdentifier SecP384r1 = new DerObjectIdentifier(EllipticCurve + ".34");
+ public static readonly DerObjectIdentifier SecP521r1 = new DerObjectIdentifier(EllipticCurve + ".35");
+ public static readonly DerObjectIdentifier SecT409k1 = new DerObjectIdentifier(EllipticCurve + ".36");
+ public static readonly DerObjectIdentifier SecT409r1 = new DerObjectIdentifier(EllipticCurve + ".37");
+ public static readonly DerObjectIdentifier SecT571k1 = new DerObjectIdentifier(EllipticCurve + ".38");
+ public static readonly DerObjectIdentifier SecT571r1 = new DerObjectIdentifier(EllipticCurve + ".39");
+
+ public static readonly DerObjectIdentifier SecP192r1 = X9ObjectIdentifiers.Prime192v1;
+ public static readonly DerObjectIdentifier SecP256r1 = X9ObjectIdentifiers.Prime256v1;
+ }
+}
\ No newline at end of file
diff --git a/Crypto/src/asn1/smime/SMIMEAttributes.cs b/Crypto/src/asn1/smime/SMIMEAttributes.cs
new file mode 100644
index 000000000..e154e5e74
--- /dev/null
+++ b/Crypto/src/asn1/smime/SMIMEAttributes.cs
@@ -0,0 +1,11 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+ public abstract class SmimeAttributes
+ {
+ public static readonly DerObjectIdentifier SmimeCapabilities = PkcsObjectIdentifiers.Pkcs9AtSmimeCapabilities;
+ public static readonly DerObjectIdentifier EncrypKeyPref = PkcsObjectIdentifiers.IdAAEncrypKeyPref;
+ }
+}
diff --git a/Crypto/src/asn1/smime/SMIMECapabilities.cs b/Crypto/src/asn1/smime/SMIMECapabilities.cs
new file mode 100644
index 000000000..adf254e56
--- /dev/null
+++ b/Crypto/src/asn1/smime/SMIMECapabilities.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+ /**
+ * Handler class for dealing with S/MIME Capabilities
+ */
+ public class SmimeCapabilities
+ : Asn1Encodable
+ {
+ /**
+ * general preferences
+ */
+ public static readonly DerObjectIdentifier PreferSignedData = PkcsObjectIdentifiers.PreferSignedData;
+ public static readonly DerObjectIdentifier CannotDecryptAny = PkcsObjectIdentifiers.CannotDecryptAny;
+ public static readonly DerObjectIdentifier SmimeCapabilitesVersions = PkcsObjectIdentifiers.SmimeCapabilitiesVersions;
+
+ /**
+ * encryption algorithms preferences
+ */
+ public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7");
+ public static readonly DerObjectIdentifier DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc;
+ public static readonly DerObjectIdentifier RC2Cbc = PkcsObjectIdentifiers.RC2Cbc;
+
+ private Asn1Sequence capabilities;
+
+ /**
+ * 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 SmimeCapabilities GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SmimeCapabilities)
+ {
+ return (SmimeCapabilities) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new SmimeCapabilities((Asn1Sequence) obj);
+ }
+
+ if (obj is AttributeX509)
+ {
+ return new SmimeCapabilities(
+ (Asn1Sequence)(((AttributeX509) obj).AttrValues[0]));
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public SmimeCapabilities(
+ Asn1Sequence seq)
+ {
+ capabilities = seq;
+ }
+
+#if !(SILVERLIGHT || PORTABLE)
+ [Obsolete("Use 'GetCapabilitiesForOid' instead")]
+ public ArrayList GetCapabilities(
+ DerObjectIdentifier capability)
+ {
+ ArrayList list = new ArrayList();
+ DoGetCapabilitiesForOid(capability, list);
+ return list;
+ }
+#endif
+
+ /**
+ * returns an ArrayList with 0 or more objects of all the capabilities
+ * matching the passed in capability Oid. If the Oid passed is null the
+ * entire set is returned.
+ */
+ public IList GetCapabilitiesForOid(
+ DerObjectIdentifier capability)
+ {
+ IList list = Platform.CreateArrayList();
+ DoGetCapabilitiesForOid(capability, list);
+ return list;
+ }
+
+ private void DoGetCapabilitiesForOid(DerObjectIdentifier capability, IList list)
+ {
+ if (capability == null)
+ {
+ foreach (object o in capabilities)
+ {
+ SmimeCapability cap = SmimeCapability.GetInstance(o);
+
+ list.Add(cap);
+ }
+ }
+ else
+ {
+ foreach (object o in capabilities)
+ {
+ SmimeCapability cap = SmimeCapability.GetInstance(o);
+
+ if (capability.Equals(cap.CapabilityID))
+ {
+ list.Add(cap);
+ }
+ }
+ }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SMIMECapabilities ::= Sequence OF SMIMECapability
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return capabilities;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/smime/SMIMECapabilitiesAttribute.cs b/Crypto/src/asn1/smime/SMIMECapabilitiesAttribute.cs
new file mode 100644
index 000000000..310c478fe
--- /dev/null
+++ b/Crypto/src/asn1/smime/SMIMECapabilitiesAttribute.cs
@@ -0,0 +1,16 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+ public class SmimeCapabilitiesAttribute
+ : AttributeX509
+ {
+ public SmimeCapabilitiesAttribute(
+ SmimeCapabilityVector capabilities)
+ : base(SmimeAttributes.SmimeCapabilities,
+ new DerSet(new DerSequence(capabilities.ToAsn1EncodableVector())))
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/smime/SMIMECapability.cs b/Crypto/src/asn1/smime/SMIMECapability.cs
new file mode 100644
index 000000000..5709cb815
--- /dev/null
+++ b/Crypto/src/asn1/smime/SMIMECapability.cs
@@ -0,0 +1,101 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+ public class SmimeCapability
+ : Asn1Encodable
+ {
+ /**
+ * general preferences
+ */
+ public static readonly DerObjectIdentifier PreferSignedData = PkcsObjectIdentifiers.PreferSignedData;
+ public static readonly DerObjectIdentifier CannotDecryptAny = PkcsObjectIdentifiers.CannotDecryptAny;
+ public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = PkcsObjectIdentifiers.SmimeCapabilitiesVersions;
+
+ /**
+ * encryption algorithms preferences
+ */
+ public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7");
+ public static readonly DerObjectIdentifier DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc;
+ public static readonly DerObjectIdentifier RC2Cbc = PkcsObjectIdentifiers.RC2Cbc;
+
+ private DerObjectIdentifier capabilityID;
+ private Asn1Object parameters;
+
+ public SmimeCapability(
+ Asn1Sequence seq)
+ {
+ capabilityID = (DerObjectIdentifier) seq[0].ToAsn1Object();
+
+ if (seq.Count > 1)
+ {
+ parameters = seq[1].ToAsn1Object();
+ }
+ }
+
+ public SmimeCapability(
+ DerObjectIdentifier capabilityID,
+ Asn1Encodable parameters)
+ {
+ if (capabilityID == null)
+ throw new ArgumentNullException("capabilityID");
+
+ this.capabilityID = capabilityID;
+
+ if (parameters != null)
+ {
+ this.parameters = parameters.ToAsn1Object();
+ }
+ }
+
+ public static SmimeCapability GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is SmimeCapability)
+ {
+ return (SmimeCapability) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new SmimeCapability((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("Invalid SmimeCapability");
+ }
+
+ public DerObjectIdentifier CapabilityID
+ {
+ get { return capabilityID; }
+ }
+
+ public Asn1Object Parameters
+ {
+ get { return parameters; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * SMIMECapability ::= Sequence {
+ * capabilityID OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY capabilityID OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(capabilityID);
+
+ if (parameters != null)
+ {
+ v.Add(parameters);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/smime/SMIMECapabilityVector.cs b/Crypto/src/asn1/smime/SMIMECapabilityVector.cs
new file mode 100644
index 000000000..842825b88
--- /dev/null
+++ b/Crypto/src/asn1/smime/SMIMECapabilityVector.cs
@@ -0,0 +1,37 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+ /**
+ * Handler for creating a vector S/MIME Capabilities
+ */
+ public class SmimeCapabilityVector
+ {
+ private readonly Asn1EncodableVector capabilities = new Asn1EncodableVector();
+
+ public void AddCapability(
+ DerObjectIdentifier capability)
+ {
+ capabilities.Add(new DerSequence(capability));
+ }
+
+ public void AddCapability(
+ DerObjectIdentifier capability,
+ int value)
+ {
+ capabilities.Add(new DerSequence(capability, new DerInteger(value)));
+ }
+
+ public void AddCapability(
+ DerObjectIdentifier capability,
+ Asn1Encodable parameters)
+ {
+ capabilities.Add(new DerSequence(capability, parameters));
+ }
+
+ public Asn1EncodableVector ToAsn1EncodableVector()
+ {
+ return capabilities;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs b/Crypto/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs
new file mode 100644
index 000000000..19c5fd78a
--- /dev/null
+++ b/Crypto/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs
@@ -0,0 +1,44 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+ /**
+ * The SmimeEncryptionKeyPreference object.
+ * <pre>
+ * SmimeEncryptionKeyPreference ::= CHOICE {
+ * issuerAndSerialNumber [0] IssuerAndSerialNumber,
+ * receipentKeyId [1] RecipientKeyIdentifier,
+ * subjectAltKeyIdentifier [2] SubjectKeyIdentifier
+ * }
+ * </pre>
+ */
+ public class SmimeEncryptionKeyPreferenceAttribute
+ : AttributeX509
+ {
+ public SmimeEncryptionKeyPreferenceAttribute(
+ IssuerAndSerialNumber issAndSer)
+ : base(SmimeAttributes.EncrypKeyPref,
+ new DerSet(new DerTaggedObject(false, 0, issAndSer)))
+ {
+ }
+
+ public SmimeEncryptionKeyPreferenceAttribute(
+ RecipientKeyIdentifier rKeyID)
+ : base(SmimeAttributes.EncrypKeyPref,
+ new DerSet(new DerTaggedObject(false, 1, rKeyID)))
+ {
+ }
+
+ /**
+ * @param sKeyId the subjectKeyIdentifier value (normally the X.509 one)
+ */
+ public SmimeEncryptionKeyPreferenceAttribute(
+ Asn1OctetString sKeyID)
+ : base(SmimeAttributes.EncrypKeyPref,
+ new DerSet(new DerTaggedObject(false, 2, sKeyID)))
+ {
+ }
+ }
+}
diff --git a/Crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs b/Crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
new file mode 100644
index 000000000..0cfdb8483
--- /dev/null
+++ b/Crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
@@ -0,0 +1,428 @@
+using System.Collections;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.TeleTrust
+{
+ /**
+ * elliptic curves defined in "ECC Brainpool Standard Curves and Curve Generation"
+ * http://www.ecc-brainpool.org/download/draft_pkix_additional_ecc_dp.txt
+ */
+ public class TeleTrusTNamedCurves
+ {
+ internal class BrainpoolP160r1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP160r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP160r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
+ new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a
+ new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
+ new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP160t1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP160t1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP160t1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ // new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z
+ new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
+ new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620C", 16), // a'
+ new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
+ new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP192r1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP192r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP192r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
+ new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a
+ new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
+ new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP192t1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP192t1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP192t1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ //new BigInteger("1B6F5CC8DB4DC7AF19458A9CB80DC2295E5EB9C3732104CB") //Z
+ new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
+ new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", 16), // a'
+ new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
+ new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP224r1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP224r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP224r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
+ new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a
+ new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
+ new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n
+ new BigInteger("01", 16)); // n
+ }
+ }
+
+ internal class BrainpoolP224t1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP224t1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP224t1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ //new BigInteger("2DF271E14427A346910CF7A2E6CFA7B3F484E5C2CCE1C8B730E28B3F") //Z
+ new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
+ new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", 16), // a'
+ new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
+ new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP256r1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP256r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP256r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
+ new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a
+ new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP256t1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP256t1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP256t1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ //new BigInteger("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0") //Z
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", 16), // a'
+ new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP320r1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP320r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP320r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
+ new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a
+ new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP320t1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP320t1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP320t1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ //new BigInteger("15F75CAF668077F7E85B42EB01F0A81FF56ECD6191D55CB82B7D861458A18FEFC3E5AB7496F3C7B1") //Z
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", 16), // a'
+ new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP384r1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP384r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP384r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
+ new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a
+ new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP384t1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP384t1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP384t1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ //new BigInteger("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C") //Z
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", 16), // a'
+ new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP512r1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP512r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP512r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
+ new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a
+ new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+ internal class BrainpoolP512t1Holder
+ : X9ECParametersHolder
+ {
+ private BrainpoolP512t1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new BrainpoolP512t1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve curve = new FpCurve(
+ //new BigInteger("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB") //Z
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", 16), // a'
+ new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.DecodePoint(Hex.Decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ }
+
+
+ private static readonly IDictionary objIds = Platform.CreateHashtable();
+ private static readonly IDictionary curves = Platform.CreateHashtable();
+ private static readonly IDictionary names = Platform.CreateHashtable();
+
+ private static void DefineCurve(
+ string name,
+ DerObjectIdentifier oid,
+ X9ECParametersHolder holder)
+ {
+ objIds.Add(name, oid);
+ names.Add(oid, name);
+ curves.Add(oid, holder);
+ }
+
+ static TeleTrusTNamedCurves()
+ {
+ DefineCurve("brainpoolp160r1", TeleTrusTObjectIdentifiers.BrainpoolP160R1, BrainpoolP160r1Holder.Instance);
+ DefineCurve("brainpoolp160t1", TeleTrusTObjectIdentifiers.BrainpoolP160T1, BrainpoolP160t1Holder.Instance);
+ DefineCurve("brainpoolp192r1", TeleTrusTObjectIdentifiers.BrainpoolP192R1, BrainpoolP192r1Holder.Instance);
+ DefineCurve("brainpoolp192t1", TeleTrusTObjectIdentifiers.BrainpoolP192T1, BrainpoolP192t1Holder.Instance);
+ DefineCurve("brainpoolp224r1", TeleTrusTObjectIdentifiers.BrainpoolP224R1, BrainpoolP224r1Holder.Instance);
+ DefineCurve("brainpoolp224t1", TeleTrusTObjectIdentifiers.BrainpoolP224T1, BrainpoolP224t1Holder.Instance);
+ DefineCurve("brainpoolp256r1", TeleTrusTObjectIdentifiers.BrainpoolP256R1, BrainpoolP256r1Holder.Instance);
+ DefineCurve("brainpoolp256t1", TeleTrusTObjectIdentifiers.BrainpoolP256T1, BrainpoolP256t1Holder.Instance);
+ DefineCurve("brainpoolp320r1", TeleTrusTObjectIdentifiers.BrainpoolP320R1, BrainpoolP320r1Holder.Instance);
+ DefineCurve("brainpoolp320t1", TeleTrusTObjectIdentifiers.BrainpoolP320T1, BrainpoolP320t1Holder.Instance);
+ DefineCurve("brainpoolp384r1", TeleTrusTObjectIdentifiers.BrainpoolP384R1, BrainpoolP384r1Holder.Instance);
+ DefineCurve("brainpoolp384t1", TeleTrusTObjectIdentifiers.BrainpoolP384T1, BrainpoolP384t1Holder.Instance);
+ DefineCurve("brainpoolp512r1", TeleTrusTObjectIdentifiers.BrainpoolP512R1, BrainpoolP512r1Holder.Instance);
+ DefineCurve("brainpoolp512t1", TeleTrusTObjectIdentifiers.BrainpoolP512T1, BrainpoolP512t1Holder.Instance);
+ }
+
+ public static X9ECParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier)
+ objIds[name.ToLowerInvariant()];
+
+ return oid == null ? null : GetByOid(oid);
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid];
+
+ return holder == null ? null : holder.Parameters;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier) objIds[name.ToLowerInvariant()];
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static string GetName(
+ DerObjectIdentifier oid)
+ {
+ return (string) names[oid];
+ }
+
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(objIds.Keys); }
+ }
+
+ public static DerObjectIdentifier GetOid(
+ short curvesize,
+ bool twisted)
+ {
+ return GetOid("brainpoolP" + curvesize + (twisted ? "t" : "r") + "1");
+ }
+ }
+}
diff --git a/Crypto/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs b/Crypto/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs
new file mode 100644
index 000000000..56e70842a
--- /dev/null
+++ b/Crypto/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs
@@ -0,0 +1,45 @@
+namespace Org.BouncyCastle.Asn1.TeleTrust
+{
+ public sealed class TeleTrusTObjectIdentifiers
+ {
+ private TeleTrusTObjectIdentifiers()
+ {
+ }
+
+ public static readonly DerObjectIdentifier TeleTrusTAlgorithm = new DerObjectIdentifier("1.3.36.3");
+
+ public static readonly DerObjectIdentifier RipeMD160 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.1");
+ public static readonly DerObjectIdentifier RipeMD128 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.2");
+ public static readonly DerObjectIdentifier RipeMD256 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.3");
+
+ public static readonly DerObjectIdentifier TeleTrusTRsaSignatureAlgorithm = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.1");
+
+ public static readonly DerObjectIdentifier RsaSignatureWithRipeMD160 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".2");
+ public static readonly DerObjectIdentifier RsaSignatureWithRipeMD128 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".3");
+ public static readonly DerObjectIdentifier RsaSignatureWithRipeMD256 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".4");
+
+ public static readonly DerObjectIdentifier ECSign = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.2");
+
+ public static readonly DerObjectIdentifier ECSignWithSha1 = new DerObjectIdentifier(ECSign + ".1");
+ public static readonly DerObjectIdentifier ECSignWithRipeMD160 = new DerObjectIdentifier(ECSign + ".2");
+
+ public static readonly DerObjectIdentifier EccBrainpool = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.2.8");
+ public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier(EccBrainpool + ".1");
+ public static readonly DerObjectIdentifier VersionOne = new DerObjectIdentifier(EllipticCurve + ".1");
+
+ public static readonly DerObjectIdentifier BrainpoolP160R1 = new DerObjectIdentifier(VersionOne + ".1");
+ public static readonly DerObjectIdentifier BrainpoolP160T1 = new DerObjectIdentifier(VersionOne + ".2");
+ public static readonly DerObjectIdentifier BrainpoolP192R1 = new DerObjectIdentifier(VersionOne + ".3");
+ public static readonly DerObjectIdentifier BrainpoolP192T1 = new DerObjectIdentifier(VersionOne + ".4");
+ public static readonly DerObjectIdentifier BrainpoolP224R1 = new DerObjectIdentifier(VersionOne + ".5");
+ public static readonly DerObjectIdentifier BrainpoolP224T1 = new DerObjectIdentifier(VersionOne + ".6");
+ public static readonly DerObjectIdentifier BrainpoolP256R1 = new DerObjectIdentifier(VersionOne + ".7");
+ public static readonly DerObjectIdentifier BrainpoolP256T1 = new DerObjectIdentifier(VersionOne + ".8");
+ public static readonly DerObjectIdentifier BrainpoolP320R1 = new DerObjectIdentifier(VersionOne + ".9");
+ public static readonly DerObjectIdentifier BrainpoolP320T1 = new DerObjectIdentifier(VersionOne + ".10");
+ public static readonly DerObjectIdentifier BrainpoolP384R1 = new DerObjectIdentifier(VersionOne + ".11");
+ public static readonly DerObjectIdentifier BrainpoolP384T1 = new DerObjectIdentifier(VersionOne + ".12");
+ public static readonly DerObjectIdentifier BrainpoolP512R1 = new DerObjectIdentifier(VersionOne + ".13");
+ public static readonly DerObjectIdentifier BrainpoolP512T1 = new DerObjectIdentifier(VersionOne + ".14");
+ }
+}
diff --git a/Crypto/src/asn1/tsp/Accuracy.cs b/Crypto/src/asn1/tsp/Accuracy.cs
new file mode 100644
index 000000000..a193f52ff
--- /dev/null
+++ b/Crypto/src/asn1/tsp/Accuracy.cs
@@ -0,0 +1,149 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+ public class Accuracy
+ : Asn1Encodable
+ {
+ private readonly DerInteger seconds;
+ private readonly DerInteger millis;
+ private readonly DerInteger micros;
+
+ // constants
+ protected const int MinMillis = 1;
+ protected const int MaxMillis = 999;
+ protected const int MinMicros = 1;
+ protected const int MaxMicros = 999;
+
+ public Accuracy(
+ DerInteger seconds,
+ DerInteger millis,
+ DerInteger micros)
+ {
+ //Verifications
+ if (millis != null
+ && (millis.Value.IntValue < MinMillis
+ || millis.Value.IntValue > MaxMillis))
+ {
+ throw new ArgumentException(
+ "Invalid millis field : not in (1..999)");
+ }
+
+ if (micros != null
+ && (micros.Value.IntValue < MinMicros
+ || micros.Value.IntValue > MaxMicros))
+ {
+ throw new ArgumentException(
+ "Invalid micros field : not in (1..999)");
+ }
+
+ this.seconds = seconds;
+ this.millis = millis;
+ this.micros = micros;
+ }
+
+ private Accuracy(
+ Asn1Sequence seq)
+ {
+ for (int i = 0; i < seq.Count; ++i)
+ {
+ // seconds
+ if (seq[i] is DerInteger)
+ {
+ seconds = (DerInteger) seq[i];
+ }
+ else if (seq[i] is DerTaggedObject)
+ {
+ DerTaggedObject extra = (DerTaggedObject) seq[i];
+
+ switch (extra.TagNo)
+ {
+ case 0:
+ millis = DerInteger.GetInstance(extra, false);
+ if (millis.Value.IntValue < MinMillis
+ || millis.Value.IntValue > MaxMillis)
+ {
+ throw new ArgumentException(
+ "Invalid millis field : not in (1..999).");
+ }
+ break;
+ case 1:
+ micros = DerInteger.GetInstance(extra, false);
+ if (micros.Value.IntValue < MinMicros
+ || micros.Value.IntValue > MaxMicros)
+ {
+ throw new ArgumentException(
+ "Invalid micros field : not in (1..999).");
+ }
+ break;
+ default:
+ throw new ArgumentException("Invalig tag number");
+ }
+ }
+ }
+ }
+
+ public static Accuracy GetInstance(
+ object o)
+ {
+ if (o == null || o is Accuracy)
+ {
+ return (Accuracy) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new Accuracy((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "Unknown object in 'Accuracy' factory: " + o.GetType().FullName);
+ }
+
+ public DerInteger Seconds
+ {
+ get { return seconds; }
+ }
+
+ public DerInteger Millis
+ {
+ get { return millis; }
+ }
+
+ public DerInteger Micros
+ {
+ get { return micros; }
+ }
+
+ /**
+ * <pre>
+ * Accuracy ::= SEQUENCE {
+ * seconds INTEGER OPTIONAL,
+ * millis [0] INTEGER (1..999) OPTIONAL,
+ * micros [1] INTEGER (1..999) OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (seconds != null)
+ {
+ v.Add(seconds);
+ }
+
+ if (millis != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, millis));
+ }
+
+ if (micros != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, micros));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/tsp/MessageImprint.cs b/Crypto/src/asn1/tsp/MessageImprint.cs
new file mode 100644
index 000000000..0933bae21
--- /dev/null
+++ b/Crypto/src/asn1/tsp/MessageImprint.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+ public class MessageImprint
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier hashAlgorithm;
+ private readonly byte[] hashedMessage;
+
+ /**
+ * @param o
+ * @return a MessageImprint object.
+ */
+ public static MessageImprint GetInstance(
+ object o)
+ {
+ if (o == null || o is MessageImprint)
+ {
+ return (MessageImprint) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new MessageImprint((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "Unknown object in 'MessageImprint' factory: " + o.GetType().FullName);
+ }
+
+ private MessageImprint(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+ this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+ this.hashedMessage = Asn1OctetString.GetInstance(seq[1]).GetOctets();
+ }
+
+ public MessageImprint(
+ AlgorithmIdentifier hashAlgorithm,
+ byte[] hashedMessage)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashedMessage = hashedMessage;
+ }
+
+ public AlgorithmIdentifier HashAlgorithm
+ {
+ get { return hashAlgorithm; }
+ }
+
+ public byte[] GetHashedMessage()
+ {
+ return hashedMessage;
+ }
+
+ /**
+ * <pre>
+ * MessageImprint ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashedMessage OCTET STRING }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(hashAlgorithm, new DerOctetString(hashedMessage));
+ }
+ }
+}
diff --git a/Crypto/src/asn1/tsp/TSTInfo.cs b/Crypto/src/asn1/tsp/TSTInfo.cs
new file mode 100644
index 000000000..61d5399c7
--- /dev/null
+++ b/Crypto/src/asn1/tsp/TSTInfo.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+ public class TstInfo
+ : Asn1Encodable
+ {
+ private readonly DerInteger version;
+ private readonly DerObjectIdentifier tsaPolicyId;
+ private readonly MessageImprint messageImprint;
+ private readonly DerInteger serialNumber;
+ private readonly DerGeneralizedTime genTime;
+ private readonly Accuracy accuracy;
+ private readonly DerBoolean ordering;
+ private readonly DerInteger nonce;
+ private readonly GeneralName tsa;
+ private readonly X509Extensions extensions;
+
+ public static TstInfo GetInstance(
+ object o)
+ {
+ if (o == null || o is TstInfo)
+ {
+ return (TstInfo) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new TstInfo((Asn1Sequence) o);
+ }
+
+ if (o is Asn1OctetString)
+ {
+ try
+ {
+ byte[] octets = ((Asn1OctetString)o).GetOctets();
+ return GetInstance(Asn1Object.FromByteArray(octets));
+ }
+ catch (IOException)
+ {
+ throw new ArgumentException(
+ "Bad object format in 'TstInfo' factory.");
+ }
+ }
+
+ throw new ArgumentException(
+ "Unknown object in 'TstInfo' factory: " + o.GetType().FullName);
+ }
+
+ private TstInfo(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ // version
+ e.MoveNext();
+ version = DerInteger.GetInstance(e.Current);
+
+ // tsaPolicy
+ e.MoveNext();
+ tsaPolicyId = DerObjectIdentifier.GetInstance(e.Current);
+
+ // messageImprint
+ e.MoveNext();
+ messageImprint = MessageImprint.GetInstance(e.Current);
+
+ // serialNumber
+ e.MoveNext();
+ serialNumber = DerInteger.GetInstance(e.Current);
+
+ // genTime
+ e.MoveNext();
+ genTime = DerGeneralizedTime.GetInstance(e.Current);
+
+ // default for ordering
+ ordering = DerBoolean.False;
+
+ while (e.MoveNext())
+ {
+ Asn1Object o = (Asn1Object) e.Current;
+
+ if (o is Asn1TaggedObject)
+ {
+ DerTaggedObject tagged = (DerTaggedObject) o;
+
+ switch (tagged.TagNo)
+ {
+ case 0:
+ tsa = GeneralName.GetInstance(tagged, true);
+ break;
+ case 1:
+ extensions = X509Extensions.GetInstance(tagged, false);
+ break;
+ default:
+ throw new ArgumentException("Unknown tag value " + tagged.TagNo);
+ }
+ }
+
+ if (o is DerSequence)
+ {
+ accuracy = Accuracy.GetInstance(o);
+ }
+
+ if (o is DerBoolean)
+ {
+ ordering = DerBoolean.GetInstance(o);
+ }
+
+ if (o is DerInteger)
+ {
+ nonce = DerInteger.GetInstance(o);
+ }
+ }
+ }
+
+ public TstInfo(
+ DerObjectIdentifier tsaPolicyId,
+ MessageImprint messageImprint,
+ DerInteger serialNumber,
+ DerGeneralizedTime genTime,
+ Accuracy accuracy,
+ DerBoolean ordering,
+ DerInteger nonce,
+ GeneralName tsa,
+ X509Extensions extensions)
+ {
+ this.version = new DerInteger(1);
+ this.tsaPolicyId = tsaPolicyId;
+ this.messageImprint = messageImprint;
+ this.serialNumber = serialNumber;
+ this.genTime = genTime;
+ this.accuracy = accuracy;
+ this.ordering = ordering;
+ this.nonce = nonce;
+ this.tsa = tsa;
+ this.extensions = extensions;
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public MessageImprint MessageImprint
+ {
+ get { return messageImprint; }
+ }
+
+ public DerObjectIdentifier Policy
+ {
+ get { return tsaPolicyId; }
+ }
+
+ public DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ public Accuracy Accuracy
+ {
+ get { return accuracy; }
+ }
+
+ public DerGeneralizedTime GenTime
+ {
+ get { return genTime; }
+ }
+
+ public DerBoolean Ordering
+ {
+ get { return ordering; }
+ }
+
+ public DerInteger Nonce
+ {
+ get { return nonce; }
+ }
+
+ public GeneralName Tsa
+ {
+ get { return tsa; }
+ }
+
+ public X509Extensions Extensions
+ {
+ get { return extensions; }
+ }
+
+ /**
+ * <pre>
+ *
+ * TstInfo ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * policy TSAPolicyId,
+ * messageImprint MessageImprint,
+ * -- MUST have the same value as the similar field in
+ * -- TimeStampReq
+ * serialNumber INTEGER,
+ * -- Time-Stamping users MUST be ready to accommodate integers
+ * -- up to 160 bits.
+ * genTime GeneralizedTime,
+ * accuracy Accuracy OPTIONAL,
+ * ordering BOOLEAN DEFAULT FALSE,
+ * nonce INTEGER OPTIONAL,
+ * -- MUST be present if the similar field was present
+ * -- in TimeStampReq. In that case it MUST have the same value.
+ * tsa [0] GeneralName OPTIONAL,
+ * extensions [1] IMPLICIT Extensions OPTIONAL }
+ *
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, tsaPolicyId, messageImprint, serialNumber, genTime);
+
+ if (accuracy != null)
+ {
+ v.Add(accuracy);
+ }
+
+ if (ordering != null && ordering.IsTrue)
+ {
+ v.Add(ordering);
+ }
+
+ if (nonce != null)
+ {
+ v.Add(nonce);
+ }
+
+ if (tsa != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, tsa));
+ }
+
+ if (extensions != null)
+ {
+ v.Add(new DerTaggedObject(false, 1, extensions));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/tsp/TimeStampReq.cs b/Crypto/src/asn1/tsp/TimeStampReq.cs
new file mode 100644
index 000000000..55e973e76
--- /dev/null
+++ b/Crypto/src/asn1/tsp/TimeStampReq.cs
@@ -0,0 +1,164 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+ public class TimeStampReq
+ : Asn1Encodable
+ {
+ private readonly DerInteger version;
+ private readonly MessageImprint messageImprint;
+ private readonly DerObjectIdentifier tsaPolicy;
+ private readonly DerInteger nonce;
+ private readonly DerBoolean certReq;
+ private readonly X509Extensions extensions;
+
+ public static TimeStampReq GetInstance(
+ object o)
+ {
+ if (o == null || o is TimeStampReq)
+ {
+ return (TimeStampReq) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new TimeStampReq((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "Unknown object in 'TimeStampReq' factory: " + o.GetType().FullName);
+ }
+
+ private TimeStampReq(
+ Asn1Sequence seq)
+ {
+ int nbObjects = seq.Count;
+ int seqStart = 0;
+
+ // version
+ version = DerInteger.GetInstance(seq[seqStart++]);
+
+ // messageImprint
+ messageImprint = MessageImprint.GetInstance(seq[seqStart++]);
+
+ for (int opt = seqStart; opt < nbObjects; opt++)
+ {
+ // tsaPolicy
+ if (seq[opt] is DerObjectIdentifier)
+ {
+ tsaPolicy = DerObjectIdentifier.GetInstance(seq[opt]);
+ }
+ // nonce
+ else if (seq[opt] is DerInteger)
+ {
+ nonce = DerInteger.GetInstance(seq[opt]);
+ }
+ // certReq
+ else if (seq[opt] is DerBoolean)
+ {
+ certReq = DerBoolean.GetInstance(seq[opt]);
+ }
+ // extensions
+ else if (seq[opt] is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagged = (Asn1TaggedObject) seq[opt];
+ if (tagged.TagNo == 0)
+ {
+ extensions = X509Extensions.GetInstance(tagged, false);
+ }
+ }
+ }
+ }
+
+ public TimeStampReq(
+ MessageImprint messageImprint,
+ DerObjectIdentifier tsaPolicy,
+ DerInteger nonce,
+ DerBoolean certReq,
+ X509Extensions extensions)
+ {
+ // default
+ this.version = new DerInteger(1);
+
+ this.messageImprint = messageImprint;
+ this.tsaPolicy = tsaPolicy;
+ this.nonce = nonce;
+ this.certReq = certReq;
+ this.extensions = extensions;
+ }
+
+ public DerInteger Version
+ {
+ get { return version; }
+ }
+
+ public MessageImprint MessageImprint
+ {
+ get { return messageImprint; }
+ }
+
+ public DerObjectIdentifier ReqPolicy
+ {
+ get { return tsaPolicy; }
+ }
+
+ public DerInteger Nonce
+ {
+ get { return nonce; }
+ }
+
+ public DerBoolean CertReq
+ {
+ get { return certReq; }
+ }
+
+ public X509Extensions Extensions
+ {
+ get { return extensions; }
+ }
+
+ /**
+ * <pre>
+ * TimeStampReq ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * messageImprint MessageImprint,
+ * --a hash algorithm OID and the hash value of the data to be
+ * --time-stamped
+ * reqPolicy TSAPolicyId OPTIONAL,
+ * nonce INTEGER OPTIONAL,
+ * certReq BOOLEAN DEFAULT FALSE,
+ * extensions [0] IMPLICIT Extensions OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ version, messageImprint);
+
+ if (tsaPolicy != null)
+ {
+ v.Add(tsaPolicy);
+ }
+
+ if (nonce != null)
+ {
+ v.Add(nonce);
+ }
+
+ if (certReq != null && certReq.IsTrue)
+ {
+ v.Add(certReq);
+ }
+
+ if (extensions != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, extensions));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/tsp/TimeStampResp.cs b/Crypto/src/asn1/tsp/TimeStampResp.cs
new file mode 100644
index 000000000..f26fb30bd
--- /dev/null
+++ b/Crypto/src/asn1/tsp/TimeStampResp.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+ public class TimeStampResp
+ : Asn1Encodable
+ {
+ private readonly PkiStatusInfo pkiStatusInfo;
+ private readonly ContentInfo timeStampToken;
+
+ public static TimeStampResp GetInstance(
+ object o)
+ {
+ if (o == null || o is TimeStampResp)
+ {
+ return (TimeStampResp) o;
+ }
+
+ if (o is Asn1Sequence)
+ {
+ return new TimeStampResp((Asn1Sequence) o);
+ }
+
+ throw new ArgumentException(
+ "Unknown object in 'TimeStampResp' factory: " + o.GetType().FullName);
+ }
+
+ private TimeStampResp(
+ Asn1Sequence seq)
+ {
+ this.pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ this.timeStampToken = ContentInfo.GetInstance(seq[1]);
+ }
+ }
+
+ public TimeStampResp(
+ PkiStatusInfo pkiStatusInfo,
+ ContentInfo timeStampToken)
+ {
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.timeStampToken = timeStampToken;
+ }
+
+ public PkiStatusInfo Status
+ {
+ get { return pkiStatusInfo; }
+ }
+
+ public ContentInfo TimeStampToken
+ {
+ get { return timeStampToken; }
+ }
+
+ /**
+ * <pre>
+ * TimeStampResp ::= SEQUENCE {
+ * status PkiStatusInfo,
+ * timeStampToken TimeStampToken OPTIONAL }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo);
+
+ if (timeStampToken != null)
+ {
+ v.Add(timeStampToken);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/util/Asn1Dump.cs b/Crypto/src/asn1/util/Asn1Dump.cs
new file mode 100644
index 000000000..43d485500
--- /dev/null
+++ b/Crypto/src/asn1/util/Asn1Dump.cs
@@ -0,0 +1,378 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Utilities
+{
+ public sealed class Asn1Dump
+ {
+ private static readonly string NewLine = Platform.NewLine;
+
+ private Asn1Dump()
+ {
+ }
+
+ private const string Tab = " ";
+ private const int SampleSize = 32;
+
+ /**
+ * dump a Der object as a formatted string with indentation
+ *
+ * @param obj the Asn1Object to be dumped out.
+ */
+ private static void AsString(
+ string indent,
+ bool verbose,
+ Asn1Object obj,
+ StringBuilder buf)
+ {
+ if (obj is Asn1Sequence)
+ {
+ string tab = indent + Tab;
+ buf.Append(indent);
+ if (obj is BerSequence)
+ {
+ buf.Append("BER Sequence");
+ }
+ else if (obj is DerSequence)
+ {
+ buf.Append("DER Sequence");
+ }
+ else
+ {
+ buf.Append("Sequence");
+ }
+
+ buf.Append(NewLine);
+
+ foreach (Asn1Encodable o in ((Asn1Sequence)obj))
+ {
+ if (o == null || o is Asn1Null)
+ {
+ buf.Append(tab);
+ buf.Append("NULL");
+ buf.Append(NewLine);
+ }
+ else
+ {
+ AsString(tab, verbose, o.ToAsn1Object(), buf);
+ }
+ }
+ }
+ else if (obj is DerTaggedObject)
+ {
+ string tab = indent + Tab;
+ buf.Append(indent);
+ if (obj is BerTaggedObject)
+ {
+ buf.Append("BER Tagged [");
+ }
+ else
+ {
+ buf.Append("Tagged [");
+ }
+
+ DerTaggedObject o = (DerTaggedObject)obj;
+
+ buf.Append(((int)o.TagNo).ToString());
+ buf.Append(']');
+
+ if (!o.IsExplicit())
+ {
+ buf.Append(" IMPLICIT ");
+ }
+
+ buf.Append(NewLine);
+
+ if (o.IsEmpty())
+ {
+ buf.Append(tab);
+ buf.Append("EMPTY");
+ buf.Append(NewLine);
+ }
+ else
+ {
+ AsString(tab, verbose, o.GetObject(), buf);
+ }
+ }
+ else if (obj is BerSet)
+ {
+ string tab = indent + Tab;
+
+ buf.Append(indent);
+ buf.Append("BER Set");
+ buf.Append(NewLine);
+
+ foreach (Asn1Encodable o in ((Asn1Set)obj))
+ {
+ if (o == null)
+ {
+ buf.Append(tab);
+ buf.Append("NULL");
+ buf.Append(NewLine);
+ }
+ else
+ {
+ AsString(tab, verbose, o.ToAsn1Object(), buf);
+ }
+ }
+ }
+ else if (obj is DerSet)
+ {
+ string tab = indent + Tab;
+
+ buf.Append(indent);
+ buf.Append("DER Set");
+ buf.Append(NewLine);
+
+ foreach (Asn1Encodable o in ((Asn1Set)obj))
+ {
+ if (o == null)
+ {
+ buf.Append(tab);
+ buf.Append("NULL");
+ buf.Append(NewLine);
+ }
+ else
+ {
+ AsString(tab, verbose, o.ToAsn1Object(), buf);
+ }
+ }
+ }
+ else if (obj is DerObjectIdentifier)
+ {
+ buf.Append(indent + "ObjectIdentifier(" + ((DerObjectIdentifier)obj).Id + ")" + NewLine);
+ }
+ else if (obj is DerBoolean)
+ {
+ buf.Append(indent + "Boolean(" + ((DerBoolean)obj).IsTrue + ")" + NewLine);
+ }
+ else if (obj is DerInteger)
+ {
+ buf.Append(indent + "Integer(" + ((DerInteger)obj).Value + ")" + NewLine);
+ }
+ else if (obj is BerOctetString)
+ {
+ byte[] octets = ((Asn1OctetString)obj).GetOctets();
+ string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
+ buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
+ }
+ else if (obj is DerOctetString)
+ {
+ byte[] octets = ((Asn1OctetString)obj).GetOctets();
+ string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
+ buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
+ }
+ else if (obj is DerBitString)
+ {
+ DerBitString bt = (DerBitString)obj;
+ byte[] bytes = bt.GetBytes();
+ string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : "";
+ buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine);
+ }
+ else if (obj is DerIA5String)
+ {
+ buf.Append(indent + "IA5String(" + ((DerIA5String)obj).GetString() + ") " + NewLine);
+ }
+ else if (obj is DerUtf8String)
+ {
+ buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine);
+ }
+ else if (obj is DerPrintableString)
+ {
+ buf.Append(indent + "PrintableString(" + ((DerPrintableString)obj).GetString() + ") " + NewLine);
+ }
+ else if (obj is DerVisibleString)
+ {
+ buf.Append(indent + "VisibleString(" + ((DerVisibleString)obj).GetString() + ") " + NewLine);
+ }
+ else if (obj is DerBmpString)
+ {
+ buf.Append(indent + "BMPString(" + ((DerBmpString)obj).GetString() + ") " + NewLine);
+ }
+ else if (obj is DerT61String)
+ {
+ buf.Append(indent + "T61String(" + ((DerT61String)obj).GetString() + ") " + NewLine);
+ }
+ else if (obj is DerUtcTime)
+ {
+ buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine);
+ }
+ else if (obj is DerGeneralizedTime)
+ {
+ buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine);
+ }
+ else if (obj is DerUnknownTag)
+ {
+ string hex = Hex.ToHexString(((DerUnknownTag)obj).GetData());
+ buf.Append(indent + "Unknown " + ((int)((DerUnknownTag)obj).Tag).ToString("X") + " " + hex + NewLine);
+ }
+ else if (obj is BerApplicationSpecific)
+ {
+ buf.Append(outputApplicationSpecific("BER", indent, verbose, (BerApplicationSpecific)obj));
+ }
+ else if (obj is DerApplicationSpecific)
+ {
+ buf.Append(outputApplicationSpecific("DER", indent, verbose, (DerApplicationSpecific)obj));
+ }
+ else if (obj is DerEnumerated)
+ {
+ DerEnumerated en = (DerEnumerated)obj;
+ buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine);
+ }
+ else if (obj is DerExternal)
+ {
+ DerExternal ext = (DerExternal)obj;
+ buf.Append(indent + "External " + NewLine);
+ string tab = indent + Tab;
+
+ if (ext.DirectReference != null)
+ {
+ buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine);
+ }
+ if (ext.IndirectReference != null)
+ {
+ buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine);
+ }
+ if (ext.DataValueDescriptor != null)
+ {
+ AsString(tab, verbose, ext.DataValueDescriptor, buf);
+ }
+ buf.Append(tab + "Encoding: " + ext.Encoding + NewLine);
+ AsString(tab, verbose, ext.ExternalContent, buf);
+ }
+ else
+ {
+ buf.Append(indent + obj.ToString() + NewLine);
+ }
+ }
+
+ private static string outputApplicationSpecific(
+ string type,
+ string indent,
+ bool verbose,
+ DerApplicationSpecific app)
+ {
+ StringBuilder buf = new StringBuilder();
+
+ if (app.IsConstructed())
+ {
+ try
+ {
+ Asn1Sequence s = Asn1Sequence.GetInstance(app.GetObject(Asn1Tags.Sequence));
+ buf.Append(indent + type + " ApplicationSpecific[" + app.ApplicationTag + "]" + NewLine);
+ foreach (Asn1Encodable ae in s)
+ {
+ AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf);
+ }
+ }
+ catch (IOException e)
+ {
+ buf.Append(e);
+ }
+ return buf.ToString();
+ }
+
+ return indent + type + " ApplicationSpecific[" + app.ApplicationTag + "] ("
+ + Hex.ToHexString(app.GetContents()) + ")" + NewLine;
+ }
+
+ [Obsolete("Use version accepting Asn1Encodable")]
+ public static string DumpAsString(
+ object obj)
+ {
+ if (obj is Asn1Encodable)
+ {
+ StringBuilder buf = new StringBuilder();
+ AsString("", false, ((Asn1Encodable)obj).ToAsn1Object(), buf);
+ return buf.ToString();
+ }
+
+ return "unknown object type " + obj.ToString();
+ }
+
+ /**
+ * dump out a DER object as a formatted string, in non-verbose mode
+ *
+ * @param obj the Asn1Encodable to be dumped out.
+ * @return the resulting string.
+ */
+ public static string DumpAsString(
+ Asn1Encodable obj)
+ {
+ return DumpAsString(obj, false);
+ }
+
+ /**
+ * Dump out the object as a string
+ *
+ * @param obj the Asn1Encodable to be dumped out.
+ * @param verbose if true, dump out the contents of octet and bit strings.
+ * @return the resulting string.
+ */
+ public static string DumpAsString(
+ Asn1Encodable obj,
+ bool verbose)
+ {
+ StringBuilder buf = new StringBuilder();
+ AsString("", verbose, obj.ToAsn1Object(), buf);
+ return buf.ToString();
+ }
+
+ private static string dumpBinaryDataAsString(string indent, byte[] bytes)
+ {
+ indent += Tab;
+
+ StringBuilder buf = new StringBuilder(NewLine);
+
+ for (int i = 0; i < bytes.Length; i += SampleSize)
+ {
+ if (bytes.Length - i > SampleSize)
+ {
+ buf.Append(indent);
+ buf.Append(Hex.ToHexString(bytes, i, SampleSize));
+ buf.Append(Tab);
+ buf.Append(calculateAscString(bytes, i, SampleSize));
+ buf.Append(NewLine);
+ }
+ else
+ {
+ buf.Append(indent);
+ buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i));
+ for (int j = bytes.Length - i; j != SampleSize; j++)
+ {
+ buf.Append(" ");
+ }
+ buf.Append(Tab);
+ buf.Append(calculateAscString(bytes, i, bytes.Length - i));
+ buf.Append(NewLine);
+ }
+ }
+
+ return buf.ToString();
+ }
+
+ private static string calculateAscString(
+ byte[] bytes,
+ int off,
+ int len)
+ {
+ StringBuilder buf = new StringBuilder();
+
+ for (int i = off; i != off + len; i++)
+ {
+ char c = (char)bytes[i];
+ if (c >= ' ' && c <= '~')
+ {
+ buf.Append(c);
+ }
+ }
+
+ return buf.ToString();
+ }
+ }
+}
diff --git a/Crypto/src/asn1/util/Dump.cs b/Crypto/src/asn1/util/Dump.cs
new file mode 100644
index 000000000..2712ca1b3
--- /dev/null
+++ b/Crypto/src/asn1/util/Dump.cs
@@ -0,0 +1,30 @@
+#if !PORTABLE
+using Org.BouncyCastle.Asn1;
+
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.Utilities
+{
+ public sealed class Dump
+ {
+ private Dump()
+ {
+ }
+
+ public static void Main(string[] args)
+ {
+ FileStream fIn = File.OpenRead(args[0]);
+ Asn1InputStream bIn = new Asn1InputStream(fIn);
+
+ Asn1Object obj;
+ while ((obj = bIn.ReadObject()) != null)
+ {
+ Console.WriteLine(Asn1Dump.DumpAsString(obj));
+ }
+
+ bIn.Dispose();
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Crypto/src/asn1/util/FilterStream.cs b/Crypto/src/asn1/util/FilterStream.cs
new file mode 100644
index 000000000..f277e33e6
--- /dev/null
+++ b/Crypto/src/asn1/util/FilterStream.cs
@@ -0,0 +1,72 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.Utilities
+{
+ public class FilterStream : Stream
+ {
+ public FilterStream(Stream s)
+ {
+ this.s = s;
+ }
+ public override bool CanRead
+ {
+ get { return s.CanRead; }
+ }
+ public override bool CanSeek
+ {
+ get { return s.CanSeek; }
+ }
+ public override bool CanWrite
+ {
+ get { return s.CanWrite; }
+ }
+ public override long Length
+ {
+ get { return s.Length; }
+ }
+ public override long Position
+ {
+ get { return s.Position; }
+ set { s.Position = value; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ s.Dispose();
+ }
+ }
+
+ public override void Flush()
+ {
+ s.Flush();
+ }
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return s.Seek(offset, origin);
+ }
+ public override void SetLength(long value)
+ {
+ s.SetLength(value);
+ }
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return s.Read(buffer, offset, count);
+ }
+ public override int ReadByte()
+ {
+ return s.ReadByte();
+ }
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ s.Write(buffer, offset, count);
+ }
+ public override void WriteByte(byte value)
+ {
+ s.WriteByte(value);
+ }
+ protected readonly Stream s;
+ }
+}
diff --git a/Crypto/src/asn1/x500/DirectoryString.cs b/Crypto/src/asn1/x500/DirectoryString.cs
new file mode 100644
index 000000000..78ecc2663
--- /dev/null
+++ b/Crypto/src/asn1/x500/DirectoryString.cs
@@ -0,0 +1,75 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X500
+{
+ public class DirectoryString
+ : Asn1Encodable, IAsn1Choice, IAsn1String
+ {
+ private readonly DerStringBase str;
+
+ public static DirectoryString GetInstance(
+ object obj)
+ {
+ if (obj is DirectoryString)
+ {
+ return (DirectoryString) obj;
+ }
+
+ if (obj is DerStringBase)
+ {
+ if (obj is DerT61String
+ || obj is DerPrintableString
+ || obj is DerUniversalString
+ || obj is DerUtf8String
+ || obj is DerBmpString)
+ {
+ return new DirectoryString((DerStringBase) obj);
+ }
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ public static DirectoryString GetInstance(
+ Asn1TaggedObject obj,
+ bool isExplicit)
+ {
+ if (!isExplicit)
+ throw new ArgumentException("choice item must be explicitly tagged");
+
+ return GetInstance(obj.GetObject());
+ }
+
+ private DirectoryString(
+ DerStringBase str)
+ {
+ this.str = str;
+ }
+
+ public DirectoryString(
+ string str)
+ {
+ this.str = new DerUtf8String(str);
+ }
+
+ public string GetString()
+ {
+ return str.GetString();
+ }
+
+ /**
+ * <pre>
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1..MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return str.ToAsn1Object();
+ }
+ }
+}
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");
+ }
+}
diff --git a/Crypto/src/asn1/x9/DHDomainParameters.cs b/Crypto/src/asn1/x9/DHDomainParameters.cs
new file mode 100644
index 000000000..8de869694
--- /dev/null
+++ b/Crypto/src/asn1/x9/DHDomainParameters.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public class DHDomainParameters
+ : Asn1Encodable
+ {
+ private readonly DerInteger p, g, q, j;
+ private readonly DHValidationParms validationParms;
+
+ public static DHDomainParameters GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public static DHDomainParameters GetInstance(object obj)
+ {
+ if (obj == null || obj is DHDomainParameters)
+ return (DHDomainParameters)obj;
+
+ if (obj is Asn1Sequence)
+ return new DHDomainParameters((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid DHDomainParameters: " + obj.GetType().FullName, "obj");
+ }
+
+ public DHDomainParameters(DerInteger p, DerInteger g, DerInteger q, DerInteger j,
+ DHValidationParms validationParms)
+ {
+ if (p == null)
+ throw new ArgumentNullException("p");
+ if (g == null)
+ throw new ArgumentNullException("g");
+ if (q == null)
+ throw new ArgumentNullException("q");
+
+ this.p = p;
+ this.g = g;
+ this.q = q;
+ this.j = j;
+ this.validationParms = validationParms;
+ }
+
+ private DHDomainParameters(Asn1Sequence seq)
+ {
+ if (seq.Count < 3 || seq.Count > 5)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ IEnumerator e = seq.GetEnumerator();
+ this.p = DerInteger.GetInstance(GetNext(e));
+ this.g = DerInteger.GetInstance(GetNext(e));
+ this.q = DerInteger.GetInstance(GetNext(e));
+
+ Asn1Encodable next = GetNext(e);
+
+ if (next != null && next is DerInteger)
+ {
+ this.j = DerInteger.GetInstance(next);
+ next = GetNext(e);
+ }
+
+ if (next != null)
+ {
+ this.validationParms = DHValidationParms.GetInstance(next.ToAsn1Object());
+ }
+ }
+
+ private static Asn1Encodable GetNext(IEnumerator e)
+ {
+ return e.MoveNext() ? (Asn1Encodable)e.Current : null;
+ }
+
+ public DerInteger P
+ {
+ get { return this.p; }
+ }
+
+ public DerInteger G
+ {
+ get { return this.g; }
+ }
+
+ public DerInteger Q
+ {
+ get { return this.q; }
+ }
+
+ public DerInteger J
+ {
+ get { return this.j; }
+ }
+
+ public DHValidationParms ValidationParms
+ {
+ get { return this.validationParms; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(p, g, q);
+
+ if (this.j != null)
+ {
+ v.Add(this.j);
+ }
+
+ if (this.validationParms != null)
+ {
+ v.Add(this.validationParms);
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/DHPublicKey.cs b/Crypto/src/asn1/x9/DHPublicKey.cs
new file mode 100644
index 000000000..1a20a8a16
--- /dev/null
+++ b/Crypto/src/asn1/x9/DHPublicKey.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public class DHPublicKey
+ : Asn1Encodable
+ {
+ private readonly DerInteger y;
+
+ public static DHPublicKey GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(DerInteger.GetInstance(obj, isExplicit));
+ }
+
+ public static DHPublicKey GetInstance(object obj)
+ {
+ if (obj == null || obj is DHPublicKey)
+ return (DHPublicKey)obj;
+
+ if (obj is DerInteger)
+ return new DHPublicKey((DerInteger)obj);
+
+ throw new ArgumentException("Invalid DHPublicKey: " + obj.GetType().FullName, "obj");
+ }
+
+ public DHPublicKey(DerInteger y)
+ {
+ if (y == null)
+ throw new ArgumentNullException("y");
+
+ this.y = y;
+ }
+
+ public DerInteger Y
+ {
+ get { return this.y; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return this.y;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/DHValidationParms.cs b/Crypto/src/asn1/x9/DHValidationParms.cs
new file mode 100644
index 000000000..a37964cfb
--- /dev/null
+++ b/Crypto/src/asn1/x9/DHValidationParms.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public class DHValidationParms
+ : Asn1Encodable
+ {
+ private readonly DerBitString seed;
+ private readonly DerInteger pgenCounter;
+
+ public static DHValidationParms GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public static DHValidationParms GetInstance(object obj)
+ {
+ if (obj == null || obj is DHDomainParameters)
+ return (DHValidationParms)obj;
+
+ if (obj is Asn1Sequence)
+ return new DHValidationParms((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid DHValidationParms: " + obj.GetType().FullName, "obj");
+ }
+
+ public DHValidationParms(DerBitString seed, DerInteger pgenCounter)
+ {
+ if (seed == null)
+ throw new ArgumentNullException("seed");
+ if (pgenCounter == null)
+ throw new ArgumentNullException("pgenCounter");
+
+ this.seed = seed;
+ this.pgenCounter = pgenCounter;
+ }
+
+ private DHValidationParms(Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+ this.seed = DerBitString.GetInstance(seq[0]);
+ this.pgenCounter = DerInteger.GetInstance(seq[1]);
+ }
+
+ public DerBitString Seed
+ {
+ get { return this.seed; }
+ }
+
+ public DerInteger PgenCounter
+ {
+ get { return this.pgenCounter; }
+ }
+
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(seed, pgenCounter);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/KeySpecificInfo.cs b/Crypto/src/asn1/x9/KeySpecificInfo.cs
new file mode 100644
index 000000000..46298646b
--- /dev/null
+++ b/Crypto/src/asn1/x9/KeySpecificInfo.cs
@@ -0,0 +1,58 @@
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
+ * RFC 2631, or X9.42, for further details.
+ */
+ public class KeySpecificInfo
+ : Asn1Encodable
+ {
+ private DerObjectIdentifier algorithm;
+ private Asn1OctetString counter;
+
+ public KeySpecificInfo(
+ DerObjectIdentifier algorithm,
+ Asn1OctetString counter)
+ {
+ this.algorithm = algorithm;
+ this.counter = counter;
+ }
+
+ public KeySpecificInfo(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ algorithm = (DerObjectIdentifier)e.Current;
+ e.MoveNext();
+ counter = (Asn1OctetString)e.Current;
+ }
+
+ public DerObjectIdentifier Algorithm
+ {
+ get { return algorithm; }
+ }
+
+ public Asn1OctetString Counter
+ {
+ get { return counter; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * KeySpecificInfo ::= Sequence {
+ * algorithm OBJECT IDENTIFIER,
+ * counter OCTET STRING SIZE (4..4)
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(algorithm, counter);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/OtherInfo.cs b/Crypto/src/asn1/x9/OtherInfo.cs
new file mode 100644
index 000000000..21863bd17
--- /dev/null
+++ b/Crypto/src/asn1/x9/OtherInfo.cs
@@ -0,0 +1,88 @@
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
+ * RFC 2631, or X9.42, for further details.
+ */
+ public class OtherInfo
+ : Asn1Encodable
+ {
+ private KeySpecificInfo keyInfo;
+ private Asn1OctetString partyAInfo;
+ private Asn1OctetString suppPubInfo;
+
+ public OtherInfo(
+ KeySpecificInfo keyInfo,
+ Asn1OctetString partyAInfo,
+ Asn1OctetString suppPubInfo)
+ {
+ this.keyInfo = keyInfo;
+ this.partyAInfo = partyAInfo;
+ this.suppPubInfo = suppPubInfo;
+ }
+
+ public OtherInfo(
+ Asn1Sequence seq)
+ {
+ IEnumerator e = seq.GetEnumerator();
+
+ e.MoveNext();
+ keyInfo = new KeySpecificInfo((Asn1Sequence) e.Current);
+
+ while (e.MoveNext())
+ {
+ DerTaggedObject o = (DerTaggedObject) e.Current;
+
+ if (o.TagNo == 0)
+ {
+ partyAInfo = (Asn1OctetString) o.GetObject();
+ }
+ else if ((int) o.TagNo == 2)
+ {
+ suppPubInfo = (Asn1OctetString) o.GetObject();
+ }
+ }
+ }
+
+ public KeySpecificInfo KeyInfo
+ {
+ get { return keyInfo; }
+ }
+
+ public Asn1OctetString PartyAInfo
+ {
+ get { return partyAInfo; }
+ }
+
+ public Asn1OctetString SuppPubInfo
+ {
+ get { return suppPubInfo; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * OtherInfo ::= Sequence {
+ * keyInfo KeySpecificInfo,
+ * partyAInfo [0] OCTET STRING OPTIONAL,
+ * suppPubInfo [2] OCTET STRING
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(keyInfo);
+
+ if (partyAInfo != null)
+ {
+ v.Add(new DerTaggedObject(0, partyAInfo));
+ }
+
+ v.Add(new DerTaggedObject(2, suppPubInfo));
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X962NamedCurves.cs b/Crypto/src/asn1/x9/X962NamedCurves.cs
new file mode 100644
index 000000000..de80ca280
--- /dev/null
+++ b/Crypto/src/asn1/x9/X962NamedCurves.cs
@@ -0,0 +1,733 @@
+using System;
+using System.Collections;
+using System.Globalization;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * table of the current named curves defined in X.962 EC-DSA.
+ */
+ public sealed class X962NamedCurves
+ {
+ private X962NamedCurves()
+ {
+ }
+
+ internal class Prime192v1Holder
+ : X9ECParametersHolder
+ {
+ private Prime192v1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Prime192v1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve cFp192v1 = new FpCurve(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16));
+
+ return new X9ECParameters(
+ cFp192v1,
+ cFp192v1.DecodePoint(
+ Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
+ new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16),
+ BigInteger.One,
+ Hex.Decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
+ }
+ }
+
+ internal class Prime192v2Holder
+ : X9ECParametersHolder
+ {
+ private Prime192v2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Prime192v2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve cFp192v2 = new FpCurve(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16));
+
+ return new X9ECParameters(
+ cFp192v2,
+ cFp192v2.DecodePoint(
+ Hex.Decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
+ new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16),
+ BigInteger.One,
+ Hex.Decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
+ }
+ }
+
+ internal class Prime192v3Holder
+ : X9ECParametersHolder
+ {
+ private Prime192v3Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Prime192v3Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve cFp192v3 = new FpCurve(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16));
+
+ return new X9ECParameters(
+ cFp192v3,
+ cFp192v3.DecodePoint(
+ Hex.Decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
+ new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16),
+ BigInteger.One,
+ Hex.Decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
+ }
+ }
+
+ internal class Prime239v1Holder
+ : X9ECParametersHolder
+ {
+ private Prime239v1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Prime239v1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve cFp239v1 = new FpCurve(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16));
+
+ return new X9ECParameters(
+ cFp239v1,
+ cFp239v1.DecodePoint(
+ Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
+ new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16),
+ BigInteger.One,
+ Hex.Decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
+ }
+ }
+
+ internal class Prime239v2Holder
+ : X9ECParametersHolder
+ {
+ private Prime239v2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Prime239v2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve cFp239v2 = new FpCurve(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16));
+
+ return new X9ECParameters(
+ cFp239v2,
+ cFp239v2.DecodePoint(
+ Hex.Decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
+ new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16),
+ BigInteger.One,
+ Hex.Decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
+ }
+ }
+
+ internal class Prime239v3Holder
+ : X9ECParametersHolder
+ {
+ private Prime239v3Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Prime239v3Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve cFp239v3 = new FpCurve(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16));
+
+ return new X9ECParameters(
+ cFp239v3,
+ cFp239v3.DecodePoint(
+ Hex.Decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
+ new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16),
+ BigInteger.One,
+ Hex.Decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
+ }
+ }
+
+ internal class Prime256v1Holder
+ : X9ECParametersHolder
+ {
+ private Prime256v1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new Prime256v1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ ECCurve cFp256v1 = new FpCurve(
+ new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
+ new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
+ new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16));
+
+ return new X9ECParameters(
+ cFp256v1,
+ cFp256v1.DecodePoint(
+ Hex.Decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
+ new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16),
+ BigInteger.One,
+ Hex.Decode("c49d360886e704936a6678e1139d26b7819f7e90"));
+ }
+ }
+
+ /*
+ * F2m Curves
+ */
+ internal class C2pnb163v1Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb163v1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb163v1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16);
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve c2m163v1 = new F2mCurve(
+ 163,
+ 1, 2, 8,
+ new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16),
+ new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m163v1,
+ c2m163v1.DecodePoint(
+ Hex.Decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")),
+ n, h,
+ Hex.Decode("D2COFB15760860DEF1EEF4D696E6768756151754"));
+ }
+ }
+
+ internal class C2pnb163v2Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb163v2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb163v2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16);
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve c2m163v2 = new F2mCurve(
+ 163,
+ 1, 2, 8,
+ new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16),
+ new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m163v2,
+ c2m163v2.DecodePoint(
+ Hex.Decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2pnb163v3Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb163v3Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb163v3Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16);
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve c2m163v3 = new F2mCurve(
+ 163,
+ 1, 2, 8,
+ new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16),
+ new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m163v3,
+ c2m163v3.DecodePoint(Hex.Decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2pnb176w1Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb176w1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb176w1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16);
+ BigInteger h = BigInteger.ValueOf(0xFF6E);
+
+ ECCurve c2m176w1 = new F2mCurve(
+ 176,
+ 1, 2, 43,
+ new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16),
+ new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m176w1,
+ c2m176w1.DecodePoint(
+ Hex.Decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2tnb191v1Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb191v1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb191v1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16);
+ BigInteger h = BigInteger.ValueOf(2);
+
+ ECCurve c2m191v1 = new F2mCurve(
+ 191,
+ 9,
+ new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16),
+ new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m191v1,
+ c2m191v1.DecodePoint(
+ Hex.Decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")),
+ n, h,
+ Hex.Decode("4E13CA542744D696E67687561517552F279A8C84"));
+ }
+ }
+
+ internal class C2tnb191v2Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb191v2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb191v2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16);
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve c2m191v2 = new F2mCurve(
+ 191,
+ 9,
+ new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16),
+ new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m191v2,
+ c2m191v2.DecodePoint(
+ Hex.Decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2tnb191v3Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb191v3Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb191v3Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16);
+ BigInteger h = BigInteger.ValueOf(6);
+
+ ECCurve c2m191v3 = new F2mCurve(
+ 191,
+ 9,
+ new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16),
+ new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m191v3,
+ c2m191v3.DecodePoint(
+ Hex.Decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2pnb208w1Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb208w1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb208w1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16);
+ BigInteger h = BigInteger.ValueOf(0xFE48);
+
+ ECCurve c2m208w1 = new F2mCurve(
+ 208,
+ 1, 2, 83,
+ new BigInteger("0", 16),
+ new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m208w1,
+ c2m208w1.DecodePoint(
+ Hex.Decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2tnb239v1Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb239v1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb239v1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16);
+ BigInteger h = BigInteger.ValueOf(4);
+
+ ECCurve c2m239v1 = new F2mCurve(
+ 239,
+ 36,
+ new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16),
+ new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m239v1,
+ c2m239v1.DecodePoint(
+ Hex.Decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2tnb239v2Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb239v2Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb239v2Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16);
+ BigInteger h = BigInteger.ValueOf(6);
+
+ ECCurve c2m239v2 = new F2mCurve(
+ 239,
+ 36,
+ new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16),
+ new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m239v2,
+ c2m239v2.DecodePoint(
+ Hex.Decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2tnb239v3Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb239v3Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb239v3Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16);
+ BigInteger h = BigInteger.ValueOf(10);
+
+ ECCurve c2m239v3 = new F2mCurve(
+ 239,
+ 36,
+ new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16),
+ new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m239v3,
+ c2m239v3.DecodePoint(
+ Hex.Decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2pnb272w1Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb272w1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb272w1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16);
+ BigInteger h = BigInteger.ValueOf(0xFF06);
+
+ ECCurve c2m272w1 = new F2mCurve(
+ 272,
+ 1, 3, 56,
+ new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16),
+ new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m272w1,
+ c2m272w1.DecodePoint(
+ Hex.Decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2pnb304w1Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb304w1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb304w1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16);
+ BigInteger h = BigInteger.ValueOf(0xFE2E);
+
+ ECCurve c2m304w1 = new F2mCurve(
+ 304,
+ 1, 2, 11,
+ new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16),
+ new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m304w1,
+ c2m304w1.DecodePoint(
+ Hex.Decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2tnb359v1Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb359v1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb359v1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16);
+ BigInteger h = BigInteger.ValueOf(0x4C);
+
+ ECCurve c2m359v1 = new F2mCurve(
+ 359,
+ 68,
+ new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16),
+ new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m359v1,
+ c2m359v1.DecodePoint(
+ Hex.Decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2pnb368w1Holder
+ : X9ECParametersHolder
+ {
+ private C2pnb368w1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2pnb368w1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16);
+ BigInteger h = BigInteger.ValueOf(0xFF70);
+
+ ECCurve c2m368w1 = new F2mCurve(
+ 368,
+ 1, 2, 85,
+ new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16),
+ new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m368w1,
+ c2m368w1.DecodePoint(
+ Hex.Decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")),
+ n, h,
+ null);
+ }
+ }
+
+ internal class C2tnb431r1Holder
+ : X9ECParametersHolder
+ {
+ private C2tnb431r1Holder() {}
+
+ internal static readonly X9ECParametersHolder Instance = new C2tnb431r1Holder();
+
+ protected override X9ECParameters CreateParameters()
+ {
+ BigInteger n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16);
+ BigInteger h = BigInteger.ValueOf(0x2760);
+
+ ECCurve c2m431r1 = new F2mCurve(
+ 431,
+ 120,
+ new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16),
+ new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16),
+ n, h);
+
+ return new X9ECParameters(
+ c2m431r1,
+ c2m431r1.DecodePoint(
+ Hex.Decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")),
+ n, h,
+ null);
+ }
+ }
+
+ private static readonly IDictionary objIds = Platform.CreateHashtable();
+ private static readonly IDictionary curves = Platform.CreateHashtable();
+ private static readonly IDictionary names = Platform.CreateHashtable();
+
+ private static void DefineCurve(
+ string name,
+ DerObjectIdentifier oid,
+ X9ECParametersHolder holder)
+ {
+ objIds.Add(name, oid);
+ names.Add(oid, name);
+ curves.Add(oid, holder);
+ }
+
+ static X962NamedCurves()
+ {
+ DefineCurve("prime192v1", X9ObjectIdentifiers.Prime192v1, Prime192v1Holder.Instance);
+ DefineCurve("prime192v2", X9ObjectIdentifiers.Prime192v2, Prime192v2Holder.Instance);
+ DefineCurve("prime192v3", X9ObjectIdentifiers.Prime192v3, Prime192v3Holder.Instance);
+ DefineCurve("prime239v1", X9ObjectIdentifiers.Prime239v1, Prime239v1Holder.Instance);
+ DefineCurve("prime239v2", X9ObjectIdentifiers.Prime239v2, Prime239v2Holder.Instance);
+ DefineCurve("prime239v3", X9ObjectIdentifiers.Prime239v3, Prime239v3Holder.Instance);
+ DefineCurve("prime256v1", X9ObjectIdentifiers.Prime256v1, Prime256v1Holder.Instance);
+ DefineCurve("c2pnb163v1", X9ObjectIdentifiers.C2Pnb163v1, C2pnb163v1Holder.Instance);
+ DefineCurve("c2pnb163v2", X9ObjectIdentifiers.C2Pnb163v2, C2pnb163v2Holder.Instance);
+ DefineCurve("c2pnb163v3", X9ObjectIdentifiers.C2Pnb163v3, C2pnb163v3Holder.Instance);
+ DefineCurve("c2pnb176w1", X9ObjectIdentifiers.C2Pnb176w1, C2pnb176w1Holder.Instance);
+ DefineCurve("c2tnb191v1", X9ObjectIdentifiers.C2Tnb191v1, C2tnb191v1Holder.Instance);
+ DefineCurve("c2tnb191v2", X9ObjectIdentifiers.C2Tnb191v2, C2tnb191v2Holder.Instance);
+ DefineCurve("c2tnb191v3", X9ObjectIdentifiers.C2Tnb191v3, C2tnb191v3Holder.Instance);
+ DefineCurve("c2pnb208w1", X9ObjectIdentifiers.C2Pnb208w1, C2pnb208w1Holder.Instance);
+ DefineCurve("c2tnb239v1", X9ObjectIdentifiers.C2Tnb239v1, C2tnb239v1Holder.Instance);
+ DefineCurve("c2tnb239v2", X9ObjectIdentifiers.C2Tnb239v2, C2tnb239v2Holder.Instance);
+ DefineCurve("c2tnb239v3", X9ObjectIdentifiers.C2Tnb239v3, C2tnb239v3Holder.Instance);
+ DefineCurve("c2pnb272w1", X9ObjectIdentifiers.C2Pnb272w1, C2pnb272w1Holder.Instance);
+ DefineCurve("c2pnb304w1", X9ObjectIdentifiers.C2Pnb304w1, C2pnb304w1Holder.Instance);
+ DefineCurve("c2tnb359v1", X9ObjectIdentifiers.C2Tnb359v1, C2tnb359v1Holder.Instance);
+ DefineCurve("c2pnb368w1", X9ObjectIdentifiers.C2Pnb368w1, C2pnb368w1Holder.Instance);
+ DefineCurve("c2tnb431r1", X9ObjectIdentifiers.C2Tnb431r1, C2tnb431r1Holder.Instance);
+ }
+
+ public static X9ECParameters GetByName(
+ string name)
+ {
+ DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name.ToLowerInvariant()];
+
+ return oid == null ? null : GetByOid(oid);
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters GetByOid(
+ DerObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid];
+
+ return holder == null ? null : holder.Parameters;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static DerObjectIdentifier GetOid(
+ string name)
+ {
+ return (DerObjectIdentifier) objIds[name.ToLowerInvariant()];
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static string GetName(
+ DerObjectIdentifier oid)
+ {
+ return (string) names[oid];
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static IEnumerable Names
+ {
+ get { return new EnumerableProxy(objIds.Keys); }
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X962Parameters.cs b/Crypto/src/asn1/x9/X962Parameters.cs
new file mode 100644
index 000000000..5b7eaa1de
--- /dev/null
+++ b/Crypto/src/asn1/x9/X962Parameters.cs
@@ -0,0 +1,53 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public class X962Parameters
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly Asn1Object _params;
+
+ public X962Parameters(
+ X9ECParameters ecParameters)
+ {
+ this._params = ecParameters.ToAsn1Object();
+ }
+
+ public X962Parameters(
+ DerObjectIdentifier namedCurve)
+ {
+ this._params = namedCurve;
+ }
+
+ public X962Parameters(
+ Asn1Object obj)
+ {
+ this._params = obj;
+ }
+
+ public bool IsNamedCurve
+ {
+ get { return (_params is DerObjectIdentifier); }
+ }
+
+ public Asn1Object Parameters
+ {
+ get { return _params; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * Parameters ::= CHOICE {
+ * ecParameters ECParameters,
+ * namedCurve CURVES.&id({CurveNames}),
+ * implicitlyCA Null
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return _params;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9Curve.cs b/Crypto/src/asn1/x9/X9Curve.cs
new file mode 100644
index 000000000..b92e7b3b5
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9Curve.cs
@@ -0,0 +1,147 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * ASN.1 def for Elliptic-Curve Curve structure. See
+ * X9.62, for further details.
+ */
+ public class X9Curve
+ : Asn1Encodable
+ {
+ private readonly ECCurve curve;
+ private readonly byte[] seed;
+ private readonly DerObjectIdentifier fieldIdentifier;
+
+ public X9Curve(
+ ECCurve curve)
+ : this(curve, null)
+ {
+ this.curve = curve;
+ }
+
+ public X9Curve(
+ ECCurve curve,
+ byte[] seed)
+ {
+ if (curve == null)
+ throw new ArgumentNullException("curve");
+
+ this.curve = curve;
+ this.seed = Arrays.Clone(seed);
+
+ if (curve is FpCurve)
+ {
+ this.fieldIdentifier = X9ObjectIdentifiers.PrimeField;
+ }
+ else if (curve is F2mCurve)
+ {
+ this.fieldIdentifier = X9ObjectIdentifiers.CharacteristicTwoField;
+ }
+ else
+ {
+ throw new ArgumentException("This type of ECCurve is not implemented");
+ }
+ }
+
+ public X9Curve(
+ X9FieldID fieldID,
+ Asn1Sequence seq)
+ {
+ if (fieldID == null)
+ throw new ArgumentNullException("fieldID");
+ if (seq == null)
+ throw new ArgumentNullException("seq");
+
+ this.fieldIdentifier = fieldID.Identifier;
+
+ if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField))
+ {
+ BigInteger q = ((DerInteger) fieldID.Parameters).Value;
+ X9FieldElement x9A = new X9FieldElement(q, (Asn1OctetString) seq[0]);
+ X9FieldElement x9B = new X9FieldElement(q, (Asn1OctetString) seq[1]);
+ curve = new FpCurve(q, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
+ }
+ else
+ {
+ if (fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
+ {
+ // Characteristic two field
+ DerSequence parameters = (DerSequence)fieldID.Parameters;
+ int m = ((DerInteger)parameters[0]).Value.IntValue;
+ DerObjectIdentifier representation
+ = (DerObjectIdentifier)parameters[1];
+
+ int k1 = 0;
+ int k2 = 0;
+ int k3 = 0;
+ if (representation.Equals(X9ObjectIdentifiers.TPBasis))
+ {
+ // Trinomial basis representation
+ k1 = ((DerInteger)parameters[2]).Value.IntValue;
+ }
+ else
+ {
+ // Pentanomial basis representation
+ DerSequence pentanomial = (DerSequence) parameters[2];
+ k1 = ((DerInteger) pentanomial[0]).Value.IntValue;
+ k2 = ((DerInteger) pentanomial[1]).Value.IntValue;
+ k3 = ((DerInteger) pentanomial[2]).Value.IntValue;
+ }
+ X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[0]);
+ X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[1]);
+ // TODO Is it possible to get the order (n) and cofactor(h) too?
+ curve = new F2mCurve(m, k1, k2, k3, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
+ }
+ }
+
+ if (seq.Count == 3)
+ {
+ seed = ((DerBitString) seq[2]).GetBytes();
+ }
+ }
+
+ public ECCurve Curve
+ {
+ get { return curve; }
+ }
+
+ public byte[] GetSeed()
+ {
+ return Arrays.Clone(seed);
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * Curve ::= Sequence {
+ * a FieldElement,
+ * b FieldElement,
+ * seed BIT STRING OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField)
+ || fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField))
+ {
+ v.Add(new X9FieldElement(curve.A).ToAsn1Object());
+ v.Add(new X9FieldElement(curve.B).ToAsn1Object());
+ }
+
+ if (seed != null)
+ {
+ v.Add(new DerBitString(seed));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9ECParameters.cs b/Crypto/src/asn1/x9/X9ECParameters.cs
new file mode 100644
index 000000000..d025b36ce
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9ECParameters.cs
@@ -0,0 +1,170 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * ASN.1 def for Elliptic-Curve ECParameters structure. See
+ * X9.62, for further details.
+ */
+ public class X9ECParameters
+ : Asn1Encodable
+ {
+ private X9FieldID fieldID;
+ private ECCurve curve;
+ private ECPoint g;
+ private BigInteger n;
+ private BigInteger h;
+ private byte[] seed;
+
+ public X9ECParameters(
+ Asn1Sequence seq)
+ {
+ if (!(seq[0] is DerInteger)
+ || !((DerInteger) seq[0]).Value.Equals(BigInteger.One))
+ {
+ throw new ArgumentException("bad version in X9ECParameters");
+ }
+
+ X9Curve x9c = null;
+ if (seq[2] is X9Curve)
+ {
+ x9c = (X9Curve) seq[2];
+ }
+ else
+ {
+ x9c = new X9Curve(
+ new X9FieldID(
+ (Asn1Sequence) seq[1]),
+ (Asn1Sequence) seq[2]);
+ }
+
+ this.curve = x9c.Curve;
+
+ if (seq[3] is X9ECPoint)
+ {
+ this.g = ((X9ECPoint) seq[3]).Point;
+ }
+ else
+ {
+ this.g = new X9ECPoint(curve, (Asn1OctetString) seq[3]).Point;
+ }
+
+ this.n = ((DerInteger) seq[4]).Value;
+ this.seed = x9c.GetSeed();
+
+ if (seq.Count == 6)
+ {
+ this.h = ((DerInteger) seq[5]).Value;
+ }
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n)
+ : this(curve, g, n, BigInteger.One, null)
+ {
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h)
+ : this(curve, g, n, h, null)
+ {
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.g = g;
+ this.n = n;
+ this.h = h;
+ this.seed = seed;
+
+ if (curve is FpCurve)
+ {
+ this.fieldID = new X9FieldID(((FpCurve) curve).Q);
+ }
+ else if (curve is F2mCurve)
+ {
+ F2mCurve curveF2m = (F2mCurve) curve;
+ this.fieldID = new X9FieldID(curveF2m.M, curveF2m.K1,
+ curveF2m.K2, curveF2m.K3);
+ }
+ }
+
+ public ECCurve Curve
+ {
+ get { return curve; }
+ }
+
+ public ECPoint G
+ {
+ get { return g; }
+ }
+
+ public BigInteger N
+ {
+ get { return n; }
+ }
+
+ public BigInteger H
+ {
+ get
+ {
+ if (h == null)
+ {
+ // TODO - this should be calculated, it will cause issues with custom curves.
+ return BigInteger.One;
+ }
+
+ return h;
+ }
+ }
+
+ public byte[] GetSeed()
+ {
+ return seed;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ECParameters ::= Sequence {
+ * version Integer { ecpVer1(1) } (ecpVer1),
+ * fieldID FieldID {{FieldTypes}},
+ * curve X9Curve,
+ * base X9ECPoint,
+ * order Integer,
+ * cofactor Integer OPTIONAL
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(
+ new DerInteger(1),
+ fieldID,
+ new X9Curve(curve, seed),
+ new X9ECPoint(g),
+ new DerInteger(n));
+
+ if (h != null)
+ {
+ v.Add(new DerInteger(h));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9ECParametersHolder.cs b/Crypto/src/asn1/x9/X9ECParametersHolder.cs
new file mode 100644
index 000000000..b3455709c
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9ECParametersHolder.cs
@@ -0,0 +1,22 @@
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public abstract class X9ECParametersHolder
+ {
+ private X9ECParameters parameters;
+
+ public X9ECParameters Parameters
+ {
+ get
+ {
+ if (parameters == null)
+ {
+ parameters = CreateParameters();
+ }
+
+ return parameters;
+ }
+ }
+
+ protected abstract X9ECParameters CreateParameters();
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9ECPoint.cs b/Crypto/src/asn1/x9/X9ECPoint.cs
new file mode 100644
index 000000000..ba2b2bcbf
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9ECPoint.cs
@@ -0,0 +1,44 @@
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * class for describing an ECPoint as a Der object.
+ */
+ public class X9ECPoint
+ : Asn1Encodable
+ {
+ private readonly ECPoint p;
+
+ public X9ECPoint(
+ ECPoint p)
+ {
+ this.p = p;
+ }
+
+ public X9ECPoint(
+ ECCurve c,
+ Asn1OctetString s)
+ {
+ this.p = c.DecodePoint(s.GetOctets());
+ }
+
+ public ECPoint Point
+ {
+ get { return p; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * ECPoint ::= OCTET STRING
+ * </pre>
+ * <p>
+ * Octet string produced using ECPoint.GetEncoded().</p>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerOctetString(p.GetEncoded());
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9FieldElement.cs b/Crypto/src/asn1/x9/X9FieldElement.cs
new file mode 100644
index 000000000..06fa0e3dc
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9FieldElement.cs
@@ -0,0 +1,69 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * Class for processing an ECFieldElement as a DER object.
+ */
+ public class X9FieldElement
+ : Asn1Encodable
+ {
+ private ECFieldElement f;
+
+ public X9FieldElement(
+ ECFieldElement f)
+ {
+ this.f = f;
+ }
+
+ public X9FieldElement(
+ BigInteger p,
+ Asn1OctetString s)
+ : this(new FpFieldElement(p, new BigInteger(1, s.GetOctets())))
+ {
+ }
+
+ public X9FieldElement(
+ int m,
+ int k1,
+ int k2,
+ int k3,
+ Asn1OctetString s)
+ : this(new F2mFieldElement(m, k1, k2, k3, new BigInteger(1, s.GetOctets())))
+ {
+ }
+
+ public ECFieldElement Value
+ {
+ get { return f; }
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <pre>
+ * FieldElement ::= OCTET STRING
+ * </pre>
+ * <p>
+ * <ol>
+ * <li> if <i>q</i> is an odd prime then the field element is
+ * processed as an Integer and converted to an octet string
+ * according to x 9.62 4.3.1.</li>
+ * <li> if <i>q</i> is 2<sup>m</sup> then the bit string
+ * contained in the field element is converted into an octet
+ * string with the same ordering padded at the front if necessary.
+ * </li>
+ * </ol>
+ * </p>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ int byteCount = X9IntegerConverter.GetByteLength(f);
+ byte[] paddedBigInteger = X9IntegerConverter.IntegerToBytes(f.ToBigInteger(), byteCount);
+
+ return new DerOctetString(paddedBigInteger);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9FieldID.cs b/Crypto/src/asn1/x9/X9FieldID.cs
new file mode 100644
index 000000000..c51cc4df2
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9FieldID.cs
@@ -0,0 +1,102 @@
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ /**
+ * ASN.1 def for Elliptic-Curve Field ID structure. See
+ * X9.62, for further details.
+ */
+ public class X9FieldID
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier id;
+ private readonly Asn1Object parameters;
+
+ /**
+ * Constructor for elliptic curves over prime fields
+ * <code>F<sub>2</sub></code>.
+ * @param primeP The prime <code>p</code> defining the prime field.
+ */
+ public X9FieldID(
+ BigInteger primeP)
+ {
+ this.id = X9ObjectIdentifiers.PrimeField;
+ this.parameters = new DerInteger(primeP);
+ }
+
+ /**
+ * Constructor for elliptic curves over binary fields
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param m The exponent <code>m</code> of
+ * <code>F<sub>2<sup>m</sup></sub></code>.
+ * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>.
+ * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+ * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+ * represents the reduction polynomial <code>f(z)</code>..
+ */
+ public X9FieldID(
+ int m,
+ int k1,
+ int k2,
+ int k3)
+ {
+ this.id = X9ObjectIdentifiers.CharacteristicTwoField;
+
+ Asn1EncodableVector fieldIdParams = new Asn1EncodableVector(new DerInteger(m));
+
+ if (k2 == 0)
+ {
+ fieldIdParams.Add(
+ X9ObjectIdentifiers.TPBasis,
+ new DerInteger(k1));
+ }
+ else
+ {
+ fieldIdParams.Add(
+ X9ObjectIdentifiers.PPBasis,
+ new DerSequence(
+ new DerInteger(k1),
+ new DerInteger(k2),
+ new DerInteger(k3)));
+ }
+
+ this.parameters = new DerSequence(fieldIdParams);
+ }
+
+ internal X9FieldID(
+ Asn1Sequence seq)
+ {
+ this.id = (DerObjectIdentifier) seq[0];
+ this.parameters = (Asn1Object) seq[1];
+ }
+
+ public DerObjectIdentifier Identifier
+ {
+ get { return id; }
+ }
+
+ public Asn1Object Parameters
+ {
+ get { return parameters; }
+ }
+
+ /**
+ * Produce a Der encoding of the following structure.
+ * <pre>
+ * FieldID ::= Sequence {
+ * fieldType FIELD-ID.&id({IOSet}),
+ * parameters FIELD-ID.&Type({IOSet}{@fieldType})
+ * }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(id, parameters);
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9IntegerConverter.cs b/Crypto/src/asn1/x9/X9IntegerConverter.cs
new file mode 100644
index 000000000..2bce20488
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9IntegerConverter.cs
@@ -0,0 +1,48 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public sealed class X9IntegerConverter
+ {
+ private X9IntegerConverter()
+ {
+ }
+
+ public static int GetByteLength(
+ ECFieldElement fe)
+ {
+ return (fe.FieldSize + 7) / 8;
+ }
+
+ public static int GetByteLength(
+ ECCurve c)
+ {
+ return (c.FieldSize + 7) / 8;
+ }
+
+ public static byte[] IntegerToBytes(
+ BigInteger s,
+ int qLength)
+ {
+ byte[] bytes = s.ToByteArrayUnsigned();
+
+ if (qLength < bytes.Length)
+ {
+ byte[] tmp = new byte[qLength];
+ Array.Copy(bytes, bytes.Length - tmp.Length, tmp, 0, tmp.Length);
+ return tmp;
+ }
+ else if (qLength > bytes.Length)
+ {
+ byte[] tmp = new byte[qLength];
+ Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length);
+ return tmp;
+ }
+
+ return bytes;
+ }
+ }
+}
diff --git a/Crypto/src/asn1/x9/X9ObjectIdentifiers.cs b/Crypto/src/asn1/x9/X9ObjectIdentifiers.cs
new file mode 100644
index 000000000..5b2fdbd2d
--- /dev/null
+++ b/Crypto/src/asn1/x9/X9ObjectIdentifiers.cs
@@ -0,0 +1,135 @@
+namespace Org.BouncyCastle.Asn1.X9
+{
+ public abstract class X9ObjectIdentifiers
+ {
+ //
+ // X9.62
+ //
+ // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) ansi-x962(10045) }
+ //
+ internal const string AnsiX962 = "1.2.840.10045";
+ internal const string IdFieldType = AnsiX962 + ".1";
+
+ public static readonly DerObjectIdentifier PrimeField
+ = new DerObjectIdentifier(IdFieldType + ".1");
+
+ public static readonly DerObjectIdentifier CharacteristicTwoField
+ = new DerObjectIdentifier(IdFieldType + ".2");
+
+ public static readonly DerObjectIdentifier GNBasis
+ = new DerObjectIdentifier(IdFieldType + ".2.3.1");
+
+ public static readonly DerObjectIdentifier TPBasis
+ = new DerObjectIdentifier(IdFieldType + ".2.3.2");
+
+ public static readonly DerObjectIdentifier PPBasis
+ = new DerObjectIdentifier(IdFieldType + ".2.3.3");
+
+ public const string IdECSigType = AnsiX962 + ".4";
+
+ public static readonly DerObjectIdentifier ECDsaWithSha1
+ = new DerObjectIdentifier(IdECSigType + ".1");
+
+ public const string IdPublicKeyType = AnsiX962 + ".2";
+
+ public static readonly DerObjectIdentifier IdECPublicKey
+ = new DerObjectIdentifier(IdPublicKeyType + ".1");
+
+ public static readonly DerObjectIdentifier ECDsaWithSha2 = new DerObjectIdentifier(IdECSigType + ".3");
+ public static readonly DerObjectIdentifier ECDsaWithSha224 = new DerObjectIdentifier(ECDsaWithSha2 + ".1");
+ public static readonly DerObjectIdentifier ECDsaWithSha256 = new DerObjectIdentifier(ECDsaWithSha2 + ".2");
+ public static readonly DerObjectIdentifier ECDsaWithSha384 = new DerObjectIdentifier(ECDsaWithSha2 + ".3");
+ public static readonly DerObjectIdentifier ECDsaWithSha512 = new DerObjectIdentifier(ECDsaWithSha2 + ".4");
+
+
+ //
+ // named curves
+ //
+ public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier(AnsiX962 + ".3");
+
+ //
+ // Two Curves
+ //
+ public static readonly DerObjectIdentifier CTwoCurve = new DerObjectIdentifier(EllipticCurve + ".0");
+
+ public static readonly DerObjectIdentifier C2Pnb163v1 = new DerObjectIdentifier(CTwoCurve + ".1");
+ public static readonly DerObjectIdentifier C2Pnb163v2 = new DerObjectIdentifier(CTwoCurve + ".2");
+ public static readonly DerObjectIdentifier C2Pnb163v3 = new DerObjectIdentifier(CTwoCurve + ".3");
+ public static readonly DerObjectIdentifier C2Pnb176w1 = new DerObjectIdentifier(CTwoCurve + ".4");
+ public static readonly DerObjectIdentifier C2Tnb191v1 = new DerObjectIdentifier(CTwoCurve + ".5");
+ public static readonly DerObjectIdentifier C2Tnb191v2 = new DerObjectIdentifier(CTwoCurve + ".6");
+ public static readonly DerObjectIdentifier C2Tnb191v3 = new DerObjectIdentifier(CTwoCurve + ".7");
+ public static readonly DerObjectIdentifier C2Onb191v4 = new DerObjectIdentifier(CTwoCurve + ".8");
+ public static readonly DerObjectIdentifier C2Onb191v5 = new DerObjectIdentifier(CTwoCurve + ".9");
+ public static readonly DerObjectIdentifier C2Pnb208w1 = new DerObjectIdentifier(CTwoCurve + ".10");
+ public static readonly DerObjectIdentifier C2Tnb239v1 = new DerObjectIdentifier(CTwoCurve + ".11");
+ public static readonly DerObjectIdentifier C2Tnb239v2 = new DerObjectIdentifier(CTwoCurve + ".12");
+ public static readonly DerObjectIdentifier C2Tnb239v3 = new DerObjectIdentifier(CTwoCurve + ".13");
+ public static readonly DerObjectIdentifier C2Onb239v4 = new DerObjectIdentifier(CTwoCurve + ".14");
+ public static readonly DerObjectIdentifier C2Onb239v5 = new DerObjectIdentifier(CTwoCurve + ".15");
+ public static readonly DerObjectIdentifier C2Pnb272w1 = new DerObjectIdentifier(CTwoCurve + ".16");
+ public static readonly DerObjectIdentifier C2Pnb304w1 = new DerObjectIdentifier(CTwoCurve + ".17");
+ public static readonly DerObjectIdentifier C2Tnb359v1 = new DerObjectIdentifier(CTwoCurve + ".18");
+ public static readonly DerObjectIdentifier C2Pnb368w1 = new DerObjectIdentifier(CTwoCurve + ".19");
+ public static readonly DerObjectIdentifier C2Tnb431r1 = new DerObjectIdentifier(CTwoCurve + ".20");
+
+ //
+ // Prime
+ //
+ public static readonly DerObjectIdentifier PrimeCurve = new DerObjectIdentifier(EllipticCurve + ".1");
+
+ public static readonly DerObjectIdentifier Prime192v1 = new DerObjectIdentifier(PrimeCurve + ".1");
+ public static readonly DerObjectIdentifier Prime192v2 = new DerObjectIdentifier(PrimeCurve + ".2");
+ public static readonly DerObjectIdentifier Prime192v3 = new DerObjectIdentifier(PrimeCurve + ".3");
+ public static readonly DerObjectIdentifier Prime239v1 = new DerObjectIdentifier(PrimeCurve + ".4");
+ public static readonly DerObjectIdentifier Prime239v2 = new DerObjectIdentifier(PrimeCurve + ".5");
+ public static readonly DerObjectIdentifier Prime239v3 = new DerObjectIdentifier(PrimeCurve + ".6");
+ public static readonly DerObjectIdentifier Prime256v1 = new DerObjectIdentifier(PrimeCurve + ".7");
+
+ //
+ // DSA
+ //
+ // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) ansi-x957(10040) number-type(4) 1 }
+ public static readonly DerObjectIdentifier IdDsa = new DerObjectIdentifier("1.2.840.10040.4.1");
+
+ /**
+ * id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ * us(840) x9-57 (10040) x9cm(4) 3 }
+ */
+ public static readonly DerObjectIdentifier IdDsaWithSha1 = new DerObjectIdentifier("1.2.840.10040.4.3");
+
+ /**
+ * X9.63
+ */
+ public static readonly DerObjectIdentifier X9x63Scheme = new DerObjectIdentifier("1.3.133.16.840.63.0");
+ public static readonly DerObjectIdentifier DHSinglePassStdDHSha1KdfScheme = new DerObjectIdentifier(X9x63Scheme + ".2");
+ public static readonly DerObjectIdentifier DHSinglePassCofactorDHSha1KdfScheme = new DerObjectIdentifier(X9x63Scheme + ".3");
+ public static readonly DerObjectIdentifier MqvSinglePassSha1KdfScheme = new DerObjectIdentifier(X9x63Scheme + ".16");
+
+ /**
+ * X9.42
+ */
+
+ internal const string AnsiX942 = "1.2.840.10046";
+
+ //
+ // Diffie-Hellman
+ //
+ // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) ansi-x942(10046) number-type(2) 1 }
+ //
+ public static readonly DerObjectIdentifier DHPublicNumber = new DerObjectIdentifier(AnsiX942 + ".2.1");
+
+ public static readonly DerObjectIdentifier X9x42Schemes = new DerObjectIdentifier(AnsiX942 + ".3");
+ public static readonly DerObjectIdentifier DHStatic = new DerObjectIdentifier(X9x42Schemes + ".1");
+ public static readonly DerObjectIdentifier DHEphem = new DerObjectIdentifier(X9x42Schemes + ".2");
+ public static readonly DerObjectIdentifier DHOneFlow = new DerObjectIdentifier(X9x42Schemes + ".3");
+ public static readonly DerObjectIdentifier DHHybrid1 = new DerObjectIdentifier(X9x42Schemes + ".4");
+ public static readonly DerObjectIdentifier DHHybrid2 = new DerObjectIdentifier(X9x42Schemes + ".5");
+ public static readonly DerObjectIdentifier DHHybridOneFlow = new DerObjectIdentifier(X9x42Schemes + ".6");
+ public static readonly DerObjectIdentifier Mqv2 = new DerObjectIdentifier(X9x42Schemes + ".7");
+ public static readonly DerObjectIdentifier Mqv1 = new DerObjectIdentifier(X9x42Schemes + ".8");
+ }
+}
|