001package org.apache.commons.ssl.org.bouncycastle.asn1.cms;
002
003import java.util.Enumeration;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Set;
012import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
013import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString;
014import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
015import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
016import org.apache.commons.ssl.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
017
018/**
019 * <a href="http://tools.ietf.org/html/rfc5652#section-5.3">RFC 5652</a>:
020 * Signature container per Signer, see {@link SignerIdentifier}.
021 * <pre>
022 * PKCS#7:
023 *
024 * SignerInfo ::= SEQUENCE {
025 *     version                   Version,
026 *     sid                       SignerIdentifier,
027 *     digestAlgorithm           DigestAlgorithmIdentifier,
028 *     authenticatedAttributes   [0] IMPLICIT Attributes OPTIONAL,
029 *     digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
030 *     encryptedDigest           EncryptedDigest,
031 *     unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
032 * }
033 *
034 * EncryptedDigest ::= OCTET STRING
035 *
036 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
037 *
038 * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
039 *
040 * -----------------------------------------
041 *
042 * RFC 5256:
043 *
044 * SignerInfo ::= SEQUENCE {
045 *     version            CMSVersion,
046 *     sid                SignerIdentifier,
047 *     digestAlgorithm    DigestAlgorithmIdentifier,
048 *     signedAttrs        [0] IMPLICIT SignedAttributes OPTIONAL,
049 *     signatureAlgorithm SignatureAlgorithmIdentifier,
050 *     signature          SignatureValue,
051 *     unsignedAttrs      [1] IMPLICIT UnsignedAttributes OPTIONAL
052 * }
053 *
054 * -- {@link SignerIdentifier} referenced certificates are at containing
055 * -- {@link SignedData} certificates element.
056 *
057 * SignerIdentifier ::= CHOICE {
058 *     issuerAndSerialNumber {@link IssuerAndSerialNumber},
059 *     subjectKeyIdentifier  [0] SubjectKeyIdentifier }
060 *
061 * -- See {@link Attributes} for generalized SET OF {@link Attribute}
062 *
063 * SignedAttributes   ::= SET SIZE (1..MAX) OF Attribute
064 * UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute
065 * 
066 * {@link Attribute} ::= SEQUENCE {
067 *     attrType   OBJECT IDENTIFIER,
068 *     attrValues SET OF AttributeValue }
069 *
070 * AttributeValue ::= ANY
071 * 
072 * SignatureValue ::= OCTET STRING
073 * </pre>
074 */
075public class SignerInfo
076    extends ASN1Object
077{
078    private ASN1Integer              version;
079    private SignerIdentifier        sid;
080    private AlgorithmIdentifier     digAlgorithm;
081    private ASN1Set                 authenticatedAttributes;
082    private AlgorithmIdentifier     digEncryptionAlgorithm;
083    private ASN1OctetString         encryptedDigest;
084    private ASN1Set                 unauthenticatedAttributes;
085
086    /**
087     * Return a SignerInfo object from the given input
088     * <p>
089     * Accepted inputs:
090     * <ul>
091     * <li> null &rarr; null
092     * <li> {@link SignerInfo} object
093     * <li> {@link org.bouncycastle.asn1.ASN1Sequence#getInstance(java.lang.Object) ASN1Sequence} input formats with SignerInfo structure inside
094     * </ul>
095     *
096     * @param o the object we want converted.
097     * @exception IllegalArgumentException if the object cannot be converted.
098     */
099    public static SignerInfo getInstance(
100        Object  o)
101        throws IllegalArgumentException
102    {
103        if (o instanceof SignerInfo)
104        {
105            return (SignerInfo)o;
106        }
107        else if (o != null)
108        {
109            return new SignerInfo(ASN1Sequence.getInstance(o));
110        }
111
112        return null;
113    }
114
115    /**
116     *
117     * @param sid
118     * @param digAlgorithm            CMS knows as 'digestAlgorithm'
119     * @param authenticatedAttributes CMS knows as 'signedAttrs'
120     * @param digEncryptionAlgorithm  CMS knows as 'signatureAlgorithm'
121     * @param encryptedDigest         CMS knows as 'signature'
122     * @param unauthenticatedAttributes CMS knows as 'unsignedAttrs'
123     */
124    public SignerInfo(
125        SignerIdentifier        sid,
126        AlgorithmIdentifier     digAlgorithm,
127        ASN1Set                 authenticatedAttributes,
128        AlgorithmIdentifier     digEncryptionAlgorithm,
129        ASN1OctetString         encryptedDigest,
130        ASN1Set                 unauthenticatedAttributes)
131    {
132        if (sid.isTagged())
133        {
134            this.version = new ASN1Integer(3);
135        }
136        else
137        {
138            this.version = new ASN1Integer(1);
139        }
140
141        this.sid = sid;
142        this.digAlgorithm = digAlgorithm;
143        this.authenticatedAttributes = authenticatedAttributes;
144        this.digEncryptionAlgorithm = digEncryptionAlgorithm;
145        this.encryptedDigest = encryptedDigest;
146        this.unauthenticatedAttributes = unauthenticatedAttributes;
147    }
148
149    /**
150     *
151     * @param sid
152     * @param digAlgorithm            CMS knows as 'digestAlgorithm'
153     * @param authenticatedAttributes CMS knows as 'signedAttrs'
154     * @param digEncryptionAlgorithm  CMS knows as 'signatureAlgorithm'
155     * @param encryptedDigest         CMS knows as 'signature'
156     * @param unauthenticatedAttributes CMS knows as 'unsignedAttrs'
157     */
158    public SignerInfo(
159        SignerIdentifier        sid,
160        AlgorithmIdentifier     digAlgorithm,
161        Attributes              authenticatedAttributes,
162        AlgorithmIdentifier     digEncryptionAlgorithm,
163        ASN1OctetString         encryptedDigest,
164        Attributes              unauthenticatedAttributes)
165    {
166        if (sid.isTagged())
167        {
168            this.version = new ASN1Integer(3);
169        }
170        else
171        {
172            this.version = new ASN1Integer(1);
173        }
174
175        this.sid = sid;
176        this.digAlgorithm = digAlgorithm;
177        this.authenticatedAttributes = ASN1Set.getInstance(authenticatedAttributes);
178        this.digEncryptionAlgorithm = digEncryptionAlgorithm;
179        this.encryptedDigest = encryptedDigest;
180        this.unauthenticatedAttributes = ASN1Set.getInstance(unauthenticatedAttributes);
181    }
182
183    /**
184     * @deprecated use getInstance() method.
185     */
186    public SignerInfo(
187        ASN1Sequence seq)
188    {
189        Enumeration     e = seq.getObjects();
190
191        version = (ASN1Integer)e.nextElement();
192        sid = SignerIdentifier.getInstance(e.nextElement());
193        digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
194
195        Object obj = e.nextElement();
196
197        if (obj instanceof ASN1TaggedObject)
198        {
199            authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
200
201            digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
202        }
203        else
204        {
205            authenticatedAttributes = null;
206            digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
207        }
208
209        encryptedDigest = DEROctetString.getInstance(e.nextElement());
210
211        if (e.hasMoreElements())
212        {
213            unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
214        }
215        else
216        {
217            unauthenticatedAttributes = null;
218        }
219    }
220
221    public ASN1Integer getVersion()
222    {
223        return version;
224    }
225
226    public SignerIdentifier getSID()
227    {
228        return sid;
229    }
230
231    public ASN1Set getAuthenticatedAttributes()
232    {
233        return authenticatedAttributes;
234    }
235
236    public AlgorithmIdentifier getDigestAlgorithm()
237    {
238        return digAlgorithm;
239    }
240
241    public ASN1OctetString getEncryptedDigest()
242    {
243        return encryptedDigest;
244    }
245
246    public AlgorithmIdentifier getDigestEncryptionAlgorithm()
247    {
248        return digEncryptionAlgorithm;
249    }
250
251    public ASN1Set getUnauthenticatedAttributes()
252    {
253        return unauthenticatedAttributes;
254    }
255
256    /**
257     * Produce an object suitable for an ASN1OutputStream.
258     */
259    public ASN1Primitive toASN1Primitive()
260    {
261        ASN1EncodableVector v = new ASN1EncodableVector();
262
263        v.add(version);
264        v.add(sid);
265        v.add(digAlgorithm);
266
267        if (authenticatedAttributes != null)
268        {
269            v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
270        }
271
272        v.add(digEncryptionAlgorithm);
273        v.add(encryptedDigest);
274
275        if (unauthenticatedAttributes != null)
276        {
277            v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
278        }
279
280        return new DERSequence(v);
281    }
282}