Преглед на файлове

Added Decrypt overload taking offset and length.

drieseng преди 9 години
родител
ревизия
6a1859c500

+ 14 - 14
src/Renci.SshNet.Tests/Classes/PrivateKeyFileTest.cs

@@ -140,7 +140,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_RSA()
         {
-            using (var stream = this.GetData("Key.RSA.txt"))
+            using (var stream = GetData("Key.RSA.txt"))
             {
                 new PrivateKeyFile(stream);
             }
@@ -151,7 +151,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_SSH2_DSA()
         {
-            using (var stream = this.GetData("Key.SSH2.DSA.txt"))
+            using (var stream = GetData("Key.SSH2.DSA.txt"))
             {
                 new PrivateKeyFile(stream);
             }
@@ -162,7 +162,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_SSH2_RSA()
         {
-            using (var stream = this.GetData("Key.SSH2.RSA.txt"))
+            using (var stream = GetData("Key.SSH2.RSA.txt"))
             {
                 new PrivateKeyFile(stream);
             }
@@ -173,7 +173,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_SSH2_Encrypted_DSA_DES_CBC()
         {
-            using (var stream = this.GetData("Key.SSH2.DSA.Encrypted.Des.CBC.12345.txt"))
+            using (var stream = GetData("Key.SSH2.DSA.Encrypted.Des.CBC.12345.txt"))
             {
                 new PrivateKeyFile(stream, "12345");
             }
@@ -184,7 +184,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_SSH2_Encrypted_RSA_DES_CBC()
         {
-            using (var stream = this.GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
+            using (var stream = GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
             {
                 new PrivateKeyFile(stream, "12345");
             }
@@ -195,7 +195,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_SSH2_Encrypted_ShouldThrowSshExceptionWhenPassphraseIsWrong()
         {
-            using (var stream = this.GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
+            using (var stream = GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
             {
                 try
                 {
@@ -216,7 +216,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_SSH2_Encrypted_ShouldThrowSshPassPhraseNullOrEmptyExceptionWhenPassphraseIsNull()
         {
-            using (var stream = this.GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
+            using (var stream = GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
             {
                 try
                 {
@@ -237,7 +237,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_SSH2_Encrypted_ShouldThrowSshPassPhraseNullOrEmptyExceptionWhenPassphraseIsEmpty()
         {
-            using (var stream = this.GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
+            using (var stream = GetData("Key.SSH2.RSA.Encrypted.Des.CBC.12345.txt"))
             {
                 try
                 {
@@ -258,7 +258,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_RSA_DES_CBC()
         {
-            using (var stream = this.GetData("Key.RSA.Encrypted.Des.CBC.12345.txt"))
+            using (var stream = GetData("Key.RSA.Encrypted.Des.CBC.12345.txt"))
             {
                 new PrivateKeyFile(stream, "12345");
             }
@@ -269,7 +269,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_RSA_DES_EDE3_CBC()
         {
-            using (var stream = this.GetData("Key.RSA.Encrypted.Des.Ede3.CBC.12345.txt"))
+            using (var stream = GetData("Key.RSA.Encrypted.Des.Ede3.CBC.12345.txt"))
             {
                 new PrivateKeyFile(stream, "12345");
             }
@@ -280,7 +280,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_RSA_AES_128_CBC()
         {
-            using (var stream = this.GetData("Key.RSA.Encrypted.Aes.128.CBC.12345.txt"))
+            using (var stream = GetData("Key.RSA.Encrypted.Aes.128.CBC.12345.txt"))
             {
                 new PrivateKeyFile(stream, "12345");
             }
@@ -291,7 +291,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_RSA_AES_192_CBC()
         {
-            using (var stream = this.GetData("Key.RSA.Encrypted.Aes.192.CBC.12345.txt"))
+            using (var stream = GetData("Key.RSA.Encrypted.Aes.192.CBC.12345.txt"))
             {
                 new PrivateKeyFile(stream, "12345");
             }
@@ -302,7 +302,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_RSA_AES_256_CBC()
         {
-            using (var stream = this.GetData("Key.RSA.Encrypted.Aes.256.CBC.12345.txt"))
+            using (var stream = GetData("Key.RSA.Encrypted.Aes.256.CBC.12345.txt"))
             {
                 new PrivateKeyFile(stream, "12345");
             }
@@ -313,7 +313,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestCategory("PrivateKey")]
         public void Test_PrivateKey_RSA_DES_EDE3_CFB()
         {
-            using (var stream = this.GetData("Key.RSA.Encrypted.Des.Ede3.CFB.1234567890.txt"))
+            using (var stream = GetData("Key.RSA.Encrypted.Des.Ede3.CFB.1234567890.txt"))
             {
                 new PrivateKeyFile(stream, "1234567890");
             }

+ 41 - 15
src/Renci.SshNet.Tests/Classes/Security/Cryptography/Ciphers/AesCipherTest.cs

@@ -1,11 +1,8 @@
-using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Renci.SshNet.Security.Cryptography.Ciphers;
 using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
 using Renci.SshNet.Tests.Common;
 using Renci.SshNet.Tests.Properties;
-using System.Linq;
-using Renci.SshNet.Common;
 
 namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
 {
@@ -16,21 +13,36 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
     public class AesCipherTest : TestBase
     {
         [TestMethod]
-        public void Test_Cipher_AES_128_CBC()
+        public void Encrypt_Input_128_CBC()
         {
             var input = new byte[] { 0x00, 0x00, 0x00, 0x2c, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x73, 0x73, 0x68, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x61, 0x75, 0x74, 0x68, 0x30, 0x9e, 0xe0, 0x9c, 0x12, 0xee, 0x3a, 0x30, 0x03, 0x52, 0x1c, 0x1a, 0xe7, 0x3e, 0x0b, 0x9a, 0xcf, 0x9a, 0x57, 0x42, 0x0b, 0x4f, 0x4a, 0x15, 0xa0, 0xf5 };
             var key = new byte[] { 0xe4, 0x94, 0xf9, 0xb1, 0x00, 0x4f, 0x16, 0x2a, 0x80, 0x11, 0xea, 0x73, 0x0d, 0xb9, 0xbf, 0x64 };
             var iv = new byte[] { 0x74, 0x8b, 0x4f, 0xe6, 0xc1, 0x29, 0xb3, 0x54, 0xec, 0x77, 0x92, 0xf3, 0x15, 0xa0, 0x41, 0xa8 };
-            var output = new byte[] { 0x19, 0x7f, 0x80, 0xd8, 0xc9, 0x89, 0xc4, 0xa7, 0xc6, 0xc6, 0x3f, 0x9f, 0x1e, 0x00, 0x1f, 0x72, 0xa7, 0x5e, 0xde, 0x40, 0x88, 0xa2, 0x72, 0xf2, 0xed, 0x3f, 0x81, 0x45, 0xb6, 0xbd, 0x45, 0x87, 0x15, 0xa5, 0x10, 0x92, 0x4a, 0x37, 0x9e, 0xa9, 0x80, 0x1c, 0x14, 0x83, 0xa3, 0x39, 0x45, 0x28 };
+            var expected = new byte[] { 0x19, 0x7f, 0x80, 0xd8, 0xc9, 0x89, 0xc4, 0xa7, 0xc6, 0xc6, 0x3f, 0x9f, 0x1e, 0x00, 0x1f, 0x72, 0xa7, 0x5e, 0xde, 0x40, 0x88, 0xa2, 0x72, 0xf2, 0xed, 0x3f, 0x81, 0x45, 0xb6, 0xbd, 0x45, 0x87, 0x15, 0xa5, 0x10, 0x92, 0x4a, 0x37, 0x9e, 0xa9, 0x80, 0x1c, 0x14, 0x83, 0xa3, 0x39, 0x45, 0x28 };
             var testCipher = new AesCipher(key, new CbcCipherMode(iv), null);
-            var r = testCipher.Encrypt(input);
 
-            if (!r.SequenceEqual(output))
-                Assert.Fail("Invalid encryption");
+            var actual = testCipher.Encrypt(input);
+
+            Assert.IsTrue(actual.IsEqualTo(expected));
         }
 
         [TestMethod]
-        public void Test_Cipher_AES_128_CTR()
+        public void Encrypt_InputAndOffsetAndLength_128_CBC()
+        {
+            // 2 dummy bytes before and 3 after the input from test case above
+            var input = new byte[] { 0x05, 0x07, 0x00, 0x00, 0x00, 0x2c, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x73, 0x73, 0x68, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x61, 0x75, 0x74, 0x68, 0x30, 0x9e, 0xe0, 0x9c, 0x12, 0xee, 0x3a, 0x30, 0x03, 0x52, 0x1c, 0x1a, 0xe7, 0x3e, 0x0b, 0x9a, 0xcf, 0x9a, 0x57, 0x42, 0x0b, 0x4f, 0x4a, 0x15, 0xa0, 0xf5, 0x0f, 0x0d, 0x03 };
+            var key = new byte[] { 0xe4, 0x94, 0xf9, 0xb1, 0x00, 0x4f, 0x16, 0x2a, 0x80, 0x11, 0xea, 0x73, 0x0d, 0xb9, 0xbf, 0x64 };
+            var iv = new byte[] { 0x74, 0x8b, 0x4f, 0xe6, 0xc1, 0x29, 0xb3, 0x54, 0xec, 0x77, 0x92, 0xf3, 0x15, 0xa0, 0x41, 0xa8 };
+            var expected = new byte[] { 0x19, 0x7f, 0x80, 0xd8, 0xc9, 0x89, 0xc4, 0xa7, 0xc6, 0xc6, 0x3f, 0x9f, 0x1e, 0x00, 0x1f, 0x72, 0xa7, 0x5e, 0xde, 0x40, 0x88, 0xa2, 0x72, 0xf2, 0xed, 0x3f, 0x81, 0x45, 0xb6, 0xbd, 0x45, 0x87, 0x15, 0xa5, 0x10, 0x92, 0x4a, 0x37, 0x9e, 0xa9, 0x80, 0x1c, 0x14, 0x83, 0xa3, 0x39, 0x45, 0x28 };
+            var testCipher = new AesCipher(key, new CbcCipherMode(iv), null);
+
+            var actual = testCipher.Encrypt(input, 2, input.Length - 5);
+
+            Assert.IsTrue(actual.IsEqualTo(expected));
+        }
+
+        [TestMethod]
+        public void Encrypt_Input_128_CTR()
         {
             var input = new byte[] { 0x00, 0x00, 0x00, 0x2c, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x73, 0x73, 0x68, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x61, 0x75, 0x74, 0x68, 0xb0, 0x74, 0x21, 0x87, 0x16, 0xb9, 0x69, 0x48, 0x33, 0xce, 0xb3, 0xe7, 0xdc, 0x3f, 0x50, 0xdc, 0xcc, 0xd5, 0x27, 0xb7, 0xfe, 0x7a, 0x78, 0x22, 0xae, 0xc8 };
             var key = new byte[] { 0x17, 0x78, 0x56, 0xe1, 0x3e, 0xbd, 0x3e, 0x50, 0x1d, 0x79, 0x3f, 0x0f, 0x55, 0x37, 0x45, 0x54 };
@@ -44,17 +56,31 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
         }
 
         [TestMethod]
-        public void Decrypt_AES_128_CTR()
+        public void Decrypt_Input_128_CTR()
+        {
+            var key = new byte[] { 0x17, 0x78, 0x56, 0xe1, 0x3e, 0xbd, 0x3e, 0x50, 0x1d, 0x79, 0x3f, 0x0f, 0x55, 0x37, 0x45, 0x54 };
+            var iv = new byte[] { 0xe6, 0x65, 0x36, 0x0d, 0xdd, 0xd7, 0x50, 0xc3, 0x48, 0xdb, 0x48, 0x07, 0xa1, 0x30, 0xd2, 0x38 };
+            var input = new byte[] { 0xca, 0xfb, 0x1c, 0x49, 0xbf, 0x82, 0x2a, 0xbb, 0x1c, 0x52, 0xc7, 0x86, 0x22, 0x8a, 0xe5, 0xa4, 0xf3, 0xda, 0x4e, 0x1c, 0x3a, 0x87, 0x41, 0x1c, 0xd2, 0x6e, 0x76, 0xdc, 0xc2, 0xe9, 0xc2, 0x0e, 0xf5, 0xc7, 0xbd, 0x12, 0x85, 0xfa, 0x0e, 0xda, 0xee, 0x50, 0xd7, 0xfd, 0x81, 0x34, 0x25, 0x6d };
+            var expected = new byte[] { 0x00, 0x00, 0x00, 0x2c, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x73, 0x73, 0x68, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x61, 0x75, 0x74, 0x68, 0xb0, 0x74, 0x21, 0x87, 0x16, 0xb9, 0x69, 0x48, 0x33, 0xce, 0xb3, 0xe7, 0xdc, 0x3f, 0x50, 0xdc, 0xcc, 0xd5, 0x27, 0xb7, 0xfe, 0x7a, 0x78, 0x22, 0xae, 0xc8 };
+            var testCipher = new AesCipher(key, new CtrCipherMode(iv), null);
+
+            var actual = testCipher.Decrypt(input);
+
+            Assert.IsTrue(expected.IsEqualTo(actual));
+        }
+
+        [TestMethod]
+        public void Decrypt_InputAndOffsetAndLength_128_CTR()
         {
-            var input = new byte[] { 0x00, 0x00, 0x00, 0x2c, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x73, 0x73, 0x68, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x61, 0x75, 0x74, 0x68, 0xb0, 0x74, 0x21, 0x87, 0x16, 0xb9, 0x69, 0x48, 0x33, 0xce, 0xb3, 0xe7, 0xdc, 0x3f, 0x50, 0xdc, 0xcc, 0xd5, 0x27, 0xb7, 0xfe, 0x7a, 0x78, 0x22, 0xae, 0xc8 };
             var key = new byte[] { 0x17, 0x78, 0x56, 0xe1, 0x3e, 0xbd, 0x3e, 0x50, 0x1d, 0x79, 0x3f, 0x0f, 0x55, 0x37, 0x45, 0x54 };
             var iv = new byte[] { 0xe6, 0x65, 0x36, 0x0d, 0xdd, 0xd7, 0x50, 0xc3, 0x48, 0xdb, 0x48, 0x07, 0xa1, 0x30, 0xd2, 0x38 };
-            var output = new byte[] { 0xca, 0xfb, 0x1c, 0x49, 0xbf, 0x82, 0x2a, 0xbb, 0x1c, 0x52, 0xc7, 0x86, 0x22, 0x8a, 0xe5, 0xa4, 0xf3, 0xda, 0x4e, 0x1c, 0x3a, 0x87, 0x41, 0x1c, 0xd2, 0x6e, 0x76, 0xdc, 0xc2, 0xe9, 0xc2, 0x0e, 0xf5, 0xc7, 0xbd, 0x12, 0x85, 0xfa, 0x0e, 0xda, 0xee, 0x50, 0xd7, 0xfd, 0x81, 0x34, 0x25, 0x6d };
+            var input = new byte[] { 0x0a, 0xca, 0xfb, 0x1c, 0x49, 0xbf, 0x82, 0x2a, 0xbb, 0x1c, 0x52, 0xc7, 0x86, 0x22, 0x8a, 0xe5, 0xa4, 0xf3, 0xda, 0x4e, 0x1c, 0x3a, 0x87, 0x41, 0x1c, 0xd2, 0x6e, 0x76, 0xdc, 0xc2, 0xe9, 0xc2, 0x0e, 0xf5, 0xc7, 0xbd, 0x12, 0x85, 0xfa, 0x0e, 0xda, 0xee, 0x50, 0xd7, 0xfd, 0x81, 0x34, 0x25, 0x6d, 0x0a, 0x05 };
+            var expected = new byte[] { 0x00, 0x00, 0x00, 0x2c, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x73, 0x73, 0x68, 0x2d, 0x75, 0x73, 0x65, 0x72, 0x61, 0x75, 0x74, 0x68, 0xb0, 0x74, 0x21, 0x87, 0x16, 0xb9, 0x69, 0x48, 0x33, 0xce, 0xb3, 0xe7, 0xdc, 0x3f, 0x50, 0xdc, 0xcc, 0xd5, 0x27, 0xb7, 0xfe, 0x7a, 0x78, 0x22, 0xae, 0xc8 };
             var testCipher = new AesCipher(key, new CtrCipherMode(iv), null);
 
-            var actual = testCipher.Decrypt(output);
+            var actual = testCipher.Decrypt(input, 1, input.Length - 3);
 
-            Assert.IsTrue(input.IsEqualTo(actual));
+            Assert.IsTrue(expected.IsEqualTo(actual));
         }
 
         [TestMethod]

+ 34 - 17
src/Renci.SshNet.Tests/Classes/Security/Cryptography/Ciphers/Arc4CipherTest.cs

@@ -1,6 +1,5 @@
 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;
@@ -53,6 +52,20 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
             Assert.AreEqual(expectedPlainText, encoding.GetString(actualPlainText));
         }
 
+        [TestMethod]
+        public void Decrypt_InputAndOffsetAndLength()
+        {
+            const string key = "Key";
+            const string expectedPlainText = "Plaintext";
+            var encoding = Encoding.ASCII;
+            var cipher = new Arc4Cipher(encoding.GetBytes(key), false);
+            var cipherText = new byte[] { 0x0A, 0x0f, 0xBB, 0xF3, 0x16, 0xE8, 0xD9, 0x40, 0xAF, 0x0A, 0xD3, 0x0d, 0x05 };
+
+            var actualPlainText = cipher.Decrypt(cipherText, 2, cipherText.Length - 4);
+
+            Assert.AreEqual(expectedPlainText, encoding.GetString(actualPlainText));
+        }
+
         /// <summary>
         ///A test for DecryptBlock
         ///</summary>
@@ -86,16 +99,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
             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]);
+            Assert.IsTrue(expectedCipherText.IsEqualTo(actualCipherText));
         }
 
         [TestMethod]
@@ -110,12 +114,25 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
             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.IsTrue(expectedCipherText.IsEqualTo(actualCipherText));
+        }
+
+        [TestMethod]
+        public void Encrypt_InputAndOffsetAndLength()
+        {
+            const string key = "Wiki";
+            const string plainText = "NOpediaNO";
+            var encoding = Encoding.ASCII;
+            var cipher = new Arc4Cipher(encoding.GetBytes(key), false);
+            var plainTextBytes = encoding.GetBytes(plainText);
+            var expectedCipherText = new byte[] { 0x10, 0X21, 0xBF, 0x04, 0x20 };
+
+            var actualCipherText = cipher.Encrypt(plainTextBytes, 2, plainTextBytes.Length - 4);
+
+            Assert.IsNotNull(actualCipherText);
+            Assert.IsTrue(expectedCipherText.IsEqualTo(actualCipherText));
+
+            Assert.IsTrue(plainTextBytes.IsEqualTo(encoding.GetBytes(plainText)));
         }
 
         /// <summary>

+ 1 - 1
src/Renci.SshNet.Tests/Classes/Security/Cryptography/Ciphers/CastCipherTest.cs

@@ -20,7 +20,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
             var key = new byte[] { 0xe4, 0x94, 0xf9, 0xb1, 0x00, 0x4f, 0x16, 0x2a, 0x80, 0x11, 0xea, 0x73, 0x0d, 0xb9, 0xbf, 0x64 };
             var iv = new byte[] { 0x74, 0x8b, 0x4f, 0xe6, 0xc1, 0x29, 0xb3, 0x54, 0xec, 0x77, 0x92, 0xf3, 0x15, 0xa0, 0x41, 0xa8 };
             var output = new byte[] { 0x32, 0xef, 0xbd, 0xac, 0xb6, 0xfd, 0x1f, 0xae, 0x1b, 0x13, 0x5f, 0x31, 0x6d, 0x38, 0xcd, 0xb0, 0xe3, 0xca, 0xe1, 0xbc, 0xf8, 0xa7, 0xc2, 0x31, 0x62, 0x14, 0x3a, 0x9a, 0xda, 0xe3, 0xf8, 0xc8, 0x70, 0x87, 0x53, 0x21, 0x5d, 0xb7, 0x94, 0xb7, 0xe8, 0xc6, 0x9d, 0x46, 0x0c, 0x6d, 0x64, 0x6d };
-            var testCipher = new Renci.SshNet.Security.Cryptography.Ciphers.CastCipher(key, new Renci.SshNet.Security.Cryptography.Ciphers.Modes.CbcCipherMode(iv), null);
+            var testCipher = new CastCipher(key, new CbcCipherMode(iv), null);
             var r = testCipher.Encrypt(input);
 
             if (!r.SequenceEqual(output))

+ 1 - 1
src/Renci.SshNet.Tests/Classes/Security/Cryptography/Ciphers/TripleDesCipherTest.cs

@@ -20,7 +20,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
             var key = new byte[] { 0x78, 0xf6, 0xc6, 0xbb, 0x57, 0x03, 0x69, 0xca, 0xba, 0x31, 0x18, 0x2f, 0x2f, 0x4c, 0x35, 0x34, 0x64, 0x06, 0x85, 0x30, 0xbe, 0x78, 0x60, 0xb3 };
             var iv = new byte[] { 0xc0, 0x75, 0xf2, 0x26, 0x0a, 0x2a, 0x42, 0x96 };
             var output = new byte[] { 0x28, 0x77, 0x2f, 0x07, 0x3e, 0xc2, 0x27, 0xa6, 0xdb, 0x36, 0x4d, 0xc6, 0x7a, 0x26, 0x7a, 0x38, 0xe6, 0x54, 0x0b, 0xab, 0x07, 0x87, 0xf0, 0xa4, 0x73, 0x1f, 0xde, 0xe6, 0x81, 0x1d, 0x4b, 0x4b };
-            var testCipher = new Renci.SshNet.Security.Cryptography.Ciphers.TripleDesCipher(key, new Renci.SshNet.Security.Cryptography.Ciphers.Modes.CbcCipherMode(iv), null);
+            var testCipher = new TripleDesCipher(key, new CbcCipherMode(iv), null);
             var r = testCipher.Encrypt(input);
 
             if (!r.SequenceEqual(output))

+ 25 - 8
src/Renci.SshNet/Security/Cryptography/BlockCipher.cs

@@ -80,8 +80,9 @@ namespace Renci.SshNet.Security.Cryptography
                     throw new ArgumentException("data");
                 }
                 var paddingLength = _blockSize - (length % _blockSize);
-                data = _padding.Pad(data, paddingLength);
+                data = _padding.Pad(data, offset, length, paddingLength);
                 length += paddingLength;
+                offset = 0;
             }
 
             var output = new byte[length];
@@ -114,31 +115,47 @@ namespace Renci.SshNet.Security.Cryptography
         /// <returns>Decrypted data</returns>
         public override byte[] Decrypt(byte[] data)
         {
-            if (data.Length % _blockSize > 0)
+            return Decrypt(data, 0, data.Length);
+        }
+
+        /// <summary>
+        /// Decrypts the specified input.
+        /// </summary>
+        /// <param name="data">The input.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="data"/> at which to begin decrypting.</param>
+        /// <param name="length">The number of bytes to decrypt from <paramref name="data"/>.</param>
+        /// <returns>
+        /// The decrypted data.
+        /// </returns>
+        public override byte[] Decrypt(byte[] data, int offset, int length)
+        {
+            if (length % _blockSize > 0)
             {
                 if (_padding == null)
                 {
                     throw new ArgumentException("data");
                 }
-                data = _padding.Pad(_blockSize, data);
+                data = _padding.Pad(_blockSize, data, offset, length);
+                offset = 0;
+                length = data.Length;
             }
 
-            var output = new byte[data.Length];
+            var output = new byte[length];
 
             var writtenBytes = 0;
-            for (var i = 0; i < data.Length / _blockSize; i++)
+            for (var i = 0; i < length / _blockSize; i++)
             {
                 if (_mode == null)
                 {
-                    writtenBytes += DecryptBlock(data, i * _blockSize, _blockSize, output, i * _blockSize);
+                    writtenBytes += DecryptBlock(data, offset + (i * _blockSize), _blockSize, output, i * _blockSize);
                 }
                 else
                 {
-                    writtenBytes += _mode.DecryptBlock(data, i * _blockSize, _blockSize, output, i * _blockSize);
+                    writtenBytes += _mode.DecryptBlock(data, offset + (i * _blockSize), _blockSize, output, i * _blockSize);
                 }
             }
 
-            if (writtenBytes < data.Length)
+            if (writtenBytes < length)
             {
                 throw new InvalidOperationException("Encryption error.");
             }

+ 17 - 2
src/Renci.SshNet/Security/Cryptography/Cipher.cs

@@ -31,16 +31,31 @@ namespace Renci.SshNet.Security.Cryptography
         /// <param name="input">The input.</param>
         /// <param name="offset">The zero-based offset in <paramref name="input"/> at which to begin encrypting.</param>
         /// <param name="length">The number of bytes to encrypt from <paramref name="input"/>.</param>
-        /// <returns>Encrypted data.</returns>
+        /// <returns>
+        /// The encrypted data.
+        /// </returns>
         public abstract byte[] Encrypt(byte[] input, int offset, int length);
 
         /// <summary>
         /// Decrypts the specified input.
         /// </summary>
         /// <param name="input">The input.</param>
-        /// <returns>Decrypted data.</returns>
+        /// <returns>
+        /// The decrypted data.
+        /// </returns>
         public abstract byte[] Decrypt(byte[] input);
 
+        /// <summary>
+        /// Decrypts the specified input.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="input"/> at which to begin decrypting.</param>
+        /// <param name="length">The number of bytes to decrypt from <paramref name="input"/>.</param>
+        /// <returns>
+        /// The decrypted data.
+        /// </returns>
+        public abstract byte[] Decrypt(byte[] input, int offset, int length);
+
         #region Packing functions
 
         /// <summary>

+ 22 - 8
src/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs

@@ -103,12 +103,26 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
         /// </summary>
         /// <param name="input">The input.</param>
         /// <returns>
-        /// Decrypted data.
+        /// The decrypted data.
         /// </returns>
         public override byte[] Decrypt(byte[] input)
         {
-            var output = new byte[input.Length];
-            ProcessBytes(input, 0, input.Length, output, 0);
+            return Decrypt(input, 0, input.Length);
+        }
+
+        /// <summary>
+        /// Decrypts the specified input.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="input"/> at which to begin decrypting.</param>
+        /// <param name="length">The number of bytes to decrypt from <paramref name="input"/>.</param>
+        /// <returns>
+        /// The decrypted data.
+        /// </returns>
+        public override byte[] Decrypt(byte[] input, int offset, int length)
+        {
+            var output = new byte[length];
+            ProcessBytes(input, offset, length, output, 0);
             return output;
         }
 
@@ -124,13 +138,13 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
                 throw new IndexOutOfRangeException("output buffer too short");
             }
 
-            for (int i = 0; i < inputCount; i++)
+            for (var i = 0; i < inputCount; i++)
             {
                 _x = (_x + 1) & 0xff;
                 _y = (_engineState[_x] + _y) & 0xff;
 
                 // swap
-                byte tmp = _engineState[_x];
+                var tmp = _engineState[_x];
                 _engineState[_x] = _engineState[_y];
                 _engineState[_y] = tmp;
 
@@ -158,14 +172,14 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
                 _engineState[i] = (byte) i;
             }
 
-            int i1 = 0;
-            int i2 = 0;
+            var i1 = 0;
+            var i2 = 0;
 
             for (var i = 0; i < STATE_LENGTH; i++)
             {
                 i2 = ((keyBytes[i1] & 0xff) + _engineState[i] + i2) & 0xff;
                 // do the byte-swap inline
-                byte tmp = _engineState[i];
+                var tmp = _engineState[i];
                 _engineState[i] = _engineState[i2];
                 _engineState[i2] = tmp;
                 i1 = (i1 + 1) % keyBytes.Length;

+ 30 - 13
src/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs

@@ -40,7 +40,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             var paddedBlock = new byte[bitLength / 8 + (bitLength % 8 > 0 ? 1 : 0) - 1];
 
             paddedBlock[0] = 0x01;
-            for (int i = 1; i < paddedBlock.Length - length - 1; i++)
+            for (var i = 1; i < paddedBlock.Length - length - 1; i++)
             {
                 paddedBlock[i] = 0xFF;
             }
@@ -55,13 +55,29 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
         /// </summary>
         /// <param name="data">The data.</param>
         /// <returns>
-        /// Decrypted data.
+        /// The decrypted data.
         /// </returns>
         /// <exception cref="NotSupportedException">Only block type 01 or 02 are supported.</exception>
         /// <exception cref="NotSupportedException">Thrown when decrypted block type is not supported.</exception>
         public override byte[] Decrypt(byte[] data)
         {
-            var paddedBlock = Transform(data);
+            return Decrypt(data, 0, data.Length);
+        }
+
+        /// <summary>
+        /// Decrypts the specified input.
+        /// </summary>
+        /// <param name="data">The input.</param>
+        /// <param name="offset">The zero-based offset in <paramref name="data"/> at which to begin decrypting.</param>
+        /// <param name="length">The number of bytes to decrypt from <paramref name="data"/>.</param>
+        /// <returns>
+        /// The decrypted data.
+        /// </returns>
+        /// <exception cref="NotSupportedException">Only block type 01 or 02 are supported.</exception>
+        /// <exception cref="NotSupportedException">Thrown when decrypted block type is not supported.</exception>
+        public override byte[] Decrypt(byte[] data, int offset, int length)
+        {
+            var paddedBlock = Transform(data, offset, length);
 
             if (paddedBlock[0] != 1 && paddedBlock[0] != 2)
                 throw new NotSupportedException("Only block type 01 or 02 are supported.");
@@ -72,18 +88,21 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             position++;
 
             var result = new byte[paddedBlock.Length - position];
-
             Buffer.BlockCopy(paddedBlock, position, result, 0, result.Length);
-
             return result;
         }
 
         private byte[] Transform(byte[] data)
         {
-            Array.Reverse(data);
+            return Transform(data, 0, data.Length);
+        }
 
-            var inputBytes = new byte[data.Length + 1];
-            Buffer.BlockCopy(data, 0, inputBytes, 0, data.Length);
+        private byte[] Transform(byte[] data, int offset, int length)
+        {
+            Array.Reverse(data, offset, length);
+
+            var inputBytes = new byte[length + 1];
+            Buffer.BlockCopy(data, offset, inputBytes, 0, length);
 
             var input = new BigInteger(inputBytes);
 
@@ -91,10 +110,8 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 
             if (_isPrivate)
             {
-                BigInteger random = BigInteger.One;
-
+                var random = BigInteger.One;
                 var max = _key.Modulus - 1;
-                
                 var bitLength = _key.Modulus.BitLength;
 
                 if (max < BigInteger.One)
@@ -105,7 +122,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
                     random = BigInteger.Random(bitLength);
                 }
 
-                BigInteger blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, _key.Exponent, _key.Modulus) * input), _key.Modulus);
+                var blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, _key.Exponent, _key.Modulus) * input), _key.Modulus);
 
                 // mP = ((input Mod p) ^ dP)) Mod p
                 var mP = BigInteger.ModPow((blindedInput % _key.P), _key.DP, _key.P);
@@ -117,7 +134,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 
                 var m = h * _key.Q + mQ;
 
-                BigInteger rInv = BigInteger.ModInverse(random, _key.Modulus);
+                var rInv = BigInteger.ModInverse(random, _key.Modulus);
 
                 result = BigInteger.PositiveMod((m * rInv), _key.Modulus);
             }