001: package org.bouncycastle.asn1.x509;
002:
003: import org.bouncycastle.asn1.ASN1Encodable;
004: import org.bouncycastle.asn1.ASN1EncodableVector;
005: import org.bouncycastle.asn1.ASN1Sequence;
006: import org.bouncycastle.asn1.ASN1TaggedObject;
007: import org.bouncycastle.asn1.DERObject;
008: import org.bouncycastle.asn1.DERSequence;
009: import org.bouncycastle.asn1.DERTaggedObject;
010:
011: import java.util.Enumeration;
012:
013: /**
014: * This class helps to support crossCerfificatePairs in a LDAP directory
015: * according RFC 2587
016: *
017: * <pre>
018: * crossCertificatePairATTRIBUTE::={
019: * WITH SYNTAX CertificatePair
020: * EQUALITY MATCHING RULE certificatePairExactMatch
021: * ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
022: * </pre>
023: *
024: * <blockquote> The forward elements of the crossCertificatePair attribute of a
025: * CA's directory entry shall be used to store all, except self-issued
026: * certificates issued to this CA. Optionally, the reverse elements of the
027: * crossCertificatePair attribute, of a CA's directory entry may contain a
028: * subset of certificates issued by this CA to other CAs. When both the forward
029: * and the reverse elements are present in a single attribute value, issuer name
030: * in one certificate shall match the subject name in the other and vice versa,
031: * and the subject public key in one certificate shall be capable of verifying
032: * the digital signature on the other certificate and vice versa.
033: *
034: * When a reverse element is present, the forward element value and the reverse
035: * element value need not be stored in the same attribute value; in other words,
036: * they can be stored in either a single attribute value or two attribute
037: * values. </blockquote>
038: *
039: * <pre>
040: * CertificatePair ::= SEQUENCE {
041: * forward [0] Certificate OPTIONAL,
042: * reverse [1] Certificate OPTIONAL,
043: * -- at least one of the pair shall be present -- }
044: * </pre>
045: */
046: public class CertificatePair extends ASN1Encodable {
047: private X509CertificateStructure forward;
048:
049: private X509CertificateStructure reverse;
050:
051: public static CertificatePair getInstance(Object obj) {
052: if (obj == null || obj instanceof CertificatePair) {
053: return (CertificatePair) obj;
054: }
055:
056: if (obj instanceof ASN1Sequence) {
057: return new CertificatePair((ASN1Sequence) obj);
058: }
059:
060: throw new IllegalArgumentException(
061: "illegal object in getInstance: "
062: + obj.getClass().getName());
063: }
064:
065: /**
066: * Constructor from ASN1Sequence.
067: * <p/>
068: * The sequence is of type CertificatePair:
069: * <p/>
070: * <pre>
071: * CertificatePair ::= SEQUENCE {
072: * forward [0] Certificate OPTIONAL,
073: * reverse [1] Certificate OPTIONAL,
074: * -- at least one of the pair shall be present -- }
075: * </pre>
076: *
077: * @param seq The ASN.1 sequence.
078: */
079: private CertificatePair(ASN1Sequence seq) {
080: if (seq.size() != 1 && seq.size() != 2) {
081: throw new IllegalArgumentException("Bad sequence size: "
082: + seq.size());
083: }
084:
085: Enumeration e = seq.getObjects();
086:
087: while (e.hasMoreElements()) {
088: ASN1TaggedObject o = ASN1TaggedObject.getInstance(e
089: .nextElement());
090: if (o.getTagNo() == 0) {
091: forward = X509CertificateStructure.getInstance(o, true);
092: } else if (o.getTagNo() == 1) {
093: reverse = X509CertificateStructure.getInstance(o, true);
094: } else {
095: throw new IllegalArgumentException("Bad tag number: "
096: + o.getTagNo());
097: }
098: }
099: }
100:
101: /**
102: * Constructor from a given details.
103: *
104: * @param forward Certificates issued to this CA.
105: * @param reverse Certificates issued by this CA to other CAs.
106: */
107: public CertificatePair(X509CertificateStructure forward,
108: X509CertificateStructure reverse) {
109: this .forward = forward;
110: this .reverse = reverse;
111: }
112:
113: /**
114: * Produce an object suitable for an ASN1OutputStream.
115: * <p/>
116: * Returns:
117: * <p/>
118: * <pre>
119: * CertificatePair ::= SEQUENCE {
120: * forward [0] Certificate OPTIONAL,
121: * reverse [1] Certificate OPTIONAL,
122: * -- at least one of the pair shall be present -- }
123: * </pre>
124: *
125: * @return a DERObject
126: */
127: public DERObject toASN1Object() {
128: ASN1EncodableVector vec = new ASN1EncodableVector();
129:
130: if (forward != null) {
131: vec.add(new DERTaggedObject(0, forward));
132: }
133: if (reverse != null) {
134: vec.add(new DERTaggedObject(1, reverse));
135: }
136:
137: return new DERSequence(vec);
138: }
139:
140: /**
141: * @return Returns the forward.
142: */
143: public X509CertificateStructure getForward() {
144: return forward;
145: }
146:
147: /**
148: * @return Returns the reverse.
149: */
150: public X509CertificateStructure getReverse() {
151: return reverse;
152: }
153: }
|