Просмотр исходного кода

Implement write pipelining
Other minor peromnace improvments

olegkap_cp 14 лет назад
Родитель
Сommit
2760c05e21
18 измененных файлов с 846 добавлено и 868 удалено
  1. 6 0
      Renci.SshClient/Renci.SshNet/Common/BigInteger.cs
  2. 28 12
      Renci.SshClient/Renci.SshNet/Security/Cryptography/BlockCipher.cs
  3. 12 12
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Cipher.cs
  4. 1 12
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs
  5. 3 14
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs
  6. 44 55
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/CastCipher.cs
  7. 10 4
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/CipherMode.cs
  8. 24 35
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs
  9. 12 12
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs
  10. 16 16
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs
  11. 12 12
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs
  12. 16 16
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs
  13. 15 27
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs
  14. 587 598
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs
  15. 21 5
      Renci.SshClient/Renci.SshNet/Sftp/SftpFileStream.cs
  16. 30 31
      Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
  17. 7 3
      Renci.SshClient/Renci.SshNet/SftpClient.cs
  18. 2 4
      Renci.SshClient/Renci.SshNet/SshCommand.cs

+ 6 - 0
Renci.SshClient/Renci.SshNet/Common/BigInteger.cs

@@ -79,6 +79,12 @@ namespace Renci.SshNet.Common
         private readonly uint[] _data;
         private readonly short _sign;
 
+        /// <summary>
+        /// Gets number of bits used by the number.
+        /// </summary>
+        /// <value>
+        /// The number of the bit used.
+        /// </value>
         public int BitLength
         {
             get

+ 28 - 12
Renci.SshClient/Renci.SshNet/Security/Cryptography/BlockCipher.cs

@@ -21,18 +21,34 @@ namespace Renci.SshNet.Security.Cryptography
         /// <value>
         /// The size of the block in bytes.
         /// </value>
-        public abstract int BlockSize { get; }
+        protected readonly int _blockSize;
+
+        /// <summary>
+        /// Gets the size of the block.
+        /// </summary>
+        /// <value>
+        /// The size of the block.
+        /// </value>
+        public int BlockSize
+        {
+            get
+            {
+                return this._blockSize;
+            }
+        }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BlockCipher"/> class.
         /// </summary>
         /// <param name="key">The key.</param>
+        /// <param name="blockSize">Size of the block.</param>
         /// <param name="mode">Cipher mode.</param>
         /// <param name="padding">Cipher padding.</param>
         /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
-        protected BlockCipher(byte[] key, CipherMode mode, CipherPadding padding)
+        protected BlockCipher(byte[] key, int blockSize, CipherMode mode, CipherPadding padding)
             : base(key)
         {
+            this._blockSize = blockSize;
             this._mode = mode;
             this._padding = padding;
 
@@ -48,7 +64,7 @@ namespace Renci.SshNet.Security.Cryptography
         {
             var output = new byte[data.Length];
 
-            if (data.Length % this.BlockSize > 0)
+            if (data.Length % this._blockSize > 0)
             {
                 if (this._padding == null)
                 {
@@ -56,21 +72,21 @@ namespace Renci.SshNet.Security.Cryptography
                 }
                 else
                 {
-                    data = this._padding.Pad(this.BlockSize, data);
+                    data = this._padding.Pad(this._blockSize, data);
                 }
             }
 
             var writtenBytes = 0;
 
-            for (int i = 0; i < data.Length / this.BlockSize; i++)
+            for (int i = 0; i < data.Length / this._blockSize; i++)
             {
                 if (this._mode == null)
                 {
-                    writtenBytes += this.EncryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
+                    writtenBytes += this.EncryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
                 }
                 else
                 {
-                    writtenBytes += this._mode.EncryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
+                    writtenBytes += this._mode.EncryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
                 }
             }
 
@@ -89,7 +105,7 @@ namespace Renci.SshNet.Security.Cryptography
         /// <returns>Decrypted data</returns>
         public override byte[] Decrypt(byte[] data)
         {
-            if (data.Length % this.BlockSize > 0)
+            if (data.Length % this._blockSize > 0)
             {
                 {
                     if (this._padding == null)
@@ -98,7 +114,7 @@ namespace Renci.SshNet.Security.Cryptography
                     }
                     else
                     {
-                        data = this._padding.Pad(this.BlockSize, data);
+                        data = this._padding.Pad(this._blockSize, data);
                     }
                 }
             }
@@ -106,15 +122,15 @@ namespace Renci.SshNet.Security.Cryptography
             var output = new byte[data.Length];
 
             var writtenBytes = 0;
-            for (int i = 0; i < data.Length / this.BlockSize; i++)
+            for (int i = 0; i < data.Length / this._blockSize; i++)
             {
                 if (this._mode == null)
                 {
-                    writtenBytes += this.DecryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
+                    writtenBytes += this.DecryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
                 }
                 else
                 {
-                    writtenBytes += this._mode.DecryptBlock(data, i * this.BlockSize, this.BlockSize, output, i * this.BlockSize);
+                    writtenBytes += this._mode.DecryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
 
                 }
             }

+ 12 - 12
Renci.SshClient/Renci.SshNet/Security/Cryptography/Cipher.cs

@@ -48,9 +48,9 @@ namespace Renci.SshNet.Security.Cryptography
         protected static void UInt32ToBigEndian(uint number, byte[] buffer, int offset)
         {
             buffer[offset] = (byte)(number >> 24);
-            buffer[++offset] = (byte)(number >> 16);
-            buffer[++offset] = (byte)(number >> 8);
-            buffer[++offset] = (byte)(number);
+            buffer[offset + 1] = (byte)(number >> 16);
+            buffer[offset + 2] = (byte)(number >> 8);
+            buffer[offset + 3] = (byte)(number);
         }
 
         /// <summary>
@@ -76,9 +76,9 @@ namespace Renci.SshNet.Security.Cryptography
         protected static uint BigEndianToUInt32(byte[] buffer, int offset)
         {
             uint n = (uint)buffer[offset] << 24;
-            n |= (uint)buffer[++offset] << 16;
-            n |= (uint)buffer[++offset] << 8;
-            n |= (uint)buffer[++offset];
+            n |= (uint)buffer[offset + 1] << 16;
+            n |= (uint)buffer[offset + 2] << 8;
+            n |= (uint)buffer[offset + 3];
             return n;
         }
 
@@ -152,9 +152,9 @@ namespace Renci.SshNet.Security.Cryptography
         protected static void UInt32ToLittleEndian(uint number, byte[] buffer, int offset)
         {
             buffer[offset] = (byte)(number);
-            buffer[++offset] = (byte)(number >> 8);
-            buffer[++offset] = (byte)(number >> 16);
-            buffer[++offset] = (byte)(number >> 24);
+            buffer[offset + 1] = (byte)(number >> 8);
+            buffer[offset + 2] = (byte)(number >> 16);
+            buffer[offset + 3] = (byte)(number >> 24);
         }
 
         /// <summary>
@@ -180,9 +180,9 @@ namespace Renci.SshNet.Security.Cryptography
         protected static uint LittleEndianToUInt32(byte[] buffer, int offset)
         {
             uint n = (uint)buffer[offset];
-            n |= (uint)buffer[++offset] << 8;
-            n |= (uint)buffer[++offset] << 16;
-            n |= (uint)buffer[++offset] << 24;
+            n |= (uint)buffer[offset + 1] << 8;
+            n |= (uint)buffer[offset + 2] << 16;
+            n |= (uint)buffer[offset + 3] << 24;
             return n;
         }
 

+ 1 - 12
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs

@@ -586,17 +586,6 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 
         #endregion
 
-        /// <summary>
-        /// Gets the size of the block in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the block in bytes.
-        /// </value>
-        public override int BlockSize
-        {
-            get { return 16; }
-        }
-
         /// <summary>
         /// Initializes a new instance of the <see cref="AesCipher"/> class.
         /// </summary>
@@ -606,7 +595,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
         /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
         /// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
         public AesCipher(byte[] key, CipherMode mode, CipherPadding padding)
-            : base(key, mode, padding)
+            : base(key, 16, mode, padding)
         {
             var keySize = key.Length * 8;
 

+ 3 - 14
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs

@@ -298,27 +298,16 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 		private readonly uint[] S0, S1, S2, S3;     // the s-boxes
 		private readonly uint[] P;                  // the p-array
 
-		/// <summary>
-		/// Gets the size of the block in bytes.
-		/// </summary>
-		/// <value>
-		/// The size of the block in bytes.
-		/// </value>
-		public override int BlockSize
-		{
-			get { return 8; }
-		}
-
 		/// <summary>
 		/// Initializes a new instance of the <see cref="BlowfishCipher"/> class.
 		/// </summary>
 		/// <param name="key">The key.</param>
 		/// <param name="mode">The mode.</param>
 		/// <param name="padding">The padding.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
-        /// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
+		/// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
+		/// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
 		public BlowfishCipher(byte[] key, CipherMode mode, CipherPadding padding)
-			: base(key, mode, padding)
+			: base(key, 8, mode, padding)
 		{
 			var keySize = key.Length * 8;
 

+ 44 - 55
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/CastCipher.cs

@@ -13,22 +13,11 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
         internal static readonly int MAX_ROUNDS = 16;
         internal static readonly int RED_ROUNDS = 12;
 
-        private int[] _Kr = new int[17];        // the rotating round key
-        private uint[] _Km = new uint[17];        // the masking round key
+        private int[] _kr = new int[17];        // the rotating round key
+        private uint[] _km = new uint[17];        // the masking round key
 
         private int _rounds = MAX_ROUNDS;
 
-        /// <summary>
-        /// Gets the size of the block in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the block in bytes.
-        /// </value>
-        public override int BlockSize
-        {
-            get { return 8; }
-        }
-
         /// <summary>
         /// Initializes a new instance of the <see cref="CastCipher"/> class.
         /// </summary>
@@ -38,7 +27,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
         /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
         /// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
         public CastCipher(byte[] key, CipherMode mode, CipherPadding padding)
-            : base(key, mode, padding)
+            : base(key, 8, mode, padding)
         {
             var keySize = key.Length * 8;
 
@@ -412,7 +401,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 
             if (key.Length < 11)
             {
-                _rounds = RED_ROUNDS;
+                this._rounds = RED_ROUNDS;
             }
 
             int[] z = new int[16];
@@ -446,10 +435,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(z8B, z, 0x8);
             zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
             Bits32ToInts(zCF, z, 0xC);
-            _Km[1] = S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
-            _Km[2] = S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
-            _Km[3] = S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
-            _Km[4] = S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
+            this._km[1] = S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
+            this._km[2] = S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
+            this._km[3] = S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
+            this._km[4] = S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
 
             z03 = IntsTo32bits(z, 0x0);
             z47 = IntsTo32bits(z, 0x4);
@@ -463,10 +452,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(x8B, x, 0x8);
             xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
             Bits32ToInts(xCF, x, 0xC);
-            _Km[5] = S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
-            _Km[6] = S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
-            _Km[7] = S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
-            _Km[8] = S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
+            this._km[5] = S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
+            this._km[6] = S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
+            this._km[7] = S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
+            this._km[8] = S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
 
             x03 = IntsTo32bits(x, 0x0);
             x47 = IntsTo32bits(x, 0x4);
@@ -480,10 +469,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(z8B, z, 0x8);
             zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
             Bits32ToInts(zCF, z, 0xC);
-            _Km[9] = S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
-            _Km[10] = S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
-            _Km[11] = S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
-            _Km[12] = S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
+            this._km[9] = S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
+            this._km[10] = S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
+            this._km[11] = S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
+            this._km[12] = S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
 
             z03 = IntsTo32bits(z, 0x0);
             z47 = IntsTo32bits(z, 0x4);
@@ -497,10 +486,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(x8B, x, 0x8);
             xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
             Bits32ToInts(xCF, x, 0xC);
-            _Km[13] = S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
-            _Km[14] = S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
-            _Km[15] = S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
-            _Km[16] = S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
+            this._km[13] = S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
+            this._km[14] = S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
+            this._km[15] = S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
+            this._km[16] = S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
 
             x03 = IntsTo32bits(x, 0x0);
             x47 = IntsTo32bits(x, 0x4);
@@ -514,10 +503,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(z8B, z, 0x8);
             zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
             Bits32ToInts(zCF, z, 0xC);
-            _Kr[1] = (int)((S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]]) & 0x1f);
-            _Kr[2] = (int)((S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]]) & 0x1f);
-            _Kr[3] = (int)((S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]]) & 0x1f);
-            _Kr[4] = (int)((S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]]) & 0x1f);
+            this._kr[1] = (int)((S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]]) & 0x1f);
+            this._kr[2] = (int)((S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]]) & 0x1f);
+            this._kr[3] = (int)((S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]]) & 0x1f);
+            this._kr[4] = (int)((S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]]) & 0x1f);
 
             z03 = IntsTo32bits(z, 0x0);
             z47 = IntsTo32bits(z, 0x4);
@@ -531,10 +520,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(x8B, x, 0x8);
             xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
             Bits32ToInts(xCF, x, 0xC);
-            _Kr[5] = (int)((S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]]) & 0x1f);
-            _Kr[6] = (int)((S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]]) & 0x1f);
-            _Kr[7] = (int)((S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]]) & 0x1f);
-            _Kr[8] = (int)((S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]]) & 0x1f);
+            this._kr[5] = (int)((S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]]) & 0x1f);
+            this._kr[6] = (int)((S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]]) & 0x1f);
+            this._kr[7] = (int)((S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]]) & 0x1f);
+            this._kr[8] = (int)((S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]]) & 0x1f);
 
             x03 = IntsTo32bits(x, 0x0);
             x47 = IntsTo32bits(x, 0x4);
@@ -548,10 +537,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(z8B, z, 0x8);
             zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
             Bits32ToInts(zCF, z, 0xC);
-            _Kr[9] = (int)((S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]]) & 0x1f);
-            _Kr[10] = (int)((S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]]) & 0x1f);
-            _Kr[11] = (int)((S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]]) & 0x1f);
-            _Kr[12] = (int)((S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]]) & 0x1f);
+            this._kr[9] = (int)((S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]]) & 0x1f);
+            this._kr[10] = (int)((S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]]) & 0x1f);
+            this._kr[11] = (int)((S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]]) & 0x1f);
+            this._kr[12] = (int)((S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]]) & 0x1f);
 
             z03 = IntsTo32bits(z, 0x0);
             z47 = IntsTo32bits(z, 0x4);
@@ -565,10 +554,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             Bits32ToInts(x8B, x, 0x8);
             xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
             Bits32ToInts(xCF, x, 0xC);
-            _Kr[13] = (int)((S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]]) & 0x1f);
-            _Kr[14] = (int)((S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]]) & 0x1f);
-            _Kr[15] = (int)((S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]]) & 0x1f);
-            _Kr[16] = (int)((S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]]) & 0x1f);
+            this._kr[13] = (int)((S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]]) & 0x1f);
+            this._kr[14] = (int)((S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]]) & 0x1f);
+            this._kr[15] = (int)((S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]]) & 0x1f);
+            this._kr[16] = (int)((S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]]) & 0x1f);
         }
 
         /**
@@ -636,7 +625,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             */
             uint Li = L0, Ri = R0;
 
-            for (int i = 1; i <= _rounds; i++)
+            for (int i = 1; i <= this._rounds; i++)
             {
                 Lp = Li;
                 Rp = Ri;
@@ -650,21 +639,21 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
                     case 10:
                     case 13:
                     case 16:
-                        Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+                        Ri = Lp ^ F1(Rp, this._km[i], this._kr[i]);
                         break;
                     case 2:
                     case 5:
                     case 8:
                     case 11:
                     case 14:
-                        Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+                        Ri = Lp ^ F2(Rp, this._km[i], this._kr[i]);
                         break;
                     case 3:
                     case 6:
                     case 9:
                     case 12:
                     case 15:
-                        Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+                        Ri = Lp ^ F3(Rp, this._km[i], this._kr[i]);
                         break;
                 }
             }
@@ -686,7 +675,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             */
             uint Li = L16, Ri = R16;
 
-            for (int i = _rounds; i > 0; i--)
+            for (int i = this._rounds; i > 0; i--)
             {
                 Lp = Li;
                 Rp = Ri;
@@ -700,21 +689,21 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
                     case 10:
                     case 13:
                     case 16:
-                        Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+                        Ri = Lp ^ F1(Rp, this._km[i], this._kr[i]);
                         break;
                     case 2:
                     case 5:
                     case 8:
                     case 11:
                     case 14:
-                        Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+                        Ri = Lp ^ F2(Rp, this._km[i], this._kr[i]);
                         break;
                     case 3:
                     case 6:
                     case 9:
                     case 12:
                     case 15:
-                        Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+                        Ri = Lp ^ F3(Rp, this._km[i], this._kr[i]);
                         break;
                 }
             }

+ 10 - 4
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/CipherMode.cs

@@ -13,12 +13,17 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
         /// <summary>
         /// Gets the cipher.
         /// </summary>
-        protected BlockCipher Cipher { get; private set; }
+        protected BlockCipher Cipher;
 
         /// <summary>
         /// Gets the IV vector.
         /// </summary>
-        protected byte[] IV { get; private set; }
+        protected byte[] IV;
+
+        /// <summary>
+        /// Holds block size of the cipher.
+        /// </summary>
+        protected int _blockSize;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="CipherMode"/> class.
@@ -30,13 +35,14 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
         }
 
         /// <summary>
-        /// Inits the specified cipher.
+        /// Initializes the specified cipher mode.
         /// </summary>
         /// <param name="cipher">The cipher.</param>
         internal void Init(BlockCipher cipher)
         {
             this.Cipher = cipher;
-            this.IV = this.IV.Take(cipher.BlockSize).ToArray();
+            this._blockSize = cipher.BlockSize;
+            this.IV = this.IV.Take(this._blockSize).ToArray();
         }
 
         /// <summary>

+ 24 - 35
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs

@@ -5,26 +5,15 @@ using System.Text;
 
 namespace Renci.SshNet.Security.Cryptography.Ciphers
 {
-    /// <summary>
-    /// Implements DES cipher algorithm.
-    /// </summary>
+	/// <summary>
+	/// Implements DES cipher algorithm.
+	/// </summary>
 	public class DesCipher : BlockCipher
 	{
 		private int[] _encryptionKey;
 
 		private int[] _decryptionKey;
 
-		/// <summary>
-		/// Gets the size of the block in bytes.
-		/// </summary>
-		/// <value>
-		/// The size of the block in bytes.
-		/// </value>
-		public override int BlockSize
-		{
-			get { return 8; }
-		}
-
 		#region Static tables
 
 		private static readonly short[] bytebit =
@@ -235,9 +224,9 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 		/// <param name="key">The key.</param>
 		/// <param name="mode">The mode.</param>
 		/// <param name="padding">The padding.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
+		/// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
 		public DesCipher(byte[] key, CipherMode mode, CipherPadding padding)
-			: base(key, mode, padding)
+			: base(key, 8, mode, padding)
 		{
 		}
 
@@ -260,10 +249,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 			if ((outputOffset + this.BlockSize) > outputBuffer.Length)
 				throw new IndexOutOfRangeException("output buffer too short");
 
-            if (this._encryptionKey == null)
-            {
-                this._encryptionKey = GenerateWorkingKey(true, this.Key);
-            }
+			if (this._encryptionKey == null)
+			{
+				this._encryptionKey = GenerateWorkingKey(true, this.Key);
+			}
 
 			DesCipher.DesFunc(this._encryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
 
@@ -289,10 +278,10 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 			if ((outputOffset + this.BlockSize) > outputBuffer.Length)
 				throw new IndexOutOfRangeException("output buffer too short");
 
-            if (this._decryptionKey == null)
-            {
-                this._decryptionKey = GenerateWorkingKey(false, this.Key);
-            }
+			if (this._decryptionKey == null)
+			{
+				this._decryptionKey = GenerateWorkingKey(false, this.Key);
+			}
 
 			DesCipher.DesFunc(this._decryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
 
@@ -307,7 +296,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 		/// <returns></returns>
 		protected int[] GenerateWorkingKey(bool encrypting, byte[] key)
 		{
-            this.ValidateKey();
+			this.ValidateKey();
 
 			int[] newKey = new int[32];
 			bool[] pc1m = new bool[56];
@@ -400,16 +389,16 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 			return newKey;
 		}
 
-        /// <summary>
-        /// Validates the key.
-        /// </summary>
-        protected virtual void ValidateKey()
-        {
-            var keySize = this.Key.Length * 8;
-            
-            if (!(keySize == 64))
-                throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
-        }
+		/// <summary>
+		/// Validates the key.
+		/// </summary>
+		protected virtual void ValidateKey()
+		{
+			var keySize = this.Key.Length * 8;
+			
+			if (!(keySize == 64))
+				throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+		}
 
 		/// <summary>
 		/// Performs DES function.

+ 12 - 12
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs

@@ -33,16 +33,16 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 this.IV[i] ^= inputBuffer[inputOffset + i];
             }
@@ -51,7 +51,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
 
             Array.Copy(outputBuffer, outputOffset, this.IV, 0, this.IV.Length);
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
 
         /// <summary>
@@ -67,25 +67,25 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
             this.Cipher.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 outputBuffer[outputOffset + i] ^= this.IV[i];
             }
 
             Array.Copy(inputBuffer, inputOffset, this.IV, 0, this.IV.Length);
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
     }
 }

+ 16 - 16
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs

@@ -36,26 +36,26 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
             this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
             }
 
-            Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
-            Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
+            Array.Copy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+            Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
 
         /// <summary>
@@ -71,26 +71,26 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
             this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
 
-            Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
-            Array.Copy(inputBuffer, inputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
+            Array.Copy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+            Array.Copy(inputBuffer, inputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
             }
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
     }
 }

+ 12 - 12
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs

@@ -36,18 +36,18 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
             this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
             }
@@ -55,7 +55,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
             int j = this.IV.Length;
             while (--j >= 0 && ++this.IV[j] == 0) ;
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
 
         /// <summary>
@@ -71,18 +71,18 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
             this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
             }
@@ -90,7 +90,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
             int j = this.IV.Length;
             while (--j >= 0 && ++this.IV[j] == 0) ;
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
     }
 }

+ 16 - 16
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs

@@ -37,26 +37,26 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
             this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
             }
 
-            Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
-            Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
+            Array.Copy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+            Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
 
         /// <summary>
@@ -72,26 +72,26 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
         /// </returns>
         public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
         {
-            if (inputBuffer.Length - inputOffset < this.Cipher.BlockSize)
+            if (inputBuffer.Length - inputOffset < this._blockSize)
                 throw new ArgumentException("Invalid input buffer");
 
-            if (outputBuffer.Length - outputOffset < this.Cipher.BlockSize)
+            if (outputBuffer.Length - outputOffset < this._blockSize)
                 throw new ArgumentException("Invalid output buffer");
 
-            if (inputCount != this.Cipher.BlockSize)
-                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this.Cipher.BlockSize));
+            if (inputCount != this._blockSize)
+                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
 
             this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
 
-            for (int i = 0; i < this.Cipher.BlockSize; i++)
+            for (int i = 0; i < this._blockSize; i++)
             {
                 outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
             }
 
-            Array.Copy(this.IV, this.Cipher.BlockSize, this.IV, 0, this.IV.Length - this.Cipher.BlockSize);
-            Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this.Cipher.BlockSize, this.Cipher.BlockSize);
+            Array.Copy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+            Array.Copy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
 
-            return this.Cipher.BlockSize;
+            return this._blockSize;
         }
 
 

+ 15 - 27
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs

@@ -5,9 +5,9 @@ using System.Text;
 
 namespace Renci.SshNet.Security.Cryptography.Ciphers
 {
-    /// <summary>
-    /// Implements Serpent cipher algorithm.
-    /// </summary>
+	/// <summary>
+	/// Implements Serpent cipher algorithm.
+	/// </summary>
 	public class SerpentCipher : BlockCipher
 	{
 		private static readonly int ROUNDS = 32;
@@ -17,34 +17,22 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 
 		private int X0, X1, X2, X3;    // registers
 
-        /// <summary>
-        /// Gets the size of the block in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the block in bytes.
-        /// </value>
-		public override int BlockSize
-		{
-			get { return 16; }
-		}
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SerpentCipher"/> class.
-        /// </summary>
-        /// <param name="key">The key.</param>
-        /// <param name="mode">The mode.</param>
-        /// <param name="padding">The padding.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
-        /// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
+		/// <summary>
+		/// Initializes a new instance of the <see cref="SerpentCipher"/> class.
+		/// </summary>
+		/// <param name="key">The key.</param>
+		/// <param name="mode">The mode.</param>
+		/// <param name="padding">The padding.</param>
+		/// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
+		/// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
 		public SerpentCipher(byte[] key, CipherMode mode, CipherPadding padding)
-			: base(key, mode, padding)
+			: base(key, 16, mode, padding)
 		{
 			//  TODO:   Refactor this algorithm
+			var keySize = key.Length * 8;
 
-            var keySize = key.Length * 8;
-
-            if (!(keySize == 128 || keySize == 192 || keySize == 256))
-                throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+			if (!(keySize == 128 || keySize == 192 || keySize == 256))
+				throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
 
 			this._workingKey = this.MakeWorkingKey(key);
 		}

+ 587 - 598
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs

@@ -5,621 +5,610 @@ using System.Text;
 
 namespace Renci.SshNet.Security.Cryptography.Ciphers
 {
-    /// <summary>
-    /// Implements Twofish cipher algorithm
-    /// </summary>
+	/// <summary>
+	/// Implements Twofish cipher algorithm
+	/// </summary>
 	public class TwofishCipher : BlockCipher
 	{
-        /// <summary>
-        /// Gets the size of the block in bytes.
-        /// </summary>
-        /// <value>
-        /// The size of the block in bytes.
-        /// </value>
-        public override int BlockSize
-        {
-            get { return 16; }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="TwofishCipher"/> class.
-        /// </summary>
-        /// <param name="key">The key.</param>
-        /// <param name="mode">The mode.</param>
-        /// <param name="padding">The padding.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
-        /// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
+		/// <summary>
+		/// Initializes a new instance of the <see cref="TwofishCipher"/> class.
+		/// </summary>
+		/// <param name="key">The key.</param>
+		/// <param name="mode">The mode.</param>
+		/// <param name="padding">The padding.</param>
+		/// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
+		/// <exception cref="ArgumentException">Keysize is not valid for this algorithm.</exception>
 		public TwofishCipher(byte[] key, CipherMode mode, CipherPadding padding)
-			: base(key, mode, padding)
+			: base(key, 16, mode, padding)
 		{
-            var keySize = key.Length * 8;
+			var keySize = key.Length * 8;
 
-            if (!(keySize == 128 || keySize == 192 || keySize == 256))
-                throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+			if (!(keySize == 128 || keySize == 192 || keySize == 256))
+				throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
 
 			//  TODO:   Refactor this algorithm
 
-            // calculate the MDS matrix
-            int[] m1 = new int[2];
-            int[] mX = new int[2];
-            int[] mY = new int[2];
-            int j;
+			// calculate the MDS matrix
+			int[] m1 = new int[2];
+			int[] mX = new int[2];
+			int[] mY = new int[2];
+			int j;
 
-            for (int i = 0; i < MAX_KEY_BITS; i++)
-            {
-                j = P[0, i] & 0xff;
-                m1[0] = j;
-                mX[0] = Mx_X(j) & 0xff;
-                mY[0] = Mx_Y(j) & 0xff;
+			for (int i = 0; i < MAX_KEY_BITS; i++)
+			{
+				j = P[0, i] & 0xff;
+				m1[0] = j;
+				mX[0] = Mx_X(j) & 0xff;
+				mY[0] = Mx_Y(j) & 0xff;
 
-                j = P[1, i] & 0xff;
-                m1[1] = j;
-                mX[1] = Mx_X(j) & 0xff;
-                mY[1] = Mx_Y(j) & 0xff;
+				j = P[1, i] & 0xff;
+				m1[1] = j;
+				mX[1] = Mx_X(j) & 0xff;
+				mY[1] = Mx_Y(j) & 0xff;
 
-                gMDS0[i] = m1[P_00] | mX[P_00] << 8 | mY[P_00] << 16 | mY[P_00] << 24;
+				gMDS0[i] = m1[P_00] | mX[P_00] << 8 | mY[P_00] << 16 | mY[P_00] << 24;
 
-                gMDS1[i] = mY[P_10] | mY[P_10] << 8 | mX[P_10] << 16 | m1[P_10] << 24;
+				gMDS1[i] = mY[P_10] | mY[P_10] << 8 | mX[P_10] << 16 | m1[P_10] << 24;
 
-                gMDS2[i] = mX[P_20] | mY[P_20] << 8 | m1[P_20] << 16 | mY[P_20] << 24;
+				gMDS2[i] = mX[P_20] | mY[P_20] << 8 | m1[P_20] << 16 | mY[P_20] << 24;
 
-                gMDS3[i] = mX[P_30] | m1[P_30] << 8 | mY[P_30] << 16 | mX[P_30] << 24;
-            }
+				gMDS3[i] = mX[P_30] | m1[P_30] << 8 | mY[P_30] << 16 | mX[P_30] << 24;
+			}
 
-            this.k64Cnt = key.Length / 8; // pre-padded ?
-            this.SetKey(key);
+			this.k64Cnt = key.Length / 8; // pre-padded ?
+			this.SetKey(key);
 		}
 
-        /// <summary>
-        /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
-        /// </summary>
-        /// <param name="inputBuffer">The input data to encrypt.</param>
-        /// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
-        /// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
-        /// <param name="outputBuffer">The output to which to write encrypted data.</param>
-        /// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
-        /// <returns>
-        /// The number of bytes encrypted.
-        /// </returns>
-        public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
-        {
-            int x0 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[INPUT_WHITEN];
-            int x1 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[INPUT_WHITEN + 1];
-            int x2 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[INPUT_WHITEN + 2];
-            int x3 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[INPUT_WHITEN + 3];
-
-            int k = ROUND_SUBKEYS;
-            int t0, t1;
-            for (int r = 0; r < ROUNDS; r += 2)
-            {
-                t0 = Fe32_0(x0);
-                t1 = Fe32_3(x1);
-                x2 ^= t0 + t1 + gSubKeys[k++];
-                x2 = (int)((uint)x2 >> 1) | x2 << 31;
-                x3 = (x3 << 1 | (int)((uint)x3 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
-
-                t0 = Fe32_0(x2);
-                t1 = Fe32_3(x3);
-                x0 ^= t0 + t1 + gSubKeys[k++];
-                x0 = (int)((uint)x0 >> 1) | x0 << 31;
-                x1 = (x1 << 1 | (int)((uint)x1 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
-            }
-
-            Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], outputBuffer, outputOffset);
-            Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
-            Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
-            Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
-
-            return this.BlockSize;
-        }
-
-        /// <summary>
-        /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
-        /// </summary>
-        /// <param name="inputBuffer">The input data to decrypt.</param>
-        /// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
-        /// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
-        /// <param name="outputBuffer">The output to which to write decrypted data.</param>
-        /// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
-        /// <returns>
-        /// The number of bytes decrypted.
-        /// </returns>
-        public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
-        {
-            int x2 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[OUTPUT_WHITEN];
-            int x3 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[OUTPUT_WHITEN + 1];
-            int x0 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[OUTPUT_WHITEN + 2];
-            int x1 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[OUTPUT_WHITEN + 3];
-
-            int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
-            int t0, t1;
-            for (int r = 0; r < ROUNDS; r += 2)
-            {
-                t0 = Fe32_0(x2);
-                t1 = Fe32_3(x3);
-                x1 ^= t0 + 2 * t1 + gSubKeys[k--];
-                x0 = (x0 << 1 | (int)((uint)x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
-                x1 = (int)((uint)x1 >> 1) | x1 << 31;
-
-                t0 = Fe32_0(x0);
-                t1 = Fe32_3(x1);
-                x3 ^= t0 + 2 * t1 + gSubKeys[k--];
-                x2 = (x2 << 1 | (int)((uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
-                x3 = (int)((uint)x3 >> 1) | x3 << 31;
-            }
-
-            Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], outputBuffer, outputOffset);
-            Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
-            Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
-            Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
-
-            return this.BlockSize;
-        }
-
-        #region Static Definition Tables
-
-        private static readonly byte[,] P =  {
-        {  // p0
-            (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
-            (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
-            (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
-            (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
-            (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
-            (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
-            (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
-            (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
-            (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
-            (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
-            (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
-            (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
-            (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
-            (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
-            (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
-            (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
-            (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
-            (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
-            (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
-            (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
-            (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
-            (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
-            (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
-            (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
-            (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
-            (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
-            (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
-            (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
-            (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
-            (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
-            (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
-            (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
-            (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
-            (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
-            (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
-            (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
-            (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
-            (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
-            (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
-            (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
-            (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
-            (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
-            (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
-            (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
-            (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
-            (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
-            (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
-            (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
-            (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
-            (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
-            (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
-            (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
-            (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
-            (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
-            (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
-            (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
-            (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
-            (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
-            (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
-            (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
-            (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
-            (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
-            (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
-            (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
-        {  // p1
-            (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
-            (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
-            (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
-            (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
-            (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
-            (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
-            (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
-            (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
-            (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
-            (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
-            (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
-            (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
-            (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
-            (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
-            (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
-            (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
-            (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
-            (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
-            (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
-            (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
-            (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
-            (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
-            (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
-            (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
-            (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
-            (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
-            (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
-            (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
-            (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
-            (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
-            (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
-            (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
-            (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
-            (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
-            (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
-            (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
-            (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
-            (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
-            (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
-            (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
-            (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
-            (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
-            (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
-            (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
-            (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
-            (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
-            (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
-            (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
-            (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
-            (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
-            (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
-            (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
-            (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
-            (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
-            (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
-            (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
-            (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
-            (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
-            (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
-            (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
-            (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
-            (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
-            (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
-            (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91  }
-        };
-
-        #endregion
-
-        /**
-        * Define the fixed p0/p1 permutations used in keyed S-box lookup.
-        * By changing the following constant definitions, the S-boxes will
-        * automatically Get changed in the Twofish engine.
-        */
-        private const int P_00 = 1;
-        private const int P_01 = 0;
-        private const int P_02 = 0;
-        private const int P_03 = P_01 ^ 1;
-        private const int P_04 = 1;
-
-        private const int P_10 = 0;
-        private const int P_11 = 0;
-        private const int P_12 = 1;
-        private const int P_13 = P_11 ^ 1;
-        private const int P_14 = 0;
-
-        private const int P_20 = 1;
-        private const int P_21 = 1;
-        private const int P_22 = 0;
-        private const int P_23 = P_21 ^ 1;
-        private const int P_24 = 0;
-
-        private const int P_30 = 0;
-        private const int P_31 = 1;
-        private const int P_32 = 1;
-        private const int P_33 = P_31 ^ 1;
-        private const int P_34 = 1;
-
-        /* Primitive polynomial for GF(256) */
-        private const int GF256_FDBK = 0x169;
-        private const int GF256_FDBK_2 = GF256_FDBK / 2;
-        private const int GF256_FDBK_4 = GF256_FDBK / 4;
-
-        private const int RS_GF_FDBK = 0x14D; // field generator
-
-        //====================================
-        // Useful constants
-        //====================================
-
-        private const int ROUNDS = 16;
-        private const int MAX_ROUNDS = 16;  // bytes = 128 bits
-        private const int MAX_KEY_BITS = 256;
-
-        private const int INPUT_WHITEN = 0;
-        private const int OUTPUT_WHITEN = INPUT_WHITEN + 16 / 4; // 4
-        private const int ROUND_SUBKEYS = OUTPUT_WHITEN + 16 / 4;// 8
-
-        private const int TOTAL_SUBKEYS = ROUND_SUBKEYS + 2 * MAX_ROUNDS;// 40
-
-        private const int SK_STEP = 0x02020202;
-        private const int SK_BUMP = 0x01010101;
-        private const int SK_ROTL = 9;
-
-        private int[] gMDS0 = new int[MAX_KEY_BITS];
-        private int[] gMDS1 = new int[MAX_KEY_BITS];
-        private int[] gMDS2 = new int[MAX_KEY_BITS];
-        private int[] gMDS3 = new int[MAX_KEY_BITS];
-
-        /**
-        * gSubKeys[] and gSBox[] are eventually used in the
-        * encryption and decryption methods.
-        */
-        private int[] gSubKeys;
-        private int[] gSBox;
-
-        private int k64Cnt;
-
-        private void SetKey(byte[] key)
-        {
-            int[] k32e = new int[MAX_KEY_BITS / 64]; // 4
-            int[] k32o = new int[MAX_KEY_BITS / 64]; // 4
-
-            int[] sBoxKeys = new int[MAX_KEY_BITS / 64]; // 4
-            gSubKeys = new int[TOTAL_SUBKEYS];
-
-            if (k64Cnt < 1)
-            {
-                throw new ArgumentException("Key size less than 64 bits");
-            }
-
-            if (k64Cnt > 4)
-            {
-                throw new ArgumentException("Key size larger than 256 bits");
-            }
-
-            /*
-            * k64Cnt is the number of 8 byte blocks (64 chunks)
-            * that are in the input key.  The input key is a
-            * maximum of 32 bytes ( 256 bits ), so the range
-            * for k64Cnt is 1..4
-            */
-            for (int i = 0, p = 0; i < k64Cnt; i++)
-            {
-                p = i * 8;
-
-                k32e[i] = BytesTo32Bits(key, p);
-                k32o[i] = BytesTo32Bits(key, p + 4);
-
-                sBoxKeys[k64Cnt - 1 - i] = RS_MDS_Encode(k32e[i], k32o[i]);
-            }
-
-            int q, A, B;
-            for (int i = 0; i < TOTAL_SUBKEYS / 2; i++)
-            {
-                q = i * SK_STEP;
-                A = F32(q, k32e);
-                B = F32(q + SK_BUMP, k32o);
-                B = B << 8 | (int)((uint)B >> 24);
-                A += B;
-                gSubKeys[i * 2] = A;
-                A += B;
-                gSubKeys[i * 2 + 1] = A << SK_ROTL | (int)((uint)A >> (32 - SK_ROTL));
-            }
-
-            /*
-            * fully expand the table for speed
-            */
-            int k0 = sBoxKeys[0];
-            int k1 = sBoxKeys[1];
-            int k2 = sBoxKeys[2];
-            int k3 = sBoxKeys[3];
-            int b0, b1, b2, b3;
-            gSBox = new int[4 * MAX_KEY_BITS];
-            for (int i = 0; i < MAX_KEY_BITS; i++)
-            {
-                b0 = b1 = b2 = b3 = i;
-                switch (k64Cnt & 3)
-                {
-                    case 1:
-                        gSBox[i * 2] = gMDS0[(P[P_01, b0] & 0xff) ^ M_b0(k0)];
-                        gSBox[i * 2 + 1] = gMDS1[(P[P_11, b1] & 0xff) ^ M_b1(k0)];
-                        gSBox[i * 2 + 0x200] = gMDS2[(P[P_21, b2] & 0xff) ^ M_b2(k0)];
-                        gSBox[i * 2 + 0x201] = gMDS3[(P[P_31, b3] & 0xff) ^ M_b3(k0)];
-                        break;
-                    case 0: /* 256 bits of key */
-                        b0 = (P[P_04, b0] & 0xff) ^ M_b0(k3);
-                        b1 = (P[P_14, b1] & 0xff) ^ M_b1(k3);
-                        b2 = (P[P_24, b2] & 0xff) ^ M_b2(k3);
-                        b3 = (P[P_34, b3] & 0xff) ^ M_b3(k3);
-                        goto case 3;
-                    case 3:
-                        b0 = (P[P_03, b0] & 0xff) ^ M_b0(k2);
-                        b1 = (P[P_13, b1] & 0xff) ^ M_b1(k2);
-                        b2 = (P[P_23, b2] & 0xff) ^ M_b2(k2);
-                        b3 = (P[P_33, b3] & 0xff) ^ M_b3(k2);
-                        goto case 2;
-                    case 2:
-                        gSBox[i * 2] = gMDS0[(P[P_01, (P[P_02, b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)];
-                        gSBox[i * 2 + 1] = gMDS1[(P[P_11, (P[P_12, b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)];
-                        gSBox[i * 2 + 0x200] = gMDS2[(P[P_21, (P[P_22, b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)];
-                        gSBox[i * 2 + 0x201] = gMDS3[(P[P_31, (P[P_32, b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
-                        break;
-                }
-            }
-
-            /*
-            * the function exits having setup the gSBox with the
-            * input key material.
-            */
-        }
-
-        /*
-        * TODO:  This can be optimised and made cleaner by combining
-        * the functionality in this function and applying it appropriately
-        * to the creation of the subkeys during key setup.
-        */
-        private int F32(int x, int[] k32)
-        {
-            int b0 = M_b0(x);
-            int b1 = M_b1(x);
-            int b2 = M_b2(x);
-            int b3 = M_b3(x);
-            int k0 = k32[0];
-            int k1 = k32[1];
-            int k2 = k32[2];
-            int k3 = k32[3];
-
-            int result = 0;
-            switch (k64Cnt & 3)
-            {
-                case 1:
-                    result = gMDS0[(P[P_01, b0] & 0xff) ^ M_b0(k0)] ^
-                             gMDS1[(P[P_11, b1] & 0xff) ^ M_b1(k0)] ^
-                             gMDS2[(P[P_21, b2] & 0xff) ^ M_b2(k0)] ^
-                             gMDS3[(P[P_31, b3] & 0xff) ^ M_b3(k0)];
-                    break;
-                case 0: /* 256 bits of key */
-                    b0 = (P[P_04, b0] & 0xff) ^ M_b0(k3);
-                    b1 = (P[P_14, b1] & 0xff) ^ M_b1(k3);
-                    b2 = (P[P_24, b2] & 0xff) ^ M_b2(k3);
-                    b3 = (P[P_34, b3] & 0xff) ^ M_b3(k3);
-                    goto case 3;
-                case 3:
-                    b0 = (P[P_03, b0] & 0xff) ^ M_b0(k2);
-                    b1 = (P[P_13, b1] & 0xff) ^ M_b1(k2);
-                    b2 = (P[P_23, b2] & 0xff) ^ M_b2(k2);
-                    b3 = (P[P_33, b3] & 0xff) ^ M_b3(k2);
-                    goto case 2;
-                case 2:
-                    result =
-                    gMDS0[(P[P_01, (P[P_02, b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)] ^
-                    gMDS1[(P[P_11, (P[P_12, b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)] ^
-                    gMDS2[(P[P_21, (P[P_22, b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)] ^
-                    gMDS3[(P[P_31, (P[P_32, b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
-                    break;
-            }
-            return result;
-        }
-
-        /**
-        * Use (12, 8) Reed-Solomon code over GF(256) to produce
-        * a key S-box 32-bit entity from 2 key material 32-bit
-        * entities.
-        *
-        * @param    k0 first 32-bit entity
-        * @param    k1 second 32-bit entity
-        * @return     Remainder polynomial Generated using RS code
-        */
-        private int RS_MDS_Encode(int k0, int k1)
-        {
-            int r = k1;
-            for (int i = 0; i < 4; i++) // shift 1 byte at a time
-            {
-                r = RS_rem(r);
-            }
-            r ^= k0;
-            for (int i = 0; i < 4; i++)
-            {
-                r = RS_rem(r);
-            }
-
-            return r;
-        }
-
-        /**
-        * Reed-Solomon code parameters: (12,8) reversible code:
+		/// <summary>
+		/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+		/// </summary>
+		/// <param name="inputBuffer">The input data to encrypt.</param>
+		/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
+		/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
+		/// <param name="outputBuffer">The output to which to write encrypted data.</param>
+		/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
+		/// <returns>
+		/// The number of bytes encrypted.
+		/// </returns>
+		public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+		{
+			int x0 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[INPUT_WHITEN];
+			int x1 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[INPUT_WHITEN + 1];
+			int x2 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[INPUT_WHITEN + 2];
+			int x3 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[INPUT_WHITEN + 3];
+
+			int k = ROUND_SUBKEYS;
+			int t0, t1;
+			for (int r = 0; r < ROUNDS; r += 2)
+			{
+				t0 = Fe32_0(x0);
+				t1 = Fe32_3(x1);
+				x2 ^= t0 + t1 + gSubKeys[k++];
+				x2 = (int)((uint)x2 >> 1) | x2 << 31;
+				x3 = (x3 << 1 | (int)((uint)x3 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
+
+				t0 = Fe32_0(x2);
+				t1 = Fe32_3(x3);
+				x0 ^= t0 + t1 + gSubKeys[k++];
+				x0 = (int)((uint)x0 >> 1) | x0 << 31;
+				x1 = (x1 << 1 | (int)((uint)x1 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
+			}
+
+			Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], outputBuffer, outputOffset);
+			Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
+			Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
+			Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
+
+			return this.BlockSize;
+		}
+
+		/// <summary>
+		/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+		/// </summary>
+		/// <param name="inputBuffer">The input data to decrypt.</param>
+		/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
+		/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
+		/// <param name="outputBuffer">The output to which to write decrypted data.</param>
+		/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
+		/// <returns>
+		/// The number of bytes decrypted.
+		/// </returns>
+		public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+		{
+			int x2 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[OUTPUT_WHITEN];
+			int x3 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[OUTPUT_WHITEN + 1];
+			int x0 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[OUTPUT_WHITEN + 2];
+			int x1 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[OUTPUT_WHITEN + 3];
+
+			int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
+			int t0, t1;
+			for (int r = 0; r < ROUNDS; r += 2)
+			{
+				t0 = Fe32_0(x2);
+				t1 = Fe32_3(x3);
+				x1 ^= t0 + 2 * t1 + gSubKeys[k--];
+				x0 = (x0 << 1 | (int)((uint)x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
+				x1 = (int)((uint)x1 >> 1) | x1 << 31;
+
+				t0 = Fe32_0(x0);
+				t1 = Fe32_3(x1);
+				x3 ^= t0 + 2 * t1 + gSubKeys[k--];
+				x2 = (x2 << 1 | (int)((uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
+				x3 = (int)((uint)x3 >> 1) | x3 << 31;
+			}
+
+			Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], outputBuffer, outputOffset);
+			Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
+			Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
+			Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
+
+			return this.BlockSize;
+		}
+
+		#region Static Definition Tables
+
+		private static readonly byte[,] P =  {
+		{  // p0
+			(byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
+			(byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
+			(byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
+			(byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
+			(byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
+			(byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
+			(byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
+			(byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
+			(byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
+			(byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
+			(byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
+			(byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
+			(byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
+			(byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
+			(byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
+			(byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
+			(byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
+			(byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
+			(byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
+			(byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
+			(byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
+			(byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
+			(byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
+			(byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
+			(byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
+			(byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
+			(byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
+			(byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
+			(byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
+			(byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
+			(byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
+			(byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
+			(byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
+			(byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
+			(byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
+			(byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
+			(byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
+			(byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
+			(byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
+			(byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
+			(byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
+			(byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
+			(byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
+			(byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
+			(byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
+			(byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
+			(byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
+			(byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
+			(byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
+			(byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
+			(byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
+			(byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
+			(byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
+			(byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
+			(byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
+			(byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
+			(byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
+			(byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
+			(byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
+			(byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
+			(byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
+			(byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
+			(byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
+			(byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
+		{  // p1
+			(byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
+			(byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
+			(byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
+			(byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
+			(byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
+			(byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
+			(byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
+			(byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
+			(byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
+			(byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
+			(byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
+			(byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
+			(byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
+			(byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
+			(byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
+			(byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
+			(byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
+			(byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
+			(byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
+			(byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
+			(byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
+			(byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
+			(byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
+			(byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
+			(byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
+			(byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
+			(byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
+			(byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
+			(byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
+			(byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
+			(byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
+			(byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
+			(byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
+			(byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
+			(byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
+			(byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
+			(byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
+			(byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
+			(byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
+			(byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
+			(byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
+			(byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
+			(byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
+			(byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
+			(byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
+			(byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
+			(byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
+			(byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
+			(byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
+			(byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
+			(byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
+			(byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
+			(byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
+			(byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
+			(byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
+			(byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
+			(byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
+			(byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
+			(byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
+			(byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
+			(byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
+			(byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
+			(byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
+			(byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91  }
+		};
+
+		#endregion
+
+		/**
+		* Define the fixed p0/p1 permutations used in keyed S-box lookup.
+		* By changing the following constant definitions, the S-boxes will
+		* automatically Get changed in the Twofish engine.
+		*/
+		private const int P_00 = 1;
+		private const int P_01 = 0;
+		private const int P_02 = 0;
+		private const int P_03 = P_01 ^ 1;
+		private const int P_04 = 1;
+
+		private const int P_10 = 0;
+		private const int P_11 = 0;
+		private const int P_12 = 1;
+		private const int P_13 = P_11 ^ 1;
+		private const int P_14 = 0;
+
+		private const int P_20 = 1;
+		private const int P_21 = 1;
+		private const int P_22 = 0;
+		private const int P_23 = P_21 ^ 1;
+		private const int P_24 = 0;
+
+		private const int P_30 = 0;
+		private const int P_31 = 1;
+		private const int P_32 = 1;
+		private const int P_33 = P_31 ^ 1;
+		private const int P_34 = 1;
+
+		/* Primitive polynomial for GF(256) */
+		private const int GF256_FDBK = 0x169;
+		private const int GF256_FDBK_2 = GF256_FDBK / 2;
+		private const int GF256_FDBK_4 = GF256_FDBK / 4;
+
+		private const int RS_GF_FDBK = 0x14D; // field generator
+
+		//====================================
+		// Useful constants
+		//====================================
+
+		private const int ROUNDS = 16;
+		private const int MAX_ROUNDS = 16;  // bytes = 128 bits
+		private const int MAX_KEY_BITS = 256;
+
+		private const int INPUT_WHITEN = 0;
+		private const int OUTPUT_WHITEN = INPUT_WHITEN + 16 / 4; // 4
+		private const int ROUND_SUBKEYS = OUTPUT_WHITEN + 16 / 4;// 8
+
+		private const int TOTAL_SUBKEYS = ROUND_SUBKEYS + 2 * MAX_ROUNDS;// 40
+
+		private const int SK_STEP = 0x02020202;
+		private const int SK_BUMP = 0x01010101;
+		private const int SK_ROTL = 9;
+
+		private int[] gMDS0 = new int[MAX_KEY_BITS];
+		private int[] gMDS1 = new int[MAX_KEY_BITS];
+		private int[] gMDS2 = new int[MAX_KEY_BITS];
+		private int[] gMDS3 = new int[MAX_KEY_BITS];
+
+		/**
+		* gSubKeys[] and gSBox[] are eventually used in the
+		* encryption and decryption methods.
+		*/
+		private int[] gSubKeys;
+		private int[] gSBox;
+
+		private int k64Cnt;
+
+		private void SetKey(byte[] key)
+		{
+			int[] k32e = new int[MAX_KEY_BITS / 64]; // 4
+			int[] k32o = new int[MAX_KEY_BITS / 64]; // 4
+
+			int[] sBoxKeys = new int[MAX_KEY_BITS / 64]; // 4
+			gSubKeys = new int[TOTAL_SUBKEYS];
+
+			if (k64Cnt < 1)
+			{
+				throw new ArgumentException("Key size less than 64 bits");
+			}
+
+			if (k64Cnt > 4)
+			{
+				throw new ArgumentException("Key size larger than 256 bits");
+			}
+
+			/*
+			* k64Cnt is the number of 8 byte blocks (64 chunks)
+			* that are in the input key.  The input key is a
+			* maximum of 32 bytes ( 256 bits ), so the range
+			* for k64Cnt is 1..4
+			*/
+			for (int i = 0, p = 0; i < k64Cnt; i++)
+			{
+				p = i * 8;
+
+				k32e[i] = BytesTo32Bits(key, p);
+				k32o[i] = BytesTo32Bits(key, p + 4);
+
+				sBoxKeys[k64Cnt - 1 - i] = RS_MDS_Encode(k32e[i], k32o[i]);
+			}
+
+			int q, A, B;
+			for (int i = 0; i < TOTAL_SUBKEYS / 2; i++)
+			{
+				q = i * SK_STEP;
+				A = F32(q, k32e);
+				B = F32(q + SK_BUMP, k32o);
+				B = B << 8 | (int)((uint)B >> 24);
+				A += B;
+				gSubKeys[i * 2] = A;
+				A += B;
+				gSubKeys[i * 2 + 1] = A << SK_ROTL | (int)((uint)A >> (32 - SK_ROTL));
+			}
+
+			/*
+			* fully expand the table for speed
+			*/
+			int k0 = sBoxKeys[0];
+			int k1 = sBoxKeys[1];
+			int k2 = sBoxKeys[2];
+			int k3 = sBoxKeys[3];
+			int b0, b1, b2, b3;
+			gSBox = new int[4 * MAX_KEY_BITS];
+			for (int i = 0; i < MAX_KEY_BITS; i++)
+			{
+				b0 = b1 = b2 = b3 = i;
+				switch (k64Cnt & 3)
+				{
+					case 1:
+						gSBox[i * 2] = gMDS0[(P[P_01, b0] & 0xff) ^ M_b0(k0)];
+						gSBox[i * 2 + 1] = gMDS1[(P[P_11, b1] & 0xff) ^ M_b1(k0)];
+						gSBox[i * 2 + 0x200] = gMDS2[(P[P_21, b2] & 0xff) ^ M_b2(k0)];
+						gSBox[i * 2 + 0x201] = gMDS3[(P[P_31, b3] & 0xff) ^ M_b3(k0)];
+						break;
+					case 0: /* 256 bits of key */
+						b0 = (P[P_04, b0] & 0xff) ^ M_b0(k3);
+						b1 = (P[P_14, b1] & 0xff) ^ M_b1(k3);
+						b2 = (P[P_24, b2] & 0xff) ^ M_b2(k3);
+						b3 = (P[P_34, b3] & 0xff) ^ M_b3(k3);
+						goto case 3;
+					case 3:
+						b0 = (P[P_03, b0] & 0xff) ^ M_b0(k2);
+						b1 = (P[P_13, b1] & 0xff) ^ M_b1(k2);
+						b2 = (P[P_23, b2] & 0xff) ^ M_b2(k2);
+						b3 = (P[P_33, b3] & 0xff) ^ M_b3(k2);
+						goto case 2;
+					case 2:
+						gSBox[i * 2] = gMDS0[(P[P_01, (P[P_02, b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)];
+						gSBox[i * 2 + 1] = gMDS1[(P[P_11, (P[P_12, b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)];
+						gSBox[i * 2 + 0x200] = gMDS2[(P[P_21, (P[P_22, b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)];
+						gSBox[i * 2 + 0x201] = gMDS3[(P[P_31, (P[P_32, b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
+						break;
+				}
+			}
+
+			/*
+			* the function exits having setup the gSBox with the
+			* input key material.
+			*/
+		}
+
+		/*
+		* TODO:  This can be optimised and made cleaner by combining
+		* the functionality in this function and applying it appropriately
+		* to the creation of the subkeys during key setup.
+		*/
+		private int F32(int x, int[] k32)
+		{
+			int b0 = M_b0(x);
+			int b1 = M_b1(x);
+			int b2 = M_b2(x);
+			int b3 = M_b3(x);
+			int k0 = k32[0];
+			int k1 = k32[1];
+			int k2 = k32[2];
+			int k3 = k32[3];
+
+			int result = 0;
+			switch (k64Cnt & 3)
+			{
+				case 1:
+					result = gMDS0[(P[P_01, b0] & 0xff) ^ M_b0(k0)] ^
+							 gMDS1[(P[P_11, b1] & 0xff) ^ M_b1(k0)] ^
+							 gMDS2[(P[P_21, b2] & 0xff) ^ M_b2(k0)] ^
+							 gMDS3[(P[P_31, b3] & 0xff) ^ M_b3(k0)];
+					break;
+				case 0: /* 256 bits of key */
+					b0 = (P[P_04, b0] & 0xff) ^ M_b0(k3);
+					b1 = (P[P_14, b1] & 0xff) ^ M_b1(k3);
+					b2 = (P[P_24, b2] & 0xff) ^ M_b2(k3);
+					b3 = (P[P_34, b3] & 0xff) ^ M_b3(k3);
+					goto case 3;
+				case 3:
+					b0 = (P[P_03, b0] & 0xff) ^ M_b0(k2);
+					b1 = (P[P_13, b1] & 0xff) ^ M_b1(k2);
+					b2 = (P[P_23, b2] & 0xff) ^ M_b2(k2);
+					b3 = (P[P_33, b3] & 0xff) ^ M_b3(k2);
+					goto case 2;
+				case 2:
+					result =
+					gMDS0[(P[P_01, (P[P_02, b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)] ^
+					gMDS1[(P[P_11, (P[P_12, b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)] ^
+					gMDS2[(P[P_21, (P[P_22, b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)] ^
+					gMDS3[(P[P_31, (P[P_32, b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
+					break;
+			}
+			return result;
+		}
+
+		/**
+		* Use (12, 8) Reed-Solomon code over GF(256) to produce
+		* a key S-box 32-bit entity from 2 key material 32-bit
+		* entities.
+		*
+		* @param    k0 first 32-bit entity
+		* @param    k1 second 32-bit entity
+		* @return     Remainder polynomial Generated using RS code
+		*/
+		private int RS_MDS_Encode(int k0, int k1)
+		{
+			int r = k1;
+			for (int i = 0; i < 4; i++) // shift 1 byte at a time
+			{
+				r = RS_rem(r);
+			}
+			r ^= k0;
+			for (int i = 0; i < 4; i++)
+			{
+				r = RS_rem(r);
+			}
+
+			return r;
+		}
+
+		/**
+		* Reed-Solomon code parameters: (12,8) reversible code:
 		* <p>
-        * <pre>
-        * G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
-        * </pre>
-        * where a = primitive root of field generator 0x14D
+		* <pre>
+		* G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+		* </pre>
+		* where a = primitive root of field generator 0x14D
 		* </p>
-        */
-        private int RS_rem(int x)
-        {
-            int b = (int)(((uint)x >> 24) & 0xff);
-            int g2 = ((b << 1) ^
-                    ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
-            int g3 = ((int)((uint)b >> 1) ^
-                    ((b & 0x01) != 0 ? (int)((uint)RS_GF_FDBK >> 1) : 0)) ^ g2;
-            return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
-        }
-
-        private int LFSR1(int x)
-        {
-            return (x >> 1) ^
-                    (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
-        }
-
-        private int LFSR2(int x)
-        {
-            return (x >> 2) ^
-                    (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
-                    (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
-        }
-
-        private int Mx_X(int x)
-        {
-            return x ^ LFSR2(x);
-        } // 5B
-
-        private int Mx_Y(int x)
-        {
-            return x ^ LFSR1(x) ^ LFSR2(x);
-        } // EF
-
-        private int M_b0(int x)
-        {
-            return x & 0xff;
-        }
-
-        private int M_b1(int x)
-        {
-            return (int)((uint)x >> 8) & 0xff;
-        }
-
-        private int M_b2(int x)
-        {
-            return (int)((uint)x >> 16) & 0xff;
-        }
-
-        private int M_b3(int x)
-        {
-            return (int)((uint)x >> 24) & 0xff;
-        }
-
-        private int Fe32_0(int x)
-        {
-            return gSBox[0x000 + 2 * (x & 0xff)] ^
-                gSBox[0x001 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
-                gSBox[0x200 + 2 * ((int)((uint)x >> 16) & 0xff)] ^
-                gSBox[0x201 + 2 * ((int)((uint)x >> 24) & 0xff)];
-        }
-
-        private int Fe32_3(int x)
-        {
-            return gSBox[0x000 + 2 * ((int)((uint)x >> 24) & 0xff)] ^
-                gSBox[0x001 + 2 * (x & 0xff)] ^
-                gSBox[0x200 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
-                gSBox[0x201 + 2 * ((int)((uint)x >> 16) & 0xff)];
-        }
-
-        private int BytesTo32Bits(byte[] b, int p)
-        {
-            return ((b[p] & 0xff)) |
-                ((b[p + 1] & 0xff) << 8) |
-                ((b[p + 2] & 0xff) << 16) |
-                ((b[p + 3] & 0xff) << 24);
-        }
-
-        private void Bits32ToBytes(int inData, byte[] b, int offset)
-        {
-            b[offset] = (byte)inData;
-            b[offset + 1] = (byte)(inData >> 8);
-            b[offset + 2] = (byte)(inData >> 16);
-            b[offset + 3] = (byte)(inData >> 24);
-        }
-    }
+		*/
+		private int RS_rem(int x)
+		{
+			int b = (int)(((uint)x >> 24) & 0xff);
+			int g2 = ((b << 1) ^
+					((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
+			int g3 = ((int)((uint)b >> 1) ^
+					((b & 0x01) != 0 ? (int)((uint)RS_GF_FDBK >> 1) : 0)) ^ g2;
+			return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
+		}
+
+		private int LFSR1(int x)
+		{
+			return (x >> 1) ^
+					(((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
+		}
+
+		private int LFSR2(int x)
+		{
+			return (x >> 2) ^
+					(((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
+					(((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
+		}
+
+		private int Mx_X(int x)
+		{
+			return x ^ LFSR2(x);
+		} // 5B
+
+		private int Mx_Y(int x)
+		{
+			return x ^ LFSR1(x) ^ LFSR2(x);
+		} // EF
+
+		private int M_b0(int x)
+		{
+			return x & 0xff;
+		}
+
+		private int M_b1(int x)
+		{
+			return (int)((uint)x >> 8) & 0xff;
+		}
+
+		private int M_b2(int x)
+		{
+			return (int)((uint)x >> 16) & 0xff;
+		}
+
+		private int M_b3(int x)
+		{
+			return (int)((uint)x >> 24) & 0xff;
+		}
+
+		private int Fe32_0(int x)
+		{
+			return gSBox[0x000 + 2 * (x & 0xff)] ^
+				gSBox[0x001 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
+				gSBox[0x200 + 2 * ((int)((uint)x >> 16) & 0xff)] ^
+				gSBox[0x201 + 2 * ((int)((uint)x >> 24) & 0xff)];
+		}
+
+		private int Fe32_3(int x)
+		{
+			return gSBox[0x000 + 2 * ((int)((uint)x >> 24) & 0xff)] ^
+				gSBox[0x001 + 2 * (x & 0xff)] ^
+				gSBox[0x200 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
+				gSBox[0x201 + 2 * ((int)((uint)x >> 16) & 0xff)];
+		}
+
+		private int BytesTo32Bits(byte[] b, int p)
+		{
+			return ((b[p] & 0xff)) |
+				((b[p + 1] & 0xff) << 8) |
+				((b[p + 2] & 0xff) << 16) |
+				((b[p + 3] & 0xff) << 24);
+		}
+
+		private void Bits32ToBytes(int inData, byte[] b, int offset)
+		{
+			b[offset] = (byte)inData;
+			b[offset + 1] = (byte)(inData >> 8);
+			b[offset + 2] = (byte)(inData >> 16);
+			b[offset + 3] = (byte)(inData >> 24);
+		}
+	}
 }

+ 21 - 5
Renci.SshClient/Renci.SshNet/Sftp/SftpFileStream.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.IO;
+using System.Threading;
 
 namespace Renci.SshNet.Sftp
 {
@@ -797,7 +798,10 @@ namespace Renci.SshNet.Sftp
 
                         Buffer.BlockCopy(this._buffer, 0, data, 0, this._bufferPosn);
 
-                        this._session.RequestWrite(this._handle, (ulong)this.Position, data);
+                        using (var wait = new AutoResetEvent(false))
+                        {
+                            this._session.RequestWrite(this._handle, (ulong)this.Position, data, wait);
+                        }
 
                         this._bufferPosn = 0;
                         tempLen = this._bufferSize;
@@ -815,7 +819,10 @@ namespace Renci.SshNet.Sftp
 
                         Buffer.BlockCopy(buffer, offset, data, 0, tempLen);
 
-                        this._session.RequestWrite(this._handle, (ulong)this.Position, data);
+                        using (var wait = new AutoResetEvent(false))
+                        {
+                            this._session.RequestWrite(this._handle, (ulong)this.Position, data, wait);
+                        }
                     }
                     else
                     {
@@ -838,7 +845,10 @@ namespace Renci.SshNet.Sftp
 
                     Buffer.BlockCopy(this._buffer, 0, data, 0, this._bufferPosn);
 
-                    this._session.RequestWrite(this._handle, (ulong)this.Position, data);
+                    using (var wait = new AutoResetEvent(false))
+                    {
+                        this._session.RequestWrite(this._handle, (ulong)this.Position, data, wait);
+                    }
 
                     this._bufferPosn = 0;
                 }
@@ -869,7 +879,10 @@ namespace Renci.SshNet.Sftp
 
                     Buffer.BlockCopy(this._buffer, 0, data, 0, this._bufferPosn);
 
-                    this._session.RequestWrite(this._handle, (ulong)this.Position, data);
+                    using (var wait = new AutoResetEvent(false))
+                    {
+                        this._session.RequestWrite(this._handle, (ulong)this.Position, data, wait);
+                    }
 
                     this._bufferPosn = 0;
                 }
@@ -933,7 +946,10 @@ namespace Renci.SshNet.Sftp
 
                 Buffer.BlockCopy(this._buffer, 0, data, 0, this._bufferPosn);
 
-                this._session.RequestWrite(this._handle, (ulong)(this.Position - this._bufferPosn), data);
+                using (var wait = new AutoResetEvent(false))
+                {
+                    this._session.RequestWrite(this._handle, (ulong)(this.Position - this._bufferPosn), data, wait);
+                }
 
                 this._bufferPosn = 0;
             }

+ 30 - 31
Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs

@@ -369,34 +369,34 @@ namespace Renci.SshNet.Sftp
         /// </summary>
         /// <param name="handle">The handle.</param>
         /// <param name="offset">The offset.</param>
-        /// <param name="data">The data.</param>
-        internal void RequestWrite(byte[] handle, UInt64 offset, byte[] data)
+        /// <param name="data">The data to send.</param>
+        /// <param name="wait">The wait event handle if needed.</param>
+        internal void RequestWrite(byte[] handle, UInt64 offset, byte[] data, EventWaitHandle wait)
         {
             var maximumDataSize = 1024 * 32 - 38;
 
             if (data.Length < maximumDataSize + 1)
             {
-                using (var wait = new AutoResetEvent(false))
-                {
-                    var request = new SftpWriteRequest(this.NextRequestId, handle, offset, data,
-                        (response) =>
+                var request = new SftpWriteRequest(this.NextRequestId, handle, offset, data,
+                    (response) =>
+                    {
+                        if (response.StatusCode == StatusCodes.Ok)
                         {
-                            if (response.StatusCode == StatusCodes.Ok)
-                            {
+                            if (wait != null)
                                 wait.Set();
-                            }
-                            else
-                            {
-                                this.ThrowSftpException(response);
-                            }
-                        });
+                        }
+                        else
+                        {
+                            this.ThrowSftpException(response);
+                        }
+                    });
 
-                    this.SendRequest(request);
+                this.SendRequest(request);
 
+                if (wait != null)
                     this.WaitHandle(wait, this._operationTimeout);
-                }
             }
-            else 
+            else
             {
                 var block = data.Length / maximumDataSize + 1;
 
@@ -407,25 +407,24 @@ namespace Renci.SshNet.Sftp
 
                     Buffer.BlockCopy(data, i * maximumDataSize, blockBuffer, 0, blockBufferSize);
 
-                    using (var wait = new AutoResetEvent(false))
-                    {
-                        var request = new SftpWriteRequest(this.NextRequestId, handle, offset + (ulong)(i * maximumDataSize), blockBuffer,
-                            (response) =>
+                    var request = new SftpWriteRequest(this.NextRequestId, handle, offset + (ulong)(i * maximumDataSize), blockBuffer,
+                        (response) =>
+                        {
+                            if (response.StatusCode == StatusCodes.Ok)
                             {
-                                if (response.StatusCode == StatusCodes.Ok)
-                                {
+                                if (wait != null)
                                     wait.Set();
-                                }
-                                else
-                                {
-                                    this.ThrowSftpException(response);
-                                }
-                            });
+                            }
+                            else
+                            {
+                                this.ThrowSftpException(response);
+                            }
+                        });
 
-                        this.SendRequest(request);
+                    this.SendRequest(request);
 
+                    if (wait != null)
                         this.WaitHandle(wait, this._operationTimeout);
-                    }
                 }
             }
         }

+ 7 - 3
Renci.SshClient/Renci.SshNet/SftpClient.cs

@@ -6,6 +6,7 @@ using Renci.SshNet.Sftp;
 using System.Text;
 using Renci.SshNet.Common;
 using System.Globalization;
+using System.Threading;
 
 namespace Renci.SshNet
 {
@@ -1131,7 +1132,7 @@ namespace Renci.SshNet
 
                 files = this._sftpSession.RequestReadDir(handle);
             }
-            
+
             this._sftpSession.RequestClose(handle);
 
             return result;
@@ -1206,12 +1207,15 @@ namespace Renci.SshNet
                 {
                     var data = new byte[bytesRead];
                     Array.Copy(buffer, data, bytesRead);
-                    this._sftpSession.RequestWrite(handle, offset, data);
+                    using (var wait = new AutoResetEvent(false))
+                    {
+                        this._sftpSession.RequestWrite(handle, offset, data, wait);
+                    }
                     uploadCompleted = true;
                 }
                 else
                 {
-                    this._sftpSession.RequestWrite(handle, offset, buffer);
+                    this._sftpSession.RequestWrite(handle, offset, buffer, null);
                 }
 
                 offset += (uint)bytesRead;

+ 2 - 4
Renci.SshClient/Renci.SshNet/SshCommand.cs

@@ -165,9 +165,7 @@ namespace Renci.SshNet
                 AsyncState = state,
             };
 
-            
-            // TODO: kenneth_aa (2011-08-16) - Need better explanation for this, to make a good exception documentation.
-            //  When command re-executed again, create a new channel
+                        //  When command re-executed again, create a new channel
             if (this._channel != null)
             {
                 throw new SshException("Invalid operation.");
@@ -177,7 +175,7 @@ namespace Renci.SshNet
 
             if (string.IsNullOrEmpty(this.CommandText))
                 throw new ArgumentException("CommandText property is empty.");
-            // TODO: What happens if callback is null?
+
             this._callback = callback;
 
             this._channel.Open();