diff --git a/crypto/src/cms/CMSEnvelopedDataGenerator.cs b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
index d260e998a..8ba41161e 100644
--- a/crypto/src/cms/CMSEnvelopedDataGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataGenerator.cs
@@ -144,7 +144,7 @@ namespace Org.BouncyCastle.Cms
try
{
CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
-
+
keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
return Generate(content, encryptionOid, keyGen);
@@ -155,6 +155,75 @@ namespace Org.BouncyCastle.Cms
}
}
+
+ public CmsEnvelopedData Generate(CmsProcessable content, ICipherBuilderWithKey cipherBuilder)
+ {
+ AlgorithmIdentifier encAlgId = null;
+ KeyParameter encKey;
+ Asn1OctetString encContent;
+
+ try
+ {
+ encKey = (KeyParameter) cipherBuilder.Key;
+
+ MemoryStream collector = new MemoryStream();
+ Stream bOut = cipherBuilder.BuildCipher(collector).Stream;
+ content.Write(bOut);
+ Platform.Dispose(bOut);
+ encContent = new BerOctetString(collector.ToArray());
+ }
+ 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("exception decoding algorithm parameters.", e);
+ }
+
+
+ Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
+
+ foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
+ {
+ try
+ {
+ recipientInfos.Add(rig.Generate(encKey, rand));
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new CmsException("key inappropriate for algorithm.", e);
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new CmsException("error making encrypted content.", e);
+ }
+ }
+
+ EncryptedContentInfo eci = new EncryptedContentInfo(
+ CmsObjectIdentifiers.Data,
+ (AlgorithmIdentifier) cipherBuilder.AlgorithmDetails,
+ encContent);
+
+ Asn1Set unprotectedAttrSet = null;
+ if (unprotectedAttributeGenerator != null)
+ {
+ Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());
+
+ unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector());
+ }
+
+ ContentInfo contentInfo = new ContentInfo(
+ CmsObjectIdentifiers.EnvelopedData,
+ new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet));
+
+ return new CmsEnvelopedData(contentInfo);
+ }
+
/// <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
public CmsEnvelopedData Generate(
CmsProcessable content,
diff --git a/crypto/src/cms/CMSEnvelopedGenerator.cs b/crypto/src/cms/CMSEnvelopedGenerator.cs
index f92ae3824..ed7e1edee 100644
--- a/crypto/src/cms/CMSEnvelopedGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedGenerator.cs
@@ -263,6 +263,16 @@ namespace Org.BouncyCastle.Cms
recipientInfoGenerators.Add(karig);
}
+ /// <summary>
+ /// Add a generator to produce the recipient info required.
+ /// </summary>
+ /// <param name="recipientInfoGenerator">a generator of a recipient info object.</param>
+ public void AddRecipientInfoGenerator(RecipientInfoGenerator recipientInfoGenerator)
+ {
+ recipientInfoGenerators.Add(recipientInfoGenerator);
+ }
+
+
protected internal virtual AlgorithmIdentifier GetAlgorithmIdentifier(
string encryptionOid,
KeyParameter encKey,
diff --git a/crypto/src/cms/CMSProcessableByteArray.cs b/crypto/src/cms/CMSProcessableByteArray.cs
index a6ab9b6a2..b09935dd8 100644
--- a/crypto/src/cms/CMSProcessableByteArray.cs
+++ b/crypto/src/cms/CMSProcessableByteArray.cs
@@ -1,5 +1,7 @@
using System;
using System.IO;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
namespace Org.BouncyCastle.Cms
{
@@ -9,13 +11,26 @@ namespace Org.BouncyCastle.Cms
public class CmsProcessableByteArray
: CmsProcessable, CmsReadable
{
+ private readonly DerObjectIdentifier type;
private readonly byte[] bytes;
public CmsProcessableByteArray(byte[] bytes)
- {
+ {
+ type = CmsObjectIdentifiers.Data;
this.bytes = bytes;
}
+ public CmsProcessableByteArray(DerObjectIdentifier type, byte[] bytes)
+ {
+ this.bytes = bytes;
+ this.type = type;
+ }
+
+ public DerObjectIdentifier Type
+ {
+ get { return type; }
+ }
+
public virtual Stream GetInputStream()
{
return new MemoryStream(bytes, false);
diff --git a/crypto/src/cms/EnvelopedDataHelper.cs b/crypto/src/cms/EnvelopedDataHelper.cs
new file mode 100644
index 000000000..89ec79691
--- /dev/null
+++ b/crypto/src/cms/EnvelopedDataHelper.cs
@@ -0,0 +1,123 @@
+using System.Collections;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+ public class EnvelopedDataHelper
+ {
+ private static readonly IDictionary BaseCipherNames = Platform.CreateHashtable();
+ private static readonly IDictionary MacAlgNames = Platform.CreateHashtable();
+
+ private static readonly IDictionary prfs = Platform.CreateHashtable();
+
+
+ public delegate IDigest DigestCreator();
+
+ static EnvelopedDataHelper()
+ {
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha1, new DigestProvider(delegate () { return new Sha1Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha224, new DigestProvider(delegate () { return new Sha224Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha256, new DigestProvider(delegate () { return new Sha256Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha384, new DigestProvider(delegate () { return new Sha384Digest(); }));
+ prfs.Add(PkcsObjectIdentifiers.IdHmacWithSha512, new DigestProvider(delegate () { return new Sha512Digest(); }));
+
+
+ BaseCipherNames.Add(PkcsObjectIdentifiers.DesEde3Cbc, "DESEDE");
+ BaseCipherNames.Add(NistObjectIdentifiers.IdAes128Cbc, "AES");
+ BaseCipherNames.Add(NistObjectIdentifiers.IdAes192Cbc, "AES");
+ BaseCipherNames.Add(NistObjectIdentifiers.IdAes256Cbc, "AES");
+
+ MacAlgNames.Add(PkcsObjectIdentifiers.DesEde3Cbc, "DESEDEMac");
+ MacAlgNames.Add(NistObjectIdentifiers.IdAes128Cbc, "AESMac");
+ MacAlgNames.Add(NistObjectIdentifiers.IdAes192Cbc, "AESMac");
+ MacAlgNames.Add(NistObjectIdentifiers.IdAes256Cbc, "AESMac");
+ MacAlgNames.Add(PkcsObjectIdentifiers.RC2Cbc, "RC2Mac");
+ }
+
+ static IDigest GetPrf(AlgorithmIdentifier algID)
+ {
+ return ((DigestCreator)prfs[algID]).Invoke();
+ }
+
+
+ static IWrapper CreateRFC3211Wrapper(DerObjectIdentifier algorithm)
+
+ {
+ if (NistObjectIdentifiers.IdAes128Cbc.Equals(algorithm)
+ || NistObjectIdentifiers.IdAes192Cbc.Equals(algorithm)
+ || NistObjectIdentifiers.IdAes256Cbc.Equals(algorithm))
+ {
+ return new Rfc3211WrapEngine(new AesEngine());
+ }
+ else if (PkcsObjectIdentifiers.DesEde3Cbc.Equals(algorithm))
+ {
+ return new Rfc3211WrapEngine(new DesEdeEngine());
+ }
+ else if (OiwObjectIdentifiers.DesCbc.Equals(algorithm))
+ {
+ return new Rfc3211WrapEngine(new DesEngine());
+ }
+ else if (PkcsObjectIdentifiers.RC2Cbc.Equals(algorithm))
+ {
+ return new Rfc3211WrapEngine(new RC2Engine());
+ }
+ else
+ {
+ throw new CmsException("cannot recognise wrapper: " + algorithm);
+ }
+ }
+
+
+
+ public static object CreateContentCipher(bool forEncryption, ICipherParameters encKey,
+ AlgorithmIdentifier encryptionAlgID)
+
+ {
+ return CipherFactory.CreateContentCipher(forEncryption, encKey, encryptionAlgID);
+ }
+
+
+ public AlgorithmIdentifier GenerateEncryptionAlgID(DerObjectIdentifier encryptionOID, KeyParameter encKey, SecureRandom random)
+
+ {
+ return AlgorithmIdentifierFactory.GenerateEncryptionAlgID(encryptionOID, encKey.GetKey().Length * 8, random);
+ }
+
+ public CipherKeyGenerator CreateKeyGenerator(DerObjectIdentifier algorithm, SecureRandom random)
+
+ {
+ return CipherKeyGeneratorFactory.CreateKeyGenerator(algorithm, random);
+ }
+
+
+ }
+
+ // This exists because we can't directly put a delegate in a map as it is
+ // not an object.
+ internal class DigestProvider
+ {
+ private readonly EnvelopedDataHelper.DigestCreator creator;
+
+ public DigestProvider(EnvelopedDataHelper.DigestCreator creator)
+ {
+ this.creator = creator;
+ }
+
+ public IDigest Create()
+ {
+ return creator.Invoke();
+ }
+ }
+}
\ No newline at end of file
diff --git a/crypto/src/cms/RecipientInfoGenerator.cs b/crypto/src/cms/RecipientInfoGenerator.cs
index c41db6122..75f5dcc33 100644
--- a/crypto/src/cms/RecipientInfoGenerator.cs
+++ b/crypto/src/cms/RecipientInfoGenerator.cs
@@ -6,7 +6,7 @@ using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Cms
{
- interface RecipientInfoGenerator
+ public interface RecipientInfoGenerator
{
/// <summary>
/// Generate a RecipientInfo object for the given key.
|