summary refs log tree commit diff
path: root/crypto/src/cms/KEKRecipientInfoGenerator.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/cms/KEKRecipientInfoGenerator.cs')
-rw-r--r--crypto/src/cms/KEKRecipientInfoGenerator.cs137
1 files changed, 137 insertions, 0 deletions
diff --git a/crypto/src/cms/KEKRecipientInfoGenerator.cs b/crypto/src/cms/KEKRecipientInfoGenerator.cs
new file mode 100644
index 000000000..a9bedade6
--- /dev/null
+++ b/crypto/src/cms/KEKRecipientInfoGenerator.cs
@@ -0,0 +1,137 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class KekRecipientInfoGenerator : RecipientInfoGenerator
+	{
+		private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
+
+		private KeyParameter	keyEncryptionKey;
+		// TODO Can get this from keyEncryptionKey?		
+		private string			keyEncryptionKeyOID;
+		private KekIdentifier	kekIdentifier;
+
+		// Derived
+		private AlgorithmIdentifier keyEncryptionAlgorithm;
+
+		internal KekRecipientInfoGenerator()
+		{
+		}
+
+		internal KekIdentifier KekIdentifier
+		{
+			set { this.kekIdentifier = value; }
+		}
+
+		internal KeyParameter KeyEncryptionKey
+		{
+			set
+			{
+				this.keyEncryptionKey = value;
+				this.keyEncryptionAlgorithm = DetermineKeyEncAlg(keyEncryptionKeyOID, keyEncryptionKey);
+			}
+		}
+
+		internal string KeyEncryptionKeyOID
+		{
+			set { this.keyEncryptionKeyOID = value; }
+		}
+
+		public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
+		{
+			byte[] keyBytes = contentEncryptionKey.GetKey();
+
+			IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.ObjectID.Id);
+			keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random));
+        	Asn1OctetString encryptedKey = new DerOctetString(
+				keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));
+
+			return new RecipientInfo(new KekRecipientInfo(kekIdentifier, keyEncryptionAlgorithm, encryptedKey));
+		}
+
+		private static AlgorithmIdentifier DetermineKeyEncAlg(
+			string algorithm, KeyParameter key)
+		{
+			if (algorithm.StartsWith("DES"))
+			{
+				return new AlgorithmIdentifier(
+					PkcsObjectIdentifiers.IdAlgCms3DesWrap,
+					DerNull.Instance);
+			}
+			else if (algorithm.StartsWith("RC2"))
+			{
+				return new AlgorithmIdentifier(
+					PkcsObjectIdentifiers.IdAlgCmsRC2Wrap,
+					new DerInteger(58));
+			}
+			else if (algorithm.StartsWith("AES"))
+			{
+				int length = key.GetKey().Length * 8;
+				DerObjectIdentifier wrapOid;
+
+				if (length == 128)
+				{
+					wrapOid = NistObjectIdentifiers.IdAes128Wrap;
+				}
+				else if (length == 192)
+				{
+					wrapOid = NistObjectIdentifiers.IdAes192Wrap;
+				}
+				else if (length == 256)
+				{
+					wrapOid = NistObjectIdentifiers.IdAes256Wrap;
+				}
+				else
+				{
+					throw new ArgumentException("illegal keysize in AES");
+				}
+
+				return new AlgorithmIdentifier(wrapOid);  // parameters absent
+			}
+			else if (algorithm.StartsWith("SEED"))
+			{
+				// parameters absent
+				return new AlgorithmIdentifier(KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap);
+			}
+			else if (algorithm.StartsWith("CAMELLIA"))
+			{
+				int length = key.GetKey().Length * 8;
+				DerObjectIdentifier wrapOid;
+
+				if (length == 128)
+				{
+					wrapOid = NttObjectIdentifiers.IdCamellia128Wrap;
+				}
+				else if (length == 192)
+				{
+					wrapOid = NttObjectIdentifiers.IdCamellia192Wrap;
+				}
+				else if (length == 256)
+				{
+					wrapOid = NttObjectIdentifiers.IdCamellia256Wrap;
+				}
+				else
+				{
+					throw new ArgumentException("illegal keysize in Camellia");
+				}
+
+				return new AlgorithmIdentifier(wrapOid); // parameters must be absent
+			}
+			else
+			{
+				throw new ArgumentException("unknown algorithm");
+			}
+		}
+	}
+}