1e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompackage org.bouncycastle.cms;
2e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
3e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.io.ByteArrayOutputStream;
4e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.io.IOException;
5e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.io.OutputStream;
6e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.ArrayList;
7e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.Iterator;
8e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.util.List;
9e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
10e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1EncodableVector;
11e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1ObjectIdentifier;
12e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1OctetString;
13e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1Set;
14e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.BEROctetString;
15e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.DERSet;
16e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
17e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.ContentInfo;
18e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.SignedData;
19e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.SignerInfo;
20e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
21e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom/**
22e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * general class for generating a pkcs7-signature message.
23e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * <p>
24e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * A simple example of usage, generating a detached signature.
25e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *
26e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * <pre>
27e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      List             certList = new ArrayList();
28e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      CMSTypedData     msg = new CMSProcessableByteArray("Hello world!".getBytes());
29e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *
30e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      certList.add(signCert);
31e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *
32e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      Store           certs = new JcaCertStore(certList);
33e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *
34e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
35e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(signKP.getPrivate());
36e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *
37e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      gen.addSignerInfoGenerator(
38e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *                new JcaSignerInfoGeneratorBuilder(
39e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *                     new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
40e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *                     .build(sha1Signer, signCert));
41e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *
42e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      gen.addCertificates(certs);
43e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *
44e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom *      CMSSignedData sigData = gen.generate(msg, false);
45e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * </pre>
46e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */
47e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompublic class CMSSignedDataGenerator
48e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    extends CMSSignedGenerator
49e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom{
50e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private List signerInfs = new ArrayList();
51e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
52e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
53e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * base constructor
54e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
55e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public CMSSignedDataGenerator()
56e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
57e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
58e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
59e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
605db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     * Generate a CMS Signed Data object carrying a detached CMS signature.
61e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
625db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     * @param content the content to be signed.
63e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
64e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public CMSSignedData generate(
65e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        CMSTypedData content)
66e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws CMSException
67e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
68e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return generate(content, false);
69e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
70e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root    /**
725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     * Generate a CMS Signed Data object which can be carrying a detached CMS signature, or have encapsulated data, depending on the value
735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     * of the encapsulated parameter.
745db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     *
755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     * @param content the content to be signed.
765db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     * @param encapsulate true if the content should be encapsulated in the signature, false otherwise.
775db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root     */
78e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public CMSSignedData generate(
79e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // FIXME Avoid accessing more than once to support CMSProcessableInputStream
80e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        CMSTypedData content,
81e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        boolean encapsulate)
82e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws CMSException
83e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
84e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (!signerInfs.isEmpty())
85e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
86e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            throw new IllegalStateException("this method can only be used with SignerInfoGenerator");
87e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
88e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
89e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                // TODO
90e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//        if (signerInfs.isEmpty())
91e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//        {
92e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            /* RFC 3852 5.2
93e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * "In the degenerate case where there are no signers, the
94e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * EncapsulatedContentInfo value being "signed" is irrelevant.  In this
95e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * case, the content type within the EncapsulatedContentInfo value being
96e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * "signed" MUST be id-data (as defined in section 4), and the content
97e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * field of the EncapsulatedContentInfo value MUST be omitted."
98e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             */
99e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            if (encapsulate)
100e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            {
101e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//                throw new IllegalArgumentException("no signers, encapsulate must be false");
102e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            }
103e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            if (!DATA.equals(eContentType))
104e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            {
105e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//                throw new IllegalArgumentException("no signers, eContentType must be id-data");
106e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            }
107e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//        }
108e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//
109e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//        if (!DATA.equals(eContentType))
110e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//        {
111e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            /* RFC 3852 5.3
112e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * [The 'signedAttrs']...
113e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * field is optional, but it MUST be present if the content type of
114e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             * the EncapsulatedContentInfo value being signed is not id-data.
115e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//             */
116e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//            // TODO signedAttrs must be present for all signers
117e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom//        }
118e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
119e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1EncodableVector  digestAlgs = new ASN1EncodableVector();
120e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1EncodableVector  signerInfos = new ASN1EncodableVector();
121e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
122e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        digests.clear();  // clear the current preserved digest state
123e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
124e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        //
125e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // add the precalculated SignerInfo objects.
126e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        //
127e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        for (Iterator it = _signers.iterator(); it.hasNext();)
128e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
129e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            SignerInformation signer = (SignerInformation)it.next();
130e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            digestAlgs.add(CMSSignedHelper.INSTANCE.fixAlgID(signer.getDigestAlgorithmID()));
131e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
132e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            // TODO Verify the content type and calculated digest match the precalculated SignerInfo
133e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            signerInfos.add(signer.toASN1Structure());
134e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
135e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
136e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        //
137e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        // add the SignerInfo objects
138e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        //
139e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1ObjectIdentifier contentTypeOID = content.getContentType();
140e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
141e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1OctetString octs = null;
142e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
143d001700a15b8bd733ae344c1fc315b97c43c6590Kenny Root        if (content.getContent() != null)
144e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
145e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            ByteArrayOutputStream bOut = null;
146e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
147e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (encapsulate)
148e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
149e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                bOut = new ByteArrayOutputStream();
150e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
151e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
152e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            OutputStream cOut = CMSUtils.attachSignersToOutputStream(signerGens, bOut);
153e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
154e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            // Just in case it's unencapsulated and there are no signers!
155e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            cOut = CMSUtils.getSafeOutputStream(cOut);
156e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
157e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            try
158e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
159e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                content.write(cOut);
160e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
161e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                cOut.close();
162e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
163e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            catch (IOException e)
164e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
165e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                throw new CMSException("data processing exception: " + e.getMessage(), e);
166e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
167e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
168e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (encapsulate)
169e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
170e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                octs = new BEROctetString(bOut.toByteArray());
171e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
172e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
173e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
174e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        for (Iterator it = signerGens.iterator(); it.hasNext();)
175e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
176e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            SignerInfoGenerator sGen = (SignerInfoGenerator)it.next();
177e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            SignerInfo inf = sGen.generate(contentTypeOID);
178e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
179e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            digestAlgs.add(inf.getDigestAlgorithm());
180e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            signerInfos.add(inf);
181e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
182e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            byte[] calcDigest = sGen.getCalculatedDigest();
183e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
184e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (calcDigest != null)
185e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
186e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                digests.put(inf.getDigestAlgorithm().getAlgorithm().getId(), calcDigest);
187e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
188e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
189e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
190e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1Set certificates = null;
191e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
192e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (certs.size() != 0)
193e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
194e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            certificates = CMSUtils.createBerSetFromList(certs);
195e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
196e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
197e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ASN1Set certrevlist = null;
198e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
199e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (crls.size() != 0)
200e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
201e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            certrevlist = CMSUtils.createBerSetFromList(crls);
202e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
203e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
204e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
205e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
206e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        SignedData  sd = new SignedData(
207e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                                 new DERSet(digestAlgs),
208e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                                 encInfo,
209e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                                 certificates,
210e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                                 certrevlist,
211e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                                 new DERSet(signerInfos));
212e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
213e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        ContentInfo contentInfo = new ContentInfo(
214e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            CMSObjectIdentifiers.signedData, sd);
215e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
216e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return new CMSSignedData(content, contentInfo);
217e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
218e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
219e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
220e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * generate a set of one or more SignerInformation objects representing counter signatures on
221e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * the passed in SignerInformation object.
222e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
223e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param signer the signer to be countersigned
224e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @return a store containing the signers.
225e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
226e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public SignerInformationStore generateCounterSigners(SignerInformation signer)
227e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        throws CMSException
228e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
229e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return this.generate(new CMSProcessableByteArray(null, signer.getSignature()), false).getSignerInfos();
230e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
231e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom}
232e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
233