summary refs log tree commit diff
path: root/Crypto/src/crypto/engines/IesEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/engines/IesEngine.cs')
-rw-r--r--Crypto/src/crypto/engines/IesEngine.cs236
1 files changed, 236 insertions, 0 deletions
diff --git a/Crypto/src/crypto/engines/IesEngine.cs b/Crypto/src/crypto/engines/IesEngine.cs
new file mode 100644
index 000000000..c49b2a9ee
--- /dev/null
+++ b/Crypto/src/crypto/engines/IesEngine.cs
@@ -0,0 +1,236 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * support class for constructing intergrated encryption ciphers
+    * for doing basic message exchanges on top of key agreement ciphers
+    */
+    public class IesEngine
+    {
+        private readonly IBasicAgreement     agree;
+        private readonly IDerivationFunction kdf;
+        private readonly IMac                mac;
+        private readonly BufferedBlockCipher cipher;
+		private readonly byte[]              macBuf;
+
+		private bool				forEncryption;
+        private ICipherParameters	privParam, pubParam;
+        private IesParameters		param;
+
+        /**
+        * set up for use with stream mode, where the key derivation function
+        * is used to provide a stream of bytes to xor with the message.
+        *
+        * @param agree the key agreement used as the basis for the encryption
+        * @param kdf the key derivation function used for byte generation
+        * @param mac the message authentication code generator for the message
+        */
+        public IesEngine(
+            IBasicAgreement     agree,
+            IDerivationFunction kdf,
+            IMac                mac)
+        {
+            this.agree = agree;
+            this.kdf = kdf;
+            this.mac = mac;
+            this.macBuf = new byte[mac.GetMacSize()];
+//            this.cipher = null;
+        }
+
+        /**
+        * set up for use in conjunction with a block cipher to handle the
+        * message.
+        *
+        * @param agree the key agreement used as the basis for the encryption
+        * @param kdf the key derivation function used for byte generation
+        * @param mac the message authentication code generator for the message
+        * @param cipher the cipher to used for encrypting the message
+        */
+        public IesEngine(
+            IBasicAgreement     agree,
+            IDerivationFunction kdf,
+            IMac                mac,
+            BufferedBlockCipher cipher)
+        {
+            this.agree = agree;
+            this.kdf = kdf;
+            this.mac = mac;
+            this.macBuf = new byte[mac.GetMacSize()];
+            this.cipher = cipher;
+        }
+
+        /**
+        * Initialise the encryptor.
+        *
+        * @param forEncryption whether or not this is encryption/decryption.
+        * @param privParam our private key parameters
+        * @param pubParam the recipient's/sender's public key parameters
+        * @param param encoding and derivation parameters.
+        */
+        public void Init(
+            bool                     forEncryption,
+            ICipherParameters            privParameters,
+            ICipherParameters            pubParameters,
+            ICipherParameters            iesParameters)
+        {
+            this.forEncryption = forEncryption;
+            this.privParam = privParameters;
+            this.pubParam = pubParameters;
+            this.param = (IesParameters)iesParameters;
+        }
+
+        private byte[] DecryptBlock(
+            byte[]  in_enc,
+            int     inOff,
+            int     inLen,
+            byte[]  z)
+        {
+            byte[]          M = null;
+            KeyParameter    macKey = null;
+            KdfParameters   kParam = new KdfParameters(z, param.GetDerivationV());
+            int             macKeySize = param.MacKeySize;
+
+            kdf.Init(kParam);
+
+            inLen -= mac.GetMacSize();
+
+            if (cipher == null)     // stream mode
+            {
+				byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
+
+                M = new byte[inLen];
+
+                for (int i = 0; i != inLen; i++)
+                {
+                    M[i] = (byte)(in_enc[inOff + i] ^ Buffer[i]);
+                }
+
+                macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
+            }
+            else
+            {
+                int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
+				byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
+
+                cipher.Init(false, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
+
+				M = cipher.DoFinal(in_enc, inOff, inLen);
+
+				macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
+            }
+
+            byte[] macIV = param.GetEncodingV();
+
+            mac.Init(macKey);
+            mac.BlockUpdate(in_enc, inOff, inLen);
+            mac.BlockUpdate(macIV, 0, macIV.Length);
+            mac.DoFinal(macBuf, 0);
+
+			inOff += inLen;
+
+			for (int t = 0; t < macBuf.Length; t++)
+            {
+                if (macBuf[t] != in_enc[inOff + t])
+                {
+                    throw (new InvalidCipherTextException("IMac codes failed to equal."));
+                }
+            }
+
+            return M;
+        }
+
+        private byte[] EncryptBlock(
+            byte[]  input,
+            int     inOff,
+            int     inLen,
+            byte[]  z)
+        {
+            byte[]          C = null;
+            KeyParameter    macKey = null;
+            KdfParameters   kParam = new KdfParameters(z, param.GetDerivationV());
+            int             c_text_length = 0;
+            int             macKeySize = param.MacKeySize;
+
+            if (cipher == null)     // stream mode
+            {
+				byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
+
+                C = new byte[inLen + mac.GetMacSize()];
+                c_text_length = inLen;
+
+				for (int i = 0; i != inLen; i++)
+                {
+                    C[i] = (byte)(input[inOff + i] ^ Buffer[i]);
+                }
+
+                macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
+            }
+            else
+            {
+                int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
+				byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
+
+                cipher.Init(true, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
+
+                c_text_length = cipher.GetOutputSize(inLen);
+				byte[] tmp = new byte[c_text_length];
+
+				int len = cipher.ProcessBytes(input, inOff, inLen, tmp, 0);
+				len += cipher.DoFinal(tmp, len);
+
+				C = new byte[len + mac.GetMacSize()];
+				c_text_length = len;
+
+				Array.Copy(tmp, 0, C, 0, len);
+
+				macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
+            }
+
+            byte[] macIV = param.GetEncodingV();
+
+            mac.Init(macKey);
+            mac.BlockUpdate(C, 0, c_text_length);
+            mac.BlockUpdate(macIV, 0, macIV.Length);
+            //
+            // return the message and it's MAC
+            //
+            mac.DoFinal(C, c_text_length);
+            return C;
+        }
+
+		private byte[] GenerateKdfBytes(
+			KdfParameters	kParam,
+			int				length)
+		{
+			byte[] buf = new byte[length];
+
+			kdf.Init(kParam);
+
+			kdf.GenerateBytes(buf, 0, buf.Length);
+
+			return buf;
+		}
+
+		public byte[] ProcessBlock(
+            byte[]  input,
+            int     inOff,
+            int     inLen)
+        {
+            agree.Init(privParam);
+
+			BigInteger z = agree.CalculateAgreement(pubParam);
+
+			// TODO Is a fixed length result expected?
+			byte[] zBytes = z.ToByteArrayUnsigned();
+
+            return forEncryption
+				?	EncryptBlock(input, inOff, inLen, zBytes)
+                :	DecryptBlock(input, inOff, inLen, zBytes);
+        }
+    }
+
+}