1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Boris Kuznetsov
20* @version $Revision$
21*/
22package org.apache.harmony.security.pkcs7;
23
24import java.io.IOException;
25import java.math.BigInteger;
26import java.util.List;
27import javax.security.auth.x500.X500Principal;
28import org.apache.harmony.security.asn1.ASN1Implicit;
29import org.apache.harmony.security.asn1.ASN1Integer;
30import org.apache.harmony.security.asn1.ASN1OctetString;
31import org.apache.harmony.security.asn1.ASN1Sequence;
32import org.apache.harmony.security.asn1.ASN1SetOf;
33import org.apache.harmony.security.asn1.ASN1Type;
34import org.apache.harmony.security.asn1.BerInputStream;
35import org.apache.harmony.security.x501.AttributeTypeAndValue;
36import org.apache.harmony.security.x501.Name;
37import org.apache.harmony.security.x509.AlgorithmIdentifier;
38
39
40/**
41 * As defined in PKCS #7: Cryptographic Message Syntax Standard
42 * (http://www.ietf.org/rfc/rfc2315.txt)
43 *
44 * SignerInfo ::= SEQUENCE {
45 *   version Version,
46 *   issuerAndSerialNumber IssuerAndSerialNumber,
47 *   digestAlgorithm DigestAlgorithmIdentifier,
48 *   authenticatedAttributes
49 *     [0] IMPLICIT Attributes OPTIONAL,
50 *   digestEncryptionAlgorithm
51 *     DigestEncryptionAlgorithmIdentifier,
52 *   encryptedDigest EncryptedDigest,
53 *   unauthenticatedAttributes
54 *     [1] IMPLICIT Attributes OPTIONAL
55 *  }
56 */
57public final class SignerInfo {
58    private final int version;
59    private final X500Principal issuer;
60    private final BigInteger serialNumber;
61    private final AlgorithmIdentifier digestAlgorithm;
62    private final AuthenticatedAttributes authenticatedAttributes;
63    private final AlgorithmIdentifier digestEncryptionAlgorithm;
64    private final byte[] encryptedDigest;
65    private final List<?> unauthenticatedAttributes;
66
67    private SignerInfo(int version,
68            Object[] issuerAndSerialNumber,
69            AlgorithmIdentifier digestAlgorithm,
70            AuthenticatedAttributes authenticatedAttributes,
71            AlgorithmIdentifier digestEncryptionAlgorithm,
72            byte[] encryptedDigest,
73            List<?> unauthenticatedAttributes) {
74        this.version = version;
75        this.issuer = ((Name)issuerAndSerialNumber[0]).getX500Principal();
76        this.serialNumber = ASN1Integer.toBigIntegerValue(issuerAndSerialNumber[1]);
77        this.digestAlgorithm = digestAlgorithm;
78        this.authenticatedAttributes = authenticatedAttributes;
79        this.digestEncryptionAlgorithm = digestEncryptionAlgorithm;
80        this.encryptedDigest = encryptedDigest;
81        this.unauthenticatedAttributes = unauthenticatedAttributes;
82    }
83
84    public X500Principal getIssuer() {
85        return issuer;
86    }
87
88    public BigInteger getSerialNumber() {
89        return serialNumber;
90    }
91
92    public String getDigestAlgorithm() {
93        return digestAlgorithm.getAlgorithm();
94    }
95
96    public String getDigestEncryptionAlgorithm() {
97        return digestEncryptionAlgorithm.getAlgorithm();
98    }
99
100    public List<AttributeTypeAndValue> getAuthenticatedAttributes() {
101        if (authenticatedAttributes == null) {
102            return null;
103        }
104        return authenticatedAttributes.getAttributes();
105    }
106
107    public byte[] getEncodedAuthenticatedAttributes() {
108        if (authenticatedAttributes == null) {
109            return null;
110        }
111        return authenticatedAttributes.getEncoded();
112    }
113
114    public byte[] getEncryptedDigest() {
115        return encryptedDigest;
116    }
117
118
119    public String toString() {
120        StringBuilder res = new StringBuilder();
121        res.append("-- SignerInfo:");
122        res.append("\n version : ");
123        res.append(version);
124        res.append("\nissuerAndSerialNumber:  ");
125        res.append(issuer);
126        res.append("   ");
127        res.append(serialNumber);
128        res.append("\ndigestAlgorithm:  ");
129        res.append(digestAlgorithm.toString());
130        res.append("\nauthenticatedAttributes:  ");
131        if (authenticatedAttributes != null) {
132            res.append(authenticatedAttributes.toString());
133        }
134        res.append("\ndigestEncryptionAlgorithm: ");
135        res.append(digestEncryptionAlgorithm.toString());
136        res.append("\nunauthenticatedAttributes: ");
137        if (unauthenticatedAttributes != null) {
138            res.append(unauthenticatedAttributes.toString());
139        }
140        res.append("\n-- SignerInfo End\n");
141        return res.toString();
142    }
143
144
145    public static final ASN1Sequence ISSUER_AND_SERIAL_NUMBER =
146            new ASN1Sequence(new ASN1Type[] {
147                Name.ASN1,                       // issuer
148                ASN1Integer.getInstance(),       // serialNumber
149            })
150        {
151            // method to encode
152            @Override public void getValues(Object object, Object[] values) {
153                Object [] issAndSerial = (Object[])object;
154                values[0] = issAndSerial[0];
155                values[1] = issAndSerial[1];
156        }
157    };
158
159    public static final ASN1Sequence ASN1 =
160        new ASN1Sequence(new ASN1Type[] {
161                ASN1Integer.getInstance(),         //version
162                ISSUER_AND_SERIAL_NUMBER,
163                AlgorithmIdentifier.ASN1,           //digestAlgorithm
164                new ASN1Implicit(0, AuthenticatedAttributes.ASN1),//authenticatedAttributes
165                AlgorithmIdentifier.ASN1,            //digestEncryptionAlgorithm
166                ASN1OctetString.getInstance(),       //encryptedDigest
167                 new ASN1Implicit(1, new ASN1SetOf(
168                         AttributeTypeAndValue.ASN1)),//unauthenticatedAttributes
169                })  {
170        {
171            setOptional(3); // authenticatedAttributes is optional
172            setOptional(6); // unauthenticatedAttributes is optional
173        }
174
175        @Override protected void getValues(Object object, Object[] values) {
176            SignerInfo si = (SignerInfo) object;
177            values[0] = new byte[] {(byte)si.version};
178            try {
179                values[1] = new Object[] { new Name(si.issuer.getName()),
180                        si.serialNumber.toByteArray() };
181            } catch (IOException e) {
182                // The exception is never thrown, because si.issuer
183                // is created using Name.getX500Principal().
184                // Throw a RuntimeException just to be safe.
185                throw new RuntimeException("Failed to encode issuer name", e);
186            }
187            values[2] = si.digestAlgorithm;
188            values[3] = si.authenticatedAttributes;
189            values[4] = si.digestEncryptionAlgorithm;
190            values[5] = si.encryptedDigest;
191            values[6] = si.unauthenticatedAttributes;
192        }
193
194        @Override protected Object getDecodedObject(BerInputStream in) {
195            Object[] values = (Object[]) in.content;
196            return new SignerInfo(
197                        ASN1Integer.toIntValue(values[0]),
198                        (Object[]) values[1],
199                        (AlgorithmIdentifier) values[2],
200                        (AuthenticatedAttributes) values[3],
201                        (AlgorithmIdentifier) values[4],
202                        (byte[]) values[5],
203                        (List) values[6]
204                    );
205        }
206   };
207}
208