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..8a3ee5d0e
--- /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
+ [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
+ [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..5b6b13034
--- /dev/null
+++ b/crypto/src/asn1/cms/Attributes.cs
@@ -0,0 +1,55 @@
+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;
+ }
+
+ public virtual Attribute[] GetAttributes()
+ {
+ Attribute[] rv = new Attribute[attributes.Count];
+
+ for (int i = 0; i != rv.Length; i++)
+ {
+ rv[i] = Attribute.GetInstance(attributes[i]);
+ }
+
+ return rv;
+ }
+
+ /**
+ * <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..2ad0a3c7c
--- /dev/null
+++ b/crypto/src/asn1/cms/CMSObjectIdentifiers.cs
@@ -0,0 +1,28 @@
+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;
+
+ /**
+ * The other Revocation Info arc
+ * id-ri OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) }
+ */
+ public static readonly DerObjectIdentifier id_ri = new DerObjectIdentifier("1.3.6.1.5.5.7.16");
+
+ public static readonly DerObjectIdentifier id_ri_ocsp_response = id_ri.Branch("2");
+ public static readonly DerObjectIdentifier id_ri_scvp = id_ri.Branch("4");
+ }
+}
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..278ceca46
--- /dev/null
+++ b/crypto/src/asn1/cms/ContentInfo.cs
@@ -0,0 +1,88 @@
+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);
+ }
+
+ public static ContentInfo GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ 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..09f291a93
--- /dev/null
+++ b/crypto/src/asn1/cms/EnvelopedData.cs
@@ -0,0 +1,176 @@
+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)
+ {
+ this.version = new DerInteger(CalculateVersion(originatorInfo, recipientInfos, unprotectedAttrs));
+ this.originatorInfo = originatorInfo;
+ this.recipientInfos = recipientInfos;
+ this.encryptedContentInfo = encryptedContentInfo;
+ this.unprotectedAttrs = unprotectedAttrs;
+ }
+
+ public EnvelopedData(
+ OriginatorInfo originatorInfo,
+ Asn1Set recipientInfos,
+ EncryptedContentInfo encryptedContentInfo,
+ Attributes unprotectedAttrs)
+ {
+ this.version = new DerInteger(CalculateVersion(originatorInfo, recipientInfos, Asn1Set.GetInstance(unprotectedAttrs)));
+ this.originatorInfo = originatorInfo;
+ this.recipientInfos = recipientInfos;
+ this.encryptedContentInfo = encryptedContentInfo;
+ this.unprotectedAttrs = Asn1Set.GetInstance(unprotectedAttrs);
+ }
+
+ [Obsolete("Use 'GetInstance' instead")]
+ 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 is EnvelopedData)
+ return (EnvelopedData)obj;
+ if (obj == null)
+ return null;
+ return new EnvelopedData(Asn1Sequence.GetInstance(obj));
+ }
+
+ 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);
+ }
+
+ public static int CalculateVersion(OriginatorInfo originatorInfo, Asn1Set recipientInfos, Asn1Set unprotectedAttrs)
+ {
+ if (originatorInfo != null || unprotectedAttrs != null)
+ {
+ return 2;
+ }
+
+ foreach (object o in recipientInfos)
+ {
+ RecipientInfo ri = RecipientInfo.GetInstance(o);
+
+ if (ri.Version.Value.IntValue != 0)
+ {
+ return 2;
+ }
+ }
+
+ return 0;
+ }
+ }
+}
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..b509e7e19
--- /dev/null
+++ b/crypto/src/asn1/cms/IssuerAndSerialNumber.cs
@@ -0,0 +1,64 @@
+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 == null)
+ return null;
+ IssuerAndSerialNumber existing = obj as IssuerAndSerialNumber;
+ if (existing != null)
+ return existing;
+ return new IssuerAndSerialNumber(Asn1Sequence.GetInstance(obj));
+ }
+
+ [Obsolete("Use GetInstance() instead")]
+ 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..80dd68e7c
--- /dev/null
+++ b/crypto/src/asn1/cms/OtherRecipientInfo.cs
@@ -0,0 +1,83 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class OtherRecipientInfo
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier oriType;
+ private readonly Asn1Encodable oriValue;
+
+ public OtherRecipientInfo(
+ DerObjectIdentifier oriType,
+ Asn1Encodable oriValue)
+ {
+ this.oriType = oriType;
+ this.oriValue = oriValue;
+ }
+
+ [Obsolete("Use GetInstance() instead")]
+ 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)
+ return null;
+ OtherRecipientInfo existing = obj as OtherRecipientInfo;
+ if (existing != null)
+ return existing;
+ return new OtherRecipientInfo(Asn1Sequence.GetInstance(obj));
+ }
+
+ public virtual DerObjectIdentifier OriType
+ {
+ get { return oriType; }
+ }
+
+ public virtual 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/OtherRevocationInfoFormat.cs b/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs
new file mode 100644
index 000000000..78354896f
--- /dev/null
+++ b/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs
@@ -0,0 +1,77 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class OtherRevocationInfoFormat
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier otherRevInfoFormat;
+ private readonly Asn1Encodable otherRevInfo;
+
+ public OtherRevocationInfoFormat(
+ DerObjectIdentifier otherRevInfoFormat,
+ Asn1Encodable otherRevInfo)
+ {
+ this.otherRevInfoFormat = otherRevInfoFormat;
+ this.otherRevInfo = otherRevInfo;
+ }
+
+ private OtherRevocationInfoFormat(Asn1Sequence seq)
+ {
+ otherRevInfoFormat = DerObjectIdentifier.GetInstance(seq[0]);
+ otherRevInfo = seq[1];
+ }
+
+ /**
+ * return a OtherRevocationInfoFormat object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OtherRevocationInfoFormat GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * return a OtherRevocationInfoFormat object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static OtherRevocationInfoFormat GetInstance(object obj)
+ {
+ if (obj is OtherRevocationInfoFormat)
+ return (OtherRevocationInfoFormat)obj;
+ if (obj != null)
+ return new OtherRevocationInfoFormat(Asn1Sequence.GetInstance(obj));
+ return null;
+ }
+
+ public virtual DerObjectIdentifier InfoFormat
+ {
+ get { return otherRevInfoFormat; }
+ }
+
+ public virtual Asn1Encodable Info
+ {
+ get { return otherRevInfo; }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ * <pre>
+ * OtherRevocationInfoFormat ::= SEQUENCE {
+ * otherRevInfoFormat OBJECT IDENTIFIER,
+ * otherRevInfo ANY DEFINED BY otherRevInfoFormat }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(otherRevInfoFormat, otherRevInfo);
+ }
+ }
+}
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/SCVPReqRes.cs b/crypto/src/asn1/cms/SCVPReqRes.cs
new file mode 100644
index 000000000..486979a29
--- /dev/null
+++ b/crypto/src/asn1/cms/SCVPReqRes.cs
@@ -0,0 +1,77 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ public class ScvpReqRes
+ : Asn1Encodable
+ {
+ private readonly ContentInfo request;
+ private readonly ContentInfo response;
+
+ public static ScvpReqRes GetInstance(object obj)
+ {
+ if (obj is ScvpReqRes)
+ return (ScvpReqRes)obj;
+ if (obj != null)
+ return new ScvpReqRes(Asn1Sequence.GetInstance(obj));
+ return null;
+ }
+
+ private ScvpReqRes(Asn1Sequence seq)
+ {
+ if (seq[0] is Asn1TaggedObject)
+ {
+ this.request = ContentInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[0]), true);
+ this.response = ContentInfo.GetInstance(seq[1]);
+ }
+ else
+ {
+ this.request = null;
+ this.response = ContentInfo.GetInstance(seq[0]);
+ }
+ }
+
+ public ScvpReqRes(ContentInfo response)
+ : this(null, response)
+ {
+ }
+
+ public ScvpReqRes(ContentInfo request, ContentInfo response)
+ {
+ this.request = request;
+ this.response = response;
+ }
+
+ public virtual ContentInfo Request
+ {
+ get { return request; }
+ }
+
+ public virtual ContentInfo Response
+ {
+ get { return response; }
+ }
+
+ /**
+ * <pre>
+ * ScvpReqRes ::= SEQUENCE {
+ * request [0] EXPLICIT ContentInfo OPTIONAL,
+ * response ContentInfo }
+ * </pre>
+ * @return the ASN.1 primitive representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (request != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, request));
+ }
+
+ v.Add(response);
+
+ 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..6cea79a49
--- /dev/null
+++ b/crypto/src/asn1/cms/SignedData.cs
@@ -0,0 +1,287 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+ /**
+ * a signed data object.
+ */
+ public class SignedData
+ : Asn1Encodable
+ {
+ private static readonly DerInteger Version1 = new DerInteger(1);
+ private static readonly DerInteger Version3 = new DerInteger(3);
+ private static readonly DerInteger Version4 = new DerInteger(4);
+ private static readonly DerInteger Version5 = new DerInteger(5);
+
+ 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 Version5;
+ }
+
+ if (crls != null)
+ {
+ foreach (object obj in crls)
+ {
+ if (obj is Asn1TaggedObject)
+ {
+ otherCrl = true;
+ break;
+ }
+ }
+ }
+
+ if (otherCrl)
+ {
+ return Version5;
+ }
+
+ if (attrCertV2Found)
+ {
+ return Version4;
+ }
+
+ if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(signerInfs))
+ {
+ return Version3;
+ }
+
+ return Version1;
+ }
+
+ 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..a4e893d96
--- /dev/null
+++ b/crypto/src/asn1/cms/SignerInfo.cs
@@ -0,0 +1,185 @@
+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)
+ {
+ this.version = new DerInteger(sid.IsTagged ? 3 : 1);
+ this.sid = sid;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = unauthenticatedAttributes;
+ }
+
+ public SignerInfo(
+ SignerIdentifier sid,
+ AlgorithmIdentifier digAlgorithm,
+ Attributes authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ Asn1OctetString encryptedDigest,
+ Attributes unauthenticatedAttributes)
+ {
+ this.version = new DerInteger(sid.IsTagged ? 3 : 1);
+ this.sid = sid;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = Asn1Set.GetInstance(authenticatedAttributes);
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = Asn1Set.GetInstance(unauthenticatedAttributes);
+ }
+
+ [Obsolete("Use 'GetInstance' instead")]
+ 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);
+ }
+ }
+}
|