Add support for arcfour cipher and hmac-ripemd160 algorithms

Refactor cipher to allow support of stream ciphers for encryption/decryption
This commit is contained in:
olegkap_cp
2013-01-10 17:00:12 +00:00
parent 2d0286b380
commit c46ceaf34b
22 changed files with 897 additions and 35 deletions
@@ -576,6 +576,9 @@
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\MD5Hash.cs">
<Link>Security\Cryptography\Hashes\MD5Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\RIPEMD160Hash.cs">
<Link>Security\Cryptography\Hashes\RIPEMD160Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\SHA1Hash.cs">
<Link>Security\Cryptography\Hashes\SHA1Hash.cs</Link>
</Compile>
@@ -830,7 +833,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -549,6 +549,9 @@
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\MD5Hash.cs">
<Link>Security\Cryptography\Hashes\MD5Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\RIPEMD160Hash.cs">
<Link>Security\Cryptography\Hashes\RIPEMD160Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\SHA1Hash.cs">
<Link>Security\Cryptography\Hashes\SHA1Hash.cs</Link>
</Compile>
@@ -797,7 +800,7 @@
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
<SilverlightProjectProperties />
</FlavorProperties>
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -555,6 +555,9 @@
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\MD5Hash.cs">
<Link>Security\Cryptography\Hashes\MD5Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\RIPEMD160Hash.cs">
<Link>Security\Cryptography\Hashes\RIPEMD160Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\SHA1Hash.cs">
<Link>Security\Cryptography\Hashes\SHA1Hash.cs</Link>
</Compile>
@@ -807,7 +810,7 @@
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
<SilverlightProjectProperties />
</FlavorProperties>
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -489,6 +489,9 @@
<Compile Include="..\Renci.SshNet.Tests\Classes\Security\Cryptography\Hashes\MD5HashTest.cs">
<Link>Classes\Security\Cryptography\Hashes\MD5HashTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\Security\Cryptography\Hashes\RIPEMD160HashTest.cs">
<Link>Classes\Security\Cryptography\Hashes\RIPEMD160HashTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\Security\Cryptography\Hashes\SHA1HashTest.cs">
<Link>Classes\Security\Cryptography\Hashes\SHA1HashTest.cs</Link>
</Compile>
@@ -723,7 +726,7 @@
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -137,6 +137,23 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
client.Disconnect();
}
}
[TestMethod]
[Owner("olegkap")]
[TestCategory("Cipher")]
public void Test_Cipher_Arcfour_Connection()
{
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, int.Parse(Resources.PORT), Resources.USERNAME, Resources.PASSWORD);
connectionInfo.Encryptions.Clear();
connectionInfo.Encryptions.Add("arcfour", new CipherInfo(128, (key, iv) => { return new Arc4Cipher(key, false); }));
using (var client = new SshClient(connectionInfo))
{
client.Connect();
client.Disconnect();
}
}
/// <summary>
///A test for DecryptBlock
///</summary>
@@ -1,6 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Tests.Common;
using Renci.SshNet.Tests.Properties;
namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
{
@@ -10,7 +11,6 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
[TestClass]
public class Arc4CipherTest : TestBase
{
/// <summary>
///A test for Arc4Cipher Constructor
///</summary>
@@ -18,7 +18,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
public void Arc4CipherConstructorTest()
{
byte[] key = null; // TODO: Initialize to an appropriate value
Arc4Cipher target = new Arc4Cipher(key);
Arc4Cipher target = new Arc4Cipher(key, true);
Assert.Inconclusive("TODO: Implement code to verify target");
}
@@ -29,7 +29,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
public void DecryptTest()
{
byte[] key = null; // TODO: Initialize to an appropriate value
Arc4Cipher target = new Arc4Cipher(key); // 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;
@@ -45,7 +45,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
public void DecryptBlockTest()
{
byte[] key = null; // TODO: Initialize to an appropriate value
Arc4Cipher target = new Arc4Cipher(key); // TODO: Initialize to an appropriate value
Arc4Cipher target = new Arc4Cipher(key, true); // TODO: Initialize to an appropriate value
byte[] inputBuffer = null; // TODO: Initialize to an appropriate value
int inputOffset = 0; // TODO: Initialize to an appropriate value
int inputCount = 0; // TODO: Initialize to an appropriate value
@@ -65,7 +65,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
public void EncryptTest()
{
byte[] key = null; // TODO: Initialize to an appropriate value
Arc4Cipher target = new Arc4Cipher(key); // 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;
@@ -81,7 +81,7 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
public void EncryptBlockTest()
{
byte[] key = null; // TODO: Initialize to an appropriate value
Arc4Cipher target = new Arc4Cipher(key); // TODO: Initialize to an appropriate value
Arc4Cipher target = new Arc4Cipher(key, true); // TODO: Initialize to an appropriate value
byte[] inputBuffer = null; // TODO: Initialize to an appropriate value
int inputOffset = 0; // TODO: Initialize to an appropriate value
int inputCount = 0; // TODO: Initialize to an appropriate value
@@ -93,5 +93,38 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography.Ciphers
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
}
[TestMethod]
[Owner("olegkap")]
[TestCategory("Cipher")]
public void Test_Cipher_Arcfour128_Connection()
{
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, int.Parse(Resources.PORT), Resources.USERNAME, Resources.PASSWORD);
connectionInfo.Encryptions.Clear();
connectionInfo.Encryptions.Add("arcfour128", new CipherInfo(128, (key, iv) => { return new Arc4Cipher(key, true); }));
using (var client = new SshClient(connectionInfo))
{
client.Connect();
client.Disconnect();
}
}
[TestMethod]
[Owner("olegkap")]
[TestCategory("Cipher")]
public void Test_Cipher_Arcfour256_Connection()
{
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, int.Parse(Resources.PORT), Resources.USERNAME, Resources.PASSWORD);
connectionInfo.Encryptions.Clear();
connectionInfo.Encryptions.Add("arcfour256", new CipherInfo(256, (key, iv) => { return new Arc4Cipher(key, true); }));
using (var client = new SshClient(connectionInfo))
{
client.Connect();
client.Disconnect();
}
}
}
}
@@ -42,6 +42,34 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography
}
}
[TestMethod]
public void Test_HMac_RIPEMD160_Connection()
{
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, int.Parse(Resources.PORT), Resources.USERNAME, Resources.PASSWORD);
connectionInfo.HmacAlgorithms.Clear();
connectionInfo.HmacAlgorithms.Add("hmac-ripemd160", (key) => { return new HMac<RIPEMD160Hash>(key.Take(20).ToArray()); });
using (var client = new SshClient(connectionInfo))
{
client.Connect();
client.Disconnect();
}
}
[TestMethod]
public void Test_HMac_RIPEMD160_OPENSSH_Connection()
{
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, int.Parse(Resources.PORT), Resources.USERNAME, Resources.PASSWORD);
connectionInfo.HmacAlgorithms.Clear();
connectionInfo.HmacAlgorithms.Add("hmac-ripemd160@openssh.com", (key) => { return new HMac<RIPEMD160Hash>(key.Take(20).ToArray()); });
using (var client = new SshClient(connectionInfo))
{
client.Connect();
client.Disconnect();
}
}
/// <summary>
///A test for HMac`1 Constructor
///</summary>
@@ -0,0 +1,120 @@
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using Renci.SshNet.Security.Cryptography;
using Renci.SshNet.Tests.Common;
namespace Renci.SshNet.Tests.Classes.Security.Cryptography
{
/// <summary>
///This is a test class for RIPEMD160HashTest and is intended
///to contain all RIPEMD160HashTest Unit Tests
///</summary>
[TestClass()]
public class RIPEMD160HashTest : TestBase
{
/// <summary>
///A test for RIPEMD160Hash Constructor
///</summary>
[TestMethod()]
public void RIPEMD160HashConstructorTest()
{
RIPEMD160Hash target = new RIPEMD160Hash();
Assert.Inconclusive("TODO: Implement code to verify target");
}
/// <summary>
///A test for Initialize
///</summary>
[TestMethod()]
public void InitializeTest()
{
RIPEMD160Hash target = new RIPEMD160Hash(); // TODO: Initialize to an appropriate value
target.Initialize();
Assert.Inconclusive("A method that does not return a value cannot be verified.");
}
/// <summary>
///A test for CanReuseTransform
///</summary>
[TestMethod()]
public void CanReuseTransformTest()
{
RIPEMD160Hash target = new RIPEMD160Hash();
Assert.IsTrue(target.CanReuseTransform);
}
/// <summary>
///A test for CanTransformMultipleBlocks
///</summary>
[TestMethod()]
public void CanTransformMultipleBlocksTest()
{
RIPEMD160Hash target = new RIPEMD160Hash();
Assert.IsTrue(target.CanTransformMultipleBlocks);
}
/// <summary>
///A test for HashSize
///</summary>
[TestMethod()]
public void HashSizeTest()
{
RIPEMD160Hash target = new RIPEMD160Hash();
Assert.AreEqual(target.HashSize, 160);
}
/// <summary>
///A test for InputBlockSize
///</summary>
[TestMethod()]
public void InputBlockSizeTest()
{
RIPEMD160Hash target = new RIPEMD160Hash();
Assert.AreEqual(target.InputBlockSize, 64);
}
/// <summary>
///A test for OutputBlockSize
///</summary>
[TestMethod()]
public void OutputBlockSizeTest()
{
RIPEMD160Hash target = new RIPEMD160Hash();
Assert.AreEqual(target.OutputBlockSize, 64);
}
[TestMethod()]
public void ComputeHash1()
{
RIPEMD160Hash target = new RIPEMD160Hash();
var input = ASCIIEncoding.ASCII.GetBytes("a");
var expeceted = new byte[] { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe };
var output = target.ComputeHash(input);
Assert.IsTrue(output.SequenceEqual(expeceted));
}
[TestMethod()]
public void ComputeHash2()
{
RIPEMD160Hash target = new RIPEMD160Hash();
var input = ASCIIEncoding.ASCII.GetBytes("abc");
var expeceted = new byte[] { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc };
var output = target.ComputeHash(input);
Assert.IsTrue(output.SequenceEqual(expeceted));
}
[TestMethod()]
public void ComputeHash3()
{
RIPEMD160Hash target = new RIPEMD160Hash();
var input = ASCIIEncoding.ASCII.GetBytes("message digest");
var expeceted = new byte[] { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 };
var output = target.ComputeHash(input);
Assert.IsTrue(output.SequenceEqual(expeceted));
}
}
}
@@ -294,6 +294,7 @@
<Compile Include="Classes\Sftp\SftpSynchronizeDirectoriesAsyncResultTest.cs" />
<Compile Include="Classes\Sftp\SftpUploadAsyncResultTest.cs" />
<Compile Include="Classes\Sftp\SubsystemSessionTest.cs" />
<Compile Include="Classes\Security\Cryptography\Hashes\RIPEMD160HashTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Renci.SshNet\Renci.SshNet.csproj">
@@ -547,6 +547,9 @@
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\MD5Hash.cs">
<Link>Security\Cryptography\Hashes\MD5Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\RIPEMD160Hash.cs">
<Link>Security\Cryptography\Hashes\RIPEMD160Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\SHA1Hash.cs">
<Link>Security\Cryptography\Hashes\SHA1Hash.cs</Link>
</Compile>
@@ -797,7 +800,7 @@
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -590,6 +590,9 @@
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\MD5Hash.cs">
<Link>Security\Cryptography\Hashes\MD5Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\RIPEMD160Hash.cs">
<Link>Security\Cryptography\Hashes\RIPEMD160Hash.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Security\Cryptography\Hashes\SHA1Hash.cs">
<Link>Security\Cryptography\Hashes\SHA1Hash.cs</Link>
</Compile>
@@ -840,7 +843,7 @@
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+2 -2
View File
@@ -22,14 +22,14 @@ namespace Renci.SshNet
/// <summary>
/// Gets the cipher.
/// </summary>
public Func<byte[], byte[], BlockCipher> Cipher { get; private set; }
public Func<byte[], byte[], Cipher> Cipher { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="CipherInfo"/> class.
/// </summary>
/// <param name="keySize">Size of the key.</param>
/// <param name="cipher">The cipher.</param>
public CipherInfo(int keySize, Func<byte[], byte[], BlockCipher> cipher)
public CipherInfo(int keySize, Func<byte[], byte[], Cipher> cipher)
{
this.KeySize = keySize;
this.Cipher = (key, iv) => (cipher(key.Take(this.KeySize / 8).ToArray(), iv));
+17 -5
View File
@@ -266,6 +266,9 @@ namespace Renci.SshNet
{"diffie-hellman-group-exchange-sha1", typeof(KeyExchangeDiffieHellmanGroupExchangeSha1)},
{"diffie-hellman-group14-sha1", typeof(KeyExchangeDiffieHellmanGroup14Sha1)},
{"diffie-hellman-group1-sha1", typeof(KeyExchangeDiffieHellmanGroup1Sha1)},
//{"ecdh-sha2-nistp256", typeof(...)},
//{"ecdh-sha2-nistp384", typeof(...)},
//{"ecdh-sha2-nistp521", typeof(...)},
};
this.Encryptions = new Dictionary<string, CipherInfo>()
@@ -279,12 +282,15 @@ namespace Renci.SshNet
////{"twofish-cbc", typeof(...)},
////{"twofish192-cbc", typeof(...)},
////{"twofish128-cbc", typeof(...)},
//{"twofish256-cbc", new CipherInfo(256, (key, iv)=>{ return new TwofishCipher(key, new CbcCipherMode(iv), null); }) },
////{"twofish256-cbc", typeof(...)},
////{"serpent256-cbc", typeof(CipherSerpent256CBC)},
////{"serpent192-cbc", typeof(...)},
////{"serpent128-cbc", typeof(...)},
////{"arcfour128", typeof(...)},
////{"arcfour256", typeof(...)},
{"arcfour", new CipherInfo(128, (key, iv)=>{ return new Arc4Cipher(key, false); }) },
{"arcfour128", new CipherInfo(128, (key, iv)=>{ return new Arc4Cipher(key, true); }) },
{"arcfour256", new CipherInfo(256, (key, iv)=>{ return new Arc4Cipher(key, true); }) },
////{"arcfour", typeof(...)},
////{"idea-cbc", typeof(...)},
{"cast128-cbc", new CipherInfo(128, (key, iv)=>{ return new CastCipher(key, new CbcCipherMode(iv), null); }) },
@@ -297,11 +303,15 @@ namespace Renci.SshNet
{
{"hmac-md5", (key) => { return new HMac<MD5Hash>(key.Take(16).ToArray());}},
{"hmac-sha1", (key) => { return new HMac<SHA1Hash>(key.Take(20).ToArray());}},
//{"hmac-sha2-256", typeof(...)},
//{"hmac-sha2-256-96", typeof(...)},
//{"hmac-sha2-512", typeof(...)},
//{"hmac-sha2-512-96", typeof(...)},
//{"umac-64@openssh.com", typeof(HMacSha1)},
//{"hmac-ripemd160", typeof(HMacSha1)},
//{"hmac-ripemd160@openssh.com", typeof(HMacSha1)},
//{"hmac-md5-96", typeof(...)},
//{"hmac-sha1-96", typeof(...)},
{"hmac-ripemd160", (key) => { return new HMac<RIPEMD160Hash>(key.Take(20).ToArray());}},
{"hmac-ripemd160@openssh.com", (key) => { return new HMac<RIPEMD160Hash>(key.Take(20).ToArray());}},
//{"hmac-md5-96", (key) => { return new HMac<MD5Hash>(key.Take(12).ToArray());}},
//{"hmac-sha1-96", (key) => { return new HMac<SHA1Hash96>(key.Take(12).ToArray());}},
//{"none", typeof(...)},
};
@@ -309,6 +319,7 @@ namespace Renci.SshNet
{
{"ssh-rsa", (data) => { return new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data); }},
{"ssh-dss", (data) => { return new KeyHostAlgorithm("ssh-dss", new DsaKey(), data); }},
//{"ecdsa-sha2-nistp256 "}
//{"x509v3-sign-rsa", () => { ... },
//{"x509v3-sign-dss", () => { ... },
//{"spki-sign-rsa", () => { ... },
@@ -324,6 +335,7 @@ namespace Renci.SshNet
//{"zlib@openssh.com", typeof(ZlibOpenSsh)},
};
this.ChannelRequests = new Dictionary<string, RequestInfo>()
{
{EnvironmentVariableRequestInfo.NAME, new EnvironmentVariableRequestInfo()},
@@ -131,6 +131,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="ConnectionInfo.cs" />
<Compile Include="Security\Cryptography\Hashes\RIPEMD160Hash.cs" />
<Compile Include="ShellStream.NET40.cs" />
<Compile Include="ExpectAsyncResult.cs" />
<Compile Include="Security\KeyExchangeDiffieHellmanGroupSha1.cs" />
@@ -10,5 +10,9 @@ namespace Renci.SshNet.Security.Cryptography
/// </summary>
public abstract class AsymmetricCipher : Cipher
{
public override byte MinimumSize
{
get { return 0; }
}
}
}
@@ -21,7 +21,18 @@ namespace Renci.SshNet.Security.Cryptography
/// <value>
/// The size of the block in bytes.
/// </value>
protected readonly int _blockSize;
protected readonly byte _blockSize;
/// <summary>
/// Gets the minimum data size.
/// </summary>
/// <value>
/// The minimum data size.
/// </value>
public override byte MinimumSize
{
get { return this.BlockSize; }
}
/// <summary>
/// Gets the size of the block.
@@ -29,7 +40,7 @@ namespace Renci.SshNet.Security.Cryptography
/// <value>
/// The size of the block.
/// </value>
public int BlockSize
public byte BlockSize
{
get
{
@@ -45,7 +56,7 @@ namespace Renci.SshNet.Security.Cryptography
/// <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, int blockSize, CipherMode mode, CipherPadding padding)
protected BlockCipher(byte[] key, byte blockSize, CipherMode mode, CipherPadding padding)
: base(key)
{
this._blockSize = blockSize;
@@ -10,6 +10,14 @@ namespace Renci.SshNet.Security.Cryptography
/// </summary>
public abstract class Cipher
{
/// <summary>
/// Gets the minimum data size.
/// </summary>
/// <value>
/// The minimum data size.
/// </value>
public abstract byte MinimumSize { get; }
/// <summary>
/// Encrypts the specified input.
/// </summary>
@@ -852,6 +852,5 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ KW[0, 2];
C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ KW[0, 3];
}
}
}
@@ -10,15 +10,27 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
/// </summary>
public class Arc4Cipher : StreamCipher
{
public override byte MinimumSize
{
get { return 0; }
}
/// <summary>
/// Initializes a new instance of the <see cref="Arc4Cipher"/> class.
/// </summary>
/// <param name="key">The key.</param>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
public Arc4Cipher(byte[] key)
public Arc4Cipher(byte[] key, bool dischargeFirstBytes)
: base(key)
{
workingKey = key;
SetKey(workingKey);
// The first 1536 bytes of keystream
// generated by the cipher MUST be discarded, and the first byte of the
// first encrypted packet MUST be encrypted using the 1537th byte of
// keystream.
if (dischargeFirstBytes)
this.Encrypt(new byte[1536]);
}
/// <summary>
@@ -34,7 +46,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
/// </returns>
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
throw new NotImplementedException();
return this.ProcessBytes(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
}
/// <summary>
@@ -50,7 +62,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
/// </returns>
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
throw new NotImplementedException();
return this.ProcessBytes(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
}
/// <summary>
@@ -63,7 +75,9 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
/// <exception cref="System.NotImplementedException"></exception>
public override byte[] Encrypt(byte[] input)
{
throw new NotImplementedException();
var output = new byte[input.Length];
this.ProcessBytes(input, 0, input.Length, output, 0);
return output;
}
/// <summary>
@@ -76,7 +90,91 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
/// <exception cref="System.NotImplementedException"></exception>
public override byte[] Decrypt(byte[] input)
{
throw new NotImplementedException();
var output = new byte[input.Length];
this.ProcessBytes(input, 0, input.Length, output, 0);
return output;
}
private readonly static int STATE_LENGTH = 256;
/*
* variables to hold the state of the RC4 engine
* during encryption and decryption
*/
private byte[] engineState;
private int x;
private int y;
private byte[] workingKey;
private int ProcessBytes(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
if ((inputOffset + inputCount) > inputBuffer.Length)
{
throw new IndexOutOfRangeException("input buffer too short");
}
if ((outputOffset + inputCount) > outputBuffer.Length)
{
throw new IndexOutOfRangeException("output buffer too short");
}
for (int i = 0; i < inputCount; i++)
{
x = (x + 1) & 0xff;
y = (engineState[x] + y) & 0xff;
// swap
byte tmp = engineState[x];
engineState[x] = engineState[y];
engineState[y] = tmp;
// xor
outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
}
return inputCount;
}
public void Reset()
{
SetKey(workingKey);
}
// Private implementation
private void SetKey(byte[] keyBytes)
{
workingKey = keyBytes;
// System.out.println("the key length is ; "+ workingKey.Length);
x = 0;
y = 0;
if (engineState == null)
{
engineState = new byte[STATE_LENGTH];
}
// reset the state of the engine
for (int i = 0; i < STATE_LENGTH; i++)
{
engineState[i] = (byte)i;
}
int i1 = 0;
int i2 = 0;
for (int i = 0; i < STATE_LENGTH; i++)
{
i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
// do the byte-swap inline
byte tmp = engineState[i];
engineState[i] = engineState[i2];
engineState[i2] = tmp;
i1 = (i1 + 1) % keyBytes.Length;
}
}
}
}
@@ -0,0 +1,512 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace Renci.SshNet.Security.Cryptography
{
/// <summary>
///
/// </summary>
public class RIPEMD160Hash : HashAlgorithm
{
private byte[] _buffer;
private int _bufferOffset;
private long _byteCount;
private const int DIGEST_SIZE = 20;
private int _offset;
private int H0, H1, H2, H3, H4; // IV's
private int[] X = new int[16];
/// <summary>
/// Gets the size, in bits, of the computed hash code.
/// </summary>
/// <returns>The size, in bits, of the computed hash code.</returns>
public override int HashSize
{
get
{
return DIGEST_SIZE * 8;
}
}
/// <summary>
/// Gets the input block size.
/// </summary>
/// <returns>The input block size.</returns>
public override int InputBlockSize
{
get
{
return 64;
}
}
/// <summary>
/// Gets the output block size.
/// </summary>
/// <returns>The output block size.</returns>
public override int OutputBlockSize
{
get
{
return 64;
}
}
/// <summary>
/// Gets a value indicating whether the current transform can be reused.
/// </summary>
/// <returns>Always true.</returns>
public override bool CanReuseTransform
{
get
{
return true;
}
}
/// <summary>
/// Gets a value indicating whether multiple blocks can be transformed.
/// </summary>
/// <returns>true if multiple blocks can be transformed; otherwise, false.</returns>
public override bool CanTransformMultipleBlocks
{
get
{
return true;
}
}
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
//
// fill the current word
//
while ((_bufferOffset != 0) && (cbSize > 0))
{
this.Update(array[ibStart]);
ibStart++;
cbSize--;
}
//
// process whole words.
//
while (cbSize > _buffer.Length)
{
this.ProcessWord(array, ibStart);
ibStart += _buffer.Length;
cbSize -= _buffer.Length;
_byteCount += _buffer.Length;
}
//
// load in the remainder.
//
while (cbSize > 0)
{
this.Update(array[ibStart]);
ibStart++;
cbSize--;
}
}
protected override byte[] HashFinal()
{
var output = new byte[DIGEST_SIZE];
long bitLength = (_byteCount << 3);
//
// add the pad bytes.
//
this.Update((byte)128);
while (this._bufferOffset != 0)
Update((byte)0);
ProcessLength(bitLength);
ProcessBlock();
UnpackWord(H0, output, 0);
UnpackWord(H1, output, 4);
UnpackWord(H2, output, 8);
UnpackWord(H3, output, 12);
UnpackWord(H4, output, 16);
this.InternalInitialize();
return output;
}
public override void Initialize()
{
this.InternalInitialize();
}
public RIPEMD160Hash()
{
this._buffer = new byte[4];
this.InternalInitialize();
}
private void ProcessWord(byte[] input, int inOff)
{
X[_offset++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
| ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
if (_offset == 16)
{
ProcessBlock();
}
}
private void ProcessLength(long bitLength)
{
if (_offset > 14)
{
ProcessBlock();
}
X[14] = (int)(bitLength & 0xffffffff);
X[15] = (int)((ulong)bitLength >> 32);
}
private void UnpackWord(int word, byte[] outBytes, int outOff)
{
outBytes[outOff] = (byte)word;
outBytes[outOff + 1] = (byte)((uint)word >> 8);
outBytes[outOff + 2] = (byte)((uint)word >> 16);
outBytes[outOff + 3] = (byte)((uint)word >> 24);
}
private void Update(byte input)
{
_buffer[_bufferOffset++] = input;
if (_bufferOffset == _buffer.Length)
{
ProcessWord(_buffer, 0);
_bufferOffset = 0;
}
_byteCount++;
}
/// <summary>
/// Reset the chaining variables to the IV values.
/// </summary>
private void InternalInitialize()
{
_byteCount = 0;
_bufferOffset = 0;
Array.Clear(_buffer, 0, _buffer.Length);
H0 = unchecked((int)0x67452301);
H1 = unchecked((int)0xefcdab89);
H2 = unchecked((int)0x98badcfe);
H3 = unchecked((int)0x10325476);
H4 = unchecked((int)0xc3d2e1f0);
_offset = 0;
for (int i = 0; i != X.Length; i++)
{
X[i] = 0;
}
}
private int RL(int x, int n)
{
return (x << n) | (int)((uint)x >> (32 - n));
}
/// <summary>
/// Rounds 0-15
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="z">The z.</param>
/// <returns></returns>
private int F1(int x, int y, int z)
{
return x ^ y ^ z;
}
/// <summary>
/// Rounds 16-31
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="z">The z.</param>
/// <returns></returns>
private int F2(int x, int y, int z)
{
return (x & y) | (~x & z);
}
/// <summary>
/// ounds 32-47
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="z">The z.</param>
/// <returns></returns>
private int F3(int x, int y, int z)
{
return (x | ~y) ^ z;
}
/// <summary>
/// Rounds 48-63
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="z">The z.</param>
/// <returns></returns>
private int F4(int x, int y, int z)
{
return (x & z) | (y & ~z);
}
/// <summary>
/// ounds 64-79
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="z">The z.</param>
/// <returns></returns>
private int F5(int x, int y, int z)
{
return x ^ (y | ~z);
}
private void ProcessBlock()
{
int a, aa;
int b, bb;
int c, cc;
int d, dd;
int e, ee;
a = aa = H0;
b = bb = H1;
c = cc = H2;
d = dd = H3;
e = ee = H4;
//
// Rounds 1 - 16
//
// left
a = RL(a + F1(b, c, d) + X[0], 11) + e; c = RL(c, 10);
e = RL(e + F1(a, b, c) + X[1], 14) + d; b = RL(b, 10);
d = RL(d + F1(e, a, b) + X[2], 15) + c; a = RL(a, 10);
c = RL(c + F1(d, e, a) + X[3], 12) + b; e = RL(e, 10);
b = RL(b + F1(c, d, e) + X[4], 5) + a; d = RL(d, 10);
a = RL(a + F1(b, c, d) + X[5], 8) + e; c = RL(c, 10);
e = RL(e + F1(a, b, c) + X[6], 7) + d; b = RL(b, 10);
d = RL(d + F1(e, a, b) + X[7], 9) + c; a = RL(a, 10);
c = RL(c + F1(d, e, a) + X[8], 11) + b; e = RL(e, 10);
b = RL(b + F1(c, d, e) + X[9], 13) + a; d = RL(d, 10);
a = RL(a + F1(b, c, d) + X[10], 14) + e; c = RL(c, 10);
e = RL(e + F1(a, b, c) + X[11], 15) + d; b = RL(b, 10);
d = RL(d + F1(e, a, b) + X[12], 6) + c; a = RL(a, 10);
c = RL(c + F1(d, e, a) + X[13], 7) + b; e = RL(e, 10);
b = RL(b + F1(c, d, e) + X[14], 9) + a; d = RL(d, 10);
a = RL(a + F1(b, c, d) + X[15], 8) + e; c = RL(c, 10);
// right
aa = RL(aa + F5(bb, cc, dd) + X[5] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
ee = RL(ee + F5(aa, bb, cc) + X[14] + unchecked((int)0x50a28be6), 9) + dd; bb = RL(bb, 10);
dd = RL(dd + F5(ee, aa, bb) + X[7] + unchecked((int)0x50a28be6), 9) + cc; aa = RL(aa, 10);
cc = RL(cc + F5(dd, ee, aa) + X[0] + unchecked((int)0x50a28be6), 11) + bb; ee = RL(ee, 10);
bb = RL(bb + F5(cc, dd, ee) + X[9] + unchecked((int)0x50a28be6), 13) + aa; dd = RL(dd, 10);
aa = RL(aa + F5(bb, cc, dd) + X[2] + unchecked((int)0x50a28be6), 15) + ee; cc = RL(cc, 10);
ee = RL(ee + F5(aa, bb, cc) + X[11] + unchecked((int)0x50a28be6), 15) + dd; bb = RL(bb, 10);
dd = RL(dd + F5(ee, aa, bb) + X[4] + unchecked((int)0x50a28be6), 5) + cc; aa = RL(aa, 10);
cc = RL(cc + F5(dd, ee, aa) + X[13] + unchecked((int)0x50a28be6), 7) + bb; ee = RL(ee, 10);
bb = RL(bb + F5(cc, dd, ee) + X[6] + unchecked((int)0x50a28be6), 7) + aa; dd = RL(dd, 10);
aa = RL(aa + F5(bb, cc, dd) + X[15] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
ee = RL(ee + F5(aa, bb, cc) + X[8] + unchecked((int)0x50a28be6), 11) + dd; bb = RL(bb, 10);
dd = RL(dd + F5(ee, aa, bb) + X[1] + unchecked((int)0x50a28be6), 14) + cc; aa = RL(aa, 10);
cc = RL(cc + F5(dd, ee, aa) + X[10] + unchecked((int)0x50a28be6), 14) + bb; ee = RL(ee, 10);
bb = RL(bb + F5(cc, dd, ee) + X[3] + unchecked((int)0x50a28be6), 12) + aa; dd = RL(dd, 10);
aa = RL(aa + F5(bb, cc, dd) + X[12] + unchecked((int)0x50a28be6), 6) + ee; cc = RL(cc, 10);
//
// Rounds 16-31
//
// left
e = RL(e + F2(a, b, c) + X[7] + unchecked((int)0x5a827999), 7) + d; b = RL(b, 10);
d = RL(d + F2(e, a, b) + X[4] + unchecked((int)0x5a827999), 6) + c; a = RL(a, 10);
c = RL(c + F2(d, e, a) + X[13] + unchecked((int)0x5a827999), 8) + b; e = RL(e, 10);
b = RL(b + F2(c, d, e) + X[1] + unchecked((int)0x5a827999), 13) + a; d = RL(d, 10);
a = RL(a + F2(b, c, d) + X[10] + unchecked((int)0x5a827999), 11) + e; c = RL(c, 10);
e = RL(e + F2(a, b, c) + X[6] + unchecked((int)0x5a827999), 9) + d; b = RL(b, 10);
d = RL(d + F2(e, a, b) + X[15] + unchecked((int)0x5a827999), 7) + c; a = RL(a, 10);
c = RL(c + F2(d, e, a) + X[3] + unchecked((int)0x5a827999), 15) + b; e = RL(e, 10);
b = RL(b + F2(c, d, e) + X[12] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
a = RL(a + F2(b, c, d) + X[0] + unchecked((int)0x5a827999), 12) + e; c = RL(c, 10);
e = RL(e + F2(a, b, c) + X[9] + unchecked((int)0x5a827999), 15) + d; b = RL(b, 10);
d = RL(d + F2(e, a, b) + X[5] + unchecked((int)0x5a827999), 9) + c; a = RL(a, 10);
c = RL(c + F2(d, e, a) + X[2] + unchecked((int)0x5a827999), 11) + b; e = RL(e, 10);
b = RL(b + F2(c, d, e) + X[14] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
a = RL(a + F2(b, c, d) + X[11] + unchecked((int)0x5a827999), 13) + e; c = RL(c, 10);
e = RL(e + F2(a, b, c) + X[8] + unchecked((int)0x5a827999), 12) + d; b = RL(b, 10);
// right
ee = RL(ee + F4(aa, bb, cc) + X[6] + unchecked((int)0x5c4dd124), 9) + dd; bb = RL(bb, 10);
dd = RL(dd + F4(ee, aa, bb) + X[11] + unchecked((int)0x5c4dd124), 13) + cc; aa = RL(aa, 10);
cc = RL(cc + F4(dd, ee, aa) + X[3] + unchecked((int)0x5c4dd124), 15) + bb; ee = RL(ee, 10);
bb = RL(bb + F4(cc, dd, ee) + X[7] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
aa = RL(aa + F4(bb, cc, dd) + X[0] + unchecked((int)0x5c4dd124), 12) + ee; cc = RL(cc, 10);
ee = RL(ee + F4(aa, bb, cc) + X[13] + unchecked((int)0x5c4dd124), 8) + dd; bb = RL(bb, 10);
dd = RL(dd + F4(ee, aa, bb) + X[5] + unchecked((int)0x5c4dd124), 9) + cc; aa = RL(aa, 10);
cc = RL(cc + F4(dd, ee, aa) + X[10] + unchecked((int)0x5c4dd124), 11) + bb; ee = RL(ee, 10);
bb = RL(bb + F4(cc, dd, ee) + X[14] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
aa = RL(aa + F4(bb, cc, dd) + X[15] + unchecked((int)0x5c4dd124), 7) + ee; cc = RL(cc, 10);
ee = RL(ee + F4(aa, bb, cc) + X[8] + unchecked((int)0x5c4dd124), 12) + dd; bb = RL(bb, 10);
dd = RL(dd + F4(ee, aa, bb) + X[12] + unchecked((int)0x5c4dd124), 7) + cc; aa = RL(aa, 10);
cc = RL(cc + F4(dd, ee, aa) + X[4] + unchecked((int)0x5c4dd124), 6) + bb; ee = RL(ee, 10);
bb = RL(bb + F4(cc, dd, ee) + X[9] + unchecked((int)0x5c4dd124), 15) + aa; dd = RL(dd, 10);
aa = RL(aa + F4(bb, cc, dd) + X[1] + unchecked((int)0x5c4dd124), 13) + ee; cc = RL(cc, 10);
ee = RL(ee + F4(aa, bb, cc) + X[2] + unchecked((int)0x5c4dd124), 11) + dd; bb = RL(bb, 10);
//
// Rounds 32-47
//
// left
d = RL(d + F3(e, a, b) + X[3] + unchecked((int)0x6ed9eba1), 11) + c; a = RL(a, 10);
c = RL(c + F3(d, e, a) + X[10] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
b = RL(b + F3(c, d, e) + X[14] + unchecked((int)0x6ed9eba1), 6) + a; d = RL(d, 10);
a = RL(a + F3(b, c, d) + X[4] + unchecked((int)0x6ed9eba1), 7) + e; c = RL(c, 10);
e = RL(e + F3(a, b, c) + X[9] + unchecked((int)0x6ed9eba1), 14) + d; b = RL(b, 10);
d = RL(d + F3(e, a, b) + X[15] + unchecked((int)0x6ed9eba1), 9) + c; a = RL(a, 10);
c = RL(c + F3(d, e, a) + X[8] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
b = RL(b + F3(c, d, e) + X[1] + unchecked((int)0x6ed9eba1), 15) + a; d = RL(d, 10);
a = RL(a + F3(b, c, d) + X[2] + unchecked((int)0x6ed9eba1), 14) + e; c = RL(c, 10);
e = RL(e + F3(a, b, c) + X[7] + unchecked((int)0x6ed9eba1), 8) + d; b = RL(b, 10);
d = RL(d + F3(e, a, b) + X[0] + unchecked((int)0x6ed9eba1), 13) + c; a = RL(a, 10);
c = RL(c + F3(d, e, a) + X[6] + unchecked((int)0x6ed9eba1), 6) + b; e = RL(e, 10);
b = RL(b + F3(c, d, e) + X[13] + unchecked((int)0x6ed9eba1), 5) + a; d = RL(d, 10);
a = RL(a + F3(b, c, d) + X[11] + unchecked((int)0x6ed9eba1), 12) + e; c = RL(c, 10);
e = RL(e + F3(a, b, c) + X[5] + unchecked((int)0x6ed9eba1), 7) + d; b = RL(b, 10);
d = RL(d + F3(e, a, b) + X[12] + unchecked((int)0x6ed9eba1), 5) + c; a = RL(a, 10);
// right
dd = RL(dd + F3(ee, aa, bb) + X[15] + unchecked((int)0x6d703ef3), 9) + cc; aa = RL(aa, 10);
cc = RL(cc + F3(dd, ee, aa) + X[5] + unchecked((int)0x6d703ef3), 7) + bb; ee = RL(ee, 10);
bb = RL(bb + F3(cc, dd, ee) + X[1] + unchecked((int)0x6d703ef3), 15) + aa; dd = RL(dd, 10);
aa = RL(aa + F3(bb, cc, dd) + X[3] + unchecked((int)0x6d703ef3), 11) + ee; cc = RL(cc, 10);
ee = RL(ee + F3(aa, bb, cc) + X[7] + unchecked((int)0x6d703ef3), 8) + dd; bb = RL(bb, 10);
dd = RL(dd + F3(ee, aa, bb) + X[14] + unchecked((int)0x6d703ef3), 6) + cc; aa = RL(aa, 10);
cc = RL(cc + F3(dd, ee, aa) + X[6] + unchecked((int)0x6d703ef3), 6) + bb; ee = RL(ee, 10);
bb = RL(bb + F3(cc, dd, ee) + X[9] + unchecked((int)0x6d703ef3), 14) + aa; dd = RL(dd, 10);
aa = RL(aa + F3(bb, cc, dd) + X[11] + unchecked((int)0x6d703ef3), 12) + ee; cc = RL(cc, 10);
ee = RL(ee + F3(aa, bb, cc) + X[8] + unchecked((int)0x6d703ef3), 13) + dd; bb = RL(bb, 10);
dd = RL(dd + F3(ee, aa, bb) + X[12] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
cc = RL(cc + F3(dd, ee, aa) + X[2] + unchecked((int)0x6d703ef3), 14) + bb; ee = RL(ee, 10);
bb = RL(bb + F3(cc, dd, ee) + X[10] + unchecked((int)0x6d703ef3), 13) + aa; dd = RL(dd, 10);
aa = RL(aa + F3(bb, cc, dd) + X[0] + unchecked((int)0x6d703ef3), 13) + ee; cc = RL(cc, 10);
ee = RL(ee + F3(aa, bb, cc) + X[4] + unchecked((int)0x6d703ef3), 7) + dd; bb = RL(bb, 10);
dd = RL(dd + F3(ee, aa, bb) + X[13] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
//
// Rounds 48-63
//
// left
c = RL(c + F4(d, e, a) + X[1] + unchecked((int)0x8f1bbcdc), 11) + b; e = RL(e, 10);
b = RL(b + F4(c, d, e) + X[9] + unchecked((int)0x8f1bbcdc), 12) + a; d = RL(d, 10);
a = RL(a + F4(b, c, d) + X[11] + unchecked((int)0x8f1bbcdc), 14) + e; c = RL(c, 10);
e = RL(e + F4(a, b, c) + X[10] + unchecked((int)0x8f1bbcdc), 15) + d; b = RL(b, 10);
d = RL(d + F4(e, a, b) + X[0] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
c = RL(c + F4(d, e, a) + X[8] + unchecked((int)0x8f1bbcdc), 15) + b; e = RL(e, 10);
b = RL(b + F4(c, d, e) + X[12] + unchecked((int)0x8f1bbcdc), 9) + a; d = RL(d, 10);
a = RL(a + F4(b, c, d) + X[4] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
e = RL(e + F4(a, b, c) + X[13] + unchecked((int)0x8f1bbcdc), 9) + d; b = RL(b, 10);
d = RL(d + F4(e, a, b) + X[3] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
c = RL(c + F4(d, e, a) + X[7] + unchecked((int)0x8f1bbcdc), 5) + b; e = RL(e, 10);
b = RL(b + F4(c, d, e) + X[15] + unchecked((int)0x8f1bbcdc), 6) + a; d = RL(d, 10);
a = RL(a + F4(b, c, d) + X[14] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
e = RL(e + F4(a, b, c) + X[5] + unchecked((int)0x8f1bbcdc), 6) + d; b = RL(b, 10);
d = RL(d + F4(e, a, b) + X[6] + unchecked((int)0x8f1bbcdc), 5) + c; a = RL(a, 10);
c = RL(c + F4(d, e, a) + X[2] + unchecked((int)0x8f1bbcdc), 12) + b; e = RL(e, 10);
// right
cc = RL(cc + F2(dd, ee, aa) + X[8] + unchecked((int)0x7a6d76e9), 15) + bb; ee = RL(ee, 10);
bb = RL(bb + F2(cc, dd, ee) + X[6] + unchecked((int)0x7a6d76e9), 5) + aa; dd = RL(dd, 10);
aa = RL(aa + F2(bb, cc, dd) + X[4] + unchecked((int)0x7a6d76e9), 8) + ee; cc = RL(cc, 10);
ee = RL(ee + F2(aa, bb, cc) + X[1] + unchecked((int)0x7a6d76e9), 11) + dd; bb = RL(bb, 10);
dd = RL(dd + F2(ee, aa, bb) + X[3] + unchecked((int)0x7a6d76e9), 14) + cc; aa = RL(aa, 10);
cc = RL(cc + F2(dd, ee, aa) + X[11] + unchecked((int)0x7a6d76e9), 14) + bb; ee = RL(ee, 10);
bb = RL(bb + F2(cc, dd, ee) + X[15] + unchecked((int)0x7a6d76e9), 6) + aa; dd = RL(dd, 10);
aa = RL(aa + F2(bb, cc, dd) + X[0] + unchecked((int)0x7a6d76e9), 14) + ee; cc = RL(cc, 10);
ee = RL(ee + F2(aa, bb, cc) + X[5] + unchecked((int)0x7a6d76e9), 6) + dd; bb = RL(bb, 10);
dd = RL(dd + F2(ee, aa, bb) + X[12] + unchecked((int)0x7a6d76e9), 9) + cc; aa = RL(aa, 10);
cc = RL(cc + F2(dd, ee, aa) + X[2] + unchecked((int)0x7a6d76e9), 12) + bb; ee = RL(ee, 10);
bb = RL(bb + F2(cc, dd, ee) + X[13] + unchecked((int)0x7a6d76e9), 9) + aa; dd = RL(dd, 10);
aa = RL(aa + F2(bb, cc, dd) + X[9] + unchecked((int)0x7a6d76e9), 12) + ee; cc = RL(cc, 10);
ee = RL(ee + F2(aa, bb, cc) + X[7] + unchecked((int)0x7a6d76e9), 5) + dd; bb = RL(bb, 10);
dd = RL(dd + F2(ee, aa, bb) + X[10] + unchecked((int)0x7a6d76e9), 15) + cc; aa = RL(aa, 10);
cc = RL(cc + F2(dd, ee, aa) + X[14] + unchecked((int)0x7a6d76e9), 8) + bb; ee = RL(ee, 10);
//
// Rounds 64-79
//
// left
b = RL(b + F5(c, d, e) + X[4] + unchecked((int)0xa953fd4e), 9) + a; d = RL(d, 10);
a = RL(a + F5(b, c, d) + X[0] + unchecked((int)0xa953fd4e), 15) + e; c = RL(c, 10);
e = RL(e + F5(a, b, c) + X[5] + unchecked((int)0xa953fd4e), 5) + d; b = RL(b, 10);
d = RL(d + F5(e, a, b) + X[9] + unchecked((int)0xa953fd4e), 11) + c; a = RL(a, 10);
c = RL(c + F5(d, e, a) + X[7] + unchecked((int)0xa953fd4e), 6) + b; e = RL(e, 10);
b = RL(b + F5(c, d, e) + X[12] + unchecked((int)0xa953fd4e), 8) + a; d = RL(d, 10);
a = RL(a + F5(b, c, d) + X[2] + unchecked((int)0xa953fd4e), 13) + e; c = RL(c, 10);
e = RL(e + F5(a, b, c) + X[10] + unchecked((int)0xa953fd4e), 12) + d; b = RL(b, 10);
d = RL(d + F5(e, a, b) + X[14] + unchecked((int)0xa953fd4e), 5) + c; a = RL(a, 10);
c = RL(c + F5(d, e, a) + X[1] + unchecked((int)0xa953fd4e), 12) + b; e = RL(e, 10);
b = RL(b + F5(c, d, e) + X[3] + unchecked((int)0xa953fd4e), 13) + a; d = RL(d, 10);
a = RL(a + F5(b, c, d) + X[8] + unchecked((int)0xa953fd4e), 14) + e; c = RL(c, 10);
e = RL(e + F5(a, b, c) + X[11] + unchecked((int)0xa953fd4e), 11) + d; b = RL(b, 10);
d = RL(d + F5(e, a, b) + X[6] + unchecked((int)0xa953fd4e), 8) + c; a = RL(a, 10);
c = RL(c + F5(d, e, a) + X[15] + unchecked((int)0xa953fd4e), 5) + b; e = RL(e, 10);
b = RL(b + F5(c, d, e) + X[13] + unchecked((int)0xa953fd4e), 6) + a; d = RL(d, 10);
// right
bb = RL(bb + F1(cc, dd, ee) + X[12], 8) + aa; dd = RL(dd, 10);
aa = RL(aa + F1(bb, cc, dd) + X[15], 5) + ee; cc = RL(cc, 10);
ee = RL(ee + F1(aa, bb, cc) + X[10], 12) + dd; bb = RL(bb, 10);
dd = RL(dd + F1(ee, aa, bb) + X[4], 9) + cc; aa = RL(aa, 10);
cc = RL(cc + F1(dd, ee, aa) + X[1], 12) + bb; ee = RL(ee, 10);
bb = RL(bb + F1(cc, dd, ee) + X[5], 5) + aa; dd = RL(dd, 10);
aa = RL(aa + F1(bb, cc, dd) + X[8], 14) + ee; cc = RL(cc, 10);
ee = RL(ee + F1(aa, bb, cc) + X[7], 6) + dd; bb = RL(bb, 10);
dd = RL(dd + F1(ee, aa, bb) + X[6], 8) + cc; aa = RL(aa, 10);
cc = RL(cc + F1(dd, ee, aa) + X[2], 13) + bb; ee = RL(ee, 10);
bb = RL(bb + F1(cc, dd, ee) + X[13], 6) + aa; dd = RL(dd, 10);
aa = RL(aa + F1(bb, cc, dd) + X[14], 5) + ee; cc = RL(cc, 10);
ee = RL(ee + F1(aa, bb, cc) + X[0], 15) + dd; bb = RL(bb, 10);
dd = RL(dd + F1(ee, aa, bb) + X[3], 13) + cc; aa = RL(aa, 10);
cc = RL(cc + F1(dd, ee, aa) + X[9], 11) + bb; ee = RL(ee, 10);
bb = RL(bb + F1(cc, dd, ee) + X[11], 11) + aa; dd = RL(dd, 10);
dd += c + H1;
H1 = H2 + d + ee;
H2 = H3 + e + aa;
H3 = H4 + a + bb;
H4 = H0 + b + cc;
H0 = dd;
//
// reset the offset and clean out the word buffer.
//
_offset = 0;
for (int i = 0; i != X.Length; i++)
{
X[i] = 0;
}
}
}
}
@@ -178,7 +178,7 @@ namespace Renci.SshNet.Security
/// Creates the server side cipher to use.
/// </summary>
/// <returns>Server cipher.</returns>
public BlockCipher CreateServerCipher()
public Cipher CreateServerCipher()
{
// Resolve Session ID
var sessionId = this.Session.SessionId ?? this.ExchangeHash;
@@ -199,7 +199,7 @@ namespace Renci.SshNet.Security
/// Creates the client side cipher to use.
/// </summary>
/// <returns>Client cipher.</returns>
public BlockCipher CreateClientCipher()
public Cipher CreateClientCipher()
{
// Resolve Session ID
var sessionId = this.Session.SessionId ?? this.ExchangeHash;
+4 -4
View File
@@ -124,9 +124,9 @@ namespace Renci.SshNet
private HashAlgorithm _clientMac;
private BlockCipher _clientCipher;
private Cipher _clientCipher;
private BlockCipher _serverCipher;
private Cipher _serverCipher;
private Compressor _serverDecompression;
@@ -664,7 +664,7 @@ namespace Renci.SshNet
this.Log(string.Format("SendMessage to server '{0}': '{1}'.", message.GetType().Name, message.ToString()));
// Messages can be sent by different thread so we need to synchronize it
var paddingMultiplier = this._clientCipher == null ? (byte)8 : (byte)this._clientCipher.BlockSize; // Should be recalculate base on cipher min length if cipher specified
var paddingMultiplier = this._clientCipher == null ? (byte)8 : Math.Max((byte)8, this._serverCipher.MinimumSize); // Should be recalculate base on cipher min length if cipher specified
var messageData = message.GetBytes();
@@ -799,7 +799,7 @@ namespace Renci.SshNet
return null;
// No lock needed since all messages read by only one thread
var blockSize = this._serverCipher == null ? (byte)8 : (byte)this._serverCipher.BlockSize;
var blockSize = this._serverCipher == null ? (byte)8 : Math.Max((byte)8, this._serverCipher.MinimumSize);
// Read packet length first
var firstBlock = this.Read(blockSize);