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