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