1package org.bouncycastle.cms; 2 3import org.bouncycastle.asn1.DEROctetString; 4import org.bouncycastle.asn1.cms.IssuerAndSerialNumber; 5import org.bouncycastle.asn1.cms.SignerIdentifier; 6import org.bouncycastle.cert.X509CertificateHolder; 7import org.bouncycastle.operator.ContentSigner; 8import org.bouncycastle.operator.DigestCalculatorProvider; 9import org.bouncycastle.operator.OperatorCreationException; 10 11/** 12 * Builder for SignerInfo generator objects. 13 */ 14public class SignerInfoGeneratorBuilder 15{ 16 private DigestCalculatorProvider digestProvider; 17 private boolean directSignature; 18 private CMSAttributeTableGenerator signedGen; 19 private CMSAttributeTableGenerator unsignedGen; 20 private CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder; 21 22 /** 23 * Base constructor. 24 * 25 * @param digestProvider a provider of digest calculators for the algorithms required in the signature and attribute calculations. 26 */ 27 public SignerInfoGeneratorBuilder(DigestCalculatorProvider digestProvider) 28 { 29 this(digestProvider, new DefaultCMSSignatureEncryptionAlgorithmFinder()); 30 } 31 32 /** 33 * Base constructor. 34 * 35 * @param digestProvider a provider of digest calculators for the algorithms required in the signature and attribute calculations. 36 */ 37 public SignerInfoGeneratorBuilder(DigestCalculatorProvider digestProvider, CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder) 38 { 39 this.digestProvider = digestProvider; 40 this.sigEncAlgFinder = sigEncAlgFinder; 41 } 42 43 /** 44 * If the passed in flag is true, the signer signature will be based on the data, not 45 * a collection of signed attributes, and no signed attributes will be included. 46 * 47 * @return the builder object 48 */ 49 public SignerInfoGeneratorBuilder setDirectSignature(boolean hasNoSignedAttributes) 50 { 51 this.directSignature = hasNoSignedAttributes; 52 53 return this; 54 } 55 56 /** 57 * Provide a custom signed attribute generator. 58 * 59 * @param signedGen a generator of signed attributes. 60 * @return the builder object 61 */ 62 public SignerInfoGeneratorBuilder setSignedAttributeGenerator(CMSAttributeTableGenerator signedGen) 63 { 64 this.signedGen = signedGen; 65 66 return this; 67 } 68 69 /** 70 * Provide a generator of unsigned attributes. 71 * 72 * @param unsignedGen a generator for signed attributes. 73 * @return the builder object 74 */ 75 public SignerInfoGeneratorBuilder setUnsignedAttributeGenerator(CMSAttributeTableGenerator unsignedGen) 76 { 77 this.unsignedGen = unsignedGen; 78 79 return this; 80 } 81 82 /** 83 * Build a generator with the passed in certHolder issuer and serial number as the signerIdentifier. 84 * 85 * @param contentSigner operator for generating the final signature in the SignerInfo with. 86 * @param certHolder carrier for the X.509 certificate related to the contentSigner. 87 * @return a SignerInfoGenerator 88 * @throws OperatorCreationException if the generator cannot be built. 89 */ 90 public SignerInfoGenerator build(ContentSigner contentSigner, X509CertificateHolder certHolder) 91 throws OperatorCreationException 92 { 93 SignerIdentifier sigId = new SignerIdentifier(new IssuerAndSerialNumber(certHolder.toASN1Structure())); 94 95 SignerInfoGenerator sigInfoGen = createGenerator(contentSigner, sigId); 96 97 sigInfoGen.setAssociatedCertificate(certHolder); 98 99 return sigInfoGen; 100 } 101 102 /** 103 * Build a generator with the passed in subjectKeyIdentifier as the signerIdentifier. If used you should 104 * try to follow the calculation described in RFC 5280 section 4.2.1.2. 105 * 106 * @param contentSigner operator for generating the final signature in the SignerInfo with. 107 * @param subjectKeyIdentifier key identifier to identify the public key for verifying the signature. 108 * @return a SignerInfoGenerator 109 * @throws OperatorCreationException if the generator cannot be built. 110 */ 111 public SignerInfoGenerator build(ContentSigner contentSigner, byte[] subjectKeyIdentifier) 112 throws OperatorCreationException 113 { 114 SignerIdentifier sigId = new SignerIdentifier(new DEROctetString(subjectKeyIdentifier)); 115 116 return createGenerator(contentSigner, sigId); 117 } 118 119 private SignerInfoGenerator createGenerator(ContentSigner contentSigner, SignerIdentifier sigId) 120 throws OperatorCreationException 121 { 122 if (directSignature) 123 { 124 return new SignerInfoGenerator(sigId, contentSigner, digestProvider, sigEncAlgFinder, true); 125 } 126 127 if (signedGen != null || unsignedGen != null) 128 { 129 if (signedGen == null) 130 { 131 signedGen = new DefaultSignedAttributeTableGenerator(); 132 } 133 134 return new SignerInfoGenerator(sigId, contentSigner, digestProvider, sigEncAlgFinder, signedGen, unsignedGen); 135 } 136 137 return new SignerInfoGenerator(sigId, contentSigner, digestProvider, sigEncAlgFinder); 138 } 139} 140