diff --git a/Crypto/src/asn1/x509/CertificatePair.cs b/Crypto/src/asn1/x509/CertificatePair.cs
new file mode 100644
index 000000000..8baa64719
--- /dev/null
+++ b/Crypto/src/asn1/x509/CertificatePair.cs
@@ -0,0 +1,160 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+ /**
+ * This class helps to support crossCerfificatePairs in a LDAP directory
+ * according RFC 2587
+ *
+ * <pre>
+ * crossCertificatePairATTRIBUTE::={
+ * WITH SYNTAX CertificatePair
+ * EQUALITY MATCHING RULE certificatePairExactMatch
+ * ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+ * </pre>
+ *
+ * <blockquote> The forward elements of the crossCertificatePair attribute of a
+ * CA's directory entry shall be used to store all, except self-issued
+ * certificates issued to this CA. Optionally, the reverse elements of the
+ * crossCertificatePair attribute, of a CA's directory entry may contain a
+ * subset of certificates issued by this CA to other CAs. When both the forward
+ * and the reverse elements are present in a single attribute value, issuer name
+ * in one certificate shall match the subject name in the other and vice versa,
+ * and the subject public key in one certificate shall be capable of verifying
+ * the digital signature on the other certificate and vice versa.
+ *
+ * When a reverse element is present, the forward element value and the reverse
+ * element value need not be stored in the same attribute value; in other words,
+ * they can be stored in either a single attribute value or two attribute
+ * values. </blockquote>
+ *
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ */
+ public class CertificatePair
+ : Asn1Encodable
+ {
+ private X509CertificateStructure forward, reverse;
+
+ public static CertificatePair GetInstance(
+ object obj)
+ {
+ if (obj == null || obj is CertificatePair)
+ {
+ return (CertificatePair) obj;
+ }
+
+ if (obj is Asn1Sequence)
+ {
+ return new CertificatePair((Asn1Sequence) obj);
+ }
+
+ throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+ }
+
+ /**
+ * Constructor from Asn1Sequence.
+ * <p/>
+ * The sequence is of type CertificatePair:
+ * <p/>
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private CertificatePair(
+ Asn1Sequence seq)
+ {
+ if (seq.Count != 1 && seq.Count != 2)
+ {
+ throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+ }
+
+ foreach (object obj in seq)
+ {
+ Asn1TaggedObject o = Asn1TaggedObject.GetInstance(obj);
+ if (o.TagNo == 0)
+ {
+ forward = X509CertificateStructure.GetInstance(o, true);
+ }
+ else if (o.TagNo == 1)
+ {
+ reverse = X509CertificateStructure.GetInstance(o, true);
+ }
+ else
+ {
+ throw new ArgumentException("Bad tag number: " + o.TagNo);
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param forward Certificates issued to this CA.
+ * @param reverse Certificates issued by this CA to other CAs.
+ */
+ public CertificatePair(
+ X509CertificateStructure forward,
+ X509CertificateStructure reverse)
+ {
+ this.forward = forward;
+ this.reverse = reverse;
+ }
+
+ /**
+ * Produce an object suitable for an Asn1OutputStream.
+ * <p/>
+ * Returns:
+ * <p/>
+ * <pre>
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ * </pre>
+ *
+ * @return a DERObject
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector vec = new Asn1EncodableVector();
+
+ if (forward != null)
+ {
+ vec.Add(new DerTaggedObject(0, forward));
+ }
+
+ if (reverse != null)
+ {
+ vec.Add(new DerTaggedObject(1, reverse));
+ }
+
+ return new DerSequence(vec);
+ }
+
+ /**
+ * @return Returns the forward.
+ */
+ public X509CertificateStructure Forward
+ {
+ get { return forward; }
+ }
+
+ /**
+ * @return Returns the reverse.
+ */
+ public X509CertificateStructure Reverse
+ {
+ get { return reverse; }
+ }
+ }
+}
|