diff options
Diffstat (limited to 'crypto/src/cms')
-rw-r--r-- | crypto/src/cms/CMSEnvelopedDataGenerator.cs | 71 | ||||
-rw-r--r-- | crypto/src/cms/CMSEnvelopedGenerator.cs | 10 | ||||
-rw-r--r-- | crypto/src/cms/CMSProcessableByteArray.cs | 17 | ||||
-rw-r--r-- | crypto/src/cms/EnvelopedDataHelper.cs | 123 | ||||
-rw-r--r-- | crypto/src/cms/RecipientInfoGenerator.cs | 2 |
5 files changed, 220 insertions, 3 deletions
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. |