Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pkix/src/main/jdk1.1/org/bouncycastle/cms')
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAbsentContent.java49
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java266
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java392
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedGenerator.java390
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedHelper.java257
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableByteArray.java54
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableFile.java80
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedData.java772
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedDataParser.java1009
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedGenerator.java281
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedHelper.java414
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSTypedStream.java86
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSUtils.java337
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/OriginatorInfoGenerator.java54
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/RecipientId.java31
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/SignerInfoGenerator.java291
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java697
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaSelectorConverter.java54
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaX509CertSelectorConverter.java24
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java166
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java184
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java212
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java92
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java66
-rw-r--r--pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java113
25 files changed, 6371 insertions, 0 deletions
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAbsentContent.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAbsentContent.java
new file mode 100644
index 00000000..d23fc8c0
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAbsentContent.java
@@ -0,0 +1,49 @@
+package org.bouncycastle.cms;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
+
+/**
+ * a class representing null or absent content.
+ */
+public class CMSAbsentContent
+ implements CMSTypedData, CMSReadable
+{
+ private ASN1ObjectIdentifier type;
+
+ public CMSAbsentContent()
+ {
+ this(new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId()));
+ }
+
+ public CMSAbsentContent(
+ ASN1ObjectIdentifier type)
+ {
+ this.type = type;
+ }
+
+ public InputStream getInputStream()
+ {
+ return null;
+ }
+
+ public void write(OutputStream zOut)
+ throws IOException, CMSException
+ {
+ // do nothing
+ }
+
+ public Object getContent()
+ {
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return type;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java
new file mode 100644
index 00000000..54d88b01
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataGenerator.java
@@ -0,0 +1,266 @@
+package org.bouncycastle.cms;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.crypto.KeyGenerator;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.BEROctetString;
+import org.bouncycastle.asn1.BERSet;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.cms.AuthenticatedData;
+import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
+import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.cms.jcajce.JceCMSMacCalculatorBuilder;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.MacCalculator;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.io.TeeOutputStream;
+
+/**
+ * General class for generating a CMS authenticated-data message.
+ *
+ * A simple example of usage.
+ *
+ * <pre>
+ * CMSAuthenticatedDataGenerator fact = new CMSAuthenticatedDataGenerator();
+ *
+ * adGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(recipientCert).setProvider("BC"));
+ *
+ * CMSAuthenticatedData data = fact.generate(new CMSProcessableByteArray(data),
+ * new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build()));
+ * </pre>
+ */
+public class CMSAuthenticatedDataGenerator
+ extends CMSAuthenticatedGenerator
+{
+ /**
+ * base constructor
+ */
+ public CMSAuthenticatedDataGenerator()
+ {
+ }
+
+ /**
+ * Generate an authenticated data object from the passed in typedData and MacCalculator.
+ *
+ * @param typedData the data to have a MAC attached.
+ * @param macCalculator the calculator of the MAC to be attached.
+ * @return the resulting CMSAuthenticatedData object.
+ * @throws CMSException on failure in encoding data or processing recipients.
+ */
+ public CMSAuthenticatedData generate(CMSTypedData typedData, MacCalculator macCalculator)
+ throws CMSException
+ {
+ return generate(typedData, macCalculator, null);
+ }
+
+ /**
+ * Generate an authenticated data object from the passed in typedData and MacCalculator.
+ *
+ * @param typedData the data to have a MAC attached.
+ * @param macCalculator the calculator of the MAC to be attached.
+ * @param digestCalculator calculator for computing digest of the encapsulated data.
+ * @return the resulting CMSAuthenticatedData object.
+ * @throws CMSException on failure in encoding data or processing recipients.
+ */
+ public CMSAuthenticatedData generate(CMSTypedData typedData, MacCalculator macCalculator, final DigestCalculator digestCalculator)
+ throws CMSException
+ {
+ ASN1EncodableVector recipientInfos = new ASN1EncodableVector();
+ ASN1OctetString encContent;
+ ASN1OctetString macResult;
+
+ for (Iterator it = recipientInfoGenerators.iterator(); it.hasNext();)
+ {
+ RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next();
+
+ recipientInfos.add(recipient.generate(macCalculator.getKey()));
+ }
+
+ AuthenticatedData authData;
+
+ if (digestCalculator != null)
+ {
+ try
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ OutputStream out = new TeeOutputStream(digestCalculator.getOutputStream(), bOut);
+
+ typedData.write(out);
+
+ out.close();
+
+ encContent = new BEROctetString(bOut.toByteArray());
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("unable to perform digest calculation: " + e.getMessage(), e);
+ }
+
+ Map parameters = getBaseParameters(typedData.getContentType(), digestCalculator.getAlgorithmIdentifier(), digestCalculator.getDigest());
+
+ if (authGen == null)
+ {
+ authGen = new DefaultAuthenticatedAttributeTableGenerator();
+ }
+ ASN1Set authed = new DERSet(authGen.getAttributes(parameters).toASN1EncodableVector());
+
+ try
+ {
+ OutputStream mOut = macCalculator.getOutputStream();
+
+ mOut.write(authed.getEncoded(ASN1Encoding.DER));
+
+ mOut.close();
+
+ macResult = new DEROctetString(macCalculator.getMac());
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("exception decoding algorithm parameters.", e);
+ }
+ ASN1Set unauthed = (unauthGen != null) ? new BERSet(unauthGen.getAttributes(parameters).toASN1EncodableVector()) : null;
+
+ ContentInfo eci = new ContentInfo(
+ CMSObjectIdentifiers.data,
+ encContent);
+
+ authData = new AuthenticatedData(originatorInfo, new DERSet(recipientInfos), macCalculator.getAlgorithmIdentifier(), digestCalculator.getAlgorithmIdentifier(), eci, authed, macResult, unauthed);
+ }
+ else
+ {
+ try
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ OutputStream mOut = new TeeOutputStream(bOut, macCalculator.getOutputStream());
+
+ typedData.write(mOut);
+
+ mOut.close();
+
+ encContent = new BEROctetString(bOut.toByteArray());
+
+ macResult = new DEROctetString(macCalculator.getMac());
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("exception decoding algorithm parameters.", e);
+ }
+
+ ASN1Set unauthed = (unauthGen != null) ? new BERSet(unauthGen.getAttributes(new HashMap()).toASN1EncodableVector()) : null;
+
+ ContentInfo eci = new ContentInfo(
+ CMSObjectIdentifiers.data,
+ encContent);
+
+ authData = new AuthenticatedData(originatorInfo, new DERSet(recipientInfos), macCalculator.getAlgorithmIdentifier(), null, eci, null, macResult, unauthed);
+ }
+
+ ContentInfo contentInfo = new ContentInfo(
+ CMSObjectIdentifiers.authenticatedData, authData);
+
+ return new CMSAuthenticatedData(contentInfo, new DigestCalculatorProvider()
+ {
+ public DigestCalculator get(AlgorithmIdentifier digestAlgorithmIdentifier)
+ throws OperatorCreationException
+ {
+ return digestCalculator;
+ }
+ });
+ }
+
+ /**
+ * constructor allowing specific source of randomness
+ * @param rand instance of SecureRandom to use
+ * @deprecated no longer required, use simple constructor.
+ */
+ public CMSAuthenticatedDataGenerator(
+ SecureRandom rand)
+ {
+ super(rand);
+ }
+
+ /**
+ * generate an authenticated object that contains an CMS Authenticated Data
+ * object using the given provider and the passed in key generator.
+ * @deprecated
+ */
+ private CMSAuthenticatedData generate(
+ final CMSProcessable content,
+ String macOID,
+ KeyGenerator keyGen,
+ Provider provider)
+ throws NoSuchAlgorithmException, CMSException
+ {
+ Provider encProvider = keyGen.getProvider();
+
+ convertOldRecipients(rand, provider);
+
+ return generate(new CMSTypedData()
+ {
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return CMSObjectIdentifiers.data;
+ }
+
+ public void write(OutputStream out)
+ throws IOException, CMSException
+ {
+ content.write(out);
+ }
+
+ public Object getContent()
+ {
+ return content;
+ }
+ }, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(macOID)).setProvider(encProvider).setSecureRandom(rand).build());
+ }
+
+ /**
+ * generate an authenticated object that contains an CMS Authenticated Data
+ * object using the given provider.
+ * @deprecated use addRecipientInfoGenerator method.
+ */
+ public CMSAuthenticatedData generate(
+ CMSProcessable content,
+ String macOID,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
+ {
+ return generate(content, macOID, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * generate an authenticated object that contains an CMS Authenticated Data
+ * object using the given provider
+ * @deprecated use addRecipientInfoGenerator method..
+ */
+ public CMSAuthenticatedData generate(
+ CMSProcessable content,
+ String encryptionOID,
+ Provider provider)
+ throws NoSuchAlgorithmException, CMSException
+ {
+ KeyGenerator keyGen = CMSEnvelopedHelper.INSTANCE.createSymmetricKeyGenerator(encryptionOID, provider);
+
+ return generate(content, encryptionOID, keyGen, provider);
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java
new file mode 100644
index 00000000..31343382
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSAuthenticatedDataStreamGenerator.java
@@ -0,0 +1,392 @@
+package org.bouncycastle.cms;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.BERSequenceGenerator;
+import org.bouncycastle.asn1.BERSet;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.cms.AuthenticatedData;
+import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.cms.jcajce.JceCMSMacCalculatorBuilder;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.operator.MacCalculator;
+import org.bouncycastle.util.io.TeeOutputStream;
+
+/**
+ * General class for generating a CMS authenticated-data message stream.
+ * <p>
+ * A simple example of usage.
+ * <pre>
+ * CMSAuthenticatedDataStreamGenerator edGen = new CMSAuthenticatedDataStreamGenerator();
+ *
+ * edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(cert).setProvider("BC"));
+ *
+ * ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ *
+ * OutputStream out = edGen.open(
+ * bOut, new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider("BC").build());*
+ * out.write(data);
+ *
+ * out.close();
+ * </pre>
+ */
+public class CMSAuthenticatedDataStreamGenerator
+ extends CMSAuthenticatedGenerator
+{
+ // Currently not handled
+// private Object _originatorInfo = null;
+// private Object _unprotectedAttributes = null;
+ private int bufferSize;
+ private boolean berEncodeRecipientSet;
+ private MacCalculator macCalculator;
+
+ /**
+ * base constructor
+ */
+ public CMSAuthenticatedDataStreamGenerator()
+ {
+ }
+
+ /**
+ * Set the underlying string size for encapsulated data
+ *
+ * @param bufferSize length of octet strings to buffer the data.
+ */
+ public void setBufferSize(
+ int bufferSize)
+ {
+ this.bufferSize = bufferSize;
+ }
+
+ /**
+ * Use a BER Set to store the recipient information. By default recipients are
+ * stored in a DER encoding.
+ *
+ * @param useBerEncodingForRecipients true if a BER set should be used, false if DER.
+ */
+ public void setBEREncodeRecipients(
+ boolean useBerEncodingForRecipients)
+ {
+ berEncodeRecipientSet = useBerEncodingForRecipients;
+ }
+
+ /**
+ * generate an authenticated data structure with the encapsulated bytes marked as DATA.
+ *
+ * @param out the stream to store the authenticated structure in.
+ * @param macCalculator calculator for the MAC to be attached to the data.
+ */
+ public OutputStream open(
+ OutputStream out,
+ MacCalculator macCalculator)
+ throws CMSException
+ {
+ return open(CMSObjectIdentifiers.data, out, macCalculator);
+ }
+
+ public OutputStream open(
+ OutputStream out,
+ MacCalculator macCalculator,
+ DigestCalculator digestCalculator)
+ throws CMSException
+ {
+ return open(CMSObjectIdentifiers.data, out, macCalculator, digestCalculator);
+ }
+
+ /**
+ * generate an authenticated data structure with the encapsulated bytes marked as type dataType.
+ *
+ * @param dataType the type of the data been written to the object.
+ * @param out the stream to store the authenticated structure in.
+ * @param macCalculator calculator for the MAC to be attached to the data.
+ */
+ public OutputStream open(
+ ASN1ObjectIdentifier dataType,
+ OutputStream out,
+ MacCalculator macCalculator)
+ throws CMSException
+ {
+ return open(dataType, out, macCalculator, null);
+ }
+
+ /**
+ * generate an authenticated data structure with the encapsulated bytes marked as type dataType.
+ *
+ * @param dataType the type of the data been written to the object.
+ * @param out the stream to store the authenticated structure in.
+ * @param macCalculator calculator for the MAC to be attached to the data.
+ * @param digestCalculator calculator for computing digest of the encapsulated data.
+ */
+ public OutputStream open(
+ ASN1ObjectIdentifier dataType,
+ OutputStream out,
+ MacCalculator macCalculator,
+ DigestCalculator digestCalculator)
+ throws CMSException
+ {
+ this.macCalculator = macCalculator;
+
+ try
+ {
+ ASN1EncodableVector recipientInfos = new ASN1EncodableVector();
+
+ for (Iterator it = recipientInfoGenerators.iterator(); it.hasNext();)
+ {
+ RecipientInfoGenerator recipient = (RecipientInfoGenerator)it.next();
+
+ recipientInfos.add(recipient.generate(macCalculator.getKey()));
+ }
+
+ //
+ // ContentInfo
+ //
+ BERSequenceGenerator cGen = new BERSequenceGenerator(out);
+
+ cGen.addObject(CMSObjectIdentifiers.authenticatedData);
+
+ //
+ // Authenticated Data
+ //
+ BERSequenceGenerator authGen = new BERSequenceGenerator(cGen.getRawOutputStream(), 0, true);
+
+ authGen.addObject(new DERInteger(AuthenticatedData.calculateVersion(originatorInfo)));
+
+ if (originatorInfo != null)
+ {
+ authGen.addObject(new DERTaggedObject(false, 0, originatorInfo));
+ }
+
+ if (berEncodeRecipientSet)
+ {
+ authGen.getRawOutputStream().write(new BERSet(recipientInfos).getEncoded());
+ }
+ else
+ {
+ authGen.getRawOutputStream().write(new DERSet(recipientInfos).getEncoded());
+ }
+
+ AlgorithmIdentifier macAlgId = macCalculator.getAlgorithmIdentifier();
+
+ authGen.getRawOutputStream().write(macAlgId.getEncoded());
+
+ if (digestCalculator != null)
+ {
+ authGen.addObject(new DERTaggedObject(false, 1, digestCalculator.getAlgorithmIdentifier()));
+ }
+
+ BERSequenceGenerator eiGen = new BERSequenceGenerator(authGen.getRawOutputStream());
+
+ eiGen.addObject(dataType);
+
+ OutputStream octetStream = CMSUtils.createBEROctetOutputStream(
+ eiGen.getRawOutputStream(), 0, false, bufferSize);
+
+ OutputStream mOut;
+
+ if (digestCalculator != null)
+ {
+ mOut = new TeeOutputStream(octetStream, digestCalculator.getOutputStream());
+ }
+ else
+ {
+ mOut = new TeeOutputStream(octetStream, macCalculator.getOutputStream());
+ }
+
+ return new CmsAuthenticatedDataOutputStream(macCalculator, digestCalculator, dataType, mOut, cGen, authGen, eiGen);
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("exception decoding algorithm parameters.", e);
+ }
+ }
+
+ private class CmsAuthenticatedDataOutputStream
+ extends OutputStream
+ {
+ private OutputStream dataStream;
+ private BERSequenceGenerator cGen;
+ private BERSequenceGenerator envGen;
+ private BERSequenceGenerator eiGen;
+ private MacCalculator macCalculator;
+ private DigestCalculator digestCalculator;
+ private ASN1ObjectIdentifier contentType;
+
+ public CmsAuthenticatedDataOutputStream(
+ MacCalculator macCalculator,
+ DigestCalculator digestCalculator,
+ ASN1ObjectIdentifier contentType,
+ OutputStream dataStream,
+ BERSequenceGenerator cGen,
+ BERSequenceGenerator envGen,
+ BERSequenceGenerator eiGen)
+ {
+ this.macCalculator = macCalculator;
+ this.digestCalculator = digestCalculator;
+ this.contentType = contentType;
+ this.dataStream = dataStream;
+ this.cGen = cGen;
+ this.envGen = envGen;
+ this.eiGen = eiGen;
+ }
+
+ public void write(
+ int b)
+ throws IOException
+ {
+ dataStream.write(b);
+ }
+
+ public void write(
+ byte[] bytes,
+ int off,
+ int len)
+ throws IOException
+ {
+ dataStream.write(bytes, off, len);
+ }
+
+ public void write(
+ byte[] bytes)
+ throws IOException
+ {
+ dataStream.write(bytes);
+ }
+
+ public void close()
+ throws IOException
+ {
+ dataStream.close();
+ eiGen.close();
+
+ Map parameters;
+
+ if (digestCalculator != null)
+ {
+ parameters = getBaseParameters(contentType, digestCalculator.getAlgorithmIdentifier(), digestCalculator.getDigest());
+
+ if (authGen == null)
+ {
+ authGen = new DefaultAuthenticatedAttributeTableGenerator();
+ }
+
+ ASN1Set authed = new DERSet(authGen.getAttributes(parameters).toASN1EncodableVector());
+
+ OutputStream mOut = macCalculator.getOutputStream();
+
+ mOut.write(authed.getEncoded(ASN1Encoding.DER));
+
+ mOut.close();
+
+ envGen.addObject(new DERTaggedObject(false, 2, authed));
+ }
+ else
+ {
+ parameters = new HashMap();
+ }
+
+ envGen.addObject(new DEROctetString(macCalculator.getMac()));
+
+ if (unauthGen != null)
+ {
+ envGen.addObject(new DERTaggedObject(false, 3, new BERSet(unauthGen.getAttributes(parameters).toASN1EncodableVector())));
+ }
+
+ envGen.close();
+ cGen.close();
+ }
+ }
+
+
+ /**
+ * constructor allowing specific source of randomness
+ * @param rand instance of SecureRandom to use
+ * @deprecated no longer of any use, use basic constructor.
+ */
+ public CMSAuthenticatedDataStreamGenerator(
+ SecureRandom rand)
+ {
+ super(rand);
+ }
+
+ /**
+ * generate an authenticated object that contains an CMS Authenticated Data
+ * object using the given provider.
+ * @throws java.io.IOException
+ * @deprecated use open(out, MacCalculator)
+ */
+ public OutputStream open(
+ OutputStream out,
+ String encryptionOID,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException
+ {
+ convertOldRecipients(rand, CMSUtils.getProvider(provider));
+
+ return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID)).setSecureRandom(rand).setProvider(provider).build());
+ }
+
+ /**
+ * @deprecated use open(out, MacCalculator)
+ */
+ public OutputStream open(
+ OutputStream out,
+ String encryptionOID,
+ Provider provider)
+ throws NoSuchAlgorithmException, CMSException, IOException
+ {
+ convertOldRecipients(rand, provider);
+
+ return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID)).setSecureRandom(rand).setProvider(provider).build());
+ }
+
+ /**
+ * generate an enveloped object that contains an CMS Enveloped Data
+ * object using the given provider.
+ * @deprecated use open(out, MacCalculator)
+ */
+ public OutputStream open(
+ OutputStream out,
+ String encryptionOID,
+ int keySize,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException
+ {
+ convertOldRecipients(rand, CMSUtils.getProvider(provider));
+
+ return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID), keySize).setSecureRandom(rand).setProvider(provider).build());
+ }
+
+ /**
+ * generate an enveloped object that contains an CMS Enveloped Data
+ * object using the given provider.
+ * @deprecated use open(out, MacCalculator)
+ */
+ public OutputStream open(
+ OutputStream out,
+ String encryptionOID,
+ int keySize,
+ Provider provider)
+ throws NoSuchAlgorithmException, CMSException, IOException
+ {
+ convertOldRecipients(rand, provider);
+
+ return open(out, new JceCMSMacCalculatorBuilder(new ASN1ObjectIdentifier(encryptionOID), keySize).setSecureRandom(rand).setProvider(provider).build());
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedGenerator.java
new file mode 100644
index 00000000..0fe9ee9a
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedGenerator.java
@@ -0,0 +1,390 @@
+package org.bouncycastle.cms;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.crypto.SecretKey;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.cms.KEKIdentifier;
+import org.bouncycastle.asn1.cms.OriginatorInfo;
+import org.bouncycastle.asn1.kisa.KISAObjectIdentifiers;
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.ntt.NTTObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.cms.jcajce.JceKEKRecipientInfoGenerator;
+import org.bouncycastle.cms.jcajce.JceKeyAgreeRecipientInfoGenerator;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
+import org.bouncycastle.cms.jcajce.JcePasswordRecipientInfoGenerator;
+
+/**
+ * General class for generating a CMS enveloped-data message.
+ */
+public class CMSEnvelopedGenerator
+{
+ public static final String DES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC.getId();
+ public static final String RC2_CBC = PKCSObjectIdentifiers.RC2_CBC.getId();
+ public static final String IDEA_CBC = "1.3.6.1.4.1.188.7.1.1.2";
+ public static final String CAST5_CBC = "1.2.840.113533.7.66.10";
+ public static final String AES128_CBC = NISTObjectIdentifiers.id_aes128_CBC.getId();
+ public static final String AES192_CBC = NISTObjectIdentifiers.id_aes192_CBC.getId();
+ public static final String AES256_CBC = NISTObjectIdentifiers.id_aes256_CBC.getId();
+ public static final String CAMELLIA128_CBC = NTTObjectIdentifiers.id_camellia128_cbc.getId();
+ public static final String CAMELLIA192_CBC = NTTObjectIdentifiers.id_camellia192_cbc.getId();
+ public static final String CAMELLIA256_CBC = NTTObjectIdentifiers.id_camellia256_cbc.getId();
+ public static final String SEED_CBC = KISAObjectIdentifiers.id_seedCBC.getId();
+
+ public static final String DES_EDE3_WRAP = PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId();
+ public static final String AES128_WRAP = NISTObjectIdentifiers.id_aes128_wrap.getId();
+ public static final String AES192_WRAP = NISTObjectIdentifiers.id_aes192_wrap.getId();
+ public static final String AES256_WRAP = NISTObjectIdentifiers.id_aes256_wrap.getId();
+ public static final String CAMELLIA128_WRAP = NTTObjectIdentifiers.id_camellia128_wrap.getId();
+ public static final String CAMELLIA192_WRAP = NTTObjectIdentifiers.id_camellia192_wrap.getId();
+ public static final String CAMELLIA256_WRAP = NTTObjectIdentifiers.id_camellia256_wrap.getId();
+ public static final String SEED_WRAP = KISAObjectIdentifiers.id_npki_app_cmsSeed_wrap.getId();
+
+ public static final String ECDH_SHA1KDF = X9ObjectIdentifiers.dhSinglePass_stdDH_sha1kdf_scheme.getId();
+ public static final String ECMQV_SHA1KDF = X9ObjectIdentifiers.mqvSinglePass_sha1kdf_scheme.getId();
+
+ List oldRecipientInfoGenerators = new ArrayList();
+ List recipientInfoGenerators = new ArrayList();
+
+ protected CMSAttributeTableGenerator unprotectedAttributeGenerator = null;
+
+ SecureRandom rand;
+ protected OriginatorInfo originatorInfo;
+
+ /**
+ * base constructor
+ */
+ public CMSEnvelopedGenerator()
+ {
+ this(new SecureRandom());
+ }
+
+ /**
+ * constructor allowing specific source of randomness
+ * @param rand instance of SecureRandom to use
+ */
+ public CMSEnvelopedGenerator(
+ SecureRandom rand)
+ {
+ this.rand = rand;
+ }
+
+ public void setUnprotectedAttributeGenerator(CMSAttributeTableGenerator unprotectedAttributeGenerator)
+ {
+ this.unprotectedAttributeGenerator = unprotectedAttributeGenerator;
+ }
+
+
+ public void setOriginatorInfo(OriginatorInformation originatorInfo)
+ {
+ this.originatorInfo = originatorInfo.toASN1Structure();
+ }
+
+ /**
+ * add a recipient.
+ *
+ * @deprecated use the addRecipientGenerator and JceKeyTransRecipientInfoGenerator
+ * @param cert recipient's public key certificate
+ * @exception IllegalArgumentException if there is a problem with the certificate
+ */
+ public void addKeyTransRecipient(
+ X509Certificate cert)
+ throws IllegalArgumentException
+ {
+ try
+ {
+ oldRecipientInfoGenerators.add(new JceKeyTransRecipientInfoGenerator(cert));
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new IllegalArgumentException("unable to encode certificate: " + e.getMessage());
+ }
+ }
+
+ /**
+ * add a recipient
+ *
+ * @deprecated use the addRecipientGenerator and JceKeyTransRecipientInfoGenerator
+ * @param key the public key used by the recipient
+ * @param subKeyId the identifier for the recipient's public key
+ * @exception IllegalArgumentException if there is a problem with the key
+ */
+ public void addKeyTransRecipient(
+ PublicKey key,
+ byte[] subKeyId)
+ throws IllegalArgumentException
+ {
+ oldRecipientInfoGenerators.add(new JceKeyTransRecipientInfoGenerator(subKeyId, key));
+ }
+
+ /**
+ * add a KEK recipient.
+ *
+ * @deprecated use the addRecipientGenerator and JceKEKRecipientInfoGenerator
+ * @param key the secret key to use for wrapping
+ * @param keyIdentifier the byte string that identifies the key
+ */
+ public void addKEKRecipient(
+ SecretKey key,
+ byte[] keyIdentifier)
+ {
+ addKEKRecipient(key, new KEKIdentifier(keyIdentifier, null, null));
+ }
+
+ /**
+ * add a KEK recipient.
+ *
+ * @deprecated use the addRecipientGenerator and JceKEKRecipientInfoGenerator
+ * @param key the secret key to use for wrapping
+ * @param kekIdentifier a KEKIdentifier structure (identifies the key)
+ */
+ public void addKEKRecipient(
+ SecretKey key,
+ KEKIdentifier kekIdentifier)
+ {
+ oldRecipientInfoGenerators.add(new JceKEKRecipientInfoGenerator(kekIdentifier, key));
+ }
+
+ /**
+ * @deprecated use addRecipientGenerator and JcePasswordRecipientInfoGenerator
+ * @param pbeKey PBE key
+ * @param kekAlgorithmOid key encryption algorithm to use.
+ */
+ public void addPasswordRecipient(
+ CMSPBEKey pbeKey,
+ String kekAlgorithmOid)
+ {
+ oldRecipientInfoGenerators.add(new JcePasswordRecipientInfoGenerator(new ASN1ObjectIdentifier(kekAlgorithmOid), pbeKey.getPassword())
+ .setSaltAndIterationCount(pbeKey.getSalt(), pbeKey.getIterationCount())
+ .setPasswordConversionScheme((pbeKey instanceof PKCS5Scheme2UTF8PBEKey) ? PasswordRecipient.PKCS5_SCHEME2_UTF8 : PasswordRecipient.PKCS5_SCHEME2));
+ }
+
+ /**
+ * Add a key agreement based recipient.
+ *
+ * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
+ * @param agreementAlgorithm key agreement algorithm to use.
+ * @param senderPrivateKey private key to initialise sender side of agreement with.
+ * @param senderPublicKey sender public key to include with message.
+ * @param recipientCert recipient's public key certificate.
+ * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+ * @param provider provider to use for the agreement calculation.
+ * @exception NoSuchProviderException if the specified provider cannot be found
+ * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
+ * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+ */
+ public void addKeyAgreementRecipient(
+ String agreementAlgorithm,
+ PrivateKey senderPrivateKey,
+ PublicKey senderPublicKey,
+ X509Certificate recipientCert,
+ String cekWrapAlgorithm,
+ String provider)
+ throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException
+ {
+ addKeyAgreementRecipient(agreementAlgorithm, senderPrivateKey, senderPublicKey, recipientCert, cekWrapAlgorithm, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * Add a key agreement based recipient.
+ *
+ * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
+ * @param agreementAlgorithm key agreement algorithm to use.
+ * @param senderPrivateKey private key to initialise sender side of agreement with.
+ * @param senderPublicKey sender public key to include with message.
+ * @param recipientCert recipient's public key certificate.
+ * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+ * @param provider provider to use for the agreement calculation.
+ * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
+ * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+ */
+ public void addKeyAgreementRecipient(
+ String agreementAlgorithm,
+ PrivateKey senderPrivateKey,
+ PublicKey senderPublicKey,
+ X509Certificate recipientCert,
+ String cekWrapAlgorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException, InvalidKeyException
+ {
+ List recipients = new ArrayList();
+
+ recipients.add(recipientCert);
+
+ addKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey,
+ recipients, cekWrapAlgorithm, provider);
+ }
+
+ /**
+ * Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
+ *
+ * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
+ * @param agreementAlgorithm key agreement algorithm to use.
+ * @param senderPrivateKey private key to initialise sender side of agreement with.
+ * @param senderPublicKey sender public key to include with message.
+ * @param recipientCerts recipients' public key certificates.
+ * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+ * @param provider provider to use for the agreement calculation.
+ * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
+ * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+ */
+ public void addKeyAgreementRecipients(
+ String agreementAlgorithm,
+ PrivateKey senderPrivateKey,
+ PublicKey senderPublicKey,
+ Collection recipientCerts,
+ String cekWrapAlgorithm,
+ String provider)
+ throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException
+ {
+ addKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey, recipientCerts, cekWrapAlgorithm, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
+ *
+ * @deprecated use the addRecipientGenerator and JceKeyAgreeRecipientInfoGenerator
+ * @param agreementAlgorithm key agreement algorithm to use.
+ * @param senderPrivateKey private key to initialise sender side of agreement with.
+ * @param senderPublicKey sender public key to include with message.
+ * @param recipientCerts recipients' public key certificates.
+ * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+ * @param provider provider to use for the agreement calculation.
+ * @exception NoSuchAlgorithmException if the algorithm requested cannot be found
+ * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+ */
+ public void addKeyAgreementRecipients(
+ String agreementAlgorithm,
+ PrivateKey senderPrivateKey,
+ PublicKey senderPublicKey,
+ Collection recipientCerts,
+ String cekWrapAlgorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException, InvalidKeyException
+ {
+ JceKeyAgreeRecipientInfoGenerator recipientInfoGenerator = new JceKeyAgreeRecipientInfoGenerator(new ASN1ObjectIdentifier(agreementAlgorithm), senderPrivateKey, senderPublicKey, new ASN1ObjectIdentifier(cekWrapAlgorithm)).setProvider(provider);
+
+ for (Iterator it = recipientCerts.iterator(); it.hasNext();)
+ {
+ try
+ {
+ recipientInfoGenerator.addRecipient((X509Certificate)it.next());
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new IllegalArgumentException("unable to encode certificate: " + e.getMessage());
+ }
+ }
+
+ oldRecipientInfoGenerators.add(recipientInfoGenerator);
+ }
+
+ /**
+ * Add a generator to produce the recipient info required.
+ *
+ * @param recipientGenerator a generator of a recipient info object.
+ */
+ public void addRecipientInfoGenerator(RecipientInfoGenerator recipientGenerator)
+ {
+ recipientInfoGenerators.add(recipientGenerator);
+ }
+
+ protected AlgorithmIdentifier getAlgorithmIdentifier(String encryptionOID, AlgorithmParameters params) throws IOException
+ {
+ ASN1Encodable asn1Params;
+ if (params != null)
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ }
+ else
+ {
+ asn1Params = DERNull.INSTANCE;
+ }
+
+ return new AlgorithmIdentifier(
+ new ASN1ObjectIdentifier(encryptionOID),
+ asn1Params);
+ }
+
+ protected void convertOldRecipients(SecureRandom rand, Provider provider)
+ {
+ for (Iterator it = oldRecipientInfoGenerators.iterator(); it.hasNext();)
+ {
+ Object recipient = it.next();
+
+ if (recipient instanceof JceKeyTransRecipientInfoGenerator)
+ {
+ JceKeyTransRecipientInfoGenerator recip = (JceKeyTransRecipientInfoGenerator)recipient;
+
+ if (provider != null)
+ {
+ recip.setProvider(provider);
+ }
+
+ recipientInfoGenerators.add(recip);
+ }
+ else if (recipient instanceof KEKRecipientInfoGenerator)
+ {
+ JceKEKRecipientInfoGenerator recip = (JceKEKRecipientInfoGenerator)recipient;
+
+ if (provider != null)
+ {
+ recip.setProvider(provider);
+ }
+
+ recip.setSecureRandom(rand);
+
+ recipientInfoGenerators.add(recip);
+ }
+ else if (recipient instanceof JcePasswordRecipientInfoGenerator)
+ {
+ JcePasswordRecipientInfoGenerator recip = (JcePasswordRecipientInfoGenerator)recipient;
+
+ if (provider != null)
+ {
+ recip.setProvider(provider);
+ }
+
+ recip.setSecureRandom(rand);
+
+ recipientInfoGenerators.add(recip);
+ }
+ else if (recipient instanceof JceKeyAgreeRecipientInfoGenerator)
+ {
+ JceKeyAgreeRecipientInfoGenerator recip = (JceKeyAgreeRecipientInfoGenerator)recipient;
+
+ if (provider != null)
+ {
+ recip.setProvider(provider);
+ }
+
+ recip.setSecureRandom(rand);
+
+ recipientInfoGenerators.add(recip);
+ }
+ }
+
+ oldRecipientInfoGenerators.clear();
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedHelper.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedHelper.java
new file mode 100644
index 00000000..54dc6af7
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSEnvelopedHelper.java
@@ -0,0 +1,257 @@
+package org.bouncycastle.cms;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.crypto.KeyGenerator;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.cms.KEKRecipientInfo;
+import org.bouncycastle.asn1.cms.KeyAgreeRecipientInfo;
+import org.bouncycastle.asn1.cms.KeyTransRecipientInfo;
+import org.bouncycastle.asn1.cms.PasswordRecipientInfo;
+import org.bouncycastle.asn1.cms.RecipientInfo;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.util.Integers;
+
+class CMSEnvelopedHelper
+{
+ static final CMSEnvelopedHelper INSTANCE = new CMSEnvelopedHelper();
+
+ private static final Map KEYSIZES = new HashMap();
+ private static final Map BASE_CIPHER_NAMES = new HashMap();
+ private static final Map CIPHER_ALG_NAMES = new HashMap();
+ private static final Map MAC_ALG_NAMES = new HashMap();
+
+ static
+ {
+ KEYSIZES.put(CMSEnvelopedGenerator.DES_EDE3_CBC, Integers.valueOf(192));
+ KEYSIZES.put(CMSEnvelopedGenerator.AES128_CBC, Integers.valueOf(128));
+ KEYSIZES.put(CMSEnvelopedGenerator.AES192_CBC, Integers.valueOf(192));
+ KEYSIZES.put(CMSEnvelopedGenerator.AES256_CBC, Integers.valueOf(256));
+
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.DES_EDE3_CBC, "DESEDE");
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.AES128_CBC, "AES");
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.AES192_CBC, "AES");
+ BASE_CIPHER_NAMES.put(CMSEnvelopedGenerator.AES256_CBC, "AES");
+
+ CIPHER_ALG_NAMES.put(CMSEnvelopedGenerator.DES_EDE3_CBC, "DESEDE/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSEnvelopedGenerator.AES128_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSEnvelopedGenerator.AES192_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSEnvelopedGenerator.AES256_CBC, "AES/CBC/PKCS5Padding");
+
+ MAC_ALG_NAMES.put(CMSEnvelopedGenerator.DES_EDE3_CBC, "DESEDEMac");
+ MAC_ALG_NAMES.put(CMSEnvelopedGenerator.AES128_CBC, "AESMac");
+ MAC_ALG_NAMES.put(CMSEnvelopedGenerator.AES192_CBC, "AESMac");
+ MAC_ALG_NAMES.put(CMSEnvelopedGenerator.AES256_CBC, "AESMac");
+ }
+
+ KeyGenerator createSymmetricKeyGenerator(
+ String encryptionOID,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ try
+ {
+ return createKeyGenerator(encryptionOID, provider);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ try
+ {
+ String algName = (String)BASE_CIPHER_NAMES.get(encryptionOID);
+ if (algName != null)
+ {
+ return createKeyGenerator(algName, provider);
+ }
+ }
+ catch (NoSuchAlgorithmException ex)
+ {
+ // ignore
+ }
+ if (provider != null)
+ {
+ return createSymmetricKeyGenerator(encryptionOID, null);
+ }
+ throw e;
+ }
+ }
+
+ int getKeySize(String oid)
+ {
+ Integer keySize = (Integer)KEYSIZES.get(oid);
+
+ if (keySize == null)
+ {
+ throw new IllegalArgumentException("no keysize for " + oid);
+ }
+
+ return keySize.intValue();
+ }
+
+ private KeyGenerator createKeyGenerator(
+ String algName,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider != null)
+ {
+ try
+ {
+ return KeyGenerator.getInstance(algName, provider.getName());
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new NoSuchAlgorithmException(e.toString());
+ }
+ }
+ else
+ {
+ return KeyGenerator.getInstance(algName);
+ }
+ }
+
+ static RecipientInformationStore buildRecipientInformationStore(
+ ASN1Set recipientInfos, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable)
+ {
+ return buildRecipientInformationStore(recipientInfos, messageAlgorithm, secureReadable, null);
+ }
+
+ static RecipientInformationStore buildRecipientInformationStore(
+ ASN1Set recipientInfos, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable, AuthAttributesProvider additionalData)
+ {
+ List infos = new ArrayList();
+ for (int i = 0; i != recipientInfos.size(); i++)
+ {
+ RecipientInfo info = RecipientInfo.getInstance(recipientInfos.getObjectAt(i));
+
+ readRecipientInfo(infos, info, messageAlgorithm, secureReadable, additionalData);
+ }
+ return new RecipientInformationStore(infos);
+ }
+
+ private static void readRecipientInfo(
+ List infos, RecipientInfo info, AlgorithmIdentifier messageAlgorithm, CMSSecureReadable secureReadable, AuthAttributesProvider additionalData)
+ {
+ ASN1Encodable recipInfo = info.getInfo();
+ if (recipInfo instanceof KeyTransRecipientInfo)
+ {
+ infos.add(new KeyTransRecipientInformation(
+ (KeyTransRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData));
+ }
+ else if (recipInfo instanceof KEKRecipientInfo)
+ {
+ infos.add(new KEKRecipientInformation(
+ (KEKRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData));
+ }
+ else if (recipInfo instanceof KeyAgreeRecipientInfo)
+ {
+ KeyAgreeRecipientInformation.readRecipientInfo(infos,
+ (KeyAgreeRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData);
+ }
+ else if (recipInfo instanceof PasswordRecipientInfo)
+ {
+ infos.add(new PasswordRecipientInformation(
+ (PasswordRecipientInfo)recipInfo, messageAlgorithm, secureReadable, additionalData));
+ }
+ }
+
+ static class CMSDigestAuthenticatedSecureReadable
+ implements CMSSecureReadable
+ {
+ private DigestCalculator digestCalculator;
+ private CMSReadable readable;
+
+ public CMSDigestAuthenticatedSecureReadable(DigestCalculator digestCalculator, CMSReadable readable)
+ {
+ this.digestCalculator = digestCalculator;
+ this.readable = readable;
+ }
+
+ public InputStream getInputStream()
+ throws IOException, CMSException
+ {
+ return new FilterInputStream(readable.getInputStream())
+ {
+ public int read()
+ throws IOException
+ {
+ int b = in.read();
+
+ if (b >= 0)
+ {
+ digestCalculator.getOutputStream().write(b);
+ }
+
+ return b;
+ }
+
+ public int read(byte[] inBuf, int inOff, int inLen)
+ throws IOException
+ {
+ int n = in.read(inBuf, inOff, inLen);
+
+ if (n >= 0)
+ {
+ digestCalculator.getOutputStream().write(inBuf, inOff, n);
+ }
+
+ return n;
+ }
+ };
+ }
+
+ public byte[] getDigest()
+ {
+ return digestCalculator.getDigest();
+ }
+ }
+
+ static class CMSAuthenticatedSecureReadable implements CMSSecureReadable
+ {
+ private AlgorithmIdentifier algorithm;
+ private CMSReadable readable;
+
+ CMSAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, CMSReadable readable)
+ {
+ this.algorithm = algorithm;
+ this.readable = readable;
+ }
+
+ public InputStream getInputStream()
+ throws IOException, CMSException
+ {
+ return readable.getInputStream();
+ }
+
+ }
+
+ static class CMSEnvelopedSecureReadable implements CMSSecureReadable
+ {
+ private AlgorithmIdentifier algorithm;
+ private CMSReadable readable;
+
+ CMSEnvelopedSecureReadable(AlgorithmIdentifier algorithm, CMSReadable readable)
+ {
+ this.algorithm = algorithm;
+ this.readable = readable;
+ }
+
+ public InputStream getInputStream()
+ throws IOException, CMSException
+ {
+ return readable.getInputStream();
+ }
+
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableByteArray.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableByteArray.java
new file mode 100644
index 00000000..005f6996
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableByteArray.java
@@ -0,0 +1,54 @@
+package org.bouncycastle.cms;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
+
+/**
+ * a holding class for a byte array of data to be processed.
+ */
+public class CMSProcessableByteArray
+ implements CMSTypedData, CMSReadable
+{
+ private ASN1ObjectIdentifier type;
+ private byte[] bytes;
+
+ public CMSProcessableByteArray(
+ byte[] bytes)
+ {
+ this(new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId()), bytes);
+ }
+
+ public CMSProcessableByteArray(
+ ASN1ObjectIdentifier type,
+ byte[] bytes)
+ {
+ this.type = type;
+ this.bytes = bytes;
+ }
+
+ public InputStream getInputStream()
+ {
+ return new ByteArrayInputStream(bytes);
+ }
+
+ public void write(OutputStream zOut)
+ throws IOException, CMSException
+ {
+ zOut.write(bytes);
+ }
+
+ public Object getContent()
+ {
+ return bytes.clone();
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return type;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableFile.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableFile.java
new file mode 100644
index 00000000..decfb38b
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSProcessableFile.java
@@ -0,0 +1,80 @@
+package org.bouncycastle.cms;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
+
+/**
+ * a holding class for a file of data to be processed.
+ */
+public class CMSProcessableFile
+ implements CMSTypedData, CMSReadable
+{
+ private static final int DEFAULT_BUF_SIZE = 32 * 1024;
+
+ private ASN1ObjectIdentifier type;
+ private File file;
+ private byte[] buf;
+
+ public CMSProcessableFile(
+ File file)
+ {
+ this(file, DEFAULT_BUF_SIZE);
+ }
+
+ public CMSProcessableFile(
+ File file,
+ int bufSize)
+ {
+ this(new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId()), file, bufSize);
+ }
+
+ public CMSProcessableFile(
+ ASN1ObjectIdentifier type,
+ File file,
+ int bufSize)
+ {
+ this.type = type;
+ this.file = file;
+ buf = new byte[bufSize];
+ }
+
+ public InputStream getInputStream()
+ throws IOException, CMSException
+ {
+ return new BufferedInputStream(new FileInputStream(file), DEFAULT_BUF_SIZE);
+ }
+
+ public void write(OutputStream zOut)
+ throws IOException, CMSException
+ {
+ FileInputStream fIn = new FileInputStream(file);
+ int len;
+
+ while ((len = fIn.read(buf, 0, buf.length)) > 0)
+ {
+ zOut.write(buf, 0, len);
+ }
+
+ fIn.close();
+ }
+
+ /**
+ * Return the file handle.
+ */
+ public Object getContent()
+ {
+ return file;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return type;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedData.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedData.java
new file mode 100644
index 00000000..c976dfee
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedData.java
@@ -0,0 +1,772 @@
+package org.bouncycastle.cms;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.BERSequence;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.asn1.cms.SignedData;
+import org.bouncycastle.asn1.cms.SignerInfo;
+import org.bouncycastle.asn1.x509.AttributeCertificate;
+import org.bouncycastle.asn1.x509.Certificate;
+import org.bouncycastle.asn1.x509.CertificateList;
+import org.bouncycastle.cert.X509AttributeCertificateHolder;
+import org.bouncycastle.cert.X509CRLHolder;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
+import org.bouncycastle.operator.SignatureAlgorithmIdentifierFinder;
+import org.bouncycastle.util.CollectionStore;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.x509.NoSuchStoreException;
+import org.bouncycastle.x509.X509Store;
+
+/**
+ * general class for handling a pkcs7-signature message.
+ *
+ * A simple example of usage - note, in the example below the validity of
+ * the certificate isn't verified, just the fact that one of the certs
+ * matches the given signer...
+ *
+ * <pre>
+ * Store certStore = s.getCertificates();
+ * SignerInformationStore signers = s.getSignerInfos();
+ * Collection c = signers.getSigners();
+ * Iterator it = c.iterator();
+ *
+ * while (it.hasNext())
+ * {
+ * SignerInformation signer = (SignerInformation)it.next();
+ * Collection certCollection = certStore.getMatches(signer.getSID());
+ *
+ * Iterator certIt = certCollection.iterator();
+ * X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
+ *
+ * if (signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert)))
+ * {
+ * verified++;
+ * }
+ * }
+ * </pre>
+ */
+public class CMSSignedData
+{
+ private static final CMSSignedHelper HELPER = CMSSignedHelper.INSTANCE;
+
+ SignedData signedData;
+ ContentInfo contentInfo;
+ CMSTypedData signedContent;
+ SignerInformationStore signerInfoStore;
+ X509Store attributeStore;
+ X509Store certificateStore;
+ X509Store crlStore;
+ private Map hashes;
+
+ private CMSSignedData(
+ CMSSignedData c)
+ {
+ this.signedData = c.signedData;
+ this.contentInfo = c.contentInfo;
+ this.signedContent = c.signedContent;
+ this.signerInfoStore = c.signerInfoStore;
+ }
+
+ public CMSSignedData(
+ byte[] sigBlock)
+ throws CMSException
+ {
+ this(CMSUtils.readContentInfo(sigBlock));
+ }
+
+ public CMSSignedData(
+ CMSProcessable signedContent,
+ byte[] sigBlock)
+ throws CMSException
+ {
+ this(signedContent, CMSUtils.readContentInfo(sigBlock));
+ }
+
+ /**
+ * Content with detached signature, digests precomputed
+ *
+ * @param hashes a map of precomputed digests for content indexed by name of hash.
+ * @param sigBlock the signature object.
+ */
+ public CMSSignedData(
+ Map hashes,
+ byte[] sigBlock)
+ throws CMSException
+ {
+ this(hashes, CMSUtils.readContentInfo(sigBlock));
+ }
+
+ /**
+ * base constructor - content with detached signature.
+ *
+ * @param signedContent the content that was signed.
+ * @param sigData the signature object.
+ */
+ public CMSSignedData(
+ CMSProcessable signedContent,
+ InputStream sigData)
+ throws CMSException
+ {
+ this(signedContent, CMSUtils.readContentInfo(new ASN1InputStream(sigData)));
+ }
+
+ /**
+ * base constructor - with encapsulated content
+ */
+ public CMSSignedData(
+ InputStream sigData)
+ throws CMSException
+ {
+ this(CMSUtils.readContentInfo(sigData));
+ }
+
+ public CMSSignedData(
+ final CMSProcessable signedContent,
+ ContentInfo sigData)
+ throws CMSException
+ {
+ if (signedContent instanceof CMSTypedData)
+ {
+ this.signedContent = (CMSTypedData)signedContent;
+ }
+ else
+ {
+ this.signedContent = new CMSTypedData()
+ {
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return signedData.getEncapContentInfo().getContentType();
+ }
+
+ public void write(OutputStream out)
+ throws IOException, CMSException
+ {
+ signedContent.write(out);
+ }
+
+ public Object getContent()
+ {
+ return signedContent.getContent();
+ }
+ };
+ }
+
+ this.contentInfo = sigData;
+ this.signedData = getSignedData();
+ }
+
+ public CMSSignedData(
+ Map hashes,
+ ContentInfo sigData)
+ throws CMSException
+ {
+ this.hashes = hashes;
+ this.contentInfo = sigData;
+ this.signedData = getSignedData();
+ }
+
+ public CMSSignedData(
+ ContentInfo sigData)
+ throws CMSException
+ {
+ this.contentInfo = sigData;
+ this.signedData = getSignedData();
+
+ //
+ // this can happen if the signed message is sent simply to send a
+ // certificate chain.
+ //
+ if (signedData.getEncapContentInfo().getContent() != null)
+ {
+ this.signedContent = new CMSProcessableByteArray(signedData.getEncapContentInfo().getContentType(),
+ ((ASN1OctetString)(signedData.getEncapContentInfo()
+ .getContent())).getOctets());
+ }
+ else
+ {
+ this.signedContent = null;
+ }
+ }
+
+ private SignedData getSignedData()
+ throws CMSException
+ {
+ try
+ {
+ return SignedData.getInstance(contentInfo.getContent());
+ }
+ catch (ClassCastException e)
+ {
+ throw new CMSException("Malformed content.", e);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("Malformed content.", e);
+ }
+ }
+
+ /**
+ * Return the version number for this object
+ */
+ public int getVersion()
+ {
+ return signedData.getVersion().getValue().intValue();
+ }
+
+ /**
+ * return the collection of signers that are associated with the
+ * signatures for the message.
+ */
+ public SignerInformationStore getSignerInfos()
+ {
+ if (signerInfoStore == null)
+ {
+ ASN1Set s = signedData.getSignerInfos();
+ List signerInfos = new ArrayList();
+ SignatureAlgorithmIdentifierFinder sigAlgFinder = new DefaultSignatureAlgorithmIdentifierFinder();
+
+ for (int i = 0; i != s.size(); i++)
+ {
+ SignerInfo info = SignerInfo.getInstance(s.getObjectAt(i));
+ ASN1ObjectIdentifier contentType = signedData.getEncapContentInfo().getContentType();
+
+ if (hashes == null)
+ {
+ signerInfos.add(new SignerInformation(info, contentType, signedContent, null));
+ }
+ else
+ {
+ Object obj = hashes.keySet().iterator().next();
+ byte[] hash = (obj instanceof String) ? (byte[])hashes.get(info.getDigestAlgorithm().getAlgorithm().getId()) : (byte[])hashes.get(info.getDigestAlgorithm().getAlgorithm());
+
+ signerInfos.add(new SignerInformation(info, contentType, null, hash));
+ }
+ }
+
+ signerInfoStore = new SignerInformationStore(signerInfos);
+ }
+
+ return signerInfoStore;
+ }
+
+ /**
+ * return a X509Store containing the attribute certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider name of provider to use
+ * @return a store of attribute certificates
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use base Store returning method
+ */
+ public X509Store getAttributeCertificates(
+ String type,
+ String provider)
+ throws NoSuchStoreException, NoSuchProviderException, CMSException
+ {
+ return getAttributeCertificates(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a X509Store containing the attribute certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider provider to use
+ * @return a store of attribute certificates
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use base Store returning method
+ */
+ public X509Store getAttributeCertificates(
+ String type,
+ Provider provider)
+ throws NoSuchStoreException, CMSException
+ {
+ if (attributeStore == null)
+ {
+ attributeStore = HELPER.createAttributeStore(type, provider, signedData.getCertificates());
+ }
+
+ return attributeStore;
+ }
+
+ /**
+ * return a X509Store containing the public key certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider name of provider to use
+ * @return a store of public key certificates
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use base Store returning method
+ */
+ public X509Store getCertificates(
+ String type,
+ String provider)
+ throws NoSuchStoreException, NoSuchProviderException, CMSException
+ {
+ return getCertificates(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a X509Store containing the public key certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider provider to use
+ * @return a store of public key certificates
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use base Store returning method
+ */
+ public X509Store getCertificates(
+ String type,
+ Provider provider)
+ throws NoSuchStoreException, CMSException
+ {
+ if (certificateStore == null)
+ {
+ certificateStore = HELPER.createCertificateStore(type, provider, signedData.getCertificates());
+ }
+
+ return certificateStore;
+ }
+
+ /**
+ * return a X509Store containing CRLs, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider name of provider to use
+ * @return a store of CRLs
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use base Store returning method
+ */
+ public X509Store getCRLs(
+ String type,
+ String provider)
+ throws NoSuchStoreException, NoSuchProviderException, CMSException
+ {
+ return getCRLs(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a X509Store containing CRLs, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider provider to use
+ * @return a store of CRLs
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use base Store returning method
+ */
+ public X509Store getCRLs(
+ String type,
+ Provider provider)
+ throws NoSuchStoreException, CMSException
+ {
+ if (crlStore == null)
+ {
+ crlStore = HELPER.createCRLsStore(type, provider, signedData.getCRLs());
+ }
+
+ return crlStore;
+ }
+
+ /**
+ * return a CertStore containing the certificates and CRLs associated with
+ * this message.
+ *
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchAlgorithmException if the cert store isn't available.
+ * @exception CMSException if a general exception prevents creation of the CertStore
+ * @deprecated use base Store returning method
+ */
+ public CertStore getCertificatesAndCRLs(
+ String type,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
+ {
+ return getCertificatesAndCRLs(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a CertStore containing the certificates and CRLs associated with
+ * this message.
+ *
+ * @exception NoSuchAlgorithmException if the cert store isn't available.
+ * @exception CMSException if a general exception prevents creation of the CertStore
+ * @deprecated use base Store returning method
+ */
+ public CertStore getCertificatesAndCRLs(
+ String type,
+ Provider provider)
+ throws NoSuchAlgorithmException, CMSException
+ {
+ ASN1Set certSet = signedData.getCertificates();
+ ASN1Set crlSet = signedData.getCRLs();
+
+ return HELPER.createCertStore(type, provider, certSet, crlSet);
+ }
+
+ public Store getCertificates()
+ {
+ ASN1Set certSet = signedData.getCertificates();
+
+ if (certSet != null)
+ {
+ List certList = new ArrayList(certSet.size());
+
+ for (Enumeration en = certSet.getObjects(); en.hasMoreElements();)
+ {
+ ASN1Primitive obj = ((ASN1Encodable)en.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1Sequence)
+ {
+ certList.add(new X509CertificateHolder(Certificate.getInstance(obj)));
+ }
+ }
+
+ return new CollectionStore(certList);
+ }
+
+ return new CollectionStore(new ArrayList());
+ }
+
+ public Store getCRLs()
+ {
+ ASN1Set crlSet = signedData.getCRLs();
+
+ if (crlSet != null)
+ {
+ List crlList = new ArrayList(crlSet.size());
+
+ for (Enumeration en = crlSet.getObjects(); en.hasMoreElements();)
+ {
+ ASN1Primitive obj = ((ASN1Encodable)en.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1Sequence)
+ {
+ crlList.add(new X509CRLHolder(CertificateList.getInstance(obj)));
+ }
+ }
+
+ return new CollectionStore(crlList);
+ }
+
+ return new CollectionStore(new ArrayList());
+ }
+
+ public Store getAttributeCertificates()
+ {
+ ASN1Set certSet = signedData.getCertificates();
+
+ if (certSet != null)
+ {
+ List certList = new ArrayList(certSet.size());
+
+ for (Enumeration en = certSet.getObjects(); en.hasMoreElements();)
+ {
+ ASN1Primitive obj = ((ASN1Encodable)en.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ certList.add(new X509AttributeCertificateHolder(AttributeCertificate.getInstance(((ASN1TaggedObject)obj).getObject())));
+ }
+ }
+
+ return new CollectionStore(certList);
+ }
+
+ return new CollectionStore(new ArrayList());
+ }
+
+ /**
+ * Return the a string representation of the OID associated with the
+ * encapsulated content info structure carried in the signed data.
+ *
+ * @return the OID for the content type.
+ */
+ public String getSignedContentTypeOID()
+ {
+ return signedData.getEncapContentInfo().getContentType().getId();
+ }
+
+ public CMSTypedData getSignedContent()
+ {
+ return signedContent;
+ }
+
+ /**
+ * return the ContentInfo
+ * @deprecated use toASN1Structure()
+ */
+ public ContentInfo getContentInfo()
+ {
+ return contentInfo;
+ }
+
+ /**
+ * return the ContentInfo
+ */
+ public ContentInfo toASN1Structure()
+ {
+ return contentInfo;
+ }
+
+ /**
+ * return the ASN.1 encoded representation of this object.
+ */
+ public byte[] getEncoded()
+ throws IOException
+ {
+ return contentInfo.getEncoded();
+ }
+
+ /**
+ * Replace the signerinformation store associated with this
+ * CMSSignedData object with the new one passed in. You would
+ * probably only want to do this if you wanted to change the unsigned
+ * attributes associated with a signer, or perhaps delete one.
+ *
+ * @param signedData the signed data object to be used as a base.
+ * @param signerInformationStore the new signer information store to use.
+ * @return a new signed data object.
+ */
+ public static CMSSignedData replaceSigners(
+ CMSSignedData signedData,
+ SignerInformationStore signerInformationStore)
+ {
+ //
+ // copy
+ //
+ CMSSignedData cms = new CMSSignedData(signedData);
+
+ //
+ // replace the store
+ //
+ cms.signerInfoStore = signerInformationStore;
+
+ //
+ // replace the signers in the SignedData object
+ //
+ ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+
+ Iterator it = signerInformationStore.getSigners().iterator();
+ while (it.hasNext())
+ {
+ SignerInformation signer = (SignerInformation)it.next();
+ digestAlgs.add(CMSSignedHelper.INSTANCE.fixAlgID(signer.getDigestAlgorithmID()));
+ vec.add(signer.toASN1Structure());
+ }
+
+ ASN1Set digests = new DERSet(digestAlgs);
+ ASN1Set signers = new DERSet(vec);
+ ASN1Sequence sD = (ASN1Sequence)signedData.signedData.toASN1Primitive();
+
+ vec = new ASN1EncodableVector();
+
+ //
+ // signers are the last item in the sequence.
+ //
+ vec.add(sD.getObjectAt(0)); // version
+ vec.add(digests);
+
+ for (int i = 2; i != sD.size() - 1; i++)
+ {
+ vec.add(sD.getObjectAt(i));
+ }
+
+ vec.add(signers);
+
+ cms.signedData = SignedData.getInstance(new BERSequence(vec));
+
+ //
+ // replace the contentInfo with the new one
+ //
+ cms.contentInfo = new ContentInfo(cms.contentInfo.getContentType(), cms.signedData);
+
+ return cms;
+ }
+
+ /**
+ * Replace the certificate and CRL information associated with this
+ * CMSSignedData object with the new one passed in.
+ *
+ * @param signedData the signed data object to be used as a base.
+ * @param certsAndCrls the new certificates and CRLs to be used.
+ * @return a new signed data object.
+ * @exception CMSException if there is an error processing the CertStore
+ * @deprecated use method taking Store arguments.
+ */
+ public static CMSSignedData replaceCertificatesAndCRLs(
+ CMSSignedData signedData,
+ CertStore certsAndCrls)
+ throws CMSException
+ {
+ //
+ // copy
+ //
+ CMSSignedData cms = new CMSSignedData(signedData);
+
+ //
+ // replace the certs and crls in the SignedData object
+ //
+ ASN1Set certs = null;
+ ASN1Set crls = null;
+
+ try
+ {
+ ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCertificatesFromStore(certsAndCrls));
+
+ if (set.size() != 0)
+ {
+ certs = set;
+ }
+ }
+ catch (CertStoreException e)
+ {
+ throw new CMSException("error getting certs from certStore", e);
+ }
+
+ try
+ {
+ ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(certsAndCrls));
+
+ if (set.size() != 0)
+ {
+ crls = set;
+ }
+ }
+ catch (CertStoreException e)
+ {
+ throw new CMSException("error getting crls from certStore", e);
+ }
+
+ //
+ // replace the CMS structure.
+ //
+ cms.signedData = new SignedData(signedData.signedData.getDigestAlgorithms(),
+ signedData.signedData.getEncapContentInfo(),
+ certs,
+ crls,
+ signedData.signedData.getSignerInfos());
+
+ //
+ // replace the contentInfo with the new one
+ //
+ cms.contentInfo = new ContentInfo(cms.contentInfo.getContentType(), cms.signedData);
+
+ return cms;
+ }
+
+ /**
+ * Replace the certificate and CRL information associated with this
+ * CMSSignedData object with the new one passed in.
+ *
+ * @param signedData the signed data object to be used as a base.
+ * @param certificates the new certificates to be used.
+ * @param attrCerts the new attribute certificates to be used.
+ * @param crls the new CRLs to be used.
+ * @return a new signed data object.
+ * @exception CMSException if there is an error processing the CertStore
+ */
+ public static CMSSignedData replaceCertificatesAndCRLs(
+ CMSSignedData signedData,
+ Store certificates,
+ Store attrCerts,
+ Store crls)
+ throws CMSException
+ {
+ //
+ // copy
+ //
+ CMSSignedData cms = new CMSSignedData(signedData);
+
+ //
+ // replace the certs and crls in the SignedData object
+ //
+ ASN1Set certSet = null;
+ ASN1Set crlSet = null;
+
+ if (certificates != null || attrCerts != null)
+ {
+ List certs = new ArrayList();
+
+ if (certificates != null)
+ {
+ certs.addAll(CMSUtils.getCertificatesFromStore(certificates));
+ }
+ if (attrCerts != null)
+ {
+ certs.addAll(CMSUtils.getAttributeCertificatesFromStore(attrCerts));
+ }
+
+ ASN1Set set = CMSUtils.createBerSetFromList(certs);
+
+ if (set.size() != 0)
+ {
+ certSet = set;
+ }
+ }
+
+ if (crls != null)
+ {
+ ASN1Set set = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(crls));
+
+ if (set.size() != 0)
+ {
+ crlSet = set;
+ }
+ }
+
+ //
+ // replace the CMS structure.
+ //
+ cms.signedData = new SignedData(signedData.signedData.getDigestAlgorithms(),
+ signedData.signedData.getEncapContentInfo(),
+ certSet,
+ crlSet,
+ signedData.signedData.getSignerInfos());
+
+ //
+ // replace the contentInfo with the new one
+ //
+ cms.contentInfo = new ContentInfo(cms.contentInfo.getContentType(), cms.signedData);
+
+ return cms;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedDataParser.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedDataParser.java
new file mode 100644
index 00000000..6452b05a
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedDataParser.java
@@ -0,0 +1,1009 @@
+package org.bouncycastle.cms;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1Generator;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetStringParser;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1SequenceParser;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.ASN1SetParser;
+import org.bouncycastle.asn1.ASN1StreamParser;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.BERSequenceGenerator;
+import org.bouncycastle.asn1.BERSetParser;
+import org.bouncycastle.asn1.BERTaggedObject;
+import org.bouncycastle.asn1.BERTags;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
+import org.bouncycastle.asn1.cms.ContentInfoParser;
+import org.bouncycastle.asn1.cms.SignedDataParser;
+import org.bouncycastle.asn1.cms.SignerInfo;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.AttributeCertificate;
+import org.bouncycastle.asn1.x509.CertificateList;
+import org.bouncycastle.asn1.x509.Certificate;
+import org.bouncycastle.cert.X509AttributeCertificateHolder;
+import org.bouncycastle.cert.X509CRLHolder;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
+import org.bouncycastle.util.CollectionStore;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.util.io.Streams;
+import org.bouncycastle.x509.NoSuchStoreException;
+import org.bouncycastle.x509.X509Store;
+
+/**
+ * Parsing class for an CMS Signed Data object from an input stream.
+ * <p>
+ * Note: that because we are in a streaming mode only one signer can be tried and it is important
+ * that the methods on the parser are called in the appropriate order.
+ * </p>
+ * <p>
+ * A simple example of usage for an encapsulated signature.
+ * </p>
+ * <p>
+ * Two notes: first, in the example below the validity of
+ * the certificate isn't verified, just the fact that one of the certs
+ * matches the given signer, and, second, because we are in a streaming
+ * mode the order of the operations is important.
+ * </p>
+ * <pre>
+ * CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build(), encapSigData);
+ *
+ * sp.getSignedContent().drain();
+ *
+ * Store certStore = sp.getCertificates();
+ * SignerInformationStore signers = sp.getSignerInfos();
+ *
+ * Collection c = signers.getSigners();
+ * Iterator it = c.iterator();
+ *
+ * while (it.hasNext())
+ * {
+ * SignerInformation signer = (SignerInformation)it.next();
+ * Collection certCollection = certStore.getMatches(signer.getSID());
+ *
+ * Iterator certIt = certCollection.iterator();
+ * X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
+ *
+ * System.out.println("verify returns: " + signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert)));
+ * }
+ * </pre>
+ * Note also: this class does not introduce buffering - if you are processing large files you should create
+ * the parser with:
+ * <pre>
+ * CMSSignedDataParser ep = new CMSSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
+ * </pre>
+ * where bufSize is a suitably large buffer size.
+ */
+public class CMSSignedDataParser
+ extends CMSContentInfoParser
+{
+ private static final CMSSignedHelper HELPER = CMSSignedHelper.INSTANCE;
+
+ private SignedDataParser _signedData;
+ private ASN1ObjectIdentifier _signedContentType;
+ private CMSTypedStream _signedContent;
+ private Map digests;
+
+ private SignerInformationStore _signerInfoStore;
+ private X509Store _attributeStore;
+ private ASN1Set _certSet, _crlSet;
+ private boolean _isCertCrlParsed;
+ private X509Store _certificateStore;
+ private X509Store _crlStore;
+
+ /**
+ * @deprecated use method taking a DigestCalculatorProvider
+ */
+ public CMSSignedDataParser(
+ byte[] sigBlock)
+ throws CMSException
+ {
+ this(createDefaultDigestProvider(), new ByteArrayInputStream(sigBlock));
+ }
+
+
+ public CMSSignedDataParser(
+ DigestCalculatorProvider digestCalculatorProvider,
+ byte[] sigBlock)
+ throws CMSException
+ {
+ this(digestCalculatorProvider, new ByteArrayInputStream(sigBlock));
+ }
+
+ /**
+ * @deprecated use method taking digest calculator provider.
+ * @param signedContent
+ * @param sigBlock
+ * @throws CMSException
+ */
+ public CMSSignedDataParser(
+ CMSTypedStream signedContent,
+ byte[] sigBlock)
+ throws CMSException
+ {
+ this(createDefaultDigestProvider(), signedContent, new ByteArrayInputStream(sigBlock));
+ }
+
+ public CMSSignedDataParser(
+ DigestCalculatorProvider digestCalculatorProvider,
+ CMSTypedStream signedContent,
+ byte[] sigBlock)
+ throws CMSException
+ {
+ this(digestCalculatorProvider, signedContent, new ByteArrayInputStream(sigBlock));
+ }
+
+ private static DigestCalculatorProvider createDefaultDigestProvider()
+ throws CMSException
+ {
+ return new BcDigestCalculatorProvider();
+ }
+
+ /**
+ * base constructor - with encapsulated content
+ *
+ * @deprecated use method taking a DigestCalculatorProvider
+ */
+ public CMSSignedDataParser(
+ InputStream sigData)
+ throws CMSException
+ {
+ this(createDefaultDigestProvider(), null, sigData);
+ }
+
+ /**
+ * base constructor - with encapsulated content
+ */
+ public CMSSignedDataParser(
+ DigestCalculatorProvider digestCalculatorProvider,
+ InputStream sigData)
+ throws CMSException
+ {
+ this(digestCalculatorProvider, null, sigData);
+ }
+
+ /**
+ * base constructor
+ *
+ * @param signedContent the content that was signed.
+ * @param sigData the signature object stream.
+ * *
+ * @deprecated use method taking a DigestCalculatorProvider
+ */
+ public CMSSignedDataParser(
+ CMSTypedStream signedContent,
+ InputStream sigData)
+ throws CMSException
+ {
+ this(createDefaultDigestProvider(), signedContent, sigData);
+ }
+
+ /**
+ * base constructor
+ *
+ * @param digestCalculatorProvider for generating accumulating digests
+ * @param signedContent the content that was signed.
+ * @param sigData the signature object stream.
+ */
+ public CMSSignedDataParser(
+ DigestCalculatorProvider digestCalculatorProvider,
+ CMSTypedStream signedContent,
+ InputStream sigData)
+ throws CMSException
+ {
+ super(sigData);
+
+ try
+ {
+ _signedContent = signedContent;
+ _signedData = SignedDataParser.getInstance(_contentInfo.getContent(BERTags.SEQUENCE));
+ digests = new HashMap();
+
+ ASN1SetParser digAlgs = _signedData.getDigestAlgorithms();
+ ASN1Encodable o;
+
+ while ((o = digAlgs.readObject()) != null)
+ {
+ AlgorithmIdentifier algId = AlgorithmIdentifier.getInstance(o);
+ try
+ {
+ DigestCalculator calculator = digestCalculatorProvider.get(algId);
+
+ if (calculator != null)
+ {
+ this.digests.put(algId.getAlgorithm(), calculator);
+ }
+ }
+ catch (OperatorCreationException e)
+ {
+ // ignore
+ }
+ }
+
+ //
+ // If the message is simply a certificate chain message getContent() may return null.
+ //
+ ContentInfoParser cont = _signedData.getEncapContentInfo();
+ ASN1OctetStringParser octs = (ASN1OctetStringParser)
+ cont.getContent(BERTags.OCTET_STRING);
+
+ if (octs != null)
+ {
+ CMSTypedStream ctStr = new CMSTypedStream(
+ cont.getContentType().getId(), octs.getOctetStream());
+
+ if (_signedContent == null)
+ {
+ _signedContent = ctStr;
+ }
+ else
+ {
+ //
+ // content passed in, need to read past empty encapsulated content info object if present
+ //
+ ctStr.drain();
+ }
+ }
+
+ if (signedContent == null)
+ {
+ _signedContentType = cont.getContentType();
+ }
+ else
+ {
+ _signedContentType = _signedContent.getContentType();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("io exception: " + e.getMessage(), e);
+ }
+
+ if (digests.isEmpty())
+ {
+ throw new CMSException("no digests could be created for message.");
+ }
+ }
+
+ /**
+ * Return the version number for the SignedData object
+ *
+ * @return the version number
+ */
+ public int getVersion()
+ {
+ return _signedData.getVersion().getValue().intValue();
+ }
+
+ /**
+ * return the collection of signers that are associated with the
+ * signatures for the message.
+ * @throws CMSException
+ */
+ public SignerInformationStore getSignerInfos()
+ throws CMSException
+ {
+ if (_signerInfoStore == null)
+ {
+ populateCertCrlSets();
+
+ List signerInfos = new ArrayList();
+ Map hashes = new HashMap();
+
+ Iterator it = digests.keySet().iterator();
+ while (it.hasNext())
+ {
+ Object digestKey = it.next();
+
+ hashes.put(digestKey, ((DigestCalculator)digests.get(digestKey)).getDigest());
+ }
+
+ try
+ {
+ ASN1SetParser s = _signedData.getSignerInfos();
+ ASN1Encodable o;
+
+ while ((o = s.readObject()) != null)
+ {
+ SignerInfo info = SignerInfo.getInstance(o.toASN1Primitive());
+
+ byte[] hash = (byte[])hashes.get(info.getDigestAlgorithm().getAlgorithm());
+
+ signerInfos.add(new SignerInformation(info, _signedContentType, null, hash));
+ }
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("io exception: " + e.getMessage(), e);
+ }
+
+ _signerInfoStore = new SignerInformationStore(signerInfos);
+ }
+
+ return _signerInfoStore;
+ }
+
+ /**
+ * return a X509Store containing the attribute certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider name of provider to use
+ * @return a store of attribute certificates
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ */
+ public X509Store getAttributeCertificates(
+ String type,
+ String provider)
+ throws NoSuchStoreException, NoSuchProviderException, CMSException
+ {
+ return getAttributeCertificates(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a X509Store containing the attribute certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider provider to use
+ * @return a store of attribute certificates
+ * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ */
+ public X509Store getAttributeCertificates(
+ String type,
+ Provider provider)
+ throws NoSuchStoreException, CMSException
+ {
+ if (_attributeStore == null)
+ {
+ populateCertCrlSets();
+
+ _attributeStore = HELPER.createAttributeStore(type, provider, _certSet);
+ }
+
+ return _attributeStore;
+ }
+
+ /**
+ * return a X509Store containing the public key certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider provider to use
+ * @return a store of public key certificates
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use getCertificates()
+ */
+ public X509Store getCertificates(
+ String type,
+ String provider)
+ throws NoSuchStoreException, NoSuchProviderException, CMSException
+ {
+ return getCertificates(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a X509Store containing the public key certificates, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider provider to use
+ * @return a store of public key certificates
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use getCertificates()
+ */
+ public X509Store getCertificates(
+ String type,
+ Provider provider)
+ throws NoSuchStoreException, CMSException
+ {
+ if (_certificateStore == null)
+ {
+ populateCertCrlSets();
+
+ _certificateStore = HELPER.createCertificateStore(type, provider, _certSet);
+ }
+
+ return _certificateStore;
+ }
+
+ /**
+ * return a X509Store containing CRLs, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider name of provider to use
+ * @return a store of CRLs
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use getCRLs()
+ */
+ public X509Store getCRLs(
+ String type,
+ String provider)
+ throws NoSuchStoreException, NoSuchProviderException, CMSException
+ {
+ return getCRLs(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a X509Store containing CRLs, if any, contained
+ * in this message.
+ *
+ * @param type type of store to create
+ * @param provider provider to use
+ * @return a store of CRLs
+ * @exception NoSuchStoreException if the store type isn't available.
+ * @exception CMSException if a general exception prevents creation of the X509Store
+ * @deprecated use getCRLs()
+ */
+ public X509Store getCRLs(
+ String type,
+ Provider provider)
+ throws NoSuchStoreException, CMSException
+ {
+ if (_crlStore == null)
+ {
+ populateCertCrlSets();
+
+ _crlStore = HELPER.createCRLsStore(type, provider, _crlSet);
+ }
+
+ return _crlStore;
+ }
+
+ /**
+ * return a CertStore containing the certificates and CRLs associated with
+ * this message.
+ *
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchAlgorithmException if the cert store isn't available.
+ * @exception CMSException if a general exception prevents creation of the CertStore
+ * @deprecated use getCertificates()
+ */
+ public CertStore getCertificatesAndCRLs(
+ String type,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
+ {
+ return getCertificatesAndCRLs(type, CMSUtils.getProvider(provider));
+ }
+
+ /**
+ * return a CertStore containing the certificates and CRLs associated with
+ * this message.
+ *
+ * @exception NoSuchProviderException if the provider requested isn't available.
+ * @exception NoSuchAlgorithmException if the cert store isn't available.
+ * @exception CMSException if a general exception prevents creation of the CertStore
+ * @deprecated use getCertificates()
+ */
+ public CertStore getCertificatesAndCRLs(
+ String type,
+ Provider provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException, CMSException
+ {
+ populateCertCrlSets();
+
+ return HELPER.createCertStore(type, provider, _certSet, _crlSet);
+ }
+
+ public Store getCertificates()
+ throws CMSException
+ {
+ populateCertCrlSets();
+
+ ASN1Set certSet = _certSet;
+
+ if (certSet != null)
+ {
+ List certList = new ArrayList(certSet.size());
+
+ for (Enumeration en = certSet.getObjects(); en.hasMoreElements();)
+ {
+ ASN1Primitive obj = ((ASN1Encodable)en.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1Sequence)
+ {
+ certList.add(new X509CertificateHolder(Certificate.getInstance(obj)));
+ }
+ }
+
+ return new CollectionStore(certList);
+ }
+
+ return new CollectionStore(new ArrayList());
+ }
+
+ public Store getCRLs()
+ throws CMSException
+ {
+ populateCertCrlSets();
+
+ ASN1Set crlSet = _crlSet;
+
+ if (crlSet != null)
+ {
+ List crlList = new ArrayList(crlSet.size());
+
+ for (Enumeration en = crlSet.getObjects(); en.hasMoreElements();)
+ {
+ ASN1Primitive obj = ((ASN1Encodable)en.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1Sequence)
+ {
+ crlList.add(new X509CRLHolder(CertificateList.getInstance(obj)));
+ }
+ }
+
+ return new CollectionStore(crlList);
+ }
+
+ return new CollectionStore(new ArrayList());
+ }
+
+ public Store getAttributeCertificates()
+ throws CMSException
+ {
+ populateCertCrlSets();
+
+ ASN1Set certSet = _certSet;
+
+ if (certSet != null)
+ {
+ List certList = new ArrayList(certSet.size());
+
+ for (Enumeration en = certSet.getObjects(); en.hasMoreElements();)
+ {
+ ASN1Primitive obj = ((ASN1Encodable)en.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)obj;
+
+ if (tagged.getTagNo() == 2)
+ {
+ certList.add(new X509AttributeCertificateHolder(AttributeCertificate.getInstance(ASN1Sequence.getInstance(tagged, false))));
+ }
+ }
+ }
+
+ return new CollectionStore(certList);
+ }
+
+ return new CollectionStore(new ArrayList());
+ }
+
+ private void populateCertCrlSets()
+ throws CMSException
+ {
+ if (_isCertCrlParsed)
+ {
+ return;
+ }
+
+ _isCertCrlParsed = true;
+
+ try
+ {
+ // care! Streaming - these must be done in exactly this order.
+ _certSet = getASN1Set(_signedData.getCertificates());
+ _crlSet = getASN1Set(_signedData.getCrls());
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("problem parsing cert/crl sets", e);
+ }
+ }
+
+ /**
+ * Return the a string representation of the OID associated with the
+ * encapsulated content info structure carried in the signed data.
+ *
+ * @return the OID for the content type.
+ */
+ public String getSignedContentTypeOID()
+ {
+ return _signedContentType.getId();
+ }
+
+ public CMSTypedStream getSignedContent()
+ {
+ if (_signedContent == null)
+ {
+ return null;
+ }
+
+ InputStream digStream = CMSUtils.attachDigestsToInputStream(
+ digests.values(), _signedContent.getContentStream());
+
+ return new CMSTypedStream(_signedContent.getContentType(), digStream);
+ }
+
+ /**
+ * Replace the signerinformation store associated with the passed
+ * in message contained in the stream original with the new one passed in.
+ * You would probably only want to do this if you wanted to change the unsigned
+ * attributes associated with a signer, or perhaps delete one.
+ * <p>
+ * The output stream is returned unclosed.
+ * </p>
+ * @param original the signed data stream to be used as a base.
+ * @param signerInformationStore the new signer information store to use.
+ * @param out the stream to write the new signed data object to.
+ * @return out.
+ */
+ public static OutputStream replaceSigners(
+ InputStream original,
+ SignerInformationStore signerInformationStore,
+ OutputStream out)
+ throws CMSException, IOException
+ {
+ ASN1StreamParser in = new ASN1StreamParser(original);
+ ContentInfoParser contentInfo = new ContentInfoParser((ASN1SequenceParser)in.readObject());
+ SignedDataParser signedData = SignedDataParser.getInstance(contentInfo.getContent(BERTags.SEQUENCE));
+
+ BERSequenceGenerator sGen = new BERSequenceGenerator(out);
+
+ sGen.addObject(CMSObjectIdentifiers.signedData);
+
+ BERSequenceGenerator sigGen = new BERSequenceGenerator(sGen.getRawOutputStream(), 0, true);
+
+ // version number
+ sigGen.addObject(signedData.getVersion());
+
+ // digests
+ signedData.getDigestAlgorithms().toASN1Primitive(); // skip old ones
+
+ ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
+
+ for (Iterator it = signerInformationStore.getSigners().iterator(); it.hasNext();)
+ {
+ SignerInformation signer = (SignerInformation)it.next();
+ digestAlgs.add(CMSSignedHelper.INSTANCE.fixAlgID(signer.getDigestAlgorithmID()));
+ }
+
+ sigGen.getRawOutputStream().write(new DERSet(digestAlgs).getEncoded());
+
+ // encap content info
+ ContentInfoParser encapContentInfo = signedData.getEncapContentInfo();
+
+ BERSequenceGenerator eiGen = new BERSequenceGenerator(sigGen.getRawOutputStream());
+
+ eiGen.addObject(encapContentInfo.getContentType());
+
+ pipeEncapsulatedOctetString(encapContentInfo, eiGen.getRawOutputStream());
+
+ eiGen.close();
+
+
+ writeSetToGeneratorTagged(sigGen, signedData.getCertificates(), 0);
+ writeSetToGeneratorTagged(sigGen, signedData.getCrls(), 1);
+
+
+ ASN1EncodableVector signerInfos = new ASN1EncodableVector();
+ for (Iterator it = signerInformationStore.getSigners().iterator(); it.hasNext();)
+ {
+ SignerInformation signer = (SignerInformation)it.next();
+
+ signerInfos.add(signer.toASN1Structure());
+ }
+
+ sigGen.getRawOutputStream().write(new DERSet(signerInfos).getEncoded());
+
+ sigGen.close();
+
+ sGen.close();
+
+ return out;
+ }
+
+ /**
+ * Replace the certificate and CRL information associated with this
+ * CMSSignedData object with the new one passed in.
+ * <p>
+ * The output stream is returned unclosed.
+ * </p>
+ * @param original the signed data stream to be used as a base.
+ * @param certsAndCrls the new certificates and CRLs to be used.
+ * @param out the stream to write the new signed data object to.
+ * @return out.
+ * @exception CMSException if there is an error processing the CertStore
+ * @deprecated use method that takes Store objects.
+ */
+ public static OutputStream replaceCertificatesAndCRLs(
+ InputStream original,
+ CertStore certsAndCrls,
+ OutputStream out)
+ throws CMSException, IOException
+ {
+ ASN1StreamParser in = new ASN1StreamParser(original);
+ ContentInfoParser contentInfo = new ContentInfoParser((ASN1SequenceParser)in.readObject());
+ SignedDataParser signedData = SignedDataParser.getInstance(contentInfo.getContent(BERTags.SEQUENCE));
+
+ BERSequenceGenerator sGen = new BERSequenceGenerator(out);
+
+ sGen.addObject(CMSObjectIdentifiers.signedData);
+
+ BERSequenceGenerator sigGen = new BERSequenceGenerator(sGen.getRawOutputStream(), 0, true);
+
+ // version number
+ sigGen.addObject(signedData.getVersion());
+
+ // digests
+ sigGen.getRawOutputStream().write(signedData.getDigestAlgorithms().toASN1Primitive().getEncoded());
+
+ // encap content info
+ ContentInfoParser encapContentInfo = signedData.getEncapContentInfo();
+
+ BERSequenceGenerator eiGen = new BERSequenceGenerator(sigGen.getRawOutputStream());
+
+ eiGen.addObject(encapContentInfo.getContentType());
+
+ pipeEncapsulatedOctetString(encapContentInfo, eiGen.getRawOutputStream());
+
+ eiGen.close();
+
+ //
+ // skip existing certs and CRLs
+ //
+ getASN1Set(signedData.getCertificates());
+ getASN1Set(signedData.getCrls());
+
+ //
+ // replace the certs and crls in the SignedData object
+ //
+ ASN1Set certs;
+
+ try
+ {
+ certs = CMSUtils.createBerSetFromList(CMSUtils.getCertificatesFromStore(certsAndCrls));
+ }
+ catch (CertStoreException e)
+ {
+ throw new CMSException("error getting certs from certStore", e);
+ }
+
+ if (certs.size() > 0)
+ {
+ sigGen.getRawOutputStream().write(new DERTaggedObject(false, 0, certs).getEncoded());
+ }
+
+ ASN1Set crls;
+
+ try
+ {
+ crls = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(certsAndCrls));
+ }
+ catch (CertStoreException e)
+ {
+ throw new CMSException("error getting crls from certStore", e);
+ }
+
+ if (crls.size() > 0)
+ {
+ sigGen.getRawOutputStream().write(new DERTaggedObject(false, 1, crls).getEncoded());
+ }
+
+ sigGen.getRawOutputStream().write(signedData.getSignerInfos().toASN1Primitive().getEncoded());
+
+ sigGen.close();
+
+ sGen.close();
+
+ return out;
+ }
+
+ /**
+ * Replace the certificate and CRL information associated with this
+ * CMSSignedData object with the new one passed in.
+ * <p>
+ * The output stream is returned unclosed.
+ * </p>
+ * @param original the signed data stream to be used as a base.
+ * @param certs new certificates to be used, if any.
+ * @param crls new CRLs to be used, if any.
+ * @param attrCerts new attribute certificates to be used, if any.
+ * @param out the stream to write the new signed data object to.
+ * @return out.
+ * @exception CMSException if there is an error processing the CertStore
+ */
+ public static OutputStream replaceCertificatesAndCRLs(
+ InputStream original,
+ Store certs,
+ Store crls,
+ Store attrCerts,
+ OutputStream out)
+ throws CMSException, IOException
+ {
+ ASN1StreamParser in = new ASN1StreamParser(original);
+ ContentInfoParser contentInfo = new ContentInfoParser((ASN1SequenceParser)in.readObject());
+ SignedDataParser signedData = SignedDataParser.getInstance(contentInfo.getContent(BERTags.SEQUENCE));
+
+ BERSequenceGenerator sGen = new BERSequenceGenerator(out);
+
+ sGen.addObject(CMSObjectIdentifiers.signedData);
+
+ BERSequenceGenerator sigGen = new BERSequenceGenerator(sGen.getRawOutputStream(), 0, true);
+
+ // version number
+ sigGen.addObject(signedData.getVersion());
+
+ // digests
+ sigGen.getRawOutputStream().write(signedData.getDigestAlgorithms().toASN1Primitive().getEncoded());
+
+ // encap content info
+ ContentInfoParser encapContentInfo = signedData.getEncapContentInfo();
+
+ BERSequenceGenerator eiGen = new BERSequenceGenerator(sigGen.getRawOutputStream());
+
+ eiGen.addObject(encapContentInfo.getContentType());
+
+ pipeEncapsulatedOctetString(encapContentInfo, eiGen.getRawOutputStream());
+
+ eiGen.close();
+
+ //
+ // skip existing certs and CRLs
+ //
+ getASN1Set(signedData.getCertificates());
+ getASN1Set(signedData.getCrls());
+
+ //
+ // replace the certs and crls in the SignedData object
+ //
+ if (certs != null || attrCerts != null)
+ {
+ List certificates = new ArrayList();
+
+ if (certs != null)
+ {
+ certificates.addAll(CMSUtils.getCertificatesFromStore(certs));
+ }
+ if (attrCerts != null)
+ {
+ certificates.addAll(CMSUtils.getAttributeCertificatesFromStore(attrCerts));
+ }
+
+ ASN1Set asn1Certs = CMSUtils.createBerSetFromList(certificates);
+
+ if (asn1Certs.size() > 0)
+ {
+ sigGen.getRawOutputStream().write(new DERTaggedObject(false, 0, asn1Certs).getEncoded());
+ }
+ }
+
+ if (crls != null)
+ {
+ ASN1Set asn1Crls = CMSUtils.createBerSetFromList(CMSUtils.getCRLsFromStore(crls));
+
+ if (asn1Crls.size() > 0)
+ {
+ sigGen.getRawOutputStream().write(new DERTaggedObject(false, 1, asn1Crls).getEncoded());
+ }
+ }
+
+ sigGen.getRawOutputStream().write(signedData.getSignerInfos().toASN1Primitive().getEncoded());
+
+ sigGen.close();
+
+ sGen.close();
+
+ return out;
+ }
+
+ private static void writeSetToGeneratorTagged(
+ ASN1Generator asn1Gen,
+ ASN1SetParser asn1SetParser,
+ int tagNo)
+ throws IOException
+ {
+ ASN1Set asn1Set = getASN1Set(asn1SetParser);
+
+ if (asn1Set != null)
+ {
+ if (asn1SetParser instanceof BERSetParser)
+ {
+ asn1Gen.getRawOutputStream().write(new BERTaggedObject(false, tagNo, asn1Set).getEncoded());
+ }
+ else
+ {
+ asn1Gen.getRawOutputStream().write(new DERTaggedObject(false, tagNo, asn1Set).getEncoded());
+ }
+ }
+ }
+
+ private static ASN1Set getASN1Set(
+ ASN1SetParser asn1SetParser)
+ {
+ return asn1SetParser == null
+ ? null
+ : ASN1Set.getInstance(asn1SetParser.toASN1Primitive());
+ }
+
+ private static void pipeEncapsulatedOctetString(ContentInfoParser encapContentInfo,
+ OutputStream rawOutputStream) throws IOException
+ {
+ ASN1OctetStringParser octs = (ASN1OctetStringParser)
+ encapContentInfo.getContent(BERTags.OCTET_STRING);
+
+ if (octs != null)
+ {
+ pipeOctetString(octs, rawOutputStream);
+ }
+
+// BERTaggedObjectParser contentObject = (BERTaggedObjectParser)encapContentInfo.getContentObject();
+// if (contentObject != null)
+// {
+// // Handle IndefiniteLengthInputStream safely
+// InputStream input = ASN1StreamParser.getSafeRawInputStream(contentObject.getContentStream(true));
+//
+// // TODO BerTaggedObjectGenerator?
+// BEROutputStream berOut = new BEROutputStream(rawOutputStream);
+// berOut.write(DERTags.CONSTRUCTED | DERTags.TAGGED | 0);
+// berOut.write(0x80);
+//
+// pipeRawOctetString(input, rawOutputStream);
+//
+// berOut.write(0x00);
+// berOut.write(0x00);
+//
+// input.close();
+// }
+ }
+
+ private static void pipeOctetString(
+ ASN1OctetStringParser octs,
+ OutputStream output)
+ throws IOException
+ {
+ // TODO Allow specification of a specific fragment size?
+ OutputStream outOctets = CMSUtils.createBEROctetOutputStream(
+ output, 0, true, 0);
+ Streams.pipeAll(octs.getOctetStream(), outOctets);
+ outOctets.close();
+ }
+
+// private static void pipeRawOctetString(
+// InputStream rawInput,
+// OutputStream rawOutput)
+// throws IOException
+// {
+// InputStream tee = new TeeInputStream(rawInput, rawOutput);
+// ASN1StreamParser sp = new ASN1StreamParser(tee);
+// ASN1OctetStringParser octs = (ASN1OctetStringParser)sp.readObject();
+// Streams.drain(octs.getOctetStream());
+// }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedGenerator.java
new file mode 100644
index 00000000..4ef4f007
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedGenerator.java
@@ -0,0 +1,281 @@
+package org.bouncycastle.cms;
+
+import java.io.IOException;
+import java.security.AlgorithmParameters;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.AttributeCertificate;
+import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.jce.interfaces.GOST3410PrivateKey;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.x509.X509AttributeCertificate;
+import org.bouncycastle.x509.X509Store;
+
+public class CMSSignedGenerator
+{
+ /**
+ * Default type for the signed data.
+ */
+ public static final String DATA = CMSObjectIdentifiers.data.getId();
+
+ public static final String DIGEST_SHA1 = OIWObjectIdentifiers.idSHA1.getId();
+ public static final String DIGEST_SHA224 = NISTObjectIdentifiers.id_sha224.getId();
+ public static final String DIGEST_SHA256 = NISTObjectIdentifiers.id_sha256.getId();
+ public static final String DIGEST_SHA384 = NISTObjectIdentifiers.id_sha384.getId();
+ public static final String DIGEST_SHA512 = NISTObjectIdentifiers.id_sha512.getId();
+ public static final String DIGEST_MD5 = PKCSObjectIdentifiers.md5.getId();
+ public static final String DIGEST_GOST3411 = CryptoProObjectIdentifiers.gostR3411.getId();
+ public static final String DIGEST_RIPEMD128 = TeleTrusTObjectIdentifiers.ripemd128.getId();
+ public static final String DIGEST_RIPEMD160 = TeleTrusTObjectIdentifiers.ripemd160.getId();
+ public static final String DIGEST_RIPEMD256 = TeleTrusTObjectIdentifiers.ripemd256.getId();
+
+ public static final String ENCRYPTION_RSA = PKCSObjectIdentifiers.rsaEncryption.getId();
+ public static final String ENCRYPTION_DSA = X9ObjectIdentifiers.id_dsa_with_sha1.getId();
+ public static final String ENCRYPTION_ECDSA = X9ObjectIdentifiers.ecdsa_with_SHA1.getId();
+ public static final String ENCRYPTION_RSA_PSS = PKCSObjectIdentifiers.id_RSASSA_PSS.getId();
+ public static final String ENCRYPTION_GOST3410 = CryptoProObjectIdentifiers.gostR3410_94.getId();
+ public static final String ENCRYPTION_ECGOST3410 = CryptoProObjectIdentifiers.gostR3410_2001.getId();
+
+ private static final String ENCRYPTION_ECDSA_WITH_SHA1 = X9ObjectIdentifiers.ecdsa_with_SHA1.getId();
+ private static final String ENCRYPTION_ECDSA_WITH_SHA224 = X9ObjectIdentifiers.ecdsa_with_SHA224.getId();
+ private static final String ENCRYPTION_ECDSA_WITH_SHA256 = X9ObjectIdentifiers.ecdsa_with_SHA256.getId();
+ private static final String ENCRYPTION_ECDSA_WITH_SHA384 = X9ObjectIdentifiers.ecdsa_with_SHA384.getId();
+ private static final String ENCRYPTION_ECDSA_WITH_SHA512 = X9ObjectIdentifiers.ecdsa_with_SHA512.getId();
+
+ private static final Set NO_PARAMS = new HashSet();
+ private static final Map EC_ALGORITHMS = new HashMap();
+
+ static
+ {
+ NO_PARAMS.add(ENCRYPTION_DSA);
+ NO_PARAMS.add(ENCRYPTION_ECDSA);
+ NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA1);
+ NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA224);
+ NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA256);
+ NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA384);
+ NO_PARAMS.add(ENCRYPTION_ECDSA_WITH_SHA512);
+
+ EC_ALGORITHMS.put(DIGEST_SHA1, ENCRYPTION_ECDSA_WITH_SHA1);
+ EC_ALGORITHMS.put(DIGEST_SHA224, ENCRYPTION_ECDSA_WITH_SHA224);
+ EC_ALGORITHMS.put(DIGEST_SHA256, ENCRYPTION_ECDSA_WITH_SHA256);
+ EC_ALGORITHMS.put(DIGEST_SHA384, ENCRYPTION_ECDSA_WITH_SHA384);
+ EC_ALGORITHMS.put(DIGEST_SHA512, ENCRYPTION_ECDSA_WITH_SHA512);
+ }
+
+ protected List certs = new ArrayList();
+ protected List crls = new ArrayList();
+ protected List _signers = new ArrayList();
+ protected List signerGens = new ArrayList();
+ protected Map digests = new HashMap();
+
+ protected SecureRandom rand;
+
+ /**
+ * base constructor
+ */
+ protected CMSSignedGenerator()
+ {
+ this(new SecureRandom());
+ }
+
+ /**
+ * constructor allowing specific source of randomness
+ * @param rand instance of SecureRandom to use
+ */
+ protected CMSSignedGenerator(
+ SecureRandom rand)
+ {
+ this.rand = rand;
+ }
+
+ protected String getEncOID(
+ PrivateKey key,
+ String digestOID)
+ {
+ String encOID = null;
+
+ if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm()))
+ {
+ encOID = ENCRYPTION_RSA;
+ }
+ else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm()))
+ {
+ encOID = ENCRYPTION_DSA;
+ if (!digestOID.equals(DIGEST_SHA1))
+ {
+ throw new IllegalArgumentException("can't mix DSA with anything but SHA1");
+ }
+ }
+ else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm()) || "EC".equalsIgnoreCase(key.getAlgorithm()))
+ {
+ encOID = (String)EC_ALGORITHMS.get(digestOID);
+ if (encOID == null)
+ {
+ throw new IllegalArgumentException("can't mix ECDSA with anything but SHA family digests");
+ }
+ }
+ else if (key instanceof GOST3410PrivateKey || "GOST3410".equalsIgnoreCase(key.getAlgorithm()))
+ {
+ encOID = ENCRYPTION_GOST3410;
+ }
+ else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm()))
+ {
+ encOID = ENCRYPTION_ECGOST3410;
+ }
+
+ return encOID;
+ }
+
+ protected Map getBaseParameters(DERObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash)
+ {
+ Map param = new HashMap();
+ param.put(CMSAttributeTableGenerator.CONTENT_TYPE, contentType);
+ param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId);
+ param.put(CMSAttributeTableGenerator.DIGEST, hash.clone());
+ return param;
+ }
+
+ protected ASN1Set getAttributeSet(
+ AttributeTable attr)
+ {
+ if (attr != null)
+ {
+ return new DERSet(attr.toASN1EncodableVector());
+ }
+
+ return null;
+ }
+
+ /**
+ * add the certificates and CRLs contained in the given CertStore
+ * to the pool that will be included in the encoded signature block.
+ * <p>
+ * Note: this assumes the CertStore will support null in the get
+ * methods.
+ * @param certStore CertStore containing the public key certificates and CRLs
+ * @throws org.bouncycastle.jce.cert.CertStoreException if an issue occurs processing the CertStore
+ * @throws CMSException if an issue occurse transforming data from the CertStore into the message
+ * @deprecated use addCertificates and addCRLs
+ */
+ public void addCertificatesAndCRLs(
+ CertStore certStore)
+ throws CertStoreException, CMSException
+ {
+ certs.addAll(CMSUtils.getCertificatesFromStore(certStore));
+ crls.addAll(CMSUtils.getCRLsFromStore(certStore));
+ }
+
+ public void addCertificates(
+ Store certStore)
+ throws CMSException
+ {
+ certs.addAll(CMSUtils.getCertificatesFromStore(certStore));
+ }
+
+ public void addCRLs(
+ Store crlStore)
+ throws CMSException
+ {
+ crls.addAll(CMSUtils.getCRLsFromStore(crlStore));
+ }
+
+ public void addAttributeCertificates(
+ Store attrStore)
+ throws CMSException
+ {
+ certs.addAll(CMSUtils.getAttributeCertificatesFromStore(attrStore));
+ }
+
+ /**
+ * Add the attribute certificates contained in the passed in store to the
+ * generator.
+ *
+ * @param store a store of Version 2 attribute certificates
+ * @throws CMSException if an error occurse processing the store.
+ * @deprecated use basic Store method
+ */
+ public void addAttributeCertificates(
+ X509Store store)
+ throws CMSException
+ {
+ try
+ {
+ for (Iterator it = store.getMatches(null).iterator(); it.hasNext();)
+ {
+ X509AttributeCertificate attrCert = (X509AttributeCertificate)it.next();
+
+ certs.add(new DERTaggedObject(false, 2,
+ AttributeCertificate.getInstance(ASN1Primitive.fromByteArray(attrCert.getEncoded()))));
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("error processing attribute certs", e);
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("error processing attribute certs", e);
+ }
+ }
+
+
+ /**
+ * Add a store of precalculated signers to the generator.
+ *
+ * @param signerStore store of signers
+ */
+ public void addSigners(
+ SignerInformationStore signerStore)
+ {
+ Iterator it = signerStore.getSigners().iterator();
+
+ while (it.hasNext())
+ {
+ _signers.add(it.next());
+ }
+ }
+
+ public void addSignerInfoGenerator(SignerInfoGenerator infoGen)
+ {
+ signerGens.add(infoGen);
+ }
+
+ /**
+ * Return a map of oids and byte arrays representing the digests calculated on the content during
+ * the last generate.
+ *
+ * @return a map of oids (as String objects) and byte[] representing digests.
+ */
+ public Map getGeneratedDigests()
+ {
+ return new HashMap(digests);
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedHelper.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedHelper.java
new file mode 100644
index 00000000..80822f47
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSSignedHelper.java
@@ -0,0 +1,414 @@
+package org.bouncycastle.cms;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.cert.CRLException;
+import java.security.cert.CertStore;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CollectionCertStoreParameters;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.ASN1TaggedObject;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
+import org.bouncycastle.asn1.eac.EACObjectIdentifiers;
+import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
+import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import org.bouncycastle.x509.NoSuchStoreException;
+import org.bouncycastle.x509.X509CollectionStoreParameters;
+import org.bouncycastle.x509.X509Store;
+import org.bouncycastle.x509.X509V2AttributeCertificate;
+
+class CMSSignedHelper
+{
+ static final CMSSignedHelper INSTANCE = new CMSSignedHelper();
+
+ private static final Map encryptionAlgs = new HashMap();
+ private static final Map digestAlgs = new HashMap();
+ private static final Map digestAliases = new HashMap();
+
+ private static void addEntries(DERObjectIdentifier alias, String digest, String encryption)
+ {
+ digestAlgs.put(alias.getId(), digest);
+ encryptionAlgs.put(alias.getId(), encryption);
+ }
+
+ static
+ {
+ addEntries(NISTObjectIdentifiers.dsa_with_sha224, "SHA224", "DSA");
+ addEntries(NISTObjectIdentifiers.dsa_with_sha256, "SHA256", "DSA");
+ addEntries(NISTObjectIdentifiers.dsa_with_sha384, "SHA384", "DSA");
+ addEntries(NISTObjectIdentifiers.dsa_with_sha512, "SHA512", "DSA");
+ addEntries(OIWObjectIdentifiers.dsaWithSHA1, "SHA1", "DSA");
+ addEntries(OIWObjectIdentifiers.md4WithRSA, "MD4", "RSA");
+ addEntries(OIWObjectIdentifiers.md4WithRSAEncryption, "MD4", "RSA");
+ addEntries(OIWObjectIdentifiers.md5WithRSA, "MD5", "RSA");
+ addEntries(OIWObjectIdentifiers.sha1WithRSA, "SHA1", "RSA");
+ addEntries(PKCSObjectIdentifiers.md2WithRSAEncryption, "MD2", "RSA");
+ addEntries(PKCSObjectIdentifiers.md4WithRSAEncryption, "MD4", "RSA");
+ addEntries(PKCSObjectIdentifiers.md5WithRSAEncryption, "MD5", "RSA");
+ addEntries(PKCSObjectIdentifiers.sha1WithRSAEncryption, "SHA1", "RSA");
+ addEntries(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224", "RSA");
+ addEntries(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256", "RSA");
+ addEntries(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384", "RSA");
+ addEntries(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512", "RSA");
+ addEntries(X9ObjectIdentifiers.ecdsa_with_SHA1, "SHA1", "ECDSA");
+ addEntries(X9ObjectIdentifiers.ecdsa_with_SHA224, "SHA224", "ECDSA");
+ addEntries(X9ObjectIdentifiers.ecdsa_with_SHA256, "SHA256", "ECDSA");
+ addEntries(X9ObjectIdentifiers.ecdsa_with_SHA384, "SHA384", "ECDSA");
+ addEntries(X9ObjectIdentifiers.ecdsa_with_SHA512, "SHA512", "ECDSA");
+ addEntries(X9ObjectIdentifiers.id_dsa_with_sha1, "SHA1", "DSA");
+ addEntries(EACObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1", "ECDSA");
+ addEntries(EACObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224", "ECDSA");
+ addEntries(EACObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256", "ECDSA");
+ addEntries(EACObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384", "ECDSA");
+ addEntries(EACObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512", "ECDSA");
+ addEntries(EACObjectIdentifiers.id_TA_RSA_v1_5_SHA_1, "SHA1", "RSA");
+ addEntries(EACObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA");
+ addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1");
+ addEntries(EACObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1");
+
+ encryptionAlgs.put(X9ObjectIdentifiers.id_dsa.getId(), "DSA");
+ encryptionAlgs.put(PKCSObjectIdentifiers.rsaEncryption.getId(), "RSA");
+ encryptionAlgs.put(TeleTrusTObjectIdentifiers.teleTrusTRSAsignatureAlgorithm, "RSA");
+ encryptionAlgs.put(X509ObjectIdentifiers.id_ea_rsa.getId(), "RSA");
+ encryptionAlgs.put(CMSSignedDataGenerator.ENCRYPTION_RSA_PSS, "RSAandMGF1");
+ encryptionAlgs.put(CryptoProObjectIdentifiers.gostR3410_94.getId(), "GOST3410");
+ encryptionAlgs.put(CryptoProObjectIdentifiers.gostR3410_2001.getId(), "ECGOST3410");
+ encryptionAlgs.put("1.3.6.1.4.1.5849.1.6.2", "ECGOST3410");
+ encryptionAlgs.put("1.3.6.1.4.1.5849.1.1.5", "GOST3410");
+ encryptionAlgs.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001.getId(), "ECGOST3410");
+ encryptionAlgs.put(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94.getId(), "GOST3410");
+
+ digestAlgs.put(PKCSObjectIdentifiers.md2.getId(), "MD2");
+ digestAlgs.put(PKCSObjectIdentifiers.md4.getId(), "MD4");
+ digestAlgs.put(PKCSObjectIdentifiers.md5.getId(), "MD5");
+ digestAlgs.put(OIWObjectIdentifiers.idSHA1.getId(), "SHA1");
+ digestAlgs.put(NISTObjectIdentifiers.id_sha224.getId(), "SHA224");
+ digestAlgs.put(NISTObjectIdentifiers.id_sha256.getId(), "SHA256");
+ digestAlgs.put(NISTObjectIdentifiers.id_sha384.getId(), "SHA384");
+ digestAlgs.put(NISTObjectIdentifiers.id_sha512.getId(), "SHA512");
+ digestAlgs.put(TeleTrusTObjectIdentifiers.ripemd128.getId(), "RIPEMD128");
+ digestAlgs.put(TeleTrusTObjectIdentifiers.ripemd160.getId(), "RIPEMD160");
+ digestAlgs.put(TeleTrusTObjectIdentifiers.ripemd256.getId(), "RIPEMD256");
+ digestAlgs.put(CryptoProObjectIdentifiers.gostR3411.getId(), "GOST3411");
+ digestAlgs.put("1.3.6.1.4.1.5849.1.2.1", "GOST3411");
+
+ digestAliases.put("SHA1", new String[] { "SHA-1" });
+ digestAliases.put("SHA224", new String[] { "SHA-224" });
+ digestAliases.put("SHA256", new String[] { "SHA-256" });
+ digestAliases.put("SHA384", new String[] { "SHA-384" });
+ digestAliases.put("SHA512", new String[] { "SHA-512" });
+ }
+
+ /**
+ * Return the digest algorithm using one of the standard JCA string
+ * representations rather than the algorithm identifier (if possible).
+ */
+ String getDigestAlgName(
+ String digestAlgOID)
+ {
+ String algName = (String)digestAlgs.get(digestAlgOID);
+
+ if (algName != null)
+ {
+ return algName;
+ }
+
+ return digestAlgOID;
+ }
+
+ /**
+ * Return the digest encryption algorithm using one of the standard
+ * JCA string representations rather the the algorithm identifier (if
+ * possible).
+ */
+ String getEncryptionAlgName(
+ String encryptionAlgOID)
+ {
+ String algName = (String)encryptionAlgs.get(encryptionAlgOID);
+
+ if (algName != null)
+ {
+ return algName;
+ }
+
+ return encryptionAlgOID;
+ }
+
+
+ X509Store createAttributeStore(
+ String type,
+ Provider provider,
+ ASN1Set certSet)
+ throws NoSuchStoreException, CMSException
+ {
+ List certs = new ArrayList();
+
+ if (certSet != null)
+ {
+ Enumeration e = certSet.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ try
+ {
+ ASN1Primitive obj = ((ASN1Encodable)e.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)obj;
+
+ if (tagged.getTagNo() == 2)
+ {
+ certs.add(new X509V2AttributeCertificate(ASN1Sequence.getInstance(tagged, false).getEncoded()));
+ }
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new CMSException(
+ "can't re-encode attribute certificate!", ex);
+ }
+ }
+ }
+
+ try
+ {
+ return X509Store.getInstance(
+ "AttributeCertificate/" +type, new X509CollectionStoreParameters(certs), provider);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("can't setup the X509Store", e);
+ }
+ }
+
+ X509Store createCertificateStore(
+ String type,
+ Provider provider,
+ ASN1Set certSet)
+ throws NoSuchStoreException, CMSException
+ {
+ List certs = new ArrayList();
+
+ if (certSet != null)
+ {
+ addCertsFromSet(certs, certSet, provider);
+ }
+
+ try
+ {
+ return X509Store.getInstance(
+ "Certificate/" +type, new X509CollectionStoreParameters(certs), provider);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("can't setup the X509Store", e);
+ }
+ }
+
+ X509Store createCRLsStore(
+ String type,
+ Provider provider,
+ ASN1Set crlSet)
+ throws NoSuchStoreException, CMSException
+ {
+ List crls = new ArrayList();
+
+ if (crlSet != null)
+ {
+ addCRLsFromSet(crls, crlSet, provider);
+ }
+
+ try
+ {
+ return X509Store.getInstance(
+ "CRL/" +type, new X509CollectionStoreParameters(crls), provider);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("can't setup the X509Store", e);
+ }
+ }
+
+ CertStore createCertStore(
+ String type,
+ Provider provider,
+ ASN1Set certSet,
+ ASN1Set crlSet)
+ throws CMSException, NoSuchAlgorithmException
+ {
+ List certsAndcrls = new ArrayList();
+
+ //
+ // load the certificates and revocation lists if we have any
+ //
+
+ if (certSet != null)
+ {
+ addCertsFromSet(certsAndcrls, certSet, provider);
+ }
+
+ if (crlSet != null)
+ {
+ addCRLsFromSet(certsAndcrls, crlSet, provider);
+ }
+
+ try
+ {
+ if (provider != null)
+ {
+ return CertStore.getInstance(type, new CollectionCertStoreParameters(certsAndcrls), provider.getName());
+ }
+ else
+ {
+ return CertStore.getInstance(type, new CollectionCertStoreParameters(certsAndcrls));
+ }
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new CMSException("can't setup the CertStore", e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("can't setup the CertStore", e);
+ }
+ }
+
+ private void addCertsFromSet(List certs, ASN1Set certSet, Provider provider)
+ throws CMSException
+ {
+ CertificateFactory cf;
+
+ try
+ {
+ if (provider != null)
+ {
+ cf = CertificateFactory.getInstance("X.509", provider.getName());
+ }
+ else
+ {
+ cf = CertificateFactory.getInstance("X.509");
+ }
+ }
+ catch (CertificateException ex)
+ {
+ throw new CMSException("can't get certificate factory.", ex);
+ }
+ catch (NoSuchProviderException ex)
+ {
+ throw new CMSException("can't get certificate factory.", ex);
+ }
+ Enumeration e = certSet.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ try
+ {
+ ASN1Primitive obj = ((ASN1Encodable)e.nextElement()).toASN1Primitive();
+
+ if (obj instanceof ASN1Sequence)
+ {
+ certs.add(cf.generateCertificate(
+ new ByteArrayInputStream(obj.getEncoded())));
+ }
+ }
+ catch (IOException ex)
+ {
+ throw new CMSException(
+ "can't re-encode certificate!", ex);
+ }
+ catch (CertificateException ex)
+ {
+ throw new CMSException(
+ "can't re-encode certificate!", ex);
+ }
+ }
+ }
+
+ private void addCRLsFromSet(List crls, ASN1Set certSet, Provider provider)
+ throws CMSException
+ {
+ CertificateFactory cf;
+
+ try
+ {
+ if (provider != null)
+ {
+ cf = CertificateFactory.getInstance("X.509", provider.getName());
+ }
+ else
+ {
+ cf = CertificateFactory.getInstance("X.509");
+ }
+ }
+ catch (CertificateException ex)
+ {
+ throw new CMSException("can't get certificate factory.", ex);
+ }
+ catch (NoSuchProviderException ex)
+ {
+ throw new CMSException("can't get certificate factory.", ex);
+ }
+ Enumeration e = certSet.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ try
+ {
+ ASN1Primitive obj = ((ASN1Encodable)e.nextElement()).toASN1Primitive();
+
+ crls.add(cf.generateCRL(
+ new ByteArrayInputStream(obj.getEncoded())));
+ }
+ catch (IOException ex)
+ {
+ throw new CMSException("can't re-encode CRL!", ex);
+ }
+ catch (CRLException ex)
+ {
+ throw new CMSException("can't re-encode CRL!", ex);
+ }
+ }
+ }
+
+ AlgorithmIdentifier fixAlgID(AlgorithmIdentifier algId)
+ {
+ if (algId.getParameters() == null)
+ {
+ return new AlgorithmIdentifier(algId.getObjectId(), DERNull.INSTANCE);
+ }
+
+ return algId;
+ }
+
+ void setSigningEncryptionAlgorithmMapping(DERObjectIdentifier oid, String algorithmName)
+ {
+ encryptionAlgs.put(oid.getId(), algorithmName);
+ }
+
+ void setSigningDigestAlgorithmMapping(DERObjectIdentifier oid, String algorithmName)
+ {
+ digestAlgs.put(oid.getId(), algorithmName);
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSTypedStream.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSTypedStream.java
new file mode 100644
index 00000000..5aa42ed0
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSTypedStream.java
@@ -0,0 +1,86 @@
+package org.bouncycastle.cms;
+
+import java.io.BufferedInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.util.io.Streams;
+
+public class CMSTypedStream
+{
+ private static final int BUF_SIZ = 32 * 1024;
+
+ private ASN1ObjectIdentifier _oid;
+ private InputStream _in;
+
+ public CMSTypedStream(
+ InputStream in)
+ {
+ this(PKCSObjectIdentifiers.data.getId(), in, BUF_SIZ);
+ }
+
+ public CMSTypedStream(
+ String oid,
+ InputStream in)
+ {
+ this(new ASN1ObjectIdentifier(oid), in, BUF_SIZ);
+ }
+
+ public CMSTypedStream(
+ String oid,
+ InputStream in,
+ int bufSize)
+ {
+ this(new ASN1ObjectIdentifier(oid), in, bufSize);
+ }
+
+ public CMSTypedStream(
+ ASN1ObjectIdentifier oid,
+ InputStream in)
+ {
+ this(oid, in, BUF_SIZ);
+ }
+
+ public CMSTypedStream(
+ ASN1ObjectIdentifier oid,
+ InputStream in,
+ int bufSize)
+ {
+ _oid = oid;
+ _in = new FullReaderStream(new BufferedInputStream(in, bufSize));
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return _oid;
+ }
+
+ public InputStream getContentStream()
+ {
+ return _in;
+ }
+
+ public void drain()
+ throws IOException
+ {
+ Streams.drain(_in);
+ _in.close();
+ }
+
+ private static class FullReaderStream extends FilterInputStream
+ {
+ FullReaderStream(InputStream in)
+ {
+ super(in);
+ }
+
+ public int read(byte[] buf, int off, int len) throws IOException
+ {
+ int totalRead = Streams.readFully(super.in, buf, off, len);
+ return totalRead > 0 ? totalRead : -1;
+ }
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSUtils.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSUtils.java
new file mode 100644
index 00000000..75c6beba
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/CMSUtils.java
@@ -0,0 +1,337 @@
+package org.bouncycastle.cms;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.NoSuchProviderException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.cert.CRLException;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.BEROctetStringGenerator;
+import org.bouncycastle.asn1.BERSet;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.DERTaggedObject;
+import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
+import org.bouncycastle.asn1.x509.CertificateList;
+import org.bouncycastle.asn1.x509.TBSCertificateStructure;
+import org.bouncycastle.asn1.x509.X509CertificateStructure;
+import org.bouncycastle.cert.X509AttributeCertificateHolder;
+import org.bouncycastle.cert.X509CRLHolder;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.util.io.Streams;
+import org.bouncycastle.util.io.TeeInputStream;
+import org.bouncycastle.util.io.TeeOutputStream;
+
+class CMSUtils
+{
+ static ContentInfo readContentInfo(
+ byte[] input)
+ throws CMSException
+ {
+ // enforce limit checking as from a byte array
+ return readContentInfo(new ASN1InputStream(input));
+ }
+
+ static ContentInfo readContentInfo(
+ InputStream input)
+ throws CMSException
+ {
+ // enforce some limit checking
+ return readContentInfo(new ASN1InputStream(input));
+ }
+
+ static List getCertificatesFromStore(CertStore certStore)
+ throws CertStoreException, CMSException
+ {
+ List certs = new ArrayList();
+
+ try
+ {
+ for (Iterator it = certStore.getCertificates(null).iterator(); it.hasNext();)
+ {
+ X509Certificate c = (X509Certificate)it.next();
+
+ certs.add(X509CertificateStructure.getInstance(
+ ASN1Primitive.fromByteArray(c.getEncoded())));
+ }
+
+ return certs;
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("error processing certs", e);
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("error processing certs", e);
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new CMSException("error encoding certs", e);
+ }
+ }
+
+ static List getCertificatesFromStore(Store certStore)
+ throws CMSException
+ {
+ List certs = new ArrayList();
+
+ try
+ {
+ for (Iterator it = certStore.getMatches(null).iterator(); it.hasNext();)
+ {
+ X509CertificateHolder c = (X509CertificateHolder)it.next();
+
+ certs.add(c.toASN1Structure());
+ }
+
+ return certs;
+ }
+ catch (ClassCastException e)
+ {
+ throw new CMSException("error processing certs", e);
+ }
+ }
+
+ static List getAttributeCertificatesFromStore(Store attrStore)
+ throws CMSException
+ {
+ List certs = new ArrayList();
+
+ try
+ {
+ for (Iterator it = attrStore.getMatches(null).iterator(); it.hasNext();)
+ {
+ X509AttributeCertificateHolder attrCert = (X509AttributeCertificateHolder)it.next();
+
+ certs.add(new DERTaggedObject(false, 2, attrCert.toASN1Structure()));
+ }
+
+ return certs;
+ }
+ catch (ClassCastException e)
+ {
+ throw new CMSException("error processing certs", e);
+ }
+ }
+
+ static List getCRLsFromStore(CertStore certStore)
+ throws CertStoreException, CMSException
+ {
+ List crls = new ArrayList();
+
+ try
+ {
+ for (Iterator it = certStore.getCRLs(null).iterator(); it.hasNext();)
+ {
+ X509CRL c = (X509CRL)it.next();
+
+ crls.add(CertificateList.getInstance(ASN1Primitive.fromByteArray(c.getEncoded())));
+ }
+
+ return crls;
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("error processing crls", e);
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("error processing crls", e);
+ }
+ catch (CRLException e)
+ {
+ throw new CMSException("error encoding crls", e);
+ }
+ }
+
+ static List getCRLsFromStore(Store crlStore)
+ throws CMSException
+ {
+ List certs = new ArrayList();
+
+ try
+ {
+ for (Iterator it = crlStore.getMatches(null).iterator(); it.hasNext();)
+ {
+ X509CRLHolder c = (X509CRLHolder)it.next();
+
+ certs.add(c.toASN1Structure());
+ }
+
+ return certs;
+ }
+ catch (ClassCastException e)
+ {
+ throw new CMSException("error processing certs", e);
+ }
+ }
+
+ static ASN1Set createBerSetFromList(List derObjects)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (Iterator it = derObjects.iterator(); it.hasNext();)
+ {
+ v.add((ASN1Encodable)it.next());
+ }
+
+ return new BERSet(v);
+ }
+
+ static ASN1Set createDerSetFromList(List derObjects)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (Iterator it = derObjects.iterator(); it.hasNext();)
+ {
+ v.add((ASN1Encodable)it.next());
+ }
+
+ return new DERSet(v);
+ }
+
+ static OutputStream createBEROctetOutputStream(OutputStream s,
+ int tagNo, boolean isExplicit, int bufferSize) throws IOException
+ {
+ BEROctetStringGenerator octGen = new BEROctetStringGenerator(s, tagNo, isExplicit);
+
+ if (bufferSize != 0)
+ {
+ return octGen.getOctetOutputStream(new byte[bufferSize]);
+ }
+
+ return octGen.getOctetOutputStream();
+ }
+
+ static TBSCertificateStructure getTBSCertificateStructure(
+ X509Certificate cert)
+ {
+ try
+ {
+ return TBSCertificateStructure.getInstance(
+ ASN1Primitive.fromByteArray(cert.getTBSCertificate()));
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException(
+ "can't extract TBS structure from this cert");
+ }
+ }
+
+ static IssuerAndSerialNumber getIssuerAndSerialNumber(X509Certificate cert)
+ {
+ TBSCertificateStructure tbsCert = getTBSCertificateStructure(cert);
+ return new IssuerAndSerialNumber(tbsCert.getIssuer(), tbsCert.getSerialNumber().getValue());
+ }
+
+ private static ContentInfo readContentInfo(
+ ASN1InputStream in)
+ throws CMSException
+ {
+ try
+ {
+ return ContentInfo.getInstance(in.readObject());
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("IOException reading content.", e);
+ }
+ catch (ClassCastException e)
+ {
+ throw new CMSException("Malformed content.", e);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new CMSException("Malformed content.", e);
+ }
+ }
+
+ public static byte[] streamToByteArray(
+ InputStream in)
+ throws IOException
+ {
+ return Streams.readAll(in);
+ }
+
+ public static byte[] streamToByteArray(
+ InputStream in,
+ int limit)
+ throws IOException
+ {
+ return Streams.readAllLimited(in, limit);
+ }
+
+ public static Provider getProvider(String providerName)
+ throws NoSuchProviderException
+ {
+ if (providerName != null)
+ {
+ Provider prov = Security.getProvider(providerName);
+
+ if (prov != null)
+ {
+ return prov;
+ }
+
+ throw new NoSuchProviderException("provider " + providerName + " not found.");
+ }
+
+ return null;
+ }
+
+ static InputStream attachDigestsToInputStream(Collection digests, InputStream s)
+ {
+ InputStream result = s;
+ Iterator it = digests.iterator();
+ while (it.hasNext())
+ {
+ DigestCalculator digest = (DigestCalculator)it.next();
+ result = new TeeInputStream(result, digest.getOutputStream());
+ }
+ return result;
+ }
+
+ static OutputStream attachSignersToOutputStream(Collection signers, OutputStream s)
+ {
+ OutputStream result = s;
+ Iterator it = signers.iterator();
+ while (it.hasNext())
+ {
+ SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
+ result = getSafeTeeOutputStream(result, signerGen.getCalculatingOutputStream());
+ }
+ return result;
+ }
+
+ static OutputStream getSafeOutputStream(OutputStream s)
+ {
+ return s == null ? new NullOutputStream() : s;
+ }
+
+ static OutputStream getSafeTeeOutputStream(OutputStream s1,
+ OutputStream s2)
+ {
+ return s1 == null ? getSafeOutputStream(s2)
+ : s2 == null ? getSafeOutputStream(s1) : new TeeOutputStream(
+ s1, s2);
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/OriginatorInfoGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/OriginatorInfoGenerator.java
new file mode 100644
index 00000000..6a5c0e9d
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/OriginatorInfoGenerator.java
@@ -0,0 +1,54 @@
+package org.bouncycastle.cms;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bouncycastle.asn1.cms.OriginatorInfo;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.util.Store;
+
+public class OriginatorInfoGenerator
+{
+ private List origCerts;
+ private List origCRLs;
+
+ public OriginatorInfoGenerator(X509CertificateHolder origCert)
+ {
+ this.origCerts = new ArrayList(1);
+ this.origCRLs = null;
+ origCerts.add(origCert.toASN1Structure());
+ }
+
+ public OriginatorInfoGenerator(Store origCerts)
+ throws CMSException
+ {
+ this(origCerts, null);
+ }
+
+ public OriginatorInfoGenerator(Store origCerts, Store origCRLs)
+ throws CMSException
+ {
+ this.origCerts = CMSUtils.getCertificatesFromStore(origCerts);
+
+ if (origCRLs != null)
+ {
+ this.origCRLs = CMSUtils.getCRLsFromStore(origCRLs);
+ }
+ else
+ {
+ this.origCRLs = null;
+ }
+ }
+
+ public OriginatorInformation generate()
+ {
+ if (origCRLs != null)
+ {
+ return new OriginatorInformation(new OriginatorInfo(CMSUtils.createDerSetFromList(origCerts), CMSUtils.createDerSetFromList(origCRLs)));
+ }
+ else
+ {
+ return new OriginatorInformation(new OriginatorInfo(CMSUtils.createDerSetFromList(origCerts), null));
+ }
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/RecipientId.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/RecipientId.java
new file mode 100644
index 00000000..7ea1f329
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/RecipientId.java
@@ -0,0 +1,31 @@
+package org.bouncycastle.cms;
+
+import org.bouncycastle.util.Selector;
+
+public abstract class RecipientId
+ implements Selector
+{
+ public static final int keyTrans = 0;
+ public static final int kek = 1;
+ public static final int keyAgree = 2;
+ public static final int password = 3;
+
+ private int type;
+
+ protected RecipientId(int type)
+ {
+ this.type = type;
+ }
+
+ /**
+ * Return the type code for this recipient ID.
+ *
+ * @return one of keyTrans, kek, keyAgree, password
+ */
+ public int getType()
+ {
+ return type;
+ }
+
+ public abstract Object clone();
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/SignerInfoGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/SignerInfoGenerator.java
new file mode 100644
index 00000000..4ac1c91a
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/SignerInfoGenerator.java
@@ -0,0 +1,291 @@
+package org.bouncycastle.cms;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bouncycastle.asn1.ASN1Encoding;
+import org.bouncycastle.asn1.ASN1Integer;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1Set;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSet;
+import org.bouncycastle.asn1.cms.AttributeTable;
+import org.bouncycastle.asn1.cms.SignerIdentifier;
+import org.bouncycastle.asn1.cms.SignerInfo;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
+import org.bouncycastle.operator.DigestAlgorithmIdentifierFinder;
+import org.bouncycastle.operator.DigestCalculator;
+import org.bouncycastle.operator.DigestCalculatorProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.util.io.TeeOutputStream;
+
+public class SignerInfoGenerator
+{
+ private SignerIdentifier signerIdentifier;
+ private CMSAttributeTableGenerator sAttrGen;
+ private CMSAttributeTableGenerator unsAttrGen;
+ private ContentSigner signer;
+ private DigestCalculator digester;
+ private DigestAlgorithmIdentifierFinder digAlgFinder = new DefaultDigestAlgorithmIdentifierFinder();
+ private CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder;
+
+ private byte[] calculatedDigest = null;
+ private X509CertificateHolder certHolder;
+
+ SignerInfoGenerator(
+ SignerIdentifier signerIdentifier,
+ ContentSigner signer,
+ DigestCalculatorProvider digesterProvider,
+ CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder)
+ throws OperatorCreationException
+ {
+ this(signerIdentifier, signer, digesterProvider, sigEncAlgFinder, false);
+ }
+
+ SignerInfoGenerator(
+ SignerIdentifier signerIdentifier,
+ ContentSigner signer,
+ DigestCalculatorProvider digesterProvider,
+ CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder,
+ boolean isDirectSignature)
+ throws OperatorCreationException
+ {
+ this.signerIdentifier = signerIdentifier;
+ this.signer = signer;
+
+ if (digesterProvider != null)
+ {
+ this.digester = digesterProvider.get(digAlgFinder.find(signer.getAlgorithmIdentifier()));
+ }
+ else
+ {
+ this.digester = null;
+ }
+
+ if (isDirectSignature)
+ {
+ this.sAttrGen = null;
+ this.unsAttrGen = null;
+ }
+ else
+ {
+ this.sAttrGen = new DefaultSignedAttributeTableGenerator();
+ this.unsAttrGen = null;
+ }
+
+ this.sigEncAlgFinder = sigEncAlgFinder;
+ }
+
+ public SignerInfoGenerator(
+ SignerInfoGenerator original,
+ CMSAttributeTableGenerator sAttrGen,
+ CMSAttributeTableGenerator unsAttrGen)
+ {
+ this.signerIdentifier = original.signerIdentifier;
+ this.signer = original.signer;
+ this.digester = original.digester;
+ this.sigEncAlgFinder = original.sigEncAlgFinder;
+ this.sAttrGen = sAttrGen;
+ this.unsAttrGen = unsAttrGen;
+ }
+
+ SignerInfoGenerator(
+ SignerIdentifier signerIdentifier,
+ ContentSigner signer,
+ DigestCalculatorProvider digesterProvider,
+ CMSSignatureEncryptionAlgorithmFinder sigEncAlgFinder,
+ CMSAttributeTableGenerator sAttrGen,
+ CMSAttributeTableGenerator unsAttrGen)
+ throws OperatorCreationException
+ {
+ this.signerIdentifier = signerIdentifier;
+ this.signer = signer;
+
+ if (digesterProvider != null)
+ {
+ this.digester = digesterProvider.get(digAlgFinder.find(signer.getAlgorithmIdentifier()));
+ }
+ else
+ {
+ this.digester = null;
+ }
+
+ this.sAttrGen = sAttrGen;
+ this.unsAttrGen = unsAttrGen;
+ this.sigEncAlgFinder = sigEncAlgFinder;
+ }
+
+ public SignerIdentifier getSID()
+ {
+ return signerIdentifier;
+ }
+
+ public ASN1Integer getGeneratedVersion()
+ {
+ return new ASN1Integer(signerIdentifier.isTagged() ? 3 : 1);
+ }
+
+ public boolean hasAssociatedCertificate()
+ {
+ return certHolder != null;
+ }
+
+ public X509CertificateHolder getAssociatedCertificate()
+ {
+ return certHolder;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ if (digester != null)
+ {
+ return digester.getAlgorithmIdentifier();
+ }
+
+ return digAlgFinder.find(signer.getAlgorithmIdentifier());
+ }
+
+ public OutputStream getCalculatingOutputStream()
+ {
+ if (digester != null)
+ {
+ if (sAttrGen == null)
+ {
+ return new TeeOutputStream(digester.getOutputStream(), signer.getOutputStream());
+ }
+ return digester.getOutputStream();
+ }
+ else
+ {
+ return signer.getOutputStream();
+ }
+ }
+
+ public SignerInfo generate(ASN1ObjectIdentifier contentType)
+ throws CMSException
+ {
+ try
+ {
+ /* RFC 3852 5.4
+ * The result of the message digest calculation process depends on
+ * whether the signedAttrs field is present. When the field is absent,
+ * the result is just the message digest of the content as described
+ *
+ * above. When the field is present, however, the result is the message
+ * digest of the complete DER encoding of the SignedAttrs value
+ * contained in the signedAttrs field.
+ */
+ ASN1Set signedAttr = null;
+
+ AlgorithmIdentifier digestAlg = null;
+
+ if (sAttrGen != null)
+ {
+ digestAlg = digester.getAlgorithmIdentifier();
+ calculatedDigest = digester.getDigest();
+ Map parameters = getBaseParameters(contentType, digester.getAlgorithmIdentifier(), calculatedDigest);
+ AttributeTable signed = sAttrGen.getAttributes(new HashMap(parameters));
+
+ signedAttr = getAttributeSet(signed);
+
+ // sig must be composed from the DER encoding.
+ OutputStream sOut = signer.getOutputStream();
+
+ sOut.write(signedAttr.getEncoded(ASN1Encoding.DER));
+
+ sOut.close();
+ }
+ else
+ {
+ if (digester != null)
+ {
+ digestAlg = digester.getAlgorithmIdentifier();
+ calculatedDigest = digester.getDigest();
+ }
+ else
+ {
+ digestAlg = digAlgFinder.find(signer.getAlgorithmIdentifier());
+ calculatedDigest = null;
+ }
+ }
+
+ byte[] sigBytes = signer.getSignature();
+
+ ASN1Set unsignedAttr = null;
+ if (unsAttrGen != null)
+ {
+ Map parameters = getBaseParameters(contentType, digestAlg, calculatedDigest);
+ parameters.put(CMSAttributeTableGenerator.SIGNATURE, sigBytes.clone());
+
+ AttributeTable unsigned = unsAttrGen.getAttributes(new HashMap(parameters));
+
+ unsignedAttr = getAttributeSet(unsigned);
+ }
+
+ AlgorithmIdentifier digestEncryptionAlgorithm = sigEncAlgFinder.findEncryptionAlgorithm(signer.getAlgorithmIdentifier());
+
+ return new SignerInfo(signerIdentifier, digestAlg,
+ signedAttr, digestEncryptionAlgorithm, new DEROctetString(sigBytes), unsignedAttr);
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("encoding error.", e);
+ }
+ }
+
+ void setAssociatedCertificate(X509CertificateHolder certHolder)
+ {
+ this.certHolder = certHolder;
+ }
+
+ private ASN1Set getAttributeSet(
+ AttributeTable attr)
+ {
+ if (attr != null)
+ {
+ return new DERSet(attr.toASN1EncodableVector());
+ }
+
+ return null;
+ }
+
+ private Map getBaseParameters(ASN1ObjectIdentifier contentType, AlgorithmIdentifier digAlgId, byte[] hash)
+ {
+ Map param = new HashMap();
+
+ if (contentType != null)
+ {
+ param.put(CMSAttributeTableGenerator.CONTENT_TYPE, contentType);
+ }
+
+ param.put(CMSAttributeTableGenerator.DIGEST_ALGORITHM_IDENTIFIER, digAlgId);
+ param.put(CMSAttributeTableGenerator.DIGEST, hash.clone());
+ return param;
+ }
+
+ public byte[] getCalculatedDigest()
+ {
+ if (calculatedDigest != null)
+ {
+ return (byte[])calculatedDigest.clone();
+ }
+
+ return null;
+ }
+
+ public CMSAttributeTableGenerator getSignedAttributeTableGenerator()
+ {
+ return sAttrGen;
+ }
+
+ public CMSAttributeTableGenerator getUnsignedAttributeTableGenerator()
+ {
+ return unsAttrGen;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java
new file mode 100644
index 00000000..9bcc4506
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/EnvelopedDataHelper.java
@@ -0,0 +1,697 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.io.IOException;
+import java.security.AlgorithmParameterGenerator;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.RC2ParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1Null;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.DERNull;
+import org.bouncycastle.asn1.DERObjectIdentifier;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.pkcs.RC2CBCParameter;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.cms.CMSAlgorithm;
+import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.operator.GenericKey;
+import org.bouncycastle.operator.SymmetricKeyUnwrapper;
+import org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper;
+
+class EnvelopedDataHelper
+{
+ protected static final Map BASE_CIPHER_NAMES = new HashMap();
+ protected static final Map CIPHER_ALG_NAMES = new HashMap();
+ protected static final Map MAC_ALG_NAMES = new HashMap();
+
+ static
+ {
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDE");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.AES128_CBC, "AES");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.AES192_CBC, "AES");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.AES256_CBC, "AES");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.RC2_CBC, "RC2");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.CAST5_CBC, "CAST5");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.CAMELLIA128_CBC, "Camellia");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.CAMELLIA192_CBC, "Camellia");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.CAMELLIA256_CBC, "Camellia");
+ BASE_CIPHER_NAMES.put(CMSAlgorithm.SEED_CBC, "SEED");
+
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDE/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.AES256_CBC, "AES/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(PKCSObjectIdentifiers.rsaEncryption, "RSA/ECB/PKCS1Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.CAST5_CBC, "CAST5/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA128_CBC, "Camellia/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA192_CBC, "Camellia/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.CAMELLIA256_CBC, "Camellia/CBC/PKCS5Padding");
+ CIPHER_ALG_NAMES.put(CMSAlgorithm.SEED_CBC, "SEED/CBC/PKCS5Padding");
+
+ MAC_ALG_NAMES.put(CMSAlgorithm.DES_EDE3_CBC, "DESEDEMac");
+ MAC_ALG_NAMES.put(CMSAlgorithm.AES128_CBC, "AESMac");
+ MAC_ALG_NAMES.put(CMSAlgorithm.AES192_CBC, "AESMac");
+ MAC_ALG_NAMES.put(CMSAlgorithm.AES256_CBC, "AESMac");
+ MAC_ALG_NAMES.put(CMSAlgorithm.RC2_CBC, "RC2Mac");
+ }
+
+ private static final short[] rc2Table = {
+ 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,
+ 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,
+ 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36,
+ 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c,
+ 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60,
+ 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa,
+ 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e,
+ 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf,
+ 0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6,
+ 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3,
+ 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c,
+ 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2,
+ 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5,
+ 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5,
+ 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,
+ 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab
+ };
+
+ private static final short[] rc2Ekb = {
+ 0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5,
+ 0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5,
+ 0xb9, 0x1e, 0x96, 0x43, 0x41, 0xd8, 0xd4, 0x2c, 0xdb, 0xf8, 0x07, 0x77, 0x2a, 0xca, 0xeb, 0xef,
+ 0x10, 0x1c, 0x16, 0x0d, 0x38, 0x72, 0x2f, 0x89, 0xc1, 0xf9, 0x80, 0xc4, 0x6d, 0xae, 0x30, 0x3d,
+ 0xce, 0x20, 0x63, 0xfe, 0xe6, 0x1a, 0xc7, 0xb8, 0x50, 0xe8, 0x24, 0x17, 0xfc, 0x25, 0x6f, 0xbb,
+ 0x6a, 0xa3, 0x44, 0x53, 0xd9, 0xa2, 0x01, 0xab, 0xbc, 0xb6, 0x1f, 0x98, 0xee, 0x9a, 0xa7, 0x2d,
+ 0x4f, 0x9e, 0x8e, 0xac, 0xe0, 0xc6, 0x49, 0x46, 0x29, 0xf4, 0x94, 0x8a, 0xaf, 0xe1, 0x5b, 0xc3,
+ 0xb3, 0x7b, 0x57, 0xd1, 0x7c, 0x9c, 0xed, 0x87, 0x40, 0x8c, 0xe2, 0xcb, 0x93, 0x14, 0xc9, 0x61,
+ 0x2e, 0xe5, 0xcc, 0xf6, 0x5e, 0xa8, 0x5c, 0xd6, 0x75, 0x8d, 0x62, 0x95, 0x58, 0x69, 0x76, 0xa1,
+ 0x4a, 0xb5, 0x55, 0x09, 0x78, 0x33, 0x82, 0xd7, 0xdd, 0x79, 0xf5, 0x1b, 0x0b, 0xde, 0x26, 0x21,
+ 0x28, 0x74, 0x04, 0x97, 0x56, 0xdf, 0x3c, 0xf0, 0x37, 0x39, 0xdc, 0xff, 0x06, 0xa4, 0xea, 0x42,
+ 0x08, 0xda, 0xb4, 0x71, 0xb0, 0xcf, 0x12, 0x7a, 0x4e, 0xfa, 0x6c, 0x1d, 0x84, 0x00, 0xc8, 0x7f,
+ 0x91, 0x45, 0xaa, 0x2b, 0xc2, 0xb1, 0x8f, 0xd5, 0xba, 0xf2, 0xad, 0x19, 0xb2, 0x67, 0x36, 0xf7,
+ 0x0f, 0x0a, 0x92, 0x7d, 0xe3, 0x9d, 0xe9, 0x90, 0x3e, 0x23, 0x27, 0x66, 0x13, 0xec, 0x81, 0x15,
+ 0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7,
+ 0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd
+ };
+
+ private JcaJceExtHelper helper;
+
+ EnvelopedDataHelper(JcaJceExtHelper helper)
+ {
+ this.helper = helper;
+ }
+
+ String getBaseCipherName(ASN1ObjectIdentifier algorithm)
+ {
+ String name = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (name == null)
+ {
+ return algorithm.getId();
+ }
+
+ return name;
+ }
+
+ Key getJceKey(GenericKey key)
+ {
+ if (key.getRepresentation() instanceof Key)
+ {
+ return (Key)key.getRepresentation();
+ }
+
+ if (key.getRepresentation() instanceof byte[])
+ {
+ return new SecretKeySpec((byte[])key.getRepresentation(), "ENC");
+ }
+
+ throw new IllegalArgumentException("unknown generic key type");
+ }
+
+ Key getJceKey(ASN1ObjectIdentifier algorithm, GenericKey key)
+ {
+ if (key.getRepresentation() instanceof Key)
+ {
+ return (Key)key.getRepresentation();
+ }
+
+ if (key.getRepresentation() instanceof byte[])
+ {
+ return new SecretKeySpec((byte[])key.getRepresentation(), getBaseCipherName(algorithm));
+ }
+
+ throw new IllegalArgumentException("unknown generic key type");
+ }
+
+ Cipher createCipher(ASN1ObjectIdentifier algorithm)
+ throws CMSException
+ {
+ try
+ {
+ String cipherName = (String)CIPHER_ALG_NAMES.get(algorithm);
+
+ if (cipherName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createCipher(cipherName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createCipher(algorithm.getId());
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new CMSException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("cannot create cipher: " + e.getMessage(), e);
+ }
+ }
+
+ Mac createMac(ASN1ObjectIdentifier algorithm)
+ throws CMSException
+ {
+ try
+ {
+ String macName = (String)MAC_ALG_NAMES.get(algorithm);
+
+ if (macName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createMac(macName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createMac(algorithm.getId());
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("cannot create mac: " + e.getMessage(), e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot create mac: " + e.getMessage(), e);
+ }
+ }
+
+ Cipher createRFC3211Wrapper(ASN1ObjectIdentifier algorithm)
+ throws CMSException
+ {
+ String cipherName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (cipherName == null)
+ {
+ throw new CMSException("no name for " + algorithm);
+ }
+
+ cipherName += "RFC3211Wrap";
+
+ try
+ {
+ return helper.createCipher(cipherName);
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new CMSException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot create cipher: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("cannot create cipher: " + e.getMessage(), e);
+ }
+ }
+
+ KeyAgreement createKeyAgreement(ASN1ObjectIdentifier algorithm)
+ throws CMSException
+ {
+ try
+ {
+ String agreementName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (agreementName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createKeyAgreement(agreementName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createKeyAgreement(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot create key pair generator: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("cannot create key pair generator: " + e.getMessage(), e);
+ }
+ }
+
+ AlgorithmParameterGenerator createAlgorithmParameterGenerator(ASN1ObjectIdentifier algorithm)
+ throws GeneralSecurityException
+ {
+ String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ try
+ {
+ if (algorithmName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createAlgorithmParameterGenerator(algorithmName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createAlgorithmParameterGenerator(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new GeneralSecurityException("cannot create key generator: " + e.getMessage());
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new GeneralSecurityException("cannot create key generator: " + e.getMessage());
+ }
+ }
+
+ Cipher createContentCipher(final Key sKey, final AlgorithmIdentifier encryptionAlgID)
+ throws CMSException
+ {
+ return (Cipher)execute(new JCECallback()
+ {
+ public Object doInJCE()
+ throws CMSException, InvalidAlgorithmParameterException,
+ InvalidKeyException, InvalidParameterSpecException, NoSuchAlgorithmException,
+ NoSuchPaddingException, NoSuchProviderException
+ {
+ Cipher cipher = createCipher(encryptionAlgID.getAlgorithm());
+ ASN1Encodable sParams = encryptionAlgID.getParameters();
+ String encAlg = encryptionAlgID.getAlgorithm().getId();
+
+ if (sParams != null && !(sParams instanceof ASN1Null))
+ {
+ try
+ {
+ AlgorithmParameters params = createAlgorithmParameters(encryptionAlgID.getAlgorithm());
+
+ try
+ {
+ params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("error decoding algorithm parameters.", e);
+ }
+
+ cipher.init(Cipher.DECRYPT_MODE, sKey, params);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.AES128_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.AES192_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.AES256_CBC))
+ {
+ cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec(
+ ASN1OctetString.getInstance(sParams).getOctets()));
+ }
+ else
+ {
+ throw e;
+ }
+ }
+ }
+ else
+ {
+ if (encAlg.equals(CMSEnvelopedDataGenerator.DES_EDE3_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.IDEA_CBC)
+ || encAlg.equals(CMSEnvelopedDataGenerator.CAST5_CBC))
+ {
+ cipher.init(Cipher.DECRYPT_MODE, sKey, new IvParameterSpec(new byte[8]));
+ }
+ else
+ {
+ cipher.init(Cipher.DECRYPT_MODE, sKey);
+ }
+ }
+
+ return cipher;
+ }
+ });
+ }
+
+ Mac createContentMac(final Key sKey, final AlgorithmIdentifier macAlgId)
+ throws CMSException
+ {
+ return (Mac)execute(new JCECallback()
+ {
+ public Object doInJCE()
+ throws CMSException, InvalidAlgorithmParameterException,
+ InvalidKeyException, InvalidParameterSpecException, NoSuchAlgorithmException,
+ NoSuchPaddingException, NoSuchProviderException
+ {
+ Mac mac = createMac(macAlgId.getAlgorithm());
+ ASN1Encodable sParams = macAlgId.getParameters();
+ String macAlg = macAlgId.getAlgorithm().getId();
+
+ if (sParams != null && !(sParams instanceof ASN1Null))
+ {
+ try
+ {
+ AlgorithmParameters params = createAlgorithmParameters(macAlgId.getAlgorithm());
+
+ try
+ {
+ params.init(sParams.toASN1Primitive().getEncoded(), "ASN.1");
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("error decoding algorithm parameters.", e);
+ }
+
+ mac.init(sKey, params.getParameterSpec(IvParameterSpec.class));
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw e;
+ }
+ }
+ else
+ {
+ mac.init(sKey);
+ }
+
+ return mac;
+ }
+ });
+ }
+
+ AlgorithmParameters createAlgorithmParameters(ASN1ObjectIdentifier algorithm)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ String algorithmName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (algorithmName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createAlgorithmParameters(algorithmName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createAlgorithmParameters(algorithm.getId());
+ }
+
+
+ KeyPairGenerator createKeyPairGenerator(DERObjectIdentifier algorithm)
+ throws CMSException
+ {
+ try
+ {
+ String cipherName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (cipherName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createKeyPairGenerator(cipherName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createKeyPairGenerator(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot create key pair generator: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("cannot create key pair generator: " + e.getMessage(), e);
+ }
+ }
+
+ public KeyGenerator createKeyGenerator(ASN1ObjectIdentifier algorithm)
+ throws CMSException
+ {
+ try
+ {
+ String cipherName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (cipherName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createKeyGenerator(cipherName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createKeyGenerator(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot create key generator: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("cannot create key generator: " + e.getMessage(), e);
+ }
+ }
+
+ AlgorithmParameters generateParameters(ASN1ObjectIdentifier encryptionOID, SecretKey encKey, SecureRandom rand)
+ throws CMSException
+ {
+ try
+ {
+ AlgorithmParameterGenerator pGen = createAlgorithmParameterGenerator(encryptionOID);
+
+ if (encryptionOID.equals(CMSEnvelopedDataGenerator.RC2_CBC))
+ {
+ byte[] iv = new byte[8];
+
+ rand.nextBytes(iv);
+
+ try
+ {
+ pGen.init(new RC2ParameterSpec(encKey.getEncoded().length * 8, iv), rand);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new CMSException("parameters generation error: " + e, e);
+ }
+ }
+
+ return pGen.generateParameters();
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CMSException("exception creating algorithm parameter generator: " + e, e);
+ }
+ }
+
+ AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier encryptionOID, AlgorithmParameters params)
+ throws CMSException
+ {
+ ASN1Encodable asn1Params;
+ if (params != null)
+ {
+ try
+ {
+ asn1Params = ASN1Primitive.fromByteArray(params.getEncoded("ASN.1"));
+ }
+ catch (IOException e)
+ {
+ throw new CMSException("cannot encode parameters: " + e.getMessage(), e);
+ }
+ }
+ else
+ {
+ asn1Params = DERNull.INSTANCE;
+ }
+
+ return new AlgorithmIdentifier(
+ encryptionOID,
+ asn1Params);
+ }
+
+ static Object execute(JCECallback callback) throws CMSException
+ {
+ try
+ {
+ return callback.doInJCE();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("can't find algorithm.", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CMSException("key invalid in message.", e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("can't find provider.", e);
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new CMSException("required padding not supported.", e);
+ }
+ catch (InvalidAlgorithmParameterException e)
+ {
+ throw new CMSException("algorithm parameters invalid.", e);
+ }
+ catch (InvalidParameterSpecException e)
+ {
+ throw new CMSException("MAC algorithm parameter spec invalid.", e);
+ }
+ }
+
+ public KeyFactory createKeyFactory(ASN1ObjectIdentifier algorithm)
+ throws CMSException
+ {
+ try
+ {
+ String cipherName = (String)BASE_CIPHER_NAMES.get(algorithm);
+
+ if (cipherName != null)
+ {
+ try
+ {
+ // this is reversed as the Sun policy files now allow unlimited strength RSA
+ return helper.createKeyFactory(cipherName);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ // Ignore
+ }
+ }
+ return helper.createKeyFactory(algorithm.getId());
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot create key factory: " + e.getMessage(), e);
+ }
+ catch (NoSuchProviderException e)
+ {
+ throw new CMSException("cannot create key factory: " + e.getMessage(), e);
+ }
+ }
+
+ public JceAsymmetricKeyUnwrapper createAsymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, PrivateKey keyEncryptionKey)
+ {
+ return helper.createAsymmetricUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey);
+ }
+
+ public SymmetricKeyUnwrapper createSymmetricUnwrapper(AlgorithmIdentifier keyEncryptionAlgorithm, SecretKey keyEncryptionKey)
+ {
+ return helper.createSymmetricUnwrapper(keyEncryptionAlgorithm, keyEncryptionKey);
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier(ASN1ObjectIdentifier macOID, AlgorithmParameterSpec paramSpec)
+ {
+ if (paramSpec instanceof IvParameterSpec)
+ {
+ return new AlgorithmIdentifier(macOID, new DEROctetString(((IvParameterSpec)paramSpec).getIV()));
+ }
+
+ if (paramSpec instanceof RC2ParameterSpec)
+ {
+ RC2ParameterSpec rc2Spec = (RC2ParameterSpec)paramSpec;
+
+ int effKeyBits = ((RC2ParameterSpec)paramSpec).getEffectiveKeyBits();
+
+ if (effKeyBits != -1)
+ {
+ int parameterVersion;
+
+ if (effKeyBits < 256)
+ {
+ parameterVersion = rc2Table[effKeyBits];
+ }
+ else
+ {
+ parameterVersion = effKeyBits;
+ }
+
+ return new AlgorithmIdentifier(macOID, new RC2CBCParameter(parameterVersion, rc2Spec.getIV()));
+ }
+
+ return new AlgorithmIdentifier(macOID, new RC2CBCParameter(rc2Spec.getIV()));
+ }
+
+ throw new IllegalStateException("unknown parameter spec: " + paramSpec);
+ }
+
+ static interface JCECallback
+ {
+ Object doInJCE()
+ throws CMSException, InvalidAlgorithmParameterException, InvalidKeyException, InvalidParameterSpecException,
+ NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaSelectorConverter.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaSelectorConverter.java
new file mode 100644
index 00000000..52dc20e8
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaSelectorConverter.java
@@ -0,0 +1,54 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.security.cert.X509CertSelector;
+
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.cms.KeyTransRecipientId;
+import org.bouncycastle.cms.SignerId;
+
+public class JcaSelectorConverter
+{
+ public JcaSelectorConverter()
+ {
+
+ }
+
+ public SignerId getSignerId(X509CertSelector certSelector)
+ {
+try
+{
+ if (certSelector.getSubjectKeyIdentifier() != null)
+ {
+ return new SignerId(X500Name.getInstance(certSelector.getIssuerAsBytes()), certSelector.getSerialNumber(), ASN1OctetString.getInstance(certSelector.getSubjectKeyIdentifier()).getOctets());
+ }
+ else
+ {
+ return new SignerId(X500Name.getInstance(certSelector.getIssuerAsBytes()), certSelector.getSerialNumber());
+ }
+}
+catch (Exception e)
+{
+ throw new IllegalArgumentException("conversion failed: " + e.toString());
+}
+ }
+
+ public KeyTransRecipientId getKeyTransRecipientId(X509CertSelector certSelector)
+ {
+try
+{
+ if (certSelector.getSubjectKeyIdentifier() != null)
+ {
+ return new KeyTransRecipientId(X500Name.getInstance(certSelector.getIssuerAsBytes()), certSelector.getSerialNumber(), ASN1OctetString.getInstance(certSelector.getSubjectKeyIdentifier()).getOctets());
+ }
+ else
+ {
+ return new KeyTransRecipientId(X500Name.getInstance(certSelector.getIssuerAsBytes()), certSelector.getSerialNumber());
+ }
+}
+catch (Exception e)
+{
+ throw new IllegalArgumentException("conversion failed: " + e.toString());
+}
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaX509CertSelectorConverter.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaX509CertSelectorConverter.java
new file mode 100644
index 00000000..86f59f69
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcaX509CertSelectorConverter.java
@@ -0,0 +1,24 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.security.cert.X509CertSelector;
+
+import org.bouncycastle.cms.KeyTransRecipientId;
+import org.bouncycastle.cms.SignerId;
+
+public class JcaX509CertSelectorConverter
+ extends org.bouncycastle.cert.selector.jcajce.JcaX509CertSelectorConverter
+{
+ public JcaX509CertSelectorConverter()
+ {
+ }
+
+ public X509CertSelector getCertSelector(KeyTransRecipientId recipientId)
+ {
+ return doConversion(recipientId.getIssuer(), recipientId.getSerialNumber(), recipientId.getSubjectKeyIdentifier());
+ }
+
+ public X509CertSelector getCertSelector(SignerId signerId)
+ {
+ return doConversion(signerId.getIssuer(), signerId.getSerialNumber(), signerId.getSubjectKeyIdentifier());
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java
new file mode 100644
index 00000000..527b28d2
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceCMSContentEncryptorBuilder.java
@@ -0,0 +1,166 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.io.OutputStream;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.cms.CMSAlgorithm;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.operator.GenericKey;
+import org.bouncycastle.operator.OutputEncryptor;
+import org.bouncycastle.util.Integers;
+
+public class JceCMSContentEncryptorBuilder
+{
+ private static Map keySizes = new HashMap();
+
+ static
+ {
+ keySizes.put(CMSAlgorithm.AES128_CBC, Integers.valueOf(128));
+ keySizes.put(CMSAlgorithm.AES192_CBC, Integers.valueOf(192));
+ keySizes.put(CMSAlgorithm.AES256_CBC, Integers.valueOf(256));
+
+ keySizes.put(CMSAlgorithm.CAMELLIA128_CBC, Integers.valueOf(128));
+ keySizes.put(CMSAlgorithm.CAMELLIA192_CBC, Integers.valueOf(192));
+ keySizes.put(CMSAlgorithm.CAMELLIA256_CBC, Integers.valueOf(256));
+ }
+
+ private static int getKeySize(ASN1ObjectIdentifier oid)
+ {
+ Integer size = (Integer)keySizes.get(oid);
+
+ if (size != null)
+ {
+ return size.intValue();
+ }
+
+ return -1;
+ }
+
+ private ASN1ObjectIdentifier encryptionOID;
+ private int keySize;
+
+ private EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper());
+ private SecureRandom random;
+
+ public JceCMSContentEncryptorBuilder(ASN1ObjectIdentifier encryptionOID)
+ {
+ this(encryptionOID, getKeySize(encryptionOID));
+ }
+
+ public JceCMSContentEncryptorBuilder(ASN1ObjectIdentifier encryptionOID, int keySize)
+ {
+ this.encryptionOID = encryptionOID;
+ this.keySize = keySize;
+ }
+
+ public JceCMSContentEncryptorBuilder setProvider(Provider provider)
+ {
+ this.helper = new EnvelopedDataHelper(new ProviderJcaJceExtHelper(provider));
+
+ return this;
+ }
+
+ public JceCMSContentEncryptorBuilder setProvider(String providerName)
+ {
+ this.helper = new EnvelopedDataHelper(new NamedJcaJceExtHelper(providerName));
+
+ return this;
+ }
+
+ public JceCMSContentEncryptorBuilder setSecureRandom(SecureRandom random)
+ {
+ this.random = random;
+
+ return this;
+ }
+
+ public OutputEncryptor build()
+ throws CMSException
+ {
+ return new CMSOutputEncryptor(encryptionOID, keySize, random);
+ }
+
+ private class CMSOutputEncryptor
+ implements OutputEncryptor
+ {
+ private SecretKey encKey;
+ private AlgorithmIdentifier algorithmIdentifier;
+ private Cipher cipher;
+
+ CMSOutputEncryptor(ASN1ObjectIdentifier encryptionOID, int keySize, SecureRandom random)
+ throws CMSException
+ {
+ KeyGenerator keyGen = helper.createKeyGenerator(encryptionOID);
+
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ if (keySize < 0)
+ {
+ keyGen.init(random);
+ }
+ else
+ {
+ keyGen.init(keySize, random);
+ }
+
+ cipher = helper.createCipher(encryptionOID);
+ encKey = keyGen.generateKey();
+ AlgorithmParameters params = helper.generateParameters(encryptionOID, encKey, random);
+
+ try
+ {
+ cipher.init(Cipher.ENCRYPT_MODE, encKey, params, random);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CMSException("unable to initialize cipher: " + e.getMessage(), e);
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CMSException("unable to initialize cipher: " + e.getMessage(), e);
+ }
+
+ //
+ // If params are null we try and second guess on them as some providers don't provide
+ // algorithm parameter generation explicity but instead generate them under the hood.
+ //
+ if (params == null)
+ {
+ params = cipher.getParameters();
+ }
+
+ algorithmIdentifier = helper.getAlgorithmIdentifier(encryptionOID, params);
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier()
+ {
+ return algorithmIdentifier;
+ }
+
+ public OutputStream getOutputStream(OutputStream dOut)
+ {
+ return new CipherOutputStream(dOut, cipher);
+ }
+
+ public GenericKey getKey()
+ {
+ return new GenericKey(encKey);
+ }
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java
new file mode 100644
index 00000000..ab77b3af
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipient.java
@@ -0,0 +1,184 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Primitive;
+import org.bouncycastle.asn1.cms.ecc.MQVuserKeyingMaterial;
+import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cms.CMSEnvelopedGenerator;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.KeyAgreeRecipient;
+import org.bouncycastle.jce.spec.MQVPrivateKeySpec;
+import org.bouncycastle.jce.spec.MQVPublicKeySpec;
+
+public abstract class JceKeyAgreeRecipient
+ implements KeyAgreeRecipient
+{
+ private PrivateKey recipientKey;
+ protected EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper());
+ protected EnvelopedDataHelper contentHelper = helper;
+
+ public JceKeyAgreeRecipient(PrivateKey recipientKey)
+ {
+ this.recipientKey = recipientKey;
+ }
+
+ /**
+ * Set the provider to use for key recovery and content processing.
+ *
+ * @param provider provider to use.
+ * @return this recipient.
+ */
+ public JceKeyAgreeRecipient setProvider(Provider provider)
+ {
+ this.helper = new EnvelopedDataHelper(new ProviderJcaJceExtHelper(provider));
+ this.contentHelper = helper;
+
+ return this;
+ }
+
+ /**
+ * Set the provider to use for key recovery and content processing.
+ *
+ * @param providerName the name of the provider to use.
+ * @return this recipient.
+ */
+ public JceKeyAgreeRecipient setProvider(String providerName)
+ {
+ this.helper = new EnvelopedDataHelper(new NamedJcaJceExtHelper(providerName));
+ this.contentHelper = helper;
+
+ return this;
+ }
+
+ /**
+ * Set the provider to use for content processing. If providerName is null a "no provider" search will be
+ * used to satisfy getInstance calls.
+ *
+ * @param provider the provider to use.
+ * @return this recipient.
+ */
+ public JceKeyAgreeRecipient setContentProvider(Provider provider)
+ {
+ this.contentHelper = CMSUtils.createContentHelper(provider);
+
+ return this;
+ }
+
+ /**
+ * Set the provider to use for content processing. If providerName is null a "no provider" search will be
+ * used to satisfy getInstance calls.
+ *
+ * @param providerName the name of the provider to use.
+ * @return this recipient.
+ */
+ public JceKeyAgreeRecipient setContentProvider(String providerName)
+ {
+ this.contentHelper = CMSUtils.createContentHelper(providerName);
+
+ return this;
+ }
+
+ private SecretKey calculateAgreedWrapKey(AlgorithmIdentifier keyEncAlg, ASN1ObjectIdentifier wrapAlg,
+ PublicKey senderPublicKey, ASN1OctetString userKeyingMaterial, PrivateKey receiverPrivateKey)
+ throws CMSException, GeneralSecurityException, IOException, InvalidKeyException, NoSuchAlgorithmException
+ {
+ String agreeAlg = keyEncAlg.getAlgorithm().getId();
+
+ if (agreeAlg.equals(CMSEnvelopedGenerator.ECMQV_SHA1KDF))
+ {
+ byte[] ukmEncoding = userKeyingMaterial.getOctets();
+ MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.getInstance(
+ ASN1Primitive.fromByteArray(ukmEncoding));
+
+ SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(
+ getPrivateKeyAlgorithmIdentifier(),
+ ukm.getEphemeralPublicKey().getPublicKey().getBytes());
+
+ X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubInfo.getEncoded());
+ KeyFactory fact = helper.createKeyFactory(keyEncAlg.getAlgorithm());
+ PublicKey ephemeralKey = fact.generatePublic(pubSpec);
+
+ senderPublicKey = new MQVPublicKeySpec(senderPublicKey, ephemeralKey);
+ receiverPrivateKey = new MQVPrivateKeySpec(receiverPrivateKey, receiverPrivateKey);
+ }
+
+ KeyAgreement agreement = helper.createKeyAgreement(keyEncAlg.getAlgorithm());
+
+ agreement.init(receiverPrivateKey);
+ agreement.doPhase(senderPublicKey, true);
+
+ return agreement.generateSecret(wrapAlg.getId());
+ }
+
+ private Key unwrapSessionKey(ASN1ObjectIdentifier wrapAlg, SecretKey agreedKey, ASN1ObjectIdentifier contentEncryptionAlgorithm, byte[] encryptedContentEncryptionKey)
+ throws CMSException, InvalidKeyException, NoSuchAlgorithmException
+ {
+ Cipher keyCipher = helper.createCipher(wrapAlg);
+ keyCipher.init(Cipher.UNWRAP_MODE, agreedKey);
+ return keyCipher.unwrap(encryptedContentEncryptionKey, helper.getBaseCipherName(contentEncryptionAlgorithm), Cipher.SECRET_KEY);
+ }
+
+ protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, SubjectPublicKeyInfo senderKey, ASN1OctetString userKeyingMaterial, byte[] encryptedContentEncryptionKey)
+ throws CMSException
+ {
+ try
+ {
+ ASN1ObjectIdentifier wrapAlg =
+ AlgorithmIdentifier.getInstance(keyEncryptionAlgorithm.getParameters()).getAlgorithm();
+
+ X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(senderKey.getEncoded());
+ KeyFactory fact = helper.createKeyFactory(keyEncryptionAlgorithm.getAlgorithm());
+ PublicKey senderPublicKey = fact.generatePublic(pubSpec);
+
+ SecretKey agreedWrapKey = calculateAgreedWrapKey(keyEncryptionAlgorithm, wrapAlg,
+ senderPublicKey, userKeyingMaterial, recipientKey);
+
+ return unwrapSessionKey(wrapAlg, agreedWrapKey, contentEncryptionAlgorithm.getAlgorithm(), encryptedContentEncryptionKey);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("can't find algorithm.", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CMSException("key invalid in message.", e);
+ }
+ catch (InvalidKeySpecException e)
+ {
+ throw new CMSException("originator key spec invalid.", e);
+ }
+ catch (NoSuchPaddingException e)
+ {
+ throw new CMSException("required padding not supported.", e);
+ }
+ catch (Exception e)
+ {
+ throw new CMSException("originator key invalid.", e);
+ }
+ }
+
+ public AlgorithmIdentifier getPrivateKeyAlgorithmIdentifier()
+ {
+ return PrivateKeyInfo.getInstance(recipientKey.getEncoded()).getAlgorithmId();
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java
new file mode 100644
index 00000000..bccb9e62
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JceKeyAgreeRecipientInfoGenerator.java
@@ -0,0 +1,212 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+
+import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.cms.KeyAgreeRecipientIdentifier;
+import org.bouncycastle.asn1.cms.RecipientEncryptedKey;
+import org.bouncycastle.asn1.cms.RecipientKeyIdentifier;
+import org.bouncycastle.asn1.cms.ecc.MQVuserKeyingMaterial;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cms.CMSAlgorithm;
+import org.bouncycastle.cms.CMSEnvelopedGenerator;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.KeyAgreeRecipientInfoGenerator;
+import org.bouncycastle.jce.interfaces.ECPublicKey;
+import org.bouncycastle.jce.spec.ECParameterSpec;
+import org.bouncycastle.jce.spec.MQVPrivateKeySpec;
+import org.bouncycastle.jce.spec.MQVPublicKeySpec;
+import org.bouncycastle.operator.GenericKey;
+
+public class JceKeyAgreeRecipientInfoGenerator
+ extends KeyAgreeRecipientInfoGenerator
+{
+ private List recipientIDs = new ArrayList();
+ private List recipientKeys = new ArrayList();
+ private PublicKey senderPublicKey;
+ private PrivateKey senderPrivateKey;
+
+ private EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper());
+ private SecureRandom random;
+ private KeyPair ephemeralKP;
+
+ public JceKeyAgreeRecipientInfoGenerator(ASN1ObjectIdentifier keyAgreementOID, PrivateKey senderPrivateKey, PublicKey senderPublicKey, ASN1ObjectIdentifier keyEncryptionOID)
+ {
+ super(keyAgreementOID, SubjectPublicKeyInfo.getInstance(senderPublicKey.getEncoded()), keyEncryptionOID);
+
+ this.senderPublicKey = senderPublicKey;
+ this.senderPrivateKey = senderPrivateKey;
+ }
+
+ public JceKeyAgreeRecipientInfoGenerator setProvider(Provider provider)
+ {
+ this.helper = new EnvelopedDataHelper(new ProviderJcaJceExtHelper(provider));
+
+ return this;
+ }
+
+ public JceKeyAgreeRecipientInfoGenerator setProvider(String providerName)
+ {
+ this.helper = new EnvelopedDataHelper(new NamedJcaJceExtHelper(providerName));
+
+ return this;
+ }
+
+ public JceKeyAgreeRecipientInfoGenerator setSecureRandom(SecureRandom random)
+ {
+ this.random = random;
+
+ return this;
+ }
+
+ /**
+ * Add a recipient based on the passed in certificate's public key and its issuer and serial number.
+ *
+ * @param recipientCert recipient's certificate
+ * @return the current instance.
+ * @throws CertificateEncodingException if the necessary data cannot be extracted from the certificate.
+ */
+ public JceKeyAgreeRecipientInfoGenerator addRecipient(X509Certificate recipientCert)
+ throws CertificateEncodingException
+ {
+ recipientIDs.add(new KeyAgreeRecipientIdentifier(CMSUtils.getIssuerAndSerialNumber(recipientCert)));
+ recipientKeys.add(recipientCert.getPublicKey());
+
+ return this;
+ }
+
+ /**
+ * Add a recipient identified by the passed in subjectKeyID and the for the passed in public key.
+ *
+ * @param subjectKeyID identifier actual recipient will use to match the private key.
+ * @param publicKey the public key for encrypting the secret key.
+ * @return the current instance.
+ * @throws CertificateEncodingException
+ */
+ public JceKeyAgreeRecipientInfoGenerator addRecipient(byte[] subjectKeyID, PublicKey publicKey)
+ throws CertificateEncodingException
+ {
+ recipientIDs.add(new KeyAgreeRecipientIdentifier(new RecipientKeyIdentifier(subjectKeyID)));
+ recipientKeys.add(publicKey);
+
+ return this;
+ }
+
+ public ASN1Sequence generateRecipientEncryptedKeys(AlgorithmIdentifier keyAgreeAlgorithm, AlgorithmIdentifier keyEncryptionAlgorithm, GenericKey contentEncryptionKey)
+ throws CMSException
+ {
+ init(keyAgreeAlgorithm.getAlgorithm());
+
+ PrivateKey senderPrivateKey = this.senderPrivateKey;
+
+ ASN1ObjectIdentifier keyAgreementOID = keyAgreeAlgorithm.getAlgorithm();
+
+ if (keyAgreementOID.getId().equals(CMSEnvelopedGenerator.ECMQV_SHA1KDF))
+ {
+ senderPrivateKey = new MQVPrivateKeySpec(
+ senderPrivateKey, ephemeralKP.getPrivate(), ephemeralKP.getPublic());
+ }
+
+ ASN1EncodableVector recipientEncryptedKeys = new ASN1EncodableVector();
+ for (int i = 0; i != recipientIDs.size(); i++)
+ {
+ PublicKey recipientPublicKey = (PublicKey)recipientKeys.get(i);
+ KeyAgreeRecipientIdentifier karId = (KeyAgreeRecipientIdentifier)recipientIDs.get(i);
+
+ if (keyAgreementOID.getId().equals(CMSEnvelopedGenerator.ECMQV_SHA1KDF))
+ {
+ recipientPublicKey = new MQVPublicKeySpec(recipientPublicKey, recipientPublicKey);
+ }
+
+ try
+ {
+ // Use key agreement to choose a wrap key for this recipient
+ KeyAgreement keyAgreement = helper.createKeyAgreement(keyAgreementOID);
+ keyAgreement.init(senderPrivateKey, random);
+ keyAgreement.doPhase(recipientPublicKey, true);
+ SecretKey keyEncryptionKey = keyAgreement.generateSecret(keyEncryptionAlgorithm.getAlgorithm().getId());
+
+ // Wrap the content encryption key with the agreement key
+ Cipher keyEncryptionCipher = helper.createCipher(keyEncryptionAlgorithm.getAlgorithm());
+
+ keyEncryptionCipher.init(Cipher.WRAP_MODE, keyEncryptionKey, random);
+
+ byte[] encryptedKeyBytes = keyEncryptionCipher.wrap(helper.getJceKey(contentEncryptionKey));
+
+ ASN1OctetString encryptedKey = new DEROctetString(encryptedKeyBytes);
+
+ recipientEncryptedKeys.add(new RecipientEncryptedKey(karId, encryptedKey));
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot perform agreement step: " + e.getMessage(), e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CMSException("cannot perform agreement step: " + e.getMessage(), e);
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CMSException("cannot perform agreement step: " + e.getMessage(), e);
+ }
+ }
+
+ return new DERSequence(recipientEncryptedKeys);
+ }
+
+ protected ASN1Encodable getUserKeyingMaterial(AlgorithmIdentifier keyAgreeAlg)
+ throws CMSException
+ {
+ init(keyAgreeAlg.getAlgorithm());
+
+ if (ephemeralKP != null)
+ {
+ return new MQVuserKeyingMaterial(
+ createOriginatorPublicKey(SubjectPublicKeyInfo.getInstance(ephemeralKP.getPublic().getEncoded())), null);
+ }
+
+ return null;
+ }
+
+ private void init(ASN1ObjectIdentifier keyAgreementOID)
+ throws CMSException
+ {
+ if (random == null)
+ {
+ random = new SecureRandom();
+ }
+
+ if (keyAgreementOID.equals(CMSAlgorithm.ECMQV_SHA1KDF))
+ {
+ if (ephemeralKP == null)
+ {
+ throw new CMSException(
+ "cannot determine MQV ephemeral key pair parameters from public key");
+ }
+ }
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java
new file mode 100644
index 00000000..0cda97c4
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipient.java
@@ -0,0 +1,92 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.Provider;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.PasswordRecipient;
+
+/**
+ * the RecipientInfo class for a recipient who has been sent a message
+ * encrypted using a password.
+ */
+public abstract class JcePasswordRecipient
+ implements PasswordRecipient
+{
+ private int schemeID = PasswordRecipient.PKCS5_SCHEME2_UTF8;
+ protected EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper());
+ private char[] password;
+
+ JcePasswordRecipient(
+ char[] password)
+ {
+ this.password = password;
+ }
+
+ public JcePasswordRecipient setPasswordConversionScheme(int schemeID)
+ {
+ this.schemeID = schemeID;
+
+ return this;
+ }
+
+ public JcePasswordRecipient setProvider(Provider provider)
+ {
+ this.helper = new EnvelopedDataHelper(new ProviderJcaJceExtHelper(provider));
+
+ return this;
+ }
+
+ public JcePasswordRecipient setProvider(String providerName)
+ {
+ this.helper = new EnvelopedDataHelper(new NamedJcaJceExtHelper(providerName));
+
+ return this;
+ }
+
+ protected Key extractSecretKey(AlgorithmIdentifier keyEncryptionAlgorithm, AlgorithmIdentifier contentEncryptionAlgorithm, byte[] derivedKey, byte[] encryptedContentEncryptionKey)
+ throws CMSException
+ {
+ Cipher keyEncryptionCipher = helper.createRFC3211Wrapper(keyEncryptionAlgorithm.getAlgorithm());
+
+ try
+ {
+ IvParameterSpec ivSpec = new IvParameterSpec(ASN1OctetString.getInstance(keyEncryptionAlgorithm.getParameters()).getOctets());
+
+ keyEncryptionCipher.init(Cipher.UNWRAP_MODE, new SecretKeySpec(derivedKey, keyEncryptionCipher.getAlgorithm()), ivSpec);
+
+ return keyEncryptionCipher.unwrap(encryptedContentEncryptionKey, contentEncryptionAlgorithm.getAlgorithm().getId(), Cipher.SECRET_KEY);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new CMSException("cannot process content encryption key: " + e.getMessage(), e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CMSException("cannot process content encryption key: " + e.getMessage(), e);
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CMSException("cannot process content encryption key: " + e.getMessage(), e);
+ }
+ }
+
+ public int getPasswordConversionScheme()
+ {
+ return schemeID;
+ }
+
+ public char[] getPassword()
+ {
+ return password;
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java
new file mode 100644
index 00000000..efbd266f
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/JcePasswordRecipientInfoGenerator.java
@@ -0,0 +1,66 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.Provider;
+import java.security.InvalidKeyException;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.cms.CMSException;
+import org.bouncycastle.cms.PasswordRecipientInfoGenerator;
+import org.bouncycastle.operator.GenericKey;
+
+public class JcePasswordRecipientInfoGenerator
+ extends PasswordRecipientInfoGenerator
+{
+ private EnvelopedDataHelper helper = new EnvelopedDataHelper(new DefaultJcaJceExtHelper());
+
+ public JcePasswordRecipientInfoGenerator(ASN1ObjectIdentifier kekAlgorithm, char[] password)
+ {
+ super(kekAlgorithm, password);
+ }
+
+ public JcePasswordRecipientInfoGenerator setProvider(Provider provider)
+ {
+ this.helper = new EnvelopedDataHelper(new ProviderJcaJceExtHelper(provider));
+
+ return this;
+ }
+
+ public JcePasswordRecipientInfoGenerator setProvider(String providerName)
+ {
+ this.helper = new EnvelopedDataHelper(new NamedJcaJceExtHelper(providerName));
+
+ return this;
+ }
+
+ public byte[] generateEncryptedBytes(AlgorithmIdentifier keyEncryptionAlgorithm, byte[] derivedKey, GenericKey contentEncryptionKey)
+ throws CMSException
+ {
+ Key contentEncryptionKeySpec = helper.getJceKey(contentEncryptionKey);
+ Cipher keyEncryptionCipher = helper.createRFC3211Wrapper(keyEncryptionAlgorithm.getAlgorithm());
+
+ try
+ {
+ IvParameterSpec ivSpec = new IvParameterSpec(ASN1OctetString.getInstance(keyEncryptionAlgorithm.getParameters()).getOctets());
+
+ keyEncryptionCipher.init(Cipher.WRAP_MODE, new SecretKeySpec(derivedKey, keyEncryptionCipher.getAlgorithm()), ivSpec);
+
+ return keyEncryptionCipher.wrap(contentEncryptionKeySpec);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CMSException("cannot process content encryption key: " + e.getMessage(), e);
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CMSException("cannot process content encryption key: " + e.getMessage(), e);
+ }
+ }
+}
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java
new file mode 100644
index 00000000..ff5c4518
--- /dev/null
+++ b/pkix/src/main/jdk1.1/org/bouncycastle/cms/jcajce/ZlibExpanderProvider.java
@@ -0,0 +1,113 @@
+package org.bouncycastle.cms.jcajce;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.InflaterInputStream;
+
+import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.operator.InputExpander;
+import org.bouncycastle.operator.InputExpanderProvider;
+import org.bouncycastle.util.io.StreamOverflowException;
+
+public class ZlibExpanderProvider
+ implements InputExpanderProvider
+{
+ private long limit;
+
+ public ZlibExpanderProvider()
+ {
+ this.limit = -1;
+ }
+
+ /**
+ * Create a provider which caps the number of expanded bytes that can be produced when the
+ * compressed stream is parsed.
+ *
+ * @param limit max number of bytes allowed in an expanded stream.
+ */
+ public ZlibExpanderProvider(long limit)
+ {
+ this.limit = limit;
+ }
+
+ public InputExpander get(final AlgorithmIdentifier algorithm)
+ {
+ return new InputExpander()
+ {
+ public AlgorithmIdentifier getAlgorithmIdentifier()
+ {
+ return algorithm;
+ }
+
+ public InputStream getInputStream(InputStream comIn)
+ {
+ InputStream s = new InflaterInputStream(comIn);
+ if (limit >= 0)
+ {
+ s = new LimitedInputStream(s, limit);
+ }
+ return s;
+ }
+ };
+ }
+
+ private static class LimitedInputStream
+ extends FilterInputStream
+ {
+ private long remaining;
+
+ public LimitedInputStream(InputStream input, long limit)
+ {
+ super(input);
+
+ this.remaining = limit;
+ }
+
+ public int read()
+ throws IOException
+ {
+ // Only a single 'extra' byte will ever be read
+ if (remaining >= 0)
+ {
+ int b = super.in.read();
+ if (b < 0 || --remaining >= 0)
+ {
+ return b;
+ }
+ }
+
+ throw new StreamOverflowException("expanded byte limit exceeded");
+ }
+
+ public int read(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (len < 1)
+ {
+ // This will give correct exceptions/returns for strange lengths
+ return super.read(buf, off, len);
+ }
+
+ if (remaining < 1)
+ {
+ // Will either return EOF or throw exception
+ read();
+ return -1;
+ }
+
+ /*
+ * Limit the underlying request to 'remaining' bytes. This ensures the
+ * caller will see the full 'limit' bytes before getting an exception.
+ * Also, only one extra byte will ever be read.
+ */
+ int actualLen = (remaining > len ? len : (int)remaining);
+ int numRead = super.in.read(buf, off, actualLen);
+ if (numRead > 0)
+ {
+ remaining -= numRead;
+ }
+ return numRead;
+ }
+ }
+}