Home | History | Annotate | Download | only in pkcs7
      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 */
     22 package org.apache.harmony.security.pkcs7;
     23 
     24 import java.io.IOException;
     25 import java.math.BigInteger;
     26 import java.util.List;
     27 import javax.security.auth.x500.X500Principal;
     28 import org.apache.harmony.security.asn1.ASN1Implicit;
     29 import org.apache.harmony.security.asn1.ASN1Integer;
     30 import org.apache.harmony.security.asn1.ASN1OctetString;
     31 import org.apache.harmony.security.asn1.ASN1Sequence;
     32 import org.apache.harmony.security.asn1.ASN1SetOf;
     33 import org.apache.harmony.security.asn1.ASN1Type;
     34 import org.apache.harmony.security.asn1.BerInputStream;
     35 import org.apache.harmony.security.x501.AttributeTypeAndValue;
     36 import org.apache.harmony.security.x501.Name;
     37 import 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  */
     57 public 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