001package org.apache.commons.ssl.org.bouncycastle.asn1.pkcs;
002
003import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
004import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Set;
009import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
010import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
011import org.apache.commons.ssl.org.bouncycastle.asn1.x500.X500Name;
012import org.apache.commons.ssl.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
013import org.apache.commons.ssl.org.bouncycastle.asn1.x509.X509Name;
014
015/**
016 * PKCS10 CertificationRequestInfo object.
017 * <pre>
018 *  CertificationRequestInfo ::= SEQUENCE {
019 *   version             INTEGER { v1(0) } (v1,...),
020 *   subject             Name,
021 *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
022 *   attributes          [0] Attributes{{ CRIAttributes }}
023 *  }
024 *
025 *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
026 *
027 *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
028 *    type    ATTRIBUTE.&amp;id({IOSet}),
029 *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&amp;Type({IOSet}{\@type})
030 *  }
031 * </pre>
032 */
033public class CertificationRequestInfo
034    extends ASN1Object
035{
036    ASN1Integer              version = new ASN1Integer(0);
037    X500Name                subject;
038    SubjectPublicKeyInfo    subjectPKInfo;
039    ASN1Set                 attributes = null;
040
041    public static CertificationRequestInfo getInstance(
042        Object  obj)
043    {
044        if (obj instanceof CertificationRequestInfo)
045        {
046            return (CertificationRequestInfo)obj;
047        }
048        else if (obj != null)
049        {
050            return new CertificationRequestInfo(ASN1Sequence.getInstance(obj));
051        }
052
053        return null;
054    }
055
056    /**
057     * Basic constructor.
058     * <p>
059     * Note: Early on a lot of CAs would only accept messages with attributes missing. As the ASN.1 def shows
060     * the attributes field is not optional so should always at least contain an empty set. If a fully compliant
061     * request is required, pass in an empty set, the class will otherwise interpret a null as it should
062     * encode the request with the field missing.
063     * </p>
064     *
065     * @param subject subject to be associated with the public key
066     * @param pkInfo public key to be associated with subject
067     * @param attributes any attributes to be associated with the request.
068     */
069    public CertificationRequestInfo(
070        X500Name                subject,
071        SubjectPublicKeyInfo    pkInfo,
072        ASN1Set                 attributes)
073    {
074        if ((subject == null) || (pkInfo == null))
075        {
076            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
077        }
078
079        this.subject = subject;
080        this.subjectPKInfo = pkInfo;
081        this.attributes = attributes;
082    }
083
084    /**
085     * @deprecated use X500Name method.
086     */
087    public CertificationRequestInfo(
088        X509Name                subject,
089        SubjectPublicKeyInfo    pkInfo,
090        ASN1Set                 attributes)
091    {
092        if ((subject == null) || (pkInfo == null))
093        {
094            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
095        }
096        
097        this.subject = X500Name.getInstance(subject.toASN1Primitive());
098        this.subjectPKInfo = pkInfo;
099        this.attributes = attributes;
100    }
101
102    /**
103     * @deprecated use getInstance().
104     */
105    public CertificationRequestInfo(
106        ASN1Sequence  seq)
107    {
108        version = (ASN1Integer)seq.getObjectAt(0);
109
110        subject = X500Name.getInstance(seq.getObjectAt(1));
111        subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2));
112
113        //
114        // some CertificationRequestInfo objects seem to treat this field
115        // as optional.
116        //
117        if (seq.size() > 3)
118        {
119            DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3);
120            attributes = ASN1Set.getInstance(tagobj, false);
121        }
122
123        if ((subject == null) || (version == null) || (subjectPKInfo == null))
124        {
125            throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
126        }
127    }
128
129    public ASN1Integer getVersion()
130    {
131        return version;
132    }
133
134    public X500Name getSubject()
135    {
136        return subject;
137    }
138
139    public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
140    {
141        return subjectPKInfo;
142    }
143
144    public ASN1Set getAttributes()
145    {
146        return attributes;
147    }
148
149    public ASN1Primitive toASN1Primitive()
150    {
151        ASN1EncodableVector  v = new ASN1EncodableVector();
152
153        v.add(version);
154        v.add(subject);
155        v.add(subjectPKInfo);
156
157        if (attributes != null)
158        {
159            v.add(new DERTaggedObject(false, 0, attributes));
160        }
161
162        return new DERSequence(v);
163    }
164}