194 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| /*
 | |
|   A C# implementation of the Twofish cipher
 | |
|   By Shaun Wilde
 | |
| 
 | |
|   An article on integrating a C# implementation of the Twofish cipher into the
 | |
|   .NET framework.
 | |
|  
 | |
|   http://www.codeproject.com/KB/recipes/twofish_csharp.aspx
 | |
|   
 | |
|   The Code Project Open License (CPOL) 1.02
 | |
|   http://www.codeproject.com/info/cpol10.aspx
 | |
|   
 | |
|   Download a copy of the CPOL.
 | |
|   http://www.codeproject.com/info/CPOL.zip
 | |
| */
 | |
| 
 | |
| using System;
 | |
| using System.Diagnostics;
 | |
| using System.Security.Cryptography;
 | |
| 
 | |
| namespace TwofishCipher.Crypto
 | |
| {
 | |
| 	/// <summary>
 | |
| 	/// Summary description for TwofishEncryption.
 | |
| 	/// </summary>
 | |
| 	internal class TwofishEncryption : TwofishBase, ICryptoTransform
 | |
| 	{
 | |
| 		public TwofishEncryption(int keyLen, ref byte[] key, ref byte[] iv, CipherMode cMode, EncryptionDirection direction)
 | |
| 		{
 | |
| 			// convert our key into an array of ints
 | |
| 			for (int i=0;i<key.Length/4;i++)
 | |
| 			{
 | |
| 				Key[i] = (uint)( key[i*4+3]<<24) | (uint)(key[i*4+2] << 16) | (uint)(key[i*4+1] << 8) | (uint)(key[i*4+0]);
 | |
| 			}
 | |
| 
 | |
| 			cipherMode = cMode;
 | |
| 
 | |
| 			// we only need to convert our IV if we are using CBC
 | |
| 			if (cipherMode == CipherMode.CBC)
 | |
| 			{
 | |
| 				for (int i=0;i<4;i++)
 | |
| 				{
 | |
| 					IV[i] = (uint)( iv[i*4+3]<<24) | (uint)(iv[i*4+2] << 16) | (uint)(iv[i*4+1] << 8) | (uint)(iv[i*4+0]);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			encryptionDirection = direction;
 | |
| 			reKey(keyLen,ref Key);
 | |
| 		}
 | |
| 
 | |
| 		// need to have this method due to IDisposable - just can't think of a reason to use it for in this class
 | |
| 		public void Dispose()
 | |
| 		{
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Transform a block depending on whether we are encrypting or decrypting
 | |
| 		/// </summary>
 | |
| 		/// <param name="inputBuffer"></param>
 | |
| 		/// <param name="inputOffset"></param>
 | |
| 		/// <param name="inputCount"></param>
 | |
| 		/// <param name="outputBuffer"></param>
 | |
| 		/// <param name="outputOffset"></param>
 | |
| 		/// <returns></returns>
 | |
| 		public int TransformBlock(
 | |
| 			byte[] inputBuffer,
 | |
| 			int inputOffset,
 | |
| 			int inputCount,
 | |
| 			byte[] outputBuffer,
 | |
| 			int outputOffset
 | |
| 			)
 | |
| 		{			
 | |
| 			uint[] x=new uint[4];
 | |
| 
 | |
| 			// load it up
 | |
| 			for (int i=0;i<4;i++)
 | |
| 			{
 | |
| 				x[i]= (uint)(inputBuffer[i*4+3+inputOffset]<<24) | (uint)(inputBuffer[i*4+2+inputOffset] << 16) | 
 | |
| 					(uint)(inputBuffer[i*4+1+inputOffset] << 8) | (uint)(inputBuffer[i*4+0+inputOffset]);
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			if (encryptionDirection == EncryptionDirection.Encrypting)
 | |
| 			{
 | |
| 				blockEncrypt(ref x);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				blockDecrypt(ref x);
 | |
| 			}
 | |
| 
 | |
| 
 | |
| 			// load it up
 | |
| 			for (int i=0;i<4;i++)
 | |
| 			{
 | |
| 				outputBuffer[i*4+0+outputOffset] = b0(x[i]);
 | |
| 				outputBuffer[i*4+1+outputOffset] = b1(x[i]);
 | |
| 				outputBuffer[i*4+2+outputOffset] = b2(x[i]);
 | |
| 				outputBuffer[i*4+3+outputOffset] = b3(x[i]);
 | |
| 			}
 | |
| 
 | |
| 
 | |
| 			return inputCount;
 | |
| 		}
 | |
| 
 | |
| 		public byte[] TransformFinalBlock(
 | |
| 			byte[] inputBuffer,
 | |
| 			int inputOffset,
 | |
| 			int inputCount
 | |
| 			)
 | |
| 		{
 | |
| 			byte[] outputBuffer;// = new byte[0];
 | |
| 			
 | |
| 			if (inputCount>0)
 | |
| 			{
 | |
| 				outputBuffer = new byte[16]; // blocksize
 | |
| 				uint[] x=new uint[4];
 | |
| 
 | |
| 				// load it up
 | |
| 				for (int i=0;i<4;i++) // should be okay as we have already said to pad with zeros
 | |
| 				{
 | |
| 					x[i]= (uint)(inputBuffer[i*4+3+inputOffset]<<24) | (uint)(inputBuffer[i*4+2+inputOffset] << 16) | 
 | |
| 						(uint)(inputBuffer[i*4+1+inputOffset] << 8) | (uint)(inputBuffer[i*4+0+inputOffset]);
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				if (encryptionDirection == EncryptionDirection.Encrypting)
 | |
| 				{
 | |
| 					blockEncrypt(ref x);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					blockDecrypt(ref x);
 | |
| 				}
 | |
| 
 | |
| 				// load it up
 | |
| 				for (int i=0;i<4;i++)
 | |
| 				{
 | |
| 					outputBuffer[i*4+0] = b0(x[i]);
 | |
| 					outputBuffer[i*4+1] = b1(x[i]);
 | |
| 					outputBuffer[i*4+2] = b2(x[i]);
 | |
| 					outputBuffer[i*4+3] = b3(x[i]);
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				outputBuffer = new byte[0]; // the .NET framework doesn't like it if you return null - this calms it down
 | |
| 			}
 | |
| 			
 | |
| 			return outputBuffer;
 | |
| 		}
 | |
| 
 | |
| 		// not worked out this property yet - placing break points here just don't get caught.
 | |
| 		private bool canReuseTransform = true;
 | |
| 		public bool CanReuseTransform
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return canReuseTransform;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// I normally set this to false when block encrypting so that I can work on one block at a time
 | |
| 		// but for compression and stream type ciphers this can be set to true so that you get all the data
 | |
| 		private bool canTransformMultipleBlocks = false;
 | |
| 		public bool CanTransformMultipleBlocks
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return canTransformMultipleBlocks;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public int InputBlockSize
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return inputBlockSize;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public int OutputBlockSize
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return outputBlockSize;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		private EncryptionDirection encryptionDirection;
 | |
| 	}
 | |
| }
 | 
