1 package org.bouncycastle.cms; 2 3 import org.bouncycastle.asn1.DEROctetString; 4 import org.bouncycastle.asn1.cms.IssuerAndSerialNumber; 5 import org.bouncycastle.asn1.cms.SignerIdentifier; 6 import org.bouncycastle.cert.X509CertificateHolder; 7 import org.bouncycastle.operator.ContentSigner; 8 import org.bouncycastle.operator.DigestCalculatorProvider; 9 import org.bouncycastle.operator.OperatorCreationException; 10 11 /** 12 * Builder for SignerInfo generator objects. 13 */ 14 public 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 */ SignerInfoGeneratorBuilder(DigestCalculatorProvider digestProvider)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 */ SignerInfoGeneratorBuilder(DigestCalculatorProvider digestProvider, CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder)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 */ setDirectSignature(boolean hasNoSignedAttributes)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 */ setSignedAttributeGenerator(CMSAttributeTableGenerator signedGen)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 */ setUnsignedAttributeGenerator(CMSAttributeTableGenerator unsignedGen)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 */ build(ContentSigner contentSigner, X509CertificateHolder certHolder)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 */ build(ContentSigner contentSigner, byte[] subjectKeyIdentifier)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 createGenerator(ContentSigner contentSigner, SignerIdentifier sigId)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