diff --git a/Crypto/src/cms/CMSEnvelopedHelper.cs b/Crypto/src/cms/CMSEnvelopedHelper.cs
new file mode 100644
index 000000000..fe2b14cd9
--- /dev/null
+++ b/Crypto/src/cms/CMSEnvelopedHelper.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+ class CmsEnvelopedHelper
+ {
+ internal static readonly CmsEnvelopedHelper Instance = new CmsEnvelopedHelper();
+
+ private static readonly IDictionary KeySizes = Platform.CreateHashtable();
+ private static readonly IDictionary BaseCipherNames = Platform.CreateHashtable();
+
+ static CmsEnvelopedHelper()
+ {
+ KeySizes.Add(CmsEnvelopedGenerator.DesEde3Cbc, 192);
+ KeySizes.Add(CmsEnvelopedGenerator.Aes128Cbc, 128);
+ KeySizes.Add(CmsEnvelopedGenerator.Aes192Cbc, 192);
+ KeySizes.Add(CmsEnvelopedGenerator.Aes256Cbc, 256);
+
+ BaseCipherNames.Add(CmsEnvelopedGenerator.DesEde3Cbc, "DESEDE");
+ BaseCipherNames.Add(CmsEnvelopedGenerator.Aes128Cbc, "AES");
+ BaseCipherNames.Add(CmsEnvelopedGenerator.Aes192Cbc, "AES");
+ BaseCipherNames.Add(CmsEnvelopedGenerator.Aes256Cbc, "AES");
+ }
+
+ private string GetAsymmetricEncryptionAlgName(
+ string encryptionAlgOid)
+ {
+ if (Asn1.Pkcs.PkcsObjectIdentifiers.RsaEncryption.Id.Equals(encryptionAlgOid))
+ {
+ return "RSA/ECB/PKCS1Padding";
+ }
+
+ return encryptionAlgOid;
+ }
+
+ internal IBufferedCipher CreateAsymmetricCipher(
+ string encryptionOid)
+ {
+ string asymName = GetAsymmetricEncryptionAlgName(encryptionOid);
+ if (!asymName.Equals(encryptionOid))
+ {
+ try
+ {
+ return CipherUtilities.GetCipher(asymName);
+ }
+ catch (SecurityUtilityException)
+ {
+ // Ignore
+ }
+ }
+ return CipherUtilities.GetCipher(encryptionOid);
+ }
+
+ internal IWrapper CreateWrapper(
+ string encryptionOid)
+ {
+ try
+ {
+ return WrapperUtilities.GetWrapper(encryptionOid);
+ }
+ catch (SecurityUtilityException)
+ {
+ return WrapperUtilities.GetWrapper(GetAsymmetricEncryptionAlgName(encryptionOid));
+ }
+ }
+
+ internal string GetRfc3211WrapperName(
+ string oid)
+ {
+ if (oid == null)
+ throw new ArgumentNullException("oid");
+
+ string alg = (string) BaseCipherNames[oid];
+
+ if (alg == null)
+ throw new ArgumentException("no name for " + oid, "oid");
+
+ return alg + "RFC3211Wrap";
+ }
+
+ internal int GetKeySize(
+ string oid)
+ {
+ if (!KeySizes.Contains(oid))
+ {
+ throw new ArgumentException("no keysize for " + oid, "oid");
+ }
+
+ return (int) KeySizes[oid];
+ }
+
+ internal static RecipientInformationStore BuildRecipientInformationStore(
+ Asn1Set recipientInfos, CmsSecureReadable secureReadable)
+ {
+ IList infos = Platform.CreateArrayList();
+ for (int i = 0; i != recipientInfos.Count; i++)
+ {
+ RecipientInfo info = RecipientInfo.GetInstance(recipientInfos[i]);
+
+ ReadRecipientInfo(infos, info, secureReadable);
+ }
+ return new RecipientInformationStore(infos);
+ }
+
+ private static void ReadRecipientInfo(
+ IList infos, RecipientInfo info, CmsSecureReadable secureReadable)
+ {
+ Asn1Encodable recipInfo = info.Info;
+ if (recipInfo is KeyTransRecipientInfo)
+ {
+ infos.Add(new KeyTransRecipientInformation((KeyTransRecipientInfo)recipInfo, secureReadable));
+ }
+ else if (recipInfo is KekRecipientInfo)
+ {
+ infos.Add(new KekRecipientInformation((KekRecipientInfo)recipInfo, secureReadable));
+ }
+ else if (recipInfo is KeyAgreeRecipientInfo)
+ {
+ KeyAgreeRecipientInformation.ReadRecipientInfo(infos, (KeyAgreeRecipientInfo)recipInfo, secureReadable);
+ }
+ else if (recipInfo is PasswordRecipientInfo)
+ {
+ infos.Add(new PasswordRecipientInformation((PasswordRecipientInfo)recipInfo, secureReadable));
+ }
+ }
+
+ internal class CmsAuthenticatedSecureReadable : CmsSecureReadable
+ {
+ private AlgorithmIdentifier algorithm;
+ private IMac mac;
+ private CmsReadable readable;
+
+ internal CmsAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
+ {
+ this.algorithm = algorithm;
+ this.readable = readable;
+ }
+
+ public AlgorithmIdentifier Algorithm
+ {
+ get { return this.algorithm; }
+ }
+
+ public object CryptoObject
+ {
+ get { return this.mac; }
+ }
+
+ public CmsReadable GetReadable(KeyParameter sKey)
+ {
+ string macAlg = this.algorithm.ObjectID.Id;
+// Asn1Object sParams = this.algorithm.Parameters.ToAsn1Object();
+
+ try
+ {
+ this.mac = MacUtilities.GetMac(macAlg);
+
+ // FIXME Support for MAC algorithm parameters similar to cipher parameters
+// ASN1Object sParams = (ASN1Object)macAlg.getParameters();
+//
+// if (sParams != null && !(sParams instanceof ASN1Null))
+// {
+// AlgorithmParameters params = CMSEnvelopedHelper.INSTANCE.createAlgorithmParameters(macAlg.getObjectId().getId(), provider);
+//
+// params.init(sParams.getEncoded(), "ASN.1");
+//
+// mac.init(sKey, params.getParameterSpec(IvParameterSpec.class));
+// }
+// else
+ {
+ mac.Init(sKey);
+ }
+
+// Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object();
+//
+// ICipherParameters cipherParameters = sKey;
+//
+// if (asn1Params != null && !(asn1Params is Asn1Null))
+// {
+// cipherParameters = ParameterUtilities.GetCipherParameters(
+// macAlg.ObjectID, cipherParameters, asn1Params);
+// }
+// else
+// {
+// string alg = macAlg.ObjectID.Id;
+// if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
+// || alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
+// || alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
+// {
+// cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
+// }
+// }
+//
+// mac.Init(cipherParameters);
+ }
+ catch (SecurityUtilityException e)
+ {
+ throw new CmsException("couldn't create cipher.", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CmsException("key invalid in message.", e);
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("error decoding algorithm parameters.", e);
+ }
+
+ try
+ {
+ return new CmsProcessableInputStream(
+ new TeeInputStream(
+ readable.GetInputStream(),
+ new MacOutputStream(this.mac)));
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("error reading content.", e);
+ }
+ }
+ }
+
+ internal class CmsEnvelopedSecureReadable : CmsSecureReadable
+ {
+ private AlgorithmIdentifier algorithm;
+ private IBufferedCipher cipher;
+ private CmsReadable readable;
+
+ internal CmsEnvelopedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
+ {
+ this.algorithm = algorithm;
+ this.readable = readable;
+ }
+
+ public AlgorithmIdentifier Algorithm
+ {
+ get { return this.algorithm; }
+ }
+
+ public object CryptoObject
+ {
+ get { return this.cipher; }
+ }
+
+ public CmsReadable GetReadable(KeyParameter sKey)
+ {
+ try
+ {
+ this.cipher = CipherUtilities.GetCipher(this.algorithm.ObjectID);
+
+ Asn1Encodable asn1Enc = this.algorithm.Parameters;
+ Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object();
+
+ ICipherParameters cipherParameters = sKey;
+
+ if (asn1Params != null && !(asn1Params is Asn1Null))
+ {
+ cipherParameters = ParameterUtilities.GetCipherParameters(
+ this.algorithm.ObjectID, cipherParameters, asn1Params);
+ }
+ else
+ {
+ string alg = this.algorithm.ObjectID.Id;
+ if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
+ || alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
+ || alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
+ {
+ cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
+ }
+ }
+
+ cipher.Init(false, cipherParameters);
+ }
+ catch (SecurityUtilityException e)
+ {
+ throw new CmsException("couldn't create cipher.", e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CmsException("key invalid in message.", e);
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("error decoding algorithm parameters.", e);
+ }
+
+ try
+ {
+ return new CmsProcessableInputStream(
+ new CipherStream(readable.GetInputStream(), cipher, null));
+ }
+ catch (IOException e)
+ {
+ throw new CmsException("error reading content.", e);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
|