summary refs log tree commit diff
path: root/Crypto/src/crypto/engines/VMPCEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/engines/VMPCEngine.cs')
-rw-r--r--Crypto/src/crypto/engines/VMPCEngine.cs139
1 files changed, 139 insertions, 0 deletions
diff --git a/Crypto/src/crypto/engines/VMPCEngine.cs b/Crypto/src/crypto/engines/VMPCEngine.cs
new file mode 100644
index 000000000..d467fbba5
--- /dev/null
+++ b/Crypto/src/crypto/engines/VMPCEngine.cs
@@ -0,0 +1,139 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	public class VmpcEngine
+		: IStreamCipher
+	{
+		/*
+		* variables to hold the state of the VMPC engine during encryption and
+		* decryption
+		*/
+		protected byte n = 0;
+		protected byte[] P = null;
+		protected byte s = 0;
+
+		protected byte[] workingIV;
+		protected byte[] workingKey;
+
+		public virtual string AlgorithmName
+		{
+			get { return "VMPC"; }
+		}
+
+		/**
+		* initialise a VMPC cipher.
+		* 
+		* @param forEncryption
+		*    whether or not we are for encryption.
+		* @param params
+		*    the parameters required to set up the cipher.
+		* @exception ArgumentException
+		*    if the params argument is inappropriate.
+		*/
+		public virtual void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (!(parameters is ParametersWithIV))
+				throw new ArgumentException("VMPC Init parameters must include an IV");
+
+			ParametersWithIV ivParams = (ParametersWithIV) parameters;
+			KeyParameter key = (KeyParameter) ivParams.Parameters;
+
+			if (!(ivParams.Parameters is KeyParameter))
+				throw new ArgumentException("VMPC Init parameters must include a key");
+
+			this.workingIV = ivParams.GetIV();
+
+			if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768)
+				throw new ArgumentException("VMPC requires 1 to 768 bytes of IV");
+
+			this.workingKey = key.GetKey();
+
+			InitKey(this.workingKey, this.workingIV);
+		}
+
+		protected virtual void InitKey(
+			byte[]	keyBytes,
+			byte[]	ivBytes)
+		{
+			s = 0;
+			P = new byte[256];
+			for (int i = 0; i < 256; i++)
+			{
+				P[i] = (byte) i;
+			}
+
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.Length]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.Length]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+			n = 0;
+		}
+
+		public virtual void ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		len,
+			byte[]	output,
+			int		outOff)
+		{
+			if ((inOff + len) > input.Length)
+			{
+				throw new DataLengthException("input buffer too short");
+			}
+
+			if ((outOff + len) > output.Length)
+			{
+				throw new DataLengthException("output buffer too short");
+			}
+
+			for (int i = 0; i < len; i++)
+			{
+				s = P[(s + P[n & 0xff]) & 0xff];
+				byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+				// encryption
+				byte temp = P[n & 0xff];
+				P[n & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+				n = (byte) ((n + 1) & 0xff);
+
+				// xor
+				output[i + outOff] = (byte) (input[i + inOff] ^ z);
+			}
+		}
+
+		public virtual void Reset()
+		{
+			InitKey(this.workingKey, this.workingIV);
+		}
+
+		public virtual byte ReturnByte(
+			byte input)
+		{
+			s = P[(s + P[n & 0xff]) & 0xff];
+			byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+			// encryption
+			byte temp = P[n & 0xff];
+			P[n & 0xff] = P[s & 0xff];
+			P[s & 0xff] = temp;
+			n = (byte) ((n + 1) & 0xff);
+
+			// xor
+			return (byte) (input ^ z);
+		}
+	}
+}