1 package org.bouncycastle.cms; 2 3 import java.io.IOException; 4 import java.security.PrivateKey; 5 import java.security.SecureRandom; 6 import java.security.cert.CertStore; 7 import java.security.cert.CertStoreException; 8 import java.security.interfaces.DSAPrivateKey; 9 import java.security.interfaces.RSAPrivateKey; 10 import java.util.ArrayList; 11 import java.util.HashMap; 12 import java.util.HashSet; 13 import java.util.Iterator; 14 import java.util.List; 15 import java.util.Map; 16 import java.util.Set; 17 18 import org.bouncycastle.asn1.ASN1Primitive; 19 import org.bouncycastle.asn1.ASN1Set; 20 import org.bouncycastle.asn1.DERObjectIdentifier; 21 import org.bouncycastle.asn1.DERSet; 22 import org.bouncycastle.asn1.DERTaggedObject; 23 import org.bouncycastle.asn1.cms.AttributeTable; 24 import org.bouncycastle.asn1.cms.CMSObjectIdentifiers; 25 // BEGIN android-removed 26 // import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; 27 // END android-removed 28 import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; 29 import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 30 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 31 import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; 32 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 33 import org.bouncycastle.asn1.x509.AttributeCertificate; 34 import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; 35 // BEGIN android-removed 36 // import org.bouncycastle.jce.interfaces.GOST3410PrivateKey; 37 // END android-removed 38 import org.bouncycastle.util.Store; 39 import org.bouncycastle.x509.X509AttributeCertificate; 40 import org.bouncycastle.x509.X509Store; 41 42 public class CMSSignedGenerator 43 { 44 /** 45 * Default type for the signed data. 46 */ 47 public static final String DATA = CMSObjectIdentifiers.data.getId(); 48 49 public static final String DIGEST_SHA1 = OIWObjectIdentifiers.idSHA1.getId(); 50 // BEGIN android-removed 51 // public static final String DIGEST_SHA224 = NISTObjectIdentifiers.id_sha224.getId(); 52 // END android-removed 53 public static final String DIGEST_SHA256 = NISTObjectIdentifiers.id_sha256.getId(); 54 public static final String DIGEST_SHA384 = NISTObjectIdentifiers.id_sha384.getId(); 55 public static final String DIGEST_SHA512 = NISTObjectIdentifiers.id_sha512.getId(); 56 public static final String DIGEST_MD5 = PKCSObjectIdentifiers.md5.getId(); 57 // BEGIN android-removed 58 // public static final String DIGEST_GOST3411 = CryptoProObjectIdentifiers.gostR3411.getId(); 59 // public static final String DIGEST_RIPEMD128 = TeleTrusTObjectIdentifiers.ripemd128.getId(); 60 // public static final String DIGEST_RIPEMD160 = TeleTrusTObjectIdentifiers.ripemd160.getId(); 61 // public static final String DIGEST_RIPEMD256 = TeleTrusTObjectIdentifiers.ripemd256.getId(); 62 // END android-removed 63 64 public static final String ENCRYPTION_RSA = PKCSObjectIdentifiers.rsaEncryption.getId(); 65 public static final String ENCRYPTION_DSA = X9ObjectIdentifiers.id_dsa_with_sha1.getId(); 66 public static final String ENCRYPTION_ECDSA = X9ObjectIdentifiers.ecdsa_with_SHA1.getId(); 67 public static final String ENCRYPTION_RSA_PSS = PKCSObjectIdentifiers.id_RSASSA_PSS.getId(); 68 // BEGIN android-removed 69 // public static final String ENCRYPTION_GOST3410 = CryptoProObjectIdentifiers.gostR3410_94.getId(); 70 // public static final String ENCRYPTION_ECGOST3410 = CryptoProObjectIdentifiers.gostR3410_2001.getId(); 71 // END android-removed 72 73 private static final String ENCRYPTION_ECDSA_WITH_SHA1 = X9ObjectIdentifiers.ecdsa_with_SHA1.getId(); 74 // BEGIN android-removed 75 // private static final String ENCRYPTION_ECDSA_WITH_SHA224 = X9ObjectIdentifiers.ecdsa_with_SHA224.getId(); 76 // END android-removed 77 private static final String ENCRYPTION_ECDSA_WITH_SHA256 = X9ObjectIdentifiers.ecdsa_with_SHA256.getId(); 78 private static final String ENCRYPTION_ECDSA_WITH_SHA384 = X9ObjectIdentifiers.ecdsa_with_SHA384.getId(); 79 private static final String ENCRYPTION_ECDSA_WITH_SHA512 = X9ObjectIdentifiers.ecdsa_with_SHA512.getId(); 80 81 private static final Set NO_PARAMS = new HashSet(); 82 private static final Map EC_ALGORITHMS = new HashMap(); 83 84 static 85 { 86 NO_PARAMS.add(ENCRYPTION_DSA); 87 NO_PARAMS.add(ENCRYPTION_ECDSA); 88 NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA1); 89 // BEGIN android-removed 90 // NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA224); 91 // END android-removed 92 NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA256); 93 NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA384); 94 NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA512); 95 96 EC_ALGORITHMS.put(DIGEST_SHA1, ENCRYPTION_ECDSA_WITH_SHA1); 97 // BEGIN android-removed 98 // EC_ALGORITHMS.put(DIGEST_SHA224, ENCRYPTION_ECDSA_WITH_SHA224); 99 // END android-removed 100 EC_ALGORITHMS.put(DIGEST_SHA256, ENCRYPTION_ECDSA_WITH_SHA256); 101 EC_ALGORITHMS.put(DIGEST_SHA384, ENCRYPTION_ECDSA_WITH_SHA384); 102 EC_ALGORITHMS.put(DIGEST_SHA512, ENCRYPTION_ECDSA_WITH_SHA512); 103 } 104 105 protected List certs = new ArrayList(); 106 protected List crls = new ArrayList(); 107 protected List _signers = new ArrayList(); 108 protected List signerGens = new ArrayList(); 109 protected Map digests = new HashMap(); 110 111 protected final SecureRandom rand; 112 113 /** 114 * base constructor 115 */ 116 protected CMSSignedGenerator() 117 { 118 this(new SecureRandom()); 119 } 120 121 /** 122 * constructor allowing specific source of randomness 123 * @param rand instance of SecureRandom to use 124 */ 125 protected CMSSignedGenerator( 126 SecureRandom rand) 127 { 128 this.rand = rand; 129 } 130 131 protected String getEncOID( 132 PrivateKey key, 133 String digestOID) 134 { 135 String encOID = null; 136 137 if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm())) 138 { 139 encOID = ENCRYPTION_RSA; 140 } 141 else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm())) 142 { 143 encOID = ENCRYPTION_DSA; 144 if (!digestOID.equals(DIGEST_SHA1)) 145 { 146 throw new IllegalArgumentException("can't mix DSA with anything but SHA1"); 147 } 148 } 149 else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm()) || "EC".equalsIgnoreCase(key.getAlgorithm())) 150 { 151 encOID = (String)EC_ALGORITHMS.get(digestOID); 152 if (encOID == null) 153 { 154 throw new IllegalArgumentException("can't mix ECDSA with anything but SHA family digests"); 155 } 156 } 157 // BEGIN android-removed 158 // else if (key instanceof GOST3410PrivateKey || "GOST3410".equalsIgnoreCase(key.getAlgorithm())) 159 // { 160 // encOID = ENCRYPTION_GOST3410; 161 // } 162 // else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm())) 163 // { 164 // encOID = ENCRYPTION_ECGOST3410; 165 // } 166 // END android-removed 167 168 return encOID; 169 } 170 171 protected Map getBaseParameters(DERObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash) 172 { 173 Map param = new HashMap(); 174 param.put(CMSAttributeTableGenerator.CONTENT_TYPE, contentType); 175 param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId); 176 param.put(CMSAttributeTableGenerator.DIGEST, hash.clone()); 177 return param; 178 } 179 180 protected ASN1Set getAttributeSet( 181 AttributeTable attr) 182 { 183 if (attr != null) 184 { 185 return new DERSet(attr.toASN1EncodableVector()); 186 } 187 188 return null; 189 } 190 191 /** 192 * add the certificates and CRLs contained in the given CertStore 193 * to the pool that will be included in the encoded signature block. 194 * <p> 195 * Note: this assumes the CertStore will support null in the get 196 * methods. 197 * @param certStore CertStore containing the public key certificates and CRLs 198 * @throws java.security.cert.CertStoreException if an issue occurs processing the CertStore 199 * @throws CMSException if an issue occurse transforming data from the CertStore into the message 200 * @deprecated use addCertificates and addCRLs 201 */ 202 public void addCertificatesAndCRLs( 203 CertStore certStore) 204 throws CertStoreException, CMSException 205 { 206 certs.addAll(CMSUtils.getCertificatesFromStore(certStore)); 207 crls.addAll(CMSUtils.getCRLsFromStore(certStore)); 208 } 209 210 public void addCertificates( 211 Store certStore) 212 throws CMSException 213 { 214 certs.addAll(CMSUtils.getCertificatesFromStore(certStore)); 215 } 216 217 public void addCRLs( 218 Store crlStore) 219 throws CMSException 220 { 221 crls.addAll(CMSUtils.getCRLsFromStore(crlStore)); 222 } 223 224 public void addAttributeCertificates( 225 Store attrStore) 226 throws CMSException 227 { 228 certs.addAll(CMSUtils.getAttributeCertificatesFromStore(attrStore)); 229 } 230 231 /** 232 * Add the attribute certificates contained in the passed in store to the 233 * generator. 234 * 235 * @param store a store of Version 2 attribute certificates 236 * @throws CMSException if an error occurse processing the store. 237 * @deprecated use basic Store method 238 */ 239 public void addAttributeCertificates( 240 X509Store store) 241 throws CMSException 242 { 243 try 244 { 245 for (Iterator it = store.getMatches(null).iterator(); it.hasNext();) 246 { 247 X509AttributeCertificate attrCert = (X509AttributeCertificate)it.next(); 248 249 certs.add(new DERTaggedObject(false, 2, 250 AttributeCertificate.getInstance(ASN1Primitive.fromByteArray(attrCert.getEncoded())))); 251 } 252 } 253 catch (IllegalArgumentException e) 254 { 255 throw new CMSException("error processing attribute certs", e); 256 } 257 catch (IOException e) 258 { 259 throw new CMSException("error processing attribute certs", e); 260 } 261 } 262 263 264 /** 265 * Add a store of precalculated signers to the generator. 266 * 267 * @param signerStore store of signers 268 */ 269 public void addSigners( 270 SignerInformationStore signerStore) 271 { 272 Iterator it = signerStore.getSigners().iterator(); 273 274 while (it.hasNext()) 275 { 276 _signers.add(it.next()); 277 } 278 } 279 280 public void addSignerInfoGenerator(SignerInfoGenerator infoGen) 281 { 282 signerGens.add(infoGen); 283 } 284 285 /** 286 * Return a map of oids and byte arrays representing the digests calculated on the content during 287 * the last generate. 288 * 289 * @return a map of oids (as String objects) and byte[] representing digests. 290 */ 291 public Map getGeneratedDigests() 292 { 293 return new HashMap(digests); 294 } 295 } 296