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 getDigestAlgorithmName() { 97 return digestAlgorithm.getAlgorithmName(); 98 } 99 100 public String getDigestEncryptionAlgorithm() { 101 return digestEncryptionAlgorithm.getAlgorithm(); 102 } 103 104 public String getDigestEncryptionAlgorithmName() { 105 return digestEncryptionAlgorithm.getAlgorithmName(); 106 } 107 108 public List<AttributeTypeAndValue> getAuthenticatedAttributes() { 109 if (authenticatedAttributes == null) { 110 return null; 111 } 112 return authenticatedAttributes.getAttributes(); 113 } 114 115 /** 116 * Returns the non-IMPLICIT ASN.1 encoding of the "authAttrs" from this 117 * SignerInfo. That is, it will return as the encoding of a generic ASN.1 118 * SET. 119 */ 120 public byte[] getEncodedAuthenticatedAttributes() { 121 if (authenticatedAttributes == null) { 122 return null; 123 } 124 return AuthenticatedAttributes.ASN1.encode(authenticatedAttributes.getAttributes()); 125 } 126 127 public byte[] getEncryptedDigest() { 128 return encryptedDigest; 129 } 130 131 132 public String toString() { 133 StringBuilder res = new StringBuilder(); 134 res.append("-- SignerInfo:"); 135 res.append("\n version : "); 136 res.append(version); 137 res.append("\nissuerAndSerialNumber: "); 138 res.append(issuer); 139 res.append(" "); 140 res.append(serialNumber); 141 res.append("\ndigestAlgorithm: "); 142 res.append(digestAlgorithm.toString()); 143 res.append("\nauthenticatedAttributes: "); 144 if (authenticatedAttributes != null) { 145 res.append(authenticatedAttributes.toString()); 146 } 147 res.append("\ndigestEncryptionAlgorithm: "); 148 res.append(digestEncryptionAlgorithm.toString()); 149 res.append("\nunauthenticatedAttributes: "); 150 if (unauthenticatedAttributes != null) { 151 res.append(unauthenticatedAttributes.toString()); 152 } 153 res.append("\n-- SignerInfo End\n"); 154 return res.toString(); 155 } 156 157 158 public static final ASN1Sequence ISSUER_AND_SERIAL_NUMBER = 159 new ASN1Sequence(new ASN1Type[] { 160 Name.ASN1, // issuer 161 ASN1Integer.getInstance(), // serialNumber 162 }) 163 { 164 // method to encode 165 @Override public void getValues(Object object, Object[] values) { 166 Object [] issAndSerial = (Object[])object; 167 values[0] = issAndSerial[0]; 168 values[1] = issAndSerial[1]; 169 } 170 }; 171 172 public static final ASN1Sequence ASN1 = 173 new ASN1Sequence(new ASN1Type[] { 174 ASN1Integer.getInstance(), //version 175 ISSUER_AND_SERIAL_NUMBER, 176 AlgorithmIdentifier.ASN1, //digestAlgorithm 177 new ASN1Implicit(0, AuthenticatedAttributes.ASN1),//authenticatedAttributes 178 AlgorithmIdentifier.ASN1, //digestEncryptionAlgorithm 179 ASN1OctetString.getInstance(), //encryptedDigest 180 new ASN1Implicit(1, new ASN1SetOf( 181 AttributeTypeAndValue.ASN1)),//unauthenticatedAttributes 182 }) { 183 { 184 setOptional(3); // authenticatedAttributes is optional 185 setOptional(6); // unauthenticatedAttributes is optional 186 } 187 188 @Override protected void getValues(Object object, Object[] values) { 189 SignerInfo si = (SignerInfo) object; 190 values[0] = new byte[] {(byte)si.version}; 191 try { 192 values[1] = new Object[] { new Name(si.issuer.getName()), 193 si.serialNumber.toByteArray() }; 194 } catch (IOException e) { 195 // The exception is never thrown, because si.issuer 196 // is created using Name.getX500Principal(). 197 // Throw a RuntimeException just to be safe. 198 throw new RuntimeException("Failed to encode issuer name", e); 199 } 200 values[2] = si.digestAlgorithm; 201 values[3] = si.authenticatedAttributes; 202 values[4] = si.digestEncryptionAlgorithm; 203 values[5] = si.encryptedDigest; 204 values[6] = si.unauthenticatedAttributes; 205 } 206 207 @Override protected Object getDecodedObject(BerInputStream in) { 208 Object[] values = (Object[]) in.content; 209 return new SignerInfo( 210 ASN1Integer.toIntValue(values[0]), 211 (Object[]) values[1], 212 (AlgorithmIdentifier) values[2], 213 (AuthenticatedAttributes) values[3], 214 (AlgorithmIdentifier) values[4], 215 (byte[]) values[5], 216 (List) values[6] 217 ); 218 } 219 }; 220 } 221