diff --git a/crypto/src/asn1/crmf/AttributeTypeAndValue.cs b/crypto/src/asn1/crmf/AttributeTypeAndValue.cs
new file mode 100644
index 000000000..823668992
--- /dev/null
+++ b/crypto/src/asn1/crmf/AttributeTypeAndValue.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class AttributeTypeAndValue
+ : Asn1Encodable
+ {
+ private readonly DerObjectIdentifier type;
+ private readonly Asn1Encodable value;
+
+ private AttributeTypeAndValue(Asn1Sequence seq)
+ {
+ type = (DerObjectIdentifier)seq[0];
+ value = (Asn1Encodable)seq[1];
+ }
+
+ public static AttributeTypeAndValue GetInstance(object obj)
+ {
+ if (obj is AttributeTypeAndValue)
+ return (AttributeTypeAndValue)obj;
+
+ if (obj is Asn1Sequence)
+ return new AttributeTypeAndValue((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public AttributeTypeAndValue(
+ String oid,
+ Asn1Encodable value)
+ : this(new DerObjectIdentifier(oid), value)
+ {
+ }
+
+ public AttributeTypeAndValue(
+ DerObjectIdentifier type,
+ Asn1Encodable value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public virtual DerObjectIdentifier Type
+ {
+ get { return type; }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get { return value; }
+ }
+
+ /**
+ * <pre>
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY DEFINED BY type }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(type, value);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/CertId.cs b/crypto/src/asn1/crmf/CertId.cs
new file mode 100644
index 000000000..10c2cc8b4
--- /dev/null
+++ b/crypto/src/asn1/crmf/CertId.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertId
+ : Asn1Encodable
+ {
+ private readonly GeneralName issuer;
+ private readonly DerInteger serialNumber;
+
+ private CertId(Asn1Sequence seq)
+ {
+ issuer = GeneralName.GetInstance(seq[0]);
+ serialNumber = DerInteger.GetInstance(seq[1]);
+ }
+
+ public static CertId GetInstance(object obj)
+ {
+ if (obj is CertId)
+ return (CertId)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertId((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public static CertId GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ public virtual GeneralName Issuer
+ {
+ get { return issuer; }
+ }
+
+ public virtual DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ /**
+ * <pre>
+ * CertId ::= SEQUENCE {
+ * issuer GeneralName,
+ * serialNumber INTEGER }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(issuer, serialNumber);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/CertReqMessages.cs b/crypto/src/asn1/crmf/CertReqMessages.cs
new file mode 100644
index 000000000..9247281e8
--- /dev/null
+++ b/crypto/src/asn1/crmf/CertReqMessages.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertReqMessages
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private CertReqMessages(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertReqMessages GetInstance(object obj)
+ {
+ if (obj is CertReqMessages)
+ return (CertReqMessages)obj;
+
+ if (obj is Asn1Sequence)
+ return new CertReqMessages((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public CertReqMessages(params CertReqMsg[] msgs)
+ {
+ content = new DerSequence(msgs);
+ }
+
+ public virtual CertReqMsg[] ToCertReqMsgArray()
+ {
+ CertReqMsg[] result = new CertReqMsg[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = CertReqMsg.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/CertReqMsg.cs b/crypto/src/asn1/crmf/CertReqMsg.cs
new file mode 100644
index 000000000..2ca319a57
--- /dev/null
+++ b/crypto/src/asn1/crmf/CertReqMsg.cs
@@ -0,0 +1,106 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertReqMsg
+ : Asn1Encodable
+ {
+ private readonly CertRequest certReq;
+ private readonly ProofOfPossession popo;
+ private readonly Asn1Sequence regInfo;
+
+ private CertReqMsg(Asn1Sequence seq)
+ {
+ certReq = CertRequest.GetInstance(seq[0]);
+
+ for (int pos = 1; pos < seq.Count; ++pos)
+ {
+ object o = seq[pos];
+
+ if (o is Asn1TaggedObject || o is ProofOfPossession)
+ {
+ popo = ProofOfPossession.GetInstance(o);
+ }
+ else
+ {
+ regInfo = Asn1Sequence.GetInstance(o);
+ }
+ }
+ }
+
+ public static CertReqMsg GetInstance(object obj)
+ {
+ if (obj is CertReqMsg)
+ return (CertReqMsg)obj;
+
+ if (obj != null)
+ return new CertReqMsg(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ /**
+ * Creates a new CertReqMsg.
+ * @param certReq CertRequest
+ * @param popo may be null
+ * @param regInfo may be null
+ */
+ public CertReqMsg(
+ CertRequest certReq,
+ ProofOfPossession popo,
+ AttributeTypeAndValue[] regInfo)
+ {
+ if (certReq == null)
+ throw new ArgumentNullException("certReq");
+
+ this.certReq = certReq;
+ this.popo = popo;
+
+ if (regInfo != null)
+ {
+ this.regInfo = new DerSequence(regInfo);
+ }
+ }
+
+ public virtual CertRequest CertReq
+ {
+ get { return certReq; }
+ }
+
+ public virtual ProofOfPossession Popo
+ {
+ get { return popo; }
+ }
+
+ public virtual AttributeTypeAndValue[] GetRegInfo()
+ {
+ if (regInfo == null)
+ return null;
+
+ AttributeTypeAndValue[] results = new AttributeTypeAndValue[regInfo.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = AttributeTypeAndValue.GetInstance(regInfo[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * CertReqMsg ::= SEQUENCE {
+ * certReq CertRequest,
+ * pop ProofOfPossession OPTIONAL,
+ * -- content depends upon key type
+ * regInfo SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReq);
+ v.AddOptional(popo);
+ v.AddOptional(regInfo);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/CertRequest.cs b/crypto/src/asn1/crmf/CertRequest.cs
new file mode 100644
index 000000000..625a9b519
--- /dev/null
+++ b/crypto/src/asn1/crmf/CertRequest.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertRequest
+ : Asn1Encodable
+ {
+ private readonly DerInteger certReqId;
+ private readonly CertTemplate certTemplate;
+ private readonly Controls controls;
+
+ private CertRequest(Asn1Sequence seq)
+ {
+ certReqId = DerInteger.GetInstance(seq[0]);
+ certTemplate = CertTemplate.GetInstance(seq[1]);
+ if (seq.Count > 2)
+ {
+ controls = Controls.GetInstance(seq[2]);
+ }
+ }
+
+ public static CertRequest GetInstance(object obj)
+ {
+ if (obj is CertRequest)
+ return (CertRequest)obj;
+
+ if (obj != null)
+ return new CertRequest(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public CertRequest(
+ int certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ : this(new DerInteger(certReqId), certTemplate, controls)
+ {
+ }
+
+ public CertRequest(
+ DerInteger certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ {
+ this.certReqId = certReqId;
+ this.certTemplate = certTemplate;
+ this.controls = controls;
+ }
+
+ public virtual DerInteger CertReqID
+ {
+ get { return certReqId; }
+ }
+
+ public virtual CertTemplate CertTemplate
+ {
+ get { return certTemplate; }
+ }
+
+ public virtual Controls Controls
+ {
+ get { return controls; }
+ }
+
+ /**
+ * <pre>
+ * CertRequest ::= SEQUENCE {
+ * certReqId INTEGER, -- ID for matching request and reply
+ * certTemplate CertTemplate, -- Selected fields of cert to be issued
+ * controls Controls OPTIONAL } -- Attributes affecting issuance
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(certReqId, certTemplate);
+ v.AddOptional(controls);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/CertTemplate.cs b/crypto/src/asn1/crmf/CertTemplate.cs
new file mode 100644
index 000000000..3de9f1d5a
--- /dev/null
+++ b/crypto/src/asn1/crmf/CertTemplate.cs
@@ -0,0 +1,149 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertTemplate
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence seq;
+
+ private readonly DerInteger version;
+ private readonly DerInteger serialNumber;
+ private readonly AlgorithmIdentifier signingAlg;
+ private readonly X509Name issuer;
+ private readonly OptionalValidity validity;
+ private readonly X509Name subject;
+ private readonly SubjectPublicKeyInfo publicKey;
+ private readonly DerBitString issuerUID;
+ private readonly DerBitString subjectUID;
+ private readonly X509Extensions extensions;
+
+ private CertTemplate(Asn1Sequence seq)
+ {
+ this.seq = seq;
+
+ foreach (Asn1TaggedObject tObj in seq)
+ {
+ switch (tObj.TagNo)
+ {
+ case 0:
+ version = DerInteger.GetInstance(tObj, false);
+ break;
+ case 1:
+ serialNumber = DerInteger.GetInstance(tObj, false);
+ break;
+ case 2:
+ signingAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 3:
+ issuer = X509Name.GetInstance(tObj, true); // CHOICE
+ break;
+ case 4:
+ validity = OptionalValidity.GetInstance(Asn1Sequence.GetInstance(tObj, false));
+ break;
+ case 5:
+ subject = X509Name.GetInstance(tObj, true); // CHOICE
+ break;
+ case 6:
+ publicKey = SubjectPublicKeyInfo.GetInstance(tObj, false);
+ break;
+ case 7:
+ issuerUID = DerBitString.GetInstance(tObj, false);
+ break;
+ case 8:
+ subjectUID = DerBitString.GetInstance(tObj, false);
+ break;
+ case 9:
+ extensions = X509Extensions.GetInstance(tObj, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag: " + tObj.TagNo, "seq");
+ }
+ }
+ }
+
+ public static CertTemplate GetInstance(object obj)
+ {
+ if (obj is CertTemplate)
+ return (CertTemplate)obj;
+
+ if (obj != null)
+ return new CertTemplate(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public virtual int Version
+ {
+ get { return version.Value.IntValue; }
+ }
+
+ public virtual DerInteger SerialNumber
+ {
+ get { return serialNumber; }
+ }
+
+ public virtual AlgorithmIdentifier SigningAlg
+ {
+ get { return signingAlg; }
+ }
+
+ public virtual X509Name Issuer
+ {
+ get { return issuer; }
+ }
+
+ public virtual OptionalValidity Validity
+ {
+ get { return validity; }
+ }
+
+ public virtual X509Name Subject
+ {
+ get { return subject; }
+ }
+
+ public virtual SubjectPublicKeyInfo PublicKey
+ {
+ get { return publicKey; }
+ }
+
+ public virtual DerBitString IssuerUID
+ {
+ get { return issuerUID; }
+ }
+
+ public virtual DerBitString SubjectUID
+ {
+ get { return subjectUID; }
+ }
+
+ public virtual X509Extensions Extensions
+ {
+ get { return extensions; }
+ }
+
+ /**
+ * <pre>
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return seq;
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/CertTemplateBuilder.cs b/crypto/src/asn1/crmf/CertTemplateBuilder.cs
new file mode 100644
index 000000000..51c73c4e1
--- /dev/null
+++ b/crypto/src/asn1/crmf/CertTemplateBuilder.cs
@@ -0,0 +1,125 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class CertTemplateBuilder
+ {
+ private DerInteger version;
+ private DerInteger serialNumber;
+ private AlgorithmIdentifier signingAlg;
+ private X509Name issuer;
+ private OptionalValidity validity;
+ private X509Name subject;
+ private SubjectPublicKeyInfo publicKey;
+ private DerBitString issuerUID;
+ private DerBitString subjectUID;
+ private X509Extensions extensions;
+
+ /** Sets the X.509 version. Note: for X509v3, use 2 here. */
+ public virtual CertTemplateBuilder SetVersion(int ver)
+ {
+ version = new DerInteger(ver);
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetSerialNumber(DerInteger ser)
+ {
+ serialNumber = ser;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetSigningAlg(AlgorithmIdentifier aid)
+ {
+ signingAlg = aid;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetIssuer(X509Name name)
+ {
+ issuer = name;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetValidity(OptionalValidity v)
+ {
+ validity = v;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetSubject(X509Name name)
+ {
+ subject = name;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetPublicKey(SubjectPublicKeyInfo spki)
+ {
+ publicKey = spki;
+ return this;
+ }
+
+ /** Sets the issuer unique ID (deprecated in X.509v3) */
+ public virtual CertTemplateBuilder SetIssuerUID(DerBitString uid)
+ {
+ issuerUID = uid;
+ return this;
+ }
+
+ /** Sets the subject unique ID (deprecated in X.509v3) */
+ public virtual CertTemplateBuilder SetSubjectUID(DerBitString uid)
+ {
+ subjectUID = uid;
+ return this;
+ }
+
+ public virtual CertTemplateBuilder SetExtensions(X509Extensions extens)
+ {
+ extensions = extens;
+ return this;
+ }
+
+ /**
+ * <pre>
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public virtual CertTemplate Build()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ AddOptional(v, 0, false, version);
+ AddOptional(v, 1, false, serialNumber);
+ AddOptional(v, 2, false, signingAlg);
+ AddOptional(v, 3, true, issuer); // CHOICE
+ AddOptional(v, 4, false, validity);
+ AddOptional(v, 5, true, subject); // CHOICE
+ AddOptional(v, 6, false, publicKey);
+ AddOptional(v, 7, false, issuerUID);
+ AddOptional(v, 8, false, subjectUID);
+ AddOptional(v, 9, false, extensions);
+
+ return CertTemplate.GetInstance(new DerSequence(v));
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, bool isExplicit, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(isExplicit, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/Controls.cs b/crypto/src/asn1/crmf/Controls.cs
new file mode 100644
index 000000000..cc52ea4bb
--- /dev/null
+++ b/crypto/src/asn1/crmf/Controls.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class Controls
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private Controls(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static Controls GetInstance(object obj)
+ {
+ if (obj is Controls)
+ return (Controls)obj;
+
+ if (obj is Asn1Sequence)
+ return new Controls((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public Controls(params AttributeTypeAndValue[] atvs)
+ {
+ content = new DerSequence(atvs);
+ }
+
+ public virtual AttributeTypeAndValue[] ToAttributeTypeAndValueArray()
+ {
+ AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = AttributeTypeAndValue.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * Controls ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs b/crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs
new file mode 100644
index 000000000..eaa1f7ba4
--- /dev/null
+++ b/crypto/src/asn1/crmf/CrmfObjectIdentifiers.cs
@@ -0,0 +1,23 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public abstract class CrmfObjectIdentifiers
+ {
+ public static readonly DerObjectIdentifier id_pkix = new DerObjectIdentifier("1.3.6.1.5.5.7");
+
+ // arc for Internet X.509 PKI protocols and their components
+
+ public static readonly DerObjectIdentifier id_pkip = id_pkix.Branch("5");
+
+ public static readonly DerObjectIdentifier id_regCtrl = id_pkip.Branch("1");
+ public static readonly DerObjectIdentifier id_regCtrl_regToken = id_regCtrl.Branch("1");
+ public static readonly DerObjectIdentifier id_regCtrl_authenticator = id_regCtrl.Branch("2");
+ public static readonly DerObjectIdentifier id_regCtrl_pkiPublicationInfo = id_regCtrl.Branch("3");
+ public static readonly DerObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.Branch("4");
+
+ public static readonly DerObjectIdentifier id_ct_encKeyWithID = new DerObjectIdentifier(PkcsObjectIdentifiers.IdCT + ".21");
+ }
+}
diff --git a/crypto/src/asn1/crmf/EncKeyWithID.cs b/crypto/src/asn1/crmf/EncKeyWithID.cs
new file mode 100644
index 000000000..6de56fa0b
--- /dev/null
+++ b/crypto/src/asn1/crmf/EncKeyWithID.cs
@@ -0,0 +1,103 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class EncKeyWithID
+ : Asn1Encodable
+ {
+ private readonly PrivateKeyInfo privKeyInfo;
+ private readonly Asn1Encodable identifier;
+
+ public static EncKeyWithID GetInstance(object obj)
+ {
+ if (obj is EncKeyWithID)
+ return (EncKeyWithID)obj;
+
+ if (obj != null)
+ return new EncKeyWithID(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ private EncKeyWithID(Asn1Sequence seq)
+ {
+ this.privKeyInfo = PrivateKeyInfo.GetInstance(seq[0]);
+
+ if (seq.Count > 1)
+ {
+ if (!(seq[1] is DerUtf8String))
+ {
+ this.identifier = GeneralName.GetInstance(seq[1]);
+ }
+ else
+ {
+ this.identifier = (Asn1Encodable)seq[1];
+ }
+ }
+ else
+ {
+ this.identifier = null;
+ }
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = null;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, DerUtf8String str)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = str;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, GeneralName generalName)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = generalName;
+ }
+
+ public virtual PrivateKeyInfo PrivateKey
+ {
+ get { return privKeyInfo; }
+ }
+
+ public virtual bool HasIdentifier
+ {
+ get { return identifier != null; }
+ }
+
+ public virtual bool IsIdentifierUtf8String
+ {
+ get { return identifier is DerUtf8String; }
+ }
+
+ public virtual Asn1Encodable Identifier
+ {
+ get { return identifier; }
+ }
+
+ /**
+ * <pre>
+ * EncKeyWithID ::= SEQUENCE {
+ * privateKey PrivateKeyInfo,
+ * identifier CHOICE {
+ * string UTF8String,
+ * generalName GeneralName
+ * } OPTIONAL
+ * }
+ * </pre>
+ * @return
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(privKeyInfo);
+ v.AddOptional(identifier);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/EncryptedKey.cs b/crypto/src/asn1/crmf/EncryptedKey.cs
new file mode 100644
index 000000000..850fbd219
--- /dev/null
+++ b/crypto/src/asn1/crmf/EncryptedKey.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class EncryptedKey
+ : Asn1Encodable, IAsn1Choice
+ {
+ private readonly EnvelopedData envelopedData;
+ private readonly EncryptedValue encryptedValue;
+
+ public static EncryptedKey GetInstance(object o)
+ {
+ if (o is EncryptedKey)
+ {
+ return (EncryptedKey)o;
+ }
+ else if (o is Asn1TaggedObject)
+ {
+ return new EncryptedKey(EnvelopedData.GetInstance((Asn1TaggedObject)o, false));
+ }
+ else if (o is EncryptedValue)
+ {
+ return new EncryptedKey((EncryptedValue)o);
+ }
+ else
+ {
+ return new EncryptedKey(EncryptedValue.GetInstance(o));
+ }
+ }
+
+ public EncryptedKey(EnvelopedData envelopedData)
+ {
+ this.envelopedData = envelopedData;
+ }
+
+ public EncryptedKey(EncryptedValue encryptedValue)
+ {
+ this.encryptedValue = encryptedValue;
+ }
+
+ public virtual bool IsEncryptedValue
+ {
+ get { return encryptedValue != null; }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get
+ {
+ if (encryptedValue != null)
+ return encryptedValue;
+
+ return envelopedData;
+ }
+ }
+
+ /**
+ * <pre>
+ * EncryptedKey ::= CHOICE {
+ * encryptedValue EncryptedValue, -- deprecated
+ * envelopedData [0] EnvelopedData }
+ * -- The encrypted private key MUST be placed in the envelopedData
+ * -- encryptedContentInfo encryptedContent OCTET STRING.
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (encryptedValue != null)
+ {
+ return encryptedValue.ToAsn1Object();
+ }
+
+ return new DerTaggedObject(false, 0, envelopedData);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/EncryptedValue.cs b/crypto/src/asn1/crmf/EncryptedValue.cs
new file mode 100644
index 000000000..83122e220
--- /dev/null
+++ b/crypto/src/asn1/crmf/EncryptedValue.cs
@@ -0,0 +1,154 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class EncryptedValue
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier intendedAlg;
+ private readonly AlgorithmIdentifier symmAlg;
+ private readonly DerBitString encSymmKey;
+ private readonly AlgorithmIdentifier keyAlg;
+ private readonly Asn1OctetString valueHint;
+ private readonly DerBitString encValue;
+
+ private EncryptedValue(Asn1Sequence seq)
+ {
+ int index = 0;
+ while (seq[index] is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tObj = (Asn1TaggedObject)seq[index];
+
+ switch (tObj.TagNo)
+ {
+ case 0:
+ intendedAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 1:
+ symmAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 2:
+ encSymmKey = DerBitString.GetInstance(tObj, false);
+ break;
+ case 3:
+ keyAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+ break;
+ case 4:
+ valueHint = Asn1OctetString.GetInstance(tObj, false);
+ break;
+ }
+ ++index;
+ }
+
+ encValue = DerBitString.GetInstance(seq[index]);
+ }
+
+ public static EncryptedValue GetInstance(object obj)
+ {
+ if (obj is EncryptedValue)
+ return (EncryptedValue)obj;
+
+ if (obj != null)
+ return new EncryptedValue(Asn1Sequence.GetInstance(obj));
+
+ return null;
+ }
+
+ public EncryptedValue(
+ AlgorithmIdentifier intendedAlg,
+ AlgorithmIdentifier symmAlg,
+ DerBitString encSymmKey,
+ AlgorithmIdentifier keyAlg,
+ Asn1OctetString valueHint,
+ DerBitString encValue)
+ {
+ if (encValue == null)
+ {
+ throw new ArgumentNullException("encValue");
+ }
+
+ this.intendedAlg = intendedAlg;
+ this.symmAlg = symmAlg;
+ this.encSymmKey = encSymmKey;
+ this.keyAlg = keyAlg;
+ this.valueHint = valueHint;
+ this.encValue = encValue;
+ }
+
+ public virtual AlgorithmIdentifier IntendedAlg
+ {
+ get { return intendedAlg; }
+ }
+
+ public virtual AlgorithmIdentifier SymmAlg
+ {
+ get { return symmAlg; }
+ }
+
+ public virtual DerBitString EncSymmKey
+ {
+ get { return encSymmKey; }
+ }
+
+ public virtual AlgorithmIdentifier KeyAlg
+ {
+ get { return keyAlg; }
+ }
+
+ public virtual Asn1OctetString ValueHint
+ {
+ get { return valueHint; }
+ }
+
+ public virtual DerBitString EncValue
+ {
+ get { return encValue; }
+ }
+
+ /**
+ * <pre>
+ * EncryptedValue ::= SEQUENCE {
+ * intendedAlg [0] AlgorithmIdentifier OPTIONAL,
+ * -- the intended algorithm for which the value will be used
+ * symmAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- the symmetric algorithm used to encrypt the value
+ * encSymmKey [2] BIT STRING OPTIONAL,
+ * -- the (encrypted) symmetric key used to encrypt the value
+ * keyAlg [3] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used to encrypt the symmetric key
+ * valueHint [4] OCTET STRING OPTIONAL,
+ * -- a brief description or identifier of the encValue content
+ * -- (may be meaningful only to the sending entity, and used only
+ * -- if EncryptedValue might be re-examined by the sending entity
+ * -- in the future)
+ * encValue BIT STRING }
+ * -- the encrypted value itself
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ AddOptional(v, 0, intendedAlg);
+ AddOptional(v, 1, symmAlg);
+ AddOptional(v, 2, encSymmKey);
+ AddOptional(v, 3, keyAlg);
+ AddOptional(v, 4, valueHint);
+
+ v.Add(encValue);
+
+ return new DerSequence(v);
+ }
+
+ private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.Add(new DerTaggedObject(false, tagNo, obj));
+ }
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/OptionalValidity.cs b/crypto/src/asn1/crmf/OptionalValidity.cs
new file mode 100644
index 000000000..d1a0f7ffb
--- /dev/null
+++ b/crypto/src/asn1/crmf/OptionalValidity.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class OptionalValidity
+ : Asn1Encodable
+ {
+ private readonly Time notBefore;
+ private readonly Time notAfter;
+
+ private OptionalValidity(Asn1Sequence seq)
+ {
+ foreach (Asn1TaggedObject tObj in seq)
+ {
+ if (tObj.TagNo == 0)
+ {
+ notBefore = Time.GetInstance(tObj, true);
+ }
+ else
+ {
+ notAfter = Time.GetInstance(tObj, true);
+ }
+ }
+ }
+
+ public static OptionalValidity GetInstance(object obj)
+ {
+ if (obj == null || obj is OptionalValidity)
+ return (OptionalValidity)obj;
+
+ return new OptionalValidity(Asn1Sequence.GetInstance(obj));
+ }
+
+ public virtual Time NotBefore
+ {
+ get { return notBefore; }
+ }
+
+ public virtual Time NotAfter
+ {
+ get { return notAfter; }
+ }
+
+ /**
+ * <pre>
+ * OptionalValidity ::= SEQUENCE {
+ * notBefore [0] Time OPTIONAL,
+ * notAfter [1] Time OPTIONAL } --at least one MUST be present
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (notBefore != null)
+ {
+ v.Add(new DerTaggedObject(true, 0, notBefore));
+ }
+
+ if (notAfter != null)
+ {
+ v.Add(new DerTaggedObject(true, 1, notAfter));
+ }
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/PKIArchiveOptions.cs b/crypto/src/asn1/crmf/PKIArchiveOptions.cs
new file mode 100644
index 000000000..910f73b22
--- /dev/null
+++ b/crypto/src/asn1/crmf/PKIArchiveOptions.cs
@@ -0,0 +1,105 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PkiArchiveOptions
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int encryptedPrivKey = 0;
+ public const int keyGenParameters = 1;
+ public const int archiveRemGenPrivKey = 2;
+
+ private readonly Asn1Encodable value;
+
+ public static PkiArchiveOptions GetInstance(object obj)
+ {
+ if (obj is PkiArchiveOptions)
+ return (PkiArchiveOptions)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new PkiArchiveOptions((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ private PkiArchiveOptions(Asn1TaggedObject tagged)
+ {
+ switch (tagged.TagNo)
+ {
+ case encryptedPrivKey:
+ value = EncryptedKey.GetInstance(tagged.GetObject());
+ break;
+ case keyGenParameters:
+ value = Asn1OctetString.GetInstance(tagged, false);
+ break;
+ case archiveRemGenPrivKey:
+ value = DerBoolean.GetInstance(tagged, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag number: " + tagged.TagNo, "tagged");
+ }
+ }
+
+ public PkiArchiveOptions(EncryptedKey encKey)
+ {
+ this.value = encKey;
+ }
+
+ public PkiArchiveOptions(Asn1OctetString keyGenParameters)
+ {
+ this.value = keyGenParameters;
+ }
+
+ public PkiArchiveOptions(bool archiveRemGenPrivKey)
+ {
+ this.value = DerBoolean.GetInstance(archiveRemGenPrivKey);
+ }
+
+ public virtual int Type
+ {
+ get
+ {
+ if (value is EncryptedKey)
+ return encryptedPrivKey;
+
+ if (value is Asn1OctetString)
+ return keyGenParameters;
+
+ return archiveRemGenPrivKey;
+ }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get { return value; }
+ }
+
+ /**
+ * <pre>
+ * PkiArchiveOptions ::= CHOICE {
+ * encryptedPrivKey [0] EncryptedKey,
+ * -- the actual value of the private key
+ * keyGenParameters [1] KeyGenParameters,
+ * -- parameters which allow the private key to be re-generated
+ * archiveRemGenPrivKey [2] BOOLEAN }
+ * -- set to TRUE if sender wishes receiver to archive the private
+ * -- key of a key pair that the receiver generates in response to
+ * -- this request; set to FALSE if no archival is desired.
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ if (value is EncryptedKey)
+ {
+ return new DerTaggedObject(true, encryptedPrivKey, value); // choice
+ }
+
+ if (value is Asn1OctetString)
+ {
+ return new DerTaggedObject(false, keyGenParameters, value);
+ }
+
+ return new DerTaggedObject(false, archiveRemGenPrivKey, value);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/PKIPublicationInfo.cs b/crypto/src/asn1/crmf/PKIPublicationInfo.cs
new file mode 100644
index 000000000..c8bc1403e
--- /dev/null
+++ b/crypto/src/asn1/crmf/PKIPublicationInfo.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PkiPublicationInfo
+ : Asn1Encodable
+ {
+ private readonly DerInteger action;
+ private readonly Asn1Sequence pubInfos;
+
+ private PkiPublicationInfo(Asn1Sequence seq)
+ {
+ action = DerInteger.GetInstance(seq[0]);
+ pubInfos = Asn1Sequence.GetInstance(seq[1]);
+ }
+
+ public static PkiPublicationInfo GetInstance(object obj)
+ {
+ if (obj is PkiPublicationInfo)
+ return (PkiPublicationInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new PkiPublicationInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual DerInteger Action
+ {
+ get { return action; }
+ }
+
+ public virtual SinglePubInfo[] GetPubInfos()
+ {
+ if (pubInfos == null)
+ return null;
+
+ SinglePubInfo[] results = new SinglePubInfo[pubInfos.Count];
+ for (int i = 0; i != results.Length; ++i)
+ {
+ results[i] = SinglePubInfo.GetInstance(pubInfos[i]);
+ }
+ return results;
+ }
+
+ /**
+ * <pre>
+ * PkiPublicationInfo ::= SEQUENCE {
+ * action INTEGER {
+ * dontPublish (0),
+ * pleasePublish (1) },
+ * pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+ * -- pubInfos MUST NOT be present if action is "dontPublish"
+ * -- (if action is "pleasePublish" and pubInfos is omitted,
+ * -- "dontCare" is assumed)
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(action, pubInfos);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/PKMacValue.cs b/crypto/src/asn1/crmf/PKMacValue.cs
new file mode 100644
index 000000000..20a08fd1d
--- /dev/null
+++ b/crypto/src/asn1/crmf/PKMacValue.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ /**
+ * Password-based MAC value for use with POPOSigningKeyInput.
+ */
+ public class PKMacValue
+ : Asn1Encodable
+ {
+ private readonly AlgorithmIdentifier algID;
+ private readonly DerBitString macValue;
+
+ private PKMacValue(Asn1Sequence seq)
+ {
+ this.algID = AlgorithmIdentifier.GetInstance(seq[0]);
+ this.macValue = DerBitString.GetInstance(seq[1]);
+ }
+
+ public static PKMacValue GetInstance(object obj)
+ {
+ if (obj is PKMacValue)
+ return (PKMacValue)obj;
+
+ if (obj is Asn1Sequence)
+ return new PKMacValue((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public static PKMacValue GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param params parameters for password-based MAC
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMacValue(
+ PbmParameter pbmParams,
+ DerBitString macValue)
+ : this(new AlgorithmIdentifier(CmpObjectIdentifiers.passwordBasedMac, pbmParams), macValue)
+ {
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMacValue(
+ AlgorithmIdentifier algID,
+ DerBitString macValue)
+ {
+ this.algID = algID;
+ this.macValue = macValue;
+ }
+
+ public virtual AlgorithmIdentifier AlgID
+ {
+ get { return algID; }
+ }
+
+ public virtual DerBitString MacValue
+ {
+ get { return macValue; }
+ }
+
+ /**
+ * <pre>
+ * PKMACValue ::= SEQUENCE {
+ * algId AlgorithmIdentifier,
+ * -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+ * -- parameter value is PBMParameter
+ * value BIT STRING }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerSequence(algID, macValue);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/PopoPrivKey.cs b/crypto/src/asn1/crmf/PopoPrivKey.cs
new file mode 100644
index 000000000..0cedc5127
--- /dev/null
+++ b/crypto/src/asn1/crmf/PopoPrivKey.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PopoPrivKey
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int thisMessage = 0;
+ public const int subsequentMessage = 1;
+ public const int dhMAC = 2;
+ public const int agreeMAC = 3;
+ public const int encryptedKey = 4;
+
+ private readonly int tagNo;
+ private readonly Asn1Encodable obj;
+
+ private PopoPrivKey(Asn1TaggedObject obj)
+ {
+ this.tagNo = obj.TagNo;
+
+ switch (tagNo)
+ {
+ case thisMessage:
+ this.obj = DerBitString.GetInstance(obj, false);
+ break;
+ case subsequentMessage:
+ this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).Value.IntValue);
+ break;
+ case dhMAC:
+ this.obj = DerBitString.GetInstance(obj, false);
+ break;
+ case agreeMAC:
+ this.obj = PKMacValue.GetInstance(obj, false);
+ break;
+ case encryptedKey:
+ this.obj = EnvelopedData.GetInstance(obj, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag in PopoPrivKey", "obj");
+ }
+ }
+
+ public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit)
+ {
+ return new PopoPrivKey(Asn1TaggedObject.GetInstance(tagged.GetObject()));
+ }
+
+ public PopoPrivKey(SubsequentMessage msg)
+ {
+ this.tagNo = subsequentMessage;
+ this.obj = msg;
+ }
+
+ public virtual int Type
+ {
+ get { return tagNo; }
+ }
+
+ public virtual Asn1Encodable Value
+ {
+ get { return obj; }
+ }
+
+ /**
+ * <pre>
+ * PopoPrivKey ::= CHOICE {
+ * thisMessage [0] BIT STRING, -- Deprecated
+ * -- possession is proven in this message (which contains the private
+ * -- key itself (encrypted for the CA))
+ * subsequentMessage [1] SubsequentMessage,
+ * -- possession will be proven in a subsequent message
+ * dhMAC [2] BIT STRING, -- Deprecated
+ * agreeMAC [3] PKMACValue,
+ * encryptedKey [4] EnvelopedData }
+ * </pre>
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, tagNo, obj);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/PopoSigningKey.cs b/crypto/src/asn1/crmf/PopoSigningKey.cs
new file mode 100644
index 000000000..614278eda
--- /dev/null
+++ b/crypto/src/asn1/crmf/PopoSigningKey.cs
@@ -0,0 +1,115 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PopoSigningKey
+ : Asn1Encodable
+ {
+ private readonly PopoSigningKeyInput poposkInput;
+ private readonly AlgorithmIdentifier algorithmIdentifier;
+ private readonly DerBitString signature;
+
+ private PopoSigningKey(Asn1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq[index] is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagObj
+ = (Asn1TaggedObject) seq[index++];
+ if (tagObj.TagNo != 0)
+ {
+ throw new ArgumentException( "Unknown PopoSigningKeyInput tag: " + tagObj.TagNo, "seq");
+ }
+ poposkInput = PopoSigningKeyInput.GetInstance(tagObj.GetObject());
+ }
+ algorithmIdentifier = AlgorithmIdentifier.GetInstance(seq[index++]);
+ signature = DerBitString.GetInstance(seq[index]);
+ }
+
+ public static PopoSigningKey GetInstance(object obj)
+ {
+ if (obj is PopoSigningKey)
+ return (PopoSigningKey)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoSigningKey((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public static PopoSigningKey GetInstance(Asn1TaggedObject obj, bool isExplicit)
+ {
+ return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+ }
+
+ /**
+ * Creates a new Proof of Possession object for a signing key.
+ * @param poposkIn the PopoSigningKeyInput structure, or null if the
+ * CertTemplate includes both subject and publicKey values.
+ * @param aid the AlgorithmIdentifier used to sign the proof of possession.
+ * @param signature a signature over the DER-encoded value of poposkIn,
+ * or the DER-encoded value of certReq if poposkIn is null.
+ */
+ public PopoSigningKey(
+ PopoSigningKeyInput poposkIn,
+ AlgorithmIdentifier aid,
+ DerBitString signature)
+ {
+ this.poposkInput = poposkIn;
+ this.algorithmIdentifier = aid;
+ this.signature = signature;
+ }
+
+ public virtual PopoSigningKeyInput PoposkInput
+ {
+ get { return poposkInput; }
+ }
+
+ public virtual AlgorithmIdentifier AlgorithmIdentifier
+ {
+ get { return algorithmIdentifier; }
+ }
+
+ public virtual DerBitString Signature
+ {
+ get { return signature; }
+ }
+
+ /**
+ * <pre>
+ * PopoSigningKey ::= SEQUENCE {
+ * poposkInput [0] PopoSigningKeyInput OPTIONAL,
+ * algorithmIdentifier AlgorithmIdentifier,
+ * signature BIT STRING }
+ * -- The signature (using "algorithmIdentifier") is on the
+ * -- DER-encoded value of poposkInput. NOTE: If the CertReqMsg
+ * -- certReq CertTemplate contains the subject and publicKey values,
+ * -- then poposkInput MUST be omitted and the signature MUST be
+ * -- computed on the DER-encoded value of CertReqMsg certReq. If
+ * -- the CertReqMsg certReq CertTemplate does not contain the public
+ * -- key and subject values, then poposkInput MUST be present and
+ * -- MUST be signed. This strategy ensures that the public key is
+ * -- not present in both the poposkInput and CertReqMsg certReq
+ * -- CertTemplate fields.
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (poposkInput != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, poposkInput));
+ }
+
+ v.Add(algorithmIdentifier);
+ v.Add(signature);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/PopoSigningKeyInput.cs b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
new file mode 100644
index 000000000..63695262f
--- /dev/null
+++ b/crypto/src/asn1/crmf/PopoSigningKeyInput.cs
@@ -0,0 +1,115 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class PopoSigningKeyInput
+ : Asn1Encodable
+ {
+ private readonly GeneralName sender;
+ private readonly PKMacValue publicKeyMac;
+ private readonly SubjectPublicKeyInfo publicKey;
+
+ private PopoSigningKeyInput(Asn1Sequence seq)
+ {
+ Asn1Encodable authInfo = (Asn1Encodable)seq[0];
+
+ if (authInfo is Asn1TaggedObject)
+ {
+ Asn1TaggedObject tagObj = (Asn1TaggedObject)authInfo;
+ if (tagObj.TagNo != 0)
+ {
+ throw new ArgumentException("Unknown authInfo tag: " + tagObj.TagNo, "seq");
+ }
+ sender = GeneralName.GetInstance(tagObj.GetObject());
+ }
+ else
+ {
+ publicKeyMac = PKMacValue.GetInstance(authInfo);
+ }
+
+ publicKey = SubjectPublicKeyInfo.GetInstance(seq[1]);
+ }
+
+ public static PopoSigningKeyInput GetInstance(object obj)
+ {
+ if (obj is PopoSigningKeyInput)
+ return (PopoSigningKeyInput)obj;
+
+ if (obj is Asn1Sequence)
+ return new PopoSigningKeyInput((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ /** Creates a new PopoSigningKeyInput with sender name as authInfo. */
+ public PopoSigningKeyInput(
+ GeneralName sender,
+ SubjectPublicKeyInfo spki)
+ {
+ this.sender = sender;
+ this.publicKey = spki;
+ }
+
+ /** Creates a new PopoSigningKeyInput using password-based MAC. */
+ public PopoSigningKeyInput(
+ PKMacValue pkmac,
+ SubjectPublicKeyInfo spki)
+ {
+ this.publicKeyMac = pkmac;
+ this.publicKey = spki;
+ }
+
+ /** Returns the sender field, or null if authInfo is publicKeyMac */
+ public virtual GeneralName Sender
+ {
+ get { return sender; }
+ }
+
+ /** Returns the publicKeyMac field, or null if authInfo is sender */
+ public virtual PKMacValue PublicKeyMac
+ {
+ get { return publicKeyMac; }
+ }
+
+ public virtual SubjectPublicKeyInfo PublicKey
+ {
+ get { return publicKey; }
+ }
+
+ /**
+ * <pre>
+ * PopoSigningKeyInput ::= SEQUENCE {
+ * authInfo CHOICE {
+ * sender [0] GeneralName,
+ * -- used only if an authenticated identity has been
+ * -- established for the sender (e.g., a DN from a
+ * -- previously-issued and currently-valid certificate
+ * publicKeyMac PKMacValue },
+ * -- used if no authenticated GeneralName currently exists for
+ * -- the sender; publicKeyMac contains a password-based MAC
+ * -- on the DER-encoded value of publicKey
+ * publicKey SubjectPublicKeyInfo } -- from CertTemplate
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ if (sender != null)
+ {
+ v.Add(new DerTaggedObject(false, 0, sender));
+ }
+ else
+ {
+ v.Add(publicKeyMac);
+ }
+
+ v.Add(publicKey);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/ProofOfPossession.cs b/crypto/src/asn1/crmf/ProofOfPossession.cs
new file mode 100644
index 000000000..fc00edb32
--- /dev/null
+++ b/crypto/src/asn1/crmf/ProofOfPossession.cs
@@ -0,0 +1,98 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class ProofOfPossession
+ : Asn1Encodable, IAsn1Choice
+ {
+ public const int TYPE_RA_VERIFIED = 0;
+ public const int TYPE_SIGNING_KEY = 1;
+ public const int TYPE_KEY_ENCIPHERMENT = 2;
+ public const int TYPE_KEY_AGREEMENT = 3;
+
+ private readonly int tagNo;
+ private readonly Asn1Encodable obj;
+
+ private ProofOfPossession(Asn1TaggedObject tagged)
+ {
+ tagNo = tagged.TagNo;
+ switch (tagNo)
+ {
+ case 0:
+ obj = DerNull.Instance;
+ break;
+ case 1:
+ obj = PopoSigningKey.GetInstance(tagged, false);
+ break;
+ case 2:
+ case 3:
+ obj = PopoPrivKey.GetInstance(tagged, false);
+ break;
+ default:
+ throw new ArgumentException("unknown tag: " + tagNo, "tagged");
+ }
+ }
+
+ public static ProofOfPossession GetInstance(object obj)
+ {
+ if (obj is ProofOfPossession)
+ return (ProofOfPossession)obj;
+
+ if (obj is Asn1TaggedObject)
+ return new ProofOfPossession((Asn1TaggedObject)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ /** Creates a ProofOfPossession with type raVerified. */
+ public ProofOfPossession()
+ {
+ tagNo = TYPE_RA_VERIFIED;
+ obj = DerNull.Instance;
+ }
+
+ /** Creates a ProofOfPossession for a signing key. */
+ public ProofOfPossession(PopoSigningKey Poposk)
+ {
+ tagNo = TYPE_SIGNING_KEY;
+ obj = Poposk;
+ }
+
+ /**
+ * Creates a ProofOfPossession for key encipherment or agreement.
+ * @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
+ */
+ public ProofOfPossession(int type, PopoPrivKey privkey)
+ {
+ tagNo = type;
+ obj = privkey;
+ }
+
+ public virtual int Type
+ {
+ get { return tagNo; }
+ }
+
+ public virtual Asn1Encodable Object
+ {
+ get { return obj; }
+ }
+
+ /**
+ * <pre>
+ * ProofOfPossession ::= CHOICE {
+ * raVerified [0] NULL,
+ * -- used if the RA has already verified that the requester is in
+ * -- possession of the private key
+ * signature [1] PopoSigningKey,
+ * keyEncipherment [2] PopoPrivKey,
+ * keyAgreement [3] PopoPrivKey }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return new DerTaggedObject(false, tagNo, obj);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/SinglePubInfo.cs b/crypto/src/asn1/crmf/SinglePubInfo.cs
new file mode 100644
index 000000000..eaf8a3efd
--- /dev/null
+++ b/crypto/src/asn1/crmf/SinglePubInfo.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class SinglePubInfo
+ : Asn1Encodable
+ {
+ private readonly DerInteger pubMethod;
+ private readonly GeneralName pubLocation;
+
+ private SinglePubInfo(Asn1Sequence seq)
+ {
+ pubMethod = DerInteger.GetInstance(seq[0]);
+
+ if (seq.Count == 2)
+ {
+ pubLocation = GeneralName.GetInstance(seq[1]);
+ }
+ }
+
+ public static SinglePubInfo GetInstance(object obj)
+ {
+ if (obj is SinglePubInfo)
+ return (SinglePubInfo)obj;
+
+ if (obj is Asn1Sequence)
+ return new SinglePubInfo((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+ }
+
+ public virtual GeneralName PubLocation
+ {
+ get { return pubLocation; }
+ }
+
+ /**
+ * <pre>
+ * SinglePubInfo ::= SEQUENCE {
+ * pubMethod INTEGER {
+ * dontCare (0),
+ * x500 (1),
+ * web (2),
+ * ldap (3) },
+ * pubLocation GeneralName OPTIONAL }
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(pubMethod);
+ v.AddOptional(pubLocation);
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/crmf/SubsequentMessage.cs b/crypto/src/asn1/crmf/SubsequentMessage.cs
new file mode 100644
index 000000000..cc1c16492
--- /dev/null
+++ b/crypto/src/asn1/crmf/SubsequentMessage.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+ public class SubsequentMessage
+ : DerInteger
+ {
+ public static readonly SubsequentMessage encrCert = new SubsequentMessage(0);
+ public static readonly SubsequentMessage challengeResp = new SubsequentMessage(1);
+
+ private SubsequentMessage(int value)
+ : base(value)
+ {
+ }
+
+ public static SubsequentMessage ValueOf(int value)
+ {
+ if (value == 0)
+ return encrCert;
+
+ if (value == 1)
+ return challengeResp;
+
+ throw new ArgumentException("unknown value: " + value, "value");
+ }
+ }
+}
|