1package org.bouncycastle.cms;
2
3import java.io.ByteArrayOutputStream;
4import java.io.IOException;
5import java.io.OutputStream;
6import java.security.NoSuchAlgorithmException;
7import java.security.NoSuchProviderException;
8import java.security.PrivateKey;
9import java.security.Provider;
10import java.security.SecureRandom;
11import java.security.cert.CertificateEncodingException;
12import java.security.cert.X509Certificate;
13import java.util.ArrayList;
14import java.util.Iterator;
15import java.util.List;
16
17import org.bouncycastle.asn1.ASN1EncodableVector;
18import org.bouncycastle.asn1.ASN1ObjectIdentifier;
19import org.bouncycastle.asn1.ASN1OctetString;
20import org.bouncycastle.asn1.ASN1Set;
21import org.bouncycastle.asn1.BEROctetString;
22import org.bouncycastle.asn1.DERSet;
23import org.bouncycastle.asn1.cms.AttributeTable;
24import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
25import org.bouncycastle.asn1.cms.ContentInfo;
26import org.bouncycastle.asn1.cms.SignedData;
27import org.bouncycastle.asn1.cms.SignerInfo;
28import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
29import org.bouncycastle.operator.ContentSigner;
30import org.bouncycastle.operator.OperatorCreationException;
31import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
32import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
33
34/**
35 * general class for generating a pkcs7-signature message.
36 * <p>
37 * A simple example of usage, generating a detached signature.
38 *
39 * <pre>
40 *      List             certList = new ArrayList();
41 *      CMSTypedData     msg = new CMSProcessableByteArray("Hello world!".getBytes());
42 *
43 *      certList.add(signCert);
44 *
45 *      Store           certs = new JcaCertStore(certList);
46 *
47 *      CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
48 *      ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(signKP.getPrivate());
49 *
50 *      gen.addSignerInfoGenerator(
51 *                new JcaSignerInfoGeneratorBuilder(
52 *                     new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
53 *                     .build(sha1Signer, signCert));
54 *
55 *      gen.addCertificates(certs);
56 *
57 *      CMSSignedData sigData = gen.generate(msg, false);
58 * </pre>
59 */
60public class CMSSignedDataGenerator
61    extends CMSSignedGenerator
62{
63    private List signerInfs = new ArrayList();
64
65    private class SignerInf
66    {
67        final PrivateKey                  key;
68        final Object                      signerIdentifier;
69        final String                      digestOID;
70        final String                      encOID;
71        final CMSAttributeTableGenerator  sAttr;
72        final CMSAttributeTableGenerator  unsAttr;
73        final AttributeTable              baseSignedTable;
74
75        SignerInf(
76            PrivateKey                 key,
77            Object                     signerIdentifier,
78            String                     digestOID,
79            String                     encOID,
80            CMSAttributeTableGenerator sAttr,
81            CMSAttributeTableGenerator unsAttr,
82            AttributeTable             baseSignedTable)
83        {
84            this.key = key;
85            this.signerIdentifier = signerIdentifier;
86            this.digestOID = digestOID;
87            this.encOID = encOID;
88            this.sAttr = sAttr;
89            this.unsAttr = unsAttr;
90            this.baseSignedTable = baseSignedTable;
91        }
92
93        SignerInfoGenerator toSignerInfoGenerator(
94            SecureRandom        random,
95            Provider sigProvider,
96            boolean             addDefaultAttributes)
97            throws IOException, CertificateEncodingException, CMSException, OperatorCreationException, NoSuchAlgorithmException
98        {
99            String              digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(digestOID);
100            String              signatureName = digestName + "with" + CMSSignedHelper.INSTANCE.getEncryptionAlgName(encOID);
101
102            JcaSignerInfoGeneratorBuilder builder = new JcaSignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
103
104            if (addDefaultAttributes)
105            {
106                builder.setSignedAttributeGenerator(sAttr);
107            }
108            builder.setDirectSignature(!addDefaultAttributes);
109
110            builder.setUnsignedAttributeGenerator(unsAttr);
111
112            JcaContentSignerBuilder signerBuilder;
113
114            try
115            {
116                signerBuilder = new JcaContentSignerBuilder(signatureName).setSecureRandom(random);
117            }
118            catch (IllegalArgumentException e)
119            {
120                throw new NoSuchAlgorithmException(e.getMessage());
121            }
122
123            if (sigProvider != null)
124            {
125                signerBuilder.setProvider(sigProvider);
126            }
127
128            ContentSigner contentSigner = signerBuilder.build(key);
129            if (signerIdentifier instanceof X509Certificate)
130            {
131                return builder.build(contentSigner, (X509Certificate)signerIdentifier);
132            }
133            else
134            {
135                return builder.build(contentSigner, (byte[])signerIdentifier);
136            }
137        }
138    }
139    /**
140     * base constructor
141     */
142    public CMSSignedDataGenerator()
143    {
144    }
145
146    /**
147     * constructor allowing specific source of randomness
148     * @param rand instance of SecureRandom to use
149     * @deprecated  rand ignored in new API, use base constructor.
150     */
151    public CMSSignedDataGenerator(
152        SecureRandom rand)
153    {
154        super(rand);
155    }
156
157    /**
158     * add a signer - no attributes other than the default ones will be
159     * provided here.
160     *
161     * @param key signing key to use
162     * @param cert certificate containing corresponding public key
163     * @param digestOID digest algorithm OID
164     * @deprecated use addSignerInfoGenerator
165     */
166    public void addSigner(
167        PrivateKey      key,
168        X509Certificate cert,
169        String          digestOID)
170        throws IllegalArgumentException
171    {
172        addSigner(key, cert, getEncOID(key, digestOID), digestOID);
173    }
174
175    /**
176     * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
177     * provided here.
178     *
179     * @param key signing key to use
180     * @param cert certificate containing corresponding public key
181     * @param encryptionOID digest encryption algorithm OID
182     * @param digestOID digest algorithm OID
183     * @deprecated use addSignerInfoGenerator
184     */
185    public void addSigner(
186        PrivateKey      key,
187        X509Certificate cert,
188        String          encryptionOID,
189        String          digestOID)
190        throws IllegalArgumentException
191    {
192        doAddSigner(key, cert, encryptionOID, digestOID,
193            new DefaultSignedAttributeTableGenerator(), null, null);
194    }
195
196    /**
197     * add a signer - no attributes other than the default ones will be
198     * provided here.
199     * @deprecated use addSignerInfoGenerator
200     */
201    public void addSigner(
202        PrivateKey      key,
203        byte[]          subjectKeyID,
204        String          digestOID)
205        throws IllegalArgumentException
206    {
207        addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID);
208    }
209
210    /**
211     * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
212     * provided here.
213     * @deprecated use addSignerInfoGenerator
214     */
215    public void addSigner(
216        PrivateKey      key,
217        byte[]          subjectKeyID,
218        String          encryptionOID,
219        String          digestOID)
220        throws IllegalArgumentException
221    {
222        doAddSigner(key, subjectKeyID, encryptionOID, digestOID,
223            new DefaultSignedAttributeTableGenerator(), null, null);
224    }
225
226    /**
227     * add a signer with extra signed/unsigned attributes.
228     *
229     * @param key signing key to use
230     * @param cert certificate containing corresponding public key
231     * @param digestOID digest algorithm OID
232     * @param signedAttr table of attributes to be included in signature
233     * @param unsignedAttr table of attributes to be included as unsigned
234     * @deprecated use addSignerInfoGenerator
235     */
236    public void addSigner(
237        PrivateKey      key,
238        X509Certificate cert,
239        String          digestOID,
240        AttributeTable  signedAttr,
241        AttributeTable  unsignedAttr)
242        throws IllegalArgumentException
243    {
244        addSigner(key, cert, getEncOID(key, digestOID), digestOID, signedAttr, unsignedAttr);
245    }
246
247    /**
248     * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
249     *
250     * @param key signing key to use
251     * @param cert certificate containing corresponding public key
252     * @param encryptionOID digest encryption algorithm OID
253     * @param digestOID digest algorithm OID
254     * @param signedAttr table of attributes to be included in signature
255     * @param unsignedAttr table of attributes to be included as unsigned
256     * @deprecated use addSignerInfoGenerator
257     */
258    public void addSigner(
259        PrivateKey      key,
260        X509Certificate cert,
261        String          encryptionOID,
262        String          digestOID,
263        AttributeTable  signedAttr,
264        AttributeTable  unsignedAttr)
265        throws IllegalArgumentException
266    {
267        doAddSigner(key, cert, encryptionOID, digestOID,
268          new DefaultSignedAttributeTableGenerator(signedAttr),
269          new SimpleAttributeTableGenerator(unsignedAttr), signedAttr);
270    }
271
272    /**
273     * add a signer with extra signed/unsigned attributes.
274     *
275     * @param key signing key to use
276     * @param subjectKeyID subjectKeyID of corresponding public key
277     * @param digestOID digest algorithm OID
278     * @param signedAttr table of attributes to be included in signature
279     * @param unsignedAttr table of attributes to be included as unsigned
280     * @deprecated use addSignerInfoGenerator
281     */
282    public void addSigner(
283        PrivateKey      key,
284        byte[]          subjectKeyID,
285        String          digestOID,
286        AttributeTable  signedAttr,
287        AttributeTable  unsignedAttr)
288        throws IllegalArgumentException
289    {
290        addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID, signedAttr,
291            unsignedAttr);
292    }
293
294    /**
295     * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
296     *
297     * @param key signing key to use
298     * @param subjectKeyID subjectKeyID of corresponding public key
299     * @param encryptionOID digest encryption algorithm OID
300     * @param digestOID digest algorithm OID
301     * @param signedAttr table of attributes to be included in signature
302     * @param unsignedAttr table of attributes to be included as unsigned
303     * @deprecated use addSignerInfoGenerator
304     */
305    public void addSigner(
306        PrivateKey      key,
307        byte[]          subjectKeyID,
308        String          encryptionOID,
309        String          digestOID,
310        AttributeTable  signedAttr,
311        AttributeTable  unsignedAttr)
312        throws IllegalArgumentException
313    {
314        doAddSigner(key, subjectKeyID, encryptionOID, digestOID,
315            new DefaultSignedAttributeTableGenerator(signedAttr),
316            new SimpleAttributeTableGenerator(unsignedAttr), signedAttr);
317    }
318
319    /**
320     * add a signer with extra signed/unsigned attributes based on generators.
321     * @deprecated use addSignerInfoGenerator
322     */
323    public void addSigner(
324        PrivateKey                  key,
325        X509Certificate             cert,
326        String                      digestOID,
327        CMSAttributeTableGenerator  signedAttrGen,
328        CMSAttributeTableGenerator  unsignedAttrGen)
329        throws IllegalArgumentException
330    {
331        addSigner(key, cert, getEncOID(key, digestOID), digestOID, signedAttrGen, unsignedAttrGen);
332    }
333
334    /**
335     * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
336     * @deprecated use addSignerInfoGenerator
337     */
338    public void addSigner(
339        PrivateKey                  key,
340        X509Certificate             cert,
341        String                      encryptionOID,
342        String                      digestOID,
343        CMSAttributeTableGenerator  signedAttrGen,
344        CMSAttributeTableGenerator  unsignedAttrGen)
345        throws IllegalArgumentException
346    {
347        doAddSigner(key, cert, encryptionOID, digestOID, signedAttrGen,
348            unsignedAttrGen, null);
349    }
350
351    /**
352     * add a signer with extra signed/unsigned attributes based on generators.
353     * @deprecated use addSignerInfoGenerator
354     */
355    public void addSigner(
356        PrivateKey                  key,
357        byte[]                      subjectKeyID,
358        String                      digestOID,
359        CMSAttributeTableGenerator  signedAttrGen,
360        CMSAttributeTableGenerator  unsignedAttrGen)
361        throws IllegalArgumentException
362    {
363        addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID, signedAttrGen,
364            unsignedAttrGen);
365    }
366
367    /**
368     * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
369     * @deprecated use addSignerInfoGenerator
370     */
371    public void addSigner(
372        PrivateKey                  key,
373        byte[]                      subjectKeyID,
374        String                      encryptionOID,
375        String                      digestOID,
376        CMSAttributeTableGenerator  signedAttrGen,
377        CMSAttributeTableGenerator  unsignedAttrGen)
378        throws IllegalArgumentException
379    {
380        doAddSigner(key, subjectKeyID, encryptionOID, digestOID,
381            signedAttrGen, unsignedAttrGen, null);
382    }
383
384    private void doAddSigner(
385        PrivateKey                  key,
386        Object                      signerIdentifier,
387        String                      encryptionOID,
388        String                      digestOID,
389        CMSAttributeTableGenerator  signedAttrGen,
390        CMSAttributeTableGenerator  unsignedAttrGen,
391        AttributeTable              baseSignedTable)
392        throws IllegalArgumentException
393    {
394        signerInfs.add(new SignerInf(key, signerIdentifier, digestOID, encryptionOID,
395            signedAttrGen, unsignedAttrGen, baseSignedTable));
396    }
397
398    /**
399     * generate a signed object that for a CMS Signed Data
400     * object using the given provider.
401     * @deprecated use generate() method not taking provider.
402     */
403    public CMSSignedData generate(
404        CMSProcessable content,
405        String         sigProvider)
406        throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
407    {
408        return generate(content, CMSUtils.getProvider(sigProvider));
409    }
410
411    /**
412     * generate a signed object that for a CMS Signed Data
413     * object using the given provider.
414     * @deprecated use generate() method not taking provider.
415     */
416    public CMSSignedData generate(
417        CMSProcessable content,
418        Provider       sigProvider)
419        throws NoSuchAlgorithmException, CMSException
420    {
421        return generate(content, false, sigProvider);
422    }
423
424    /**
425     * generate a signed object that for a CMS Signed Data
426     * object using the given provider - if encapsulate is true a copy
427     * of the message will be included in the signature. The content type
428     * is set according to the OID represented by the string signedContentType.
429     * @deprecated use generate(CMSTypedData, boolean)
430     */
431    public CMSSignedData generate(
432        String          eContentType,
433        CMSProcessable  content,
434        boolean         encapsulate,
435        String          sigProvider)
436        throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
437    {
438        return generate(eContentType, content, encapsulate, CMSUtils.getProvider(sigProvider),
439            true);
440    }
441
442    /**
443     * generate a signed object that for a CMS Signed Data
444     * object using the given provider - if encapsulate is true a copy
445     * of the message will be included in the signature. The content type
446     * is set according to the OID represented by the string signedContentType.
447     * @deprecated use generate(CMSTypedData, boolean)
448     */
449    public CMSSignedData generate(
450        String          eContentType,
451        CMSProcessable  content,
452        boolean         encapsulate,
453        Provider        sigProvider)
454        throws NoSuchAlgorithmException, CMSException
455    {
456        return generate(eContentType, content, encapsulate, sigProvider, true);
457    }
458
459    /**
460     * Similar method to the other generate methods. The additional argument
461     * addDefaultAttributes indicates whether or not a default set of signed attributes
462     * need to be added automatically. If the argument is set to false, no
463     * attributes will get added at all.
464     * @deprecated use generate(CMSTypedData, boolean)
465     */
466    public CMSSignedData generate(
467        String                  eContentType,
468        CMSProcessable          content,
469        boolean                 encapsulate,
470        String                  sigProvider,
471        boolean                 addDefaultAttributes)
472        throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
473    {
474        return generate(eContentType, content, encapsulate, CMSUtils.getProvider(sigProvider),
475            addDefaultAttributes);
476    }
477
478    /**
479     * Similar method to the other generate methods. The additional argument
480     * addDefaultAttributes indicates whether or not a default set of signed attributes
481     * need to be added automatically. If the argument is set to false, no
482     * attributes will get added at all.
483     * @deprecated use setDirectSignature() on SignerInformationGenerator.
484     */
485    public CMSSignedData generate(
486        String                  eContentType,
487        final CMSProcessable    content,
488        boolean                 encapsulate,
489        Provider                sigProvider,
490        boolean                 addDefaultAttributes)
491        throws NoSuchAlgorithmException, CMSException
492    {
493        boolean isCounterSignature = (eContentType == null);
494
495        final ASN1ObjectIdentifier contentTypeOID = isCounterSignature
496            ?   null
497            :   new ASN1ObjectIdentifier(eContentType);
498
499        for (Iterator it = signerInfs.iterator(); it.hasNext();)
500        {
501            SignerInf signer = (SignerInf)it.next();
502
503            try
504            {
505                signerGens.add(signer.toSignerInfoGenerator(rand, sigProvider,
506                    addDefaultAttributes));
507            }
508            catch (OperatorCreationException e)
509            {
510                throw new CMSException("exception creating signerInf", e);
511            }
512            catch (IOException e)
513            {
514                throw new CMSException("exception encoding attributes", e);
515            }
516            catch (CertificateEncodingException e)
517            {
518                throw new CMSException("error creating sid.", e);
519            }
520        }
521
522        signerInfs.clear();
523
524        if (content != null)
525        {
526            return generate(new CMSTypedData()
527            {
528                public ASN1ObjectIdentifier getContentType()
529                {
530                    return contentTypeOID;
531                }
532
533                public void write(OutputStream out)
534                    throws IOException, CMSException
535                {
536                    content.write(out);
537                }
538
539                public Object getContent()
540                {
541                    return content.getContent();
542                }
543            }, encapsulate);
544        }
545        else
546        {
547            return generate(new CMSAbsentContent(contentTypeOID), encapsulate);
548        }
549    }
550
551    /**
552     * generate a signed object that for a CMS Signed Data
553     * object using the given provider - if encapsulate is true a copy
554     * of the message will be included in the signature with the
555     * default content type "data".
556     * @deprecated use generate(CMSTypedData, boolean)
557     */
558    public CMSSignedData generate(
559        CMSProcessable  content,
560        boolean         encapsulate,
561        String          sigProvider)
562        throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
563    {
564        if (content instanceof CMSTypedData)
565        {
566            return this.generate(((CMSTypedData)content).getContentType().getId(), content, encapsulate, sigProvider);
567        }
568        else
569        {
570            return this.generate(DATA, content, encapsulate, sigProvider);
571        }
572    }
573
574    /**
575     * generate a signed object that for a CMS Signed Data
576     * object using the given provider - if encapsulate is true a copy
577     * of the message will be included in the signature with the
578     * default content type "data".
579     * @deprecated use generate(CMSTypedData, boolean)
580     */
581    public CMSSignedData generate(
582        CMSProcessable  content,
583        boolean         encapsulate,
584        Provider        sigProvider)
585        throws NoSuchAlgorithmException, CMSException
586    {
587        if (content instanceof CMSTypedData)
588        {
589            return this.generate(((CMSTypedData)content).getContentType().getId(), content, encapsulate, sigProvider);
590        }
591        else
592        {
593            return this.generate(DATA, content, encapsulate, sigProvider);
594        }
595    }
596
597    public CMSSignedData generate(
598        CMSTypedData content)
599        throws CMSException
600    {
601        return generate(content, false);
602    }
603
604    public CMSSignedData generate(
605        // FIXME Avoid accessing more than once to support CMSProcessableInputStream
606        CMSTypedData content,
607        boolean encapsulate)
608        throws CMSException
609    {
610        if (!signerInfs.isEmpty())
611        {
612            throw new IllegalStateException("this method can only be used with SignerInfoGenerator");
613        }
614
615                // TODO
616//        if (signerInfs.isEmpty())
617//        {
618//            /* RFC 3852 5.2
619//             * "In the degenerate case where there are no signers, the
620//             * EncapsulatedContentInfo value being "signed" is irrelevant.  In this
621//             * case, the content type within the EncapsulatedContentInfo value being
622//             * "signed" MUST be id-data (as defined in section 4), and the content
623//             * field of the EncapsulatedContentInfo value MUST be omitted."
624//             */
625//            if (encapsulate)
626//            {
627//                throw new IllegalArgumentException("no signers, encapsulate must be false");
628//            }
629//            if (!DATA.equals(eContentType))
630//            {
631//                throw new IllegalArgumentException("no signers, eContentType must be id-data");
632//            }
633//        }
634//
635//        if (!DATA.equals(eContentType))
636//        {
637//            /* RFC 3852 5.3
638//             * [The 'signedAttrs']...
639//             * field is optional, but it MUST be present if the content type of
640//             * the EncapsulatedContentInfo value being signed is not id-data.
641//             */
642//            // TODO signedAttrs must be present for all signers
643//        }
644
645        ASN1EncodableVector  digestAlgs = new ASN1EncodableVector();
646        ASN1EncodableVector  signerInfos = new ASN1EncodableVector();
647
648        digests.clear();  // clear the current preserved digest state
649
650        //
651        // add the precalculated SignerInfo objects.
652        //
653        for (Iterator it = _signers.iterator(); it.hasNext();)
654        {
655            SignerInformation signer = (SignerInformation)it.next();
656            digestAlgs.add(CMSSignedHelper.INSTANCE.fixAlgID(signer.getDigestAlgorithmID()));
657
658            // TODO Verify the content type and calculated digest match the precalculated SignerInfo
659            signerInfos.add(signer.toASN1Structure());
660        }
661
662        //
663        // add the SignerInfo objects
664        //
665        ASN1ObjectIdentifier contentTypeOID = content.getContentType();
666
667        ASN1OctetString octs = null;
668
669        if (content != null)
670        {
671            ByteArrayOutputStream bOut = null;
672
673            if (encapsulate)
674            {
675                bOut = new ByteArrayOutputStream();
676            }
677
678            OutputStream cOut = CMSUtils.attachSignersToOutputStream(signerGens, bOut);
679
680            // Just in case it's unencapsulated and there are no signers!
681            cOut = CMSUtils.getSafeOutputStream(cOut);
682
683            try
684            {
685                content.write(cOut);
686
687                cOut.close();
688            }
689            catch (IOException e)
690            {
691                throw new CMSException("data processing exception: " + e.getMessage(), e);
692            }
693
694            if (encapsulate)
695            {
696                octs = new BEROctetString(bOut.toByteArray());
697            }
698        }
699
700        for (Iterator it = signerGens.iterator(); it.hasNext();)
701        {
702            SignerInfoGenerator sGen = (SignerInfoGenerator)it.next();
703            SignerInfo inf = sGen.generate(contentTypeOID);
704
705            digestAlgs.add(inf.getDigestAlgorithm());
706            signerInfos.add(inf);
707
708            byte[] calcDigest = sGen.getCalculatedDigest();
709
710            if (calcDigest != null)
711            {
712                digests.put(inf.getDigestAlgorithm().getAlgorithm().getId(), calcDigest);
713            }
714        }
715
716        ASN1Set certificates = null;
717
718        if (certs.size() != 0)
719        {
720            certificates = CMSUtils.createBerSetFromList(certs);
721        }
722
723        ASN1Set certrevlist = null;
724
725        if (crls.size() != 0)
726        {
727            certrevlist = CMSUtils.createBerSetFromList(crls);
728        }
729
730        ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
731
732        SignedData  sd = new SignedData(
733                                 new DERSet(digestAlgs),
734                                 encInfo,
735                                 certificates,
736                                 certrevlist,
737                                 new DERSet(signerInfos));
738
739        ContentInfo contentInfo = new ContentInfo(
740            CMSObjectIdentifiers.signedData, sd);
741
742        return new CMSSignedData(content, contentInfo);
743    }
744
745    /**
746     * generate a set of one or more SignerInformation objects representing counter signatures on
747     * the passed in SignerInformation object.
748     *
749     * @param signer the signer to be countersigned
750     * @param sigProvider the provider to be used for counter signing.
751     * @return a store containing the signers.
752     * @deprecated use generateCounterSigners(SignerInformation)
753     */
754    public SignerInformationStore generateCounterSigners(SignerInformation signer, Provider sigProvider)
755        throws NoSuchAlgorithmException, CMSException
756    {
757        return this.generate(null, new CMSProcessableByteArray(signer.getSignature()), false, sigProvider).getSignerInfos();
758    }
759
760    /**
761     * generate a set of one or more SignerInformation objects representing counter signatures on
762     * the passed in SignerInformation object.
763     *
764     * @param signer the signer to be countersigned
765     * @param sigProvider the provider to be used for counter signing.
766     * @return a store containing the signers.
767     * @deprecated use generateCounterSigners(SignerInformation)
768     */
769    public SignerInformationStore generateCounterSigners(SignerInformation signer, String sigProvider)
770        throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
771    {
772        return this.generate(null, new CMSProcessableByteArray(signer.getSignature()), false, CMSUtils.getProvider(sigProvider)).getSignerInfos();
773    }
774
775    /**
776     * generate a set of one or more SignerInformation objects representing counter signatures on
777     * the passed in SignerInformation object.
778     *
779     * @param signer the signer to be countersigned
780     * @return a store containing the signers.
781     */
782    public SignerInformationStore generateCounterSigners(SignerInformation signer)
783        throws CMSException
784    {
785        return this.generate(new CMSProcessableByteArray(null, signer.getSignature()), false).getSignerInfos();
786    }
787}
788
789