package org.bouncycastle.cms;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.BERConstructedOctetString;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.SignedData;
import org.bouncycastle.asn1.cms.SignerIdentifier;
import org.bouncycastle.asn1.cms.SignerInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
/**
* general class for generating a pkcs7-signature message.
* <p>
* A simple example of usage, generating a detached signature.
*
* <pre>
* List certList = new ArrayList();
* CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes());
*
* certList.add(signCert);
*
* Store certs = new JcaCertStore(certList);
*
* CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
* ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(signKP.getPrivate());
*
* gen.addSignerInfoGenerator(
* new JcaSignerInfoGeneratorBuilder(
* new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
* .build(sha1Signer, signCert));
*
* gen.addCertificates(certs);
*
* CMSSignedData sigData = gen.generate(msg, false);
* </pre>
*/
public class CMSSignedDataGenerator
extends CMSSignedGenerator
{
private List signerInfs = new ArrayList();
private class SignerInf
{
final PrivateKey key;
final SignerIdentifier signerIdentifier;
final String digestOID;
final String encOID;
final CMSAttributeTableGenerator sAttr;
final CMSAttributeTableGenerator unsAttr;
final AttributeTable baseSignedTable;
SignerInf(
PrivateKey key,
SignerIdentifier signerIdentifier,
String digestOID,
String encOID,
CMSAttributeTableGenerator sAttr,
CMSAttributeTableGenerator unsAttr,
AttributeTable baseSignedTable)
{
this.key = key;
this.signerIdentifier = signerIdentifier;
this.digestOID = digestOID;
this.encOID = encOID;
this.sAttr = sAttr;
this.unsAttr = unsAttr;
this.baseSignedTable = baseSignedTable;
}
AlgorithmIdentifier getDigestAlgorithmID()
{
return new AlgorithmIdentifier(new DERObjectIdentifier(digestOID), new DERNull());
}
SignerInfo toSignerInfo(
DERObjectIdentifier contentType,
CMSProcessable content,
SecureRandom random,
Provider sigProvider,
boolean addDefaultAttributes)
throws IOException, SignatureException, InvalidKeyException, NoSuchAlgorithmException, CertificateEncodingException, CMSException
{
AlgorithmIdentifier digAlgId = getDigestAlgorithmID();
String digestName = CMSSignedHelper.INSTANCE.getDigestAlgName(digestOID);
String signatureName = digestName + "with" + CMSSignedHelper.INSTANCE.getEncryptionAlgName(encOID);
Signature sig = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, sigProvider);
MessageDigest dig = CMSSignedHelper.INSTANCE.getDigestInstance(digestName, sigProvider);
AlgorithmIdentifier encAlgId = getEncAlgorithmIdentifier(encOID, sig);
if (content != null)
{
content.write(new DigOutputStream(dig));
}
byte[] hash = dig.digest();
digests.put(digestOID, hash.clone());
AttributeTable signed;
if (addDefaultAttributes)
{
Map parameters = getBaseParameters(contentType, digAlgId, hash);
signed = (sAttr != null) ? sAttr.getAttributes(Collections.unmodifiableMap(parameters)) : null;
}
else
{
signed = baseSignedTable;
}
sig.initSign(key, random);
OutputStream sigStr = new BufferedOutputStream(new SigOutputStream(sig));
ASN1Set signedAttr = null;
if (signed != null)
{
if (contentType == null) //counter signature
{
if (signed.get(CMSAttributes.contentType) != null)
{
Hashtable tmpSigned = signed.toHashtable();
tmpSigned.remove(CMSAttributes.contentType);
signed = new AttributeTable(tmpSigned);
}
}
// TODO Validate proposed signed attributes
signedAttr = getAttributeSet(signed);
// sig must be composed from the DER encoding.
new DEROutputStream(sigStr).writeObject(signedAttr);
}
else if (content != null)
{
// TODO Use raw signature of the hash value instead
content.write(sigStr);
}
sigStr.close();
byte[] sigBytes = sig.sign();
ASN1Set unsignedAttr = null;
if (unsAttr != null)
{
Map parameters = getBaseParameters(contentType, digAlgId, hash);
parameters.put(CMSAttributeTableGenerator.SIGNATURE, sigBytes.clone());
AttributeTable unsigned = unsAttr.getAttributes(Collections.unmodifiableMap(parameters));
// TODO Validate proposed unsigned attributes
unsignedAttr = getAttributeSet(unsigned);
}
return new SignerInfo(signerIdentifier, digAlgId,
signedAttr, encAlgId, new DEROctetString(sigBytes), unsignedAttr);
}
}
/**
* base constructor
*/
public CMSSignedDataGenerator()
{
}
/**
* constructor allowing specific source of randomness
* @param rand instance of SecureRandom to use
*/
public CMSSignedDataGenerator(
SecureRandom rand)
{
super(rand);
}
/**
* add a signer - no attributes other than the default ones will be
* provided here.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param digestOID digest algorithm OID
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
X509Certificate cert,
String digestOID)
throws IllegalArgumentException
{
addSigner(key, cert, getEncOID(key, digestOID), digestOID);
}
/**
* add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
* provided here.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param encryptionOID digest encryption algorithm OID
* @param digestOID digest algorithm OID
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
X509Certificate cert,
String encryptionOID,
String digestOID)
throws IllegalArgumentException
{
doAddSigner(key, getSignerIdentifier(cert), encryptionOID, digestOID,
new DefaultSignedAttributeTableGenerator(), null, null);
}
/**
* add a signer - no attributes other than the default ones will be
* provided here.
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
byte[] subjectKeyID,
String digestOID)
throws IllegalArgumentException
{
addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID);
}
/**
* add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
* provided here.
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
byte[] subjectKeyID,
String encryptionOID,
String digestOID)
throws IllegalArgumentException
{
doAddSigner(key, getSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
new DefaultSignedAttributeTableGenerator(), null, null);
}
/**
* add a signer with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
X509Certificate cert,
String digestOID,
AttributeTable signedAttr,
AttributeTable unsignedAttr)
throws IllegalArgumentException
{
addSigner(key, cert, getEncOID(key, digestOID), digestOID, signedAttr, unsignedAttr);
}
/**
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param cert certificate containing corresponding public key
* @param encryptionOID digest encryption algorithm OID
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
X509Certificate cert,
String encryptionOID,
String digestOID,
AttributeTable signedAttr,
AttributeTable unsignedAttr)
throws IllegalArgumentException
{
doAddSigner(key, getSignerIdentifier(cert), encryptionOID, digestOID,
new DefaultSignedAttributeTableGenerator(signedAttr),
new SimpleAttributeTableGenerator(unsignedAttr), signedAttr);
}
/**
* add a signer with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param subjectKeyID subjectKeyID of corresponding public key
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
byte[] subjectKeyID,
String digestOID,
AttributeTable signedAttr,
AttributeTable unsignedAttr)
throws IllegalArgumentException
{
addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID, signedAttr,
unsignedAttr);
}
/**
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
*
* @param key signing key to use
* @param subjectKeyID subjectKeyID of corresponding public key
* @param encryptionOID digest encryption algorithm OID
* @param digestOID digest algorithm OID
* @param signedAttr table of attributes to be included in signature
* @param unsignedAttr table of attributes to be included as unsigned
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
byte[] subjectKeyID,
String encryptionOID,
String digestOID,
AttributeTable signedAttr,
AttributeTable unsignedAttr)
throws IllegalArgumentException
{
doAddSigner(key, getSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
new DefaultSignedAttributeTableGenerator(signedAttr),
new SimpleAttributeTableGenerator(unsignedAttr), signedAttr);
}
/**
* add a signer with extra signed/unsigned attributes based on generators.
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
X509Certificate cert,
String digestOID,
CMSAttributeTableGenerator signedAttrGen,
CMSAttributeTableGenerator unsignedAttrGen)
throws IllegalArgumentException
{
addSigner(key, cert, getEncOID(key, digestOID), digestOID, signedAttrGen, unsignedAttrGen);
}
/**
* add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
X509Certificate cert,
String encryptionOID,
String digestOID,
CMSAttributeTableGenerator signedAttrGen,
CMSAttributeTableGenerator unsignedAttrGen)
throws IllegalArgumentException
{
doAddSigner(key, getSignerIdentifier(cert), encryptionOID, digestOID, signedAttrGen,
unsignedAttrGen, null);
}
/**
* add a signer with extra signed/unsigned attributes based on generators.
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
byte[] subjectKeyID,
String digestOID,
CMSAttributeTableGenerator signedAttrGen,
CMSAttributeTableGenerator unsignedAttrGen)
throws IllegalArgumentException
{
addSigner(key, subjectKeyID, getEncOID(key, digestOID), digestOID, signedAttrGen,
unsignedAttrGen);
}
/**
* add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
* @deprecated use addSignerInfoGenerator
*/
public void addSigner(
PrivateKey key,
byte[] subjectKeyID,
String encryptionOID,
String digestOID,
CMSAttributeTableGenerator signedAttrGen,
CMSAttributeTableGenerator unsignedAttrGen)
throws IllegalArgumentException
{
doAddSigner(key, getSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
signedAttrGen, unsignedAttrGen, null);
}
private void doAddSigner(
PrivateKey key,
SignerIdentifier signerIdentifier,
String encryptionOID,
String digestOID,
CMSAttributeTableGenerator signedAttrGen,
CMSAttributeTableGenerator unsignedAttrGen,
AttributeTable baseSignedTable)
throws IllegalArgumentException
{
signerInfs.add(new SignerInf(key, signerIdentifier, digestOID, encryptionOID,
signedAttrGen, unsignedAttrGen, baseSignedTable));
}
/**
* generate a signed object that for a CMS Signed Data
* object using the given provider.
*/
public CMSSignedData generate(
CMSProcessable content,
String sigProvider)
throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
{
return generate(content, CMSUtils.getProvider(sigProvider));
}
/**
* generate a signed object that for a CMS Signed Data
* object using the given provider.
*/
public CMSSignedData generate(
CMSProcessable content,
Provider sigProvider)
throws NoSuchAlgorithmException, CMSException
{
return generate(content, false, sigProvider);
}
/**
* generate a signed object that for a CMS Signed Data
* object using the given provider - if encapsulate is true a copy
* of the message will be included in the signature. The content type
* is set according to the OID represented by the string signedContentType.
* @deprecated use generate(CMSTypedData, boolean)
*/
public CMSSignedData generate(
String eContentType,
CMSProcessable content,
boolean encapsulate,
String sigProvider)
throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
{
return generate(eContentType, content, encapsulate, CMSUtils.getProvider(sigProvider),
true);
}
/**
* generate a signed object that for a CMS Signed Data
* object using the given provider - if encapsulate is true a copy
* of the message will be included in the signature. The content type
* is set according to the OID represented by the string signedContentType.
* @deprecated use generate(CMSTypedData, boolean)
*/
public CMSSignedData generate(
String eContentType,
CMSProcessable content,
boolean encapsulate,
Provider sigProvider)
throws NoSuchAlgorithmException, CMSException
{
return generate(eContentType, content, encapsulate, sigProvider, true);
}
/**
* Similar method to the other generate methods. The additional argument
* addDefaultAttributes indicates whether or not a default set of signed attributes
* need to be added automatically. If the argument is set to false, no
* attributes will get added at all.
* @deprecated use generate(CMSTypedData, boolean)
*/
public CMSSignedData generate(
String eContentType,
CMSProcessable content,
boolean encapsulate,
String sigProvider,
boolean addDefaultAttributes)
throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
{
return generate(eContentType, content, encapsulate, CMSUtils.getProvider(sigProvider),
addDefaultAttributes);
}
/**
* Similar method to the other generate methods. The additional argument
* addDefaultAttributes indicates whether or not a default set of signed attributes
* need to be added automatically. If the argument is set to false, no
* attributes will get added at all.
*/
public CMSSignedData generate(
String eContentType,
// FIXME Avoid accessing more than once to support CMSProcessableInputStream
CMSProcessable content,
boolean encapsulate,
Provider sigProvider,
boolean addDefaultAttributes)
throws NoSuchAlgorithmException, CMSException
{
// TODO
// if (signerInfs.isEmpty())
// {
// /* RFC 3852 5.2
// * "In the degenerate case where there are no signers, the
// * EncapsulatedContentInfo value being "signed" is irrelevant. In this
// * case, the content type within the EncapsulatedContentInfo value being
// * "signed" MUST be id-data (as defined in section 4), and the content
// * field of the EncapsulatedContentInfo value MUST be omitted."
// */
// if (encapsulate)
// {
// throw new IllegalArgumentException("no signers, encapsulate must be false");
// }
// if (!DATA.equals(eContentType))
// {
// throw new IllegalArgumentException("no signers, eContentType must be id-data");
// }
// }
//
// if (!DATA.equals(eContentType))
// {
// /* RFC 3852 5.3
// * [The 'signedAttrs']...
// * field is optional, but it MUST be present if the content type of
// * the EncapsulatedContentInfo value being signed is not id-data.
// */
// // TODO signedAttrs must be present for all signers
// }
ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
ASN1EncodableVector signerInfos = new ASN1EncodableVector();
digests.clear(); // clear the current preserved digest state
//
// add the precalculated SignerInfo objects.
//
for (Iterator it = _signers.iterator(); it.hasNext();)
{
SignerInformation signer = (SignerInformation)it.next();
digestAlgs.add(CMSSignedHelper.INSTANCE.fixAlgID(signer.getDigestAlgorithmID()));
// TODO Verify the content type and calculated digest match the precalculated SignerInfo
signerInfos.add(signer.toSignerInfo());
}
//
// add the SignerInfo objects
//
boolean isCounterSignature = (eContentType == null);
ASN1ObjectIdentifier contentTypeOID = isCounterSignature
? null
: new ASN1ObjectIdentifier(eContentType);
for (Iterator it = signerGens.iterator(); it.hasNext();)
{
SignerInfoGenerator sGen = (SignerInfoGenerator)it.next();
if (content != null)
{
OutputStream cOut = sGen.getCalculatingOutputStream();
try
{
content.write(cOut);
cOut.close();
}
catch (IOException e)
{
throw new CMSException("data processing exception: " + e.getMessage(), e);
}
}
SignerInfo inf = sGen.generate(contentTypeOID);
digestAlgs.add(inf.getDigestAlgorithm());
signerInfos.add(inf);
}
for (Iterator it = signerInfs.iterator(); it.hasNext();)
{
SignerInf signer = (SignerInf)it.next();
try
{
digestAlgs.add(signer.getDigestAlgorithmID());
signerInfos.add(signer.toSignerInfo(contentTypeOID, content, rand, sigProvider,
addDefaultAttributes));
}
catch (IOException e)
{
throw new CMSException("encoding error.", e);
}
catch (InvalidKeyException e)
{
throw new CMSException("key inappropriate for signature.", e);
}
catch (SignatureException e)
{
throw new CMSException("error creating signature.", e);
}
catch (CertificateEncodingException e)
{
throw new CMSException("error creating sid.", e);
}
}
ASN1Set certificates = null;
if (certs.size() != 0)
{
certificates = CMSUtils.createBerSetFromList(certs);
}
ASN1Set certrevlist = null;
if (crls.size() != 0)
{
certrevlist = CMSUtils.createBerSetFromList(crls);
}
ASN1OctetString octs = null;
if (encapsulate)
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
if (content != null)
{
try
{
content.write(bOut);
}
catch (IOException e)
{
throw new CMSException("encapsulation error.", e);
}
}
octs = new BERConstructedOctetString(bOut.toByteArray());
}
ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
SignedData sd = new SignedData(
new DERSet(digestAlgs),
encInfo,
certificates,
certrevlist,
new DERSet(signerInfos));
ContentInfo contentInfo = new ContentInfo(
CMSObjectIdentifiers.signedData, sd);
return new CMSSignedData(content, contentInfo);
}
/**
* generate a signed object that for a CMS Signed Data
* object using the given provider - if encapsulate is true a copy
* of the message will be included in the signature with the
* default content type "data".
* @deprecated use generate(CMSTypedData, boolean)
*/
public CMSSignedData generate(
CMSProcessable content,
boolean encapsulate,
String sigProvider)
throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
{
if (content instanceof CMSTypedData)
{
return this.generate(((CMSTypedData)content).getContentType().getId(), content, encapsulate, sigProvider);
}
else
{
return this.generate(DATA, content, encapsulate, sigProvider);
}
}
/**
* generate a signed object that for a CMS Signed Data
* object using the given provider - if encapsulate is true a copy
* of the message will be included in the signature with the
* default content type "data".
* @deprecated use generate(CMSTypedData, boolean)
*/
public CMSSignedData generate(
CMSProcessable content,
boolean encapsulate,
Provider sigProvider)
throws NoSuchAlgorithmException, CMSException
{
if (content instanceof CMSTypedData)
{
return this.generate(((CMSTypedData)content).getContentType().getId(), content, encapsulate, sigProvider);
}
else
{
return this.generate(DATA, content, encapsulate, sigProvider);
}
}
public CMSSignedData generate(
CMSTypedData content)
throws CMSException
{
return generate(content, false);
}
public CMSSignedData generate(
CMSTypedData content,
boolean encapsulate)
throws CMSException
{
if (!signerInfs.isEmpty())
{
throw new IllegalStateException("this method can only be used with SignerInfoGenerator");
}
// TODO
// if (signerInfs.isEmpty())
// {
// /* RFC 3852 5.2
// * "In the degenerate case where there are no signers, the
// * EncapsulatedContentInfo value being "signed" is irrelevant. In this
// * case, the content type within the EncapsulatedContentInfo value being
// * "signed" MUST be id-data (as defined in section 4), and the content
// * field of the EncapsulatedContentInfo value MUST be omitted."
// */
// if (encapsulate)
// {
// throw new IllegalArgumentException("no signers, encapsulate must be false");
// }
// if (!DATA.equals(eContentType))
// {
// throw new IllegalArgumentException("no signers, eContentType must be id-data");
// }
// }
//
// if (!DATA.equals(eContentType))
// {
// /* RFC 3852 5.3
// * [The 'signedAttrs']...
// * field is optional, but it MUST be present if the content type of
// * the EncapsulatedContentInfo value being signed is not id-data.
// */
// // TODO signedAttrs must be present for all signers
// }
ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
ASN1EncodableVector signerInfos = new ASN1EncodableVector();
digests.clear(); // clear the current preserved digest state
//
// add the precalculated SignerInfo objects.
//
for (Iterator it = _signers.iterator(); it.hasNext();)
{
SignerInformation signer = (SignerInformation)it.next();
digestAlgs.add(CMSSignedHelper.INSTANCE.fixAlgID(signer.getDigestAlgorithmID()));
// TODO Verify the content type and calculated digest match the precalculated SignerInfo
signerInfos.add(signer.toSignerInfo());
}
//
// add the SignerInfo objects
//
ASN1ObjectIdentifier contentTypeOID = content.getContentType();
ASN1OctetString octs = null;
if (encapsulate)
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
if (content != null)
{
try
{
content.write(bOut);
}
catch (IOException e)
{
throw new CMSException("encapsulation error.", e);
}
}
octs = new BERConstructedOctetString(bOut.toByteArray());
}
if (content != null)
{
ByteArrayOutputStream bOut = null;
if (encapsulate)
{
bOut = new ByteArrayOutputStream();
}
OutputStream cOut = CMSUtils.attachSignersToOutputStream(signerGens, bOut);
// Just in case it's unencapsulated and there are no signers!
cOut = CMSUtils.getSafeOutputStream(cOut);
try
{
content.write(cOut);
cOut.close();
}
catch (IOException e)
{
throw new CMSException("data processing exception: " + e.getMessage(), e);
}
if (encapsulate)
{
octs = new BERConstructedOctetString(bOut.toByteArray());
}
}
for (Iterator it = signerGens.iterator(); it.hasNext();)
{
SignerInfoGenerator sGen = (SignerInfoGenerator)it.next();
SignerInfo inf = sGen.generate(contentTypeOID);
digestAlgs.add(inf.getDigestAlgorithm());
signerInfos.add(inf);
byte[] calcDigest = sGen.getCalculatedDigest();
if (calcDigest != null)
{
digests.put(inf.getDigestAlgorithm().getAlgorithm().getId(), calcDigest);
}
}
ASN1Set certificates = null;
if (certs.size() != 0)
{
certificates = CMSUtils.createBerSetFromList(certs);
}
ASN1Set certrevlist = null;
if (crls.size() != 0)
{
certrevlist = CMSUtils.createBerSetFromList(crls);
}
ContentInfo encInfo = new ContentInfo(contentTypeOID, octs);
SignedData sd = new SignedData(
new DERSet(digestAlgs),
encInfo,
certificates,
certrevlist,
new DERSet(signerInfos));
ContentInfo contentInfo = new ContentInfo(
CMSObjectIdentifiers.signedData, sd);
return new CMSSignedData(content, contentInfo);
}
/**
* generate a set of one or more SignerInformation objects representing counter signatures on
* the passed in SignerInformation object.
*
* @param signer the signer to be countersigned
* @param sigProvider the provider to be used for counter signing.
* @return a store containing the signers.
* @deprecated use generateCounterSigners(SignerInformation)
*/
public SignerInformationStore generateCounterSigners(SignerInformation signer, Provider sigProvider)
throws NoSuchAlgorithmException, CMSException
{
return this.generate(null, new CMSProcessableByteArray(signer.getSignature()), false, sigProvider).getSignerInfos();
}
/**
* generate a set of one or more SignerInformation objects representing counter signatures on
* the passed in SignerInformation object.
*
* @param signer the signer to be countersigned
* @param sigProvider the provider to be used for counter signing.
* @return a store containing the signers.
* @deprecated use generateCounterSigners(SignerInformation)
*/
public SignerInformationStore generateCounterSigners(SignerInformation signer, String sigProvider)
throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
{
return this.generate(null, new CMSProcessableByteArray(signer.getSignature()), false, CMSUtils.getProvider(sigProvider)).getSignerInfos();
}
/**
* generate a set of one or more SignerInformation objects representing counter signatures on
* the passed in SignerInformation object.
*
* @param signer the signer to be countersigned
* @return a store containing the signers.
*/
public SignerInformationStore generateCounterSigners(SignerInformation signer)
throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
{
return this.generate(new CMSProcessableByteArray(null, signer.getSignature()), false).getSignerInfos();
}
}