Home | History | Annotate | Download | only in cms
      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      */
     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