浏览代码

Use an int to hold position when iterating of state. Stuck loop on key exchange using arcfour encryption (issue #1922)

Gert Driesen 11 年之前
父节点
当前提交
46d15325e9

+ 1 - 0
Renci.SshClient/Build/nuget/SSH.NET.nuspec

@@ -30,6 +30,7 @@
 
           Fixes:
 
+          * Stuck loop on key exchange using arcfour encryption (issue #1922)
           * Timeout sending data to server with low window size (issue #1706)
           * No connection possible with the same auth method requested multiple times (issue #1930)
           * Unobserved exception rethrown by finalizer thread (issue #1298 and #1587)

+ 69 - 27
Renci.SshClient/Renci.SshNet.Tests/Classes/Security/Cryptography/Ciphers/Arc4CipherTest.cs

@@ -1,4 +1,6 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Renci.SshNet.Common;
 using Renci.SshNet.Security.Cryptography.Ciphers;
 using Renci.SshNet.Tests.Common;
 using Renci.SshNet.Tests.Properties;
@@ -22,20 +24,32 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
             Assert.Inconclusive("TODO: Implement code to verify target");
         }
 
-        /// <summary>
-        ///A test for Decrypt
-        ///</summary>
-        [TestMethod()]
-        public void DecryptTest()
+        [TestMethod]
+        public void Decrypt_DischargeFirstBytes_False1()
         {
-            byte[] key = null; // TODO: Initialize to an appropriate value
-            Arc4Cipher target = new Arc4Cipher(key, true); // TODO: Initialize to an appropriate value
-            byte[] input = null; // TODO: Initialize to an appropriate value
-            byte[] expected = null; // TODO: Initialize to an appropriate value
-            byte[] actual;
-            actual = target.Decrypt(input);
-            Assert.AreEqual(expected, actual);
-            Assert.Inconclusive("Verify the correctness of this test method.");
+            const string key = "Key";
+            const string expectedPlainText = "Plaintext";
+            var encoding = Encoding.ASCII;
+            var cipher = new Arc4Cipher(encoding.GetBytes(key), false);
+            var cipherText = new byte[] { 0xBB, 0xF3, 0x16, 0xE8, 0xD9, 0x40, 0xAF, 0x0A, 0xD3 };
+
+            var actualPlainText = cipher.Decrypt(cipherText);
+
+            Assert.AreEqual(expectedPlainText, encoding.GetString(actualPlainText));
+        }
+
+        [TestMethod]
+        public void Decrypt_DischargeFirstBytes_False2()
+        {
+            const string key = "Wiki";
+            const string expectedPlainText = "pedia";
+            var encoding = Encoding.ASCII;
+            var cipher = new Arc4Cipher(encoding.GetBytes(key), false);
+            var cipherText = new byte[] { 0x10, 0X21, 0xBF, 0x04, 0x20 };
+
+            var actualPlainText = cipher.Decrypt(cipherText);
+
+            Assert.AreEqual(expectedPlainText, encoding.GetString(actualPlainText));
         }
 
         /// <summary>
@@ -58,20 +72,48 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
             Assert.Inconclusive("Verify the correctness of this test method.");
         }
 
-        /// <summary>
-        ///A test for Encrypt
-        ///</summary>
-        [TestMethod()]
-        public void EncryptTest()
+        [TestMethod]
+        public void Encrypt_DischargeFirstBytes_False1()
         {
-            byte[] key = null; // TODO: Initialize to an appropriate value
-            Arc4Cipher target = new Arc4Cipher(key, true); // TODO: Initialize to an appropriate value
-            byte[] input = null; // TODO: Initialize to an appropriate value
-            byte[] expected = null; // TODO: Initialize to an appropriate value
-            byte[] actual;
-            actual = target.Encrypt(input);
-            Assert.AreEqual(expected, actual);
-            Assert.Inconclusive("Verify the correctness of this test method.");
+            const string key = "Key";
+            const string plainText = "Plaintext";
+            var encoding = Encoding.ASCII;
+            var cipher = new Arc4Cipher(encoding.GetBytes(key), false);
+            var expectedCipherText = new byte[] { 0xBB, 0xF3, 0x16, 0xE8, 0xD9, 0x40, 0xAF, 0x0A, 0xD3 };
+
+            var actualCipherText = cipher.Encrypt(encoding.GetBytes(plainText));
+
+            Assert.IsNotNull(actualCipherText);
+            Assert.AreEqual(expectedCipherText.Length, actualCipherText.Length);
+            Assert.AreEqual(expectedCipherText[0], actualCipherText[0]);
+            Assert.AreEqual(expectedCipherText[1], actualCipherText[1]);
+            Assert.AreEqual(expectedCipherText[2], actualCipherText[2]);
+            Assert.AreEqual(expectedCipherText[3], actualCipherText[3]);
+            Assert.AreEqual(expectedCipherText[4], actualCipherText[4]);
+            Assert.AreEqual(expectedCipherText[5], actualCipherText[5]);
+            Assert.AreEqual(expectedCipherText[6], actualCipherText[6]);
+            Assert.AreEqual(expectedCipherText[7], actualCipherText[7]);
+            Assert.AreEqual(expectedCipherText[8], actualCipherText[8]);
+        }
+
+        [TestMethod]
+        public void Encrypt_DischargeFirstBytes_False2()
+        {
+            const string key = "Wiki";
+            const string plainText = "pedia";
+            var encoding = Encoding.ASCII;
+            var cipher = new Arc4Cipher(encoding.GetBytes(key), false);
+            var expectedCipherText = new byte[] { 0x10, 0X21, 0xBF, 0x04, 0x20 };
+
+            var actualCipherText = cipher.Encrypt(encoding.GetBytes(plainText));
+
+            Assert.IsNotNull(actualCipherText);
+            Assert.AreEqual(expectedCipherText.Length, actualCipherText.Length);
+            Assert.AreEqual(expectedCipherText[0], actualCipherText[0]);
+            Assert.AreEqual(expectedCipherText[1], actualCipherText[1]);
+            Assert.AreEqual(expectedCipherText[2], actualCipherText[2]);
+            Assert.AreEqual(expectedCipherText[3], actualCipherText[3]);
+            Assert.AreEqual(expectedCipherText[4], actualCipherText[4]);
         }
 
         /// <summary>

+ 3 - 8
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs

@@ -140,11 +140,6 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             return inputCount;
         }
 
-        private void Reset()
-        {
-            SetKey(this._workingKey);
-        }
-
         private void SetKey(byte[] keyBytes)
         {
             this._workingKey = keyBytes;
@@ -158,15 +153,15 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             }
 
             // reset the state of the engine
-            for (byte i = 0; i < STATE_LENGTH; i++)
+            for (var i = 0; i < STATE_LENGTH; i++)
             {
-                this._engineState[i] = i;
+                this._engineState[i] = (byte) i;
             }
 
             int i1 = 0;
             int i2 = 0;
 
-            for (int i = 0; i < STATE_LENGTH; i++)
+            for (var i = 0; i < STATE_LENGTH; i++)
             {
                 i2 = ((keyBytes[i1] & 0xff) + this._engineState[i] + i2) & 0xff;
                 // do the byte-swap inline