Some cosmetic changes

Fixes suggested in issue #703
Add tests for implemented issues
This commit is contained in:
olegkap_cp
2011-05-11 14:52:23 +00:00
parent 223b1fd909
commit 0854d152db
40 changed files with 1026 additions and 657 deletions
@@ -7,6 +7,7 @@ using System.IO;
using Renci.SshClient.Tests.Properties;
using System.Security.Authentication;
using Renci.SshClient.Common;
using System.Net;
namespace Renci.SshClient.Tests
{
@@ -130,5 +131,27 @@ namespace Renci.SshClient.Tests
client.Disconnect();
}
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void Test_ConnectionInfo_NullHost()
{
var connectionInfo = new PasswordConnectionInfo(null, null, null);
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Test_ConnectionInfo_SmallPortNumber()
{
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, IPEndPoint.MinPort - 1, null, null);
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Test_ConnectionInfo_BigPortNumber()
{
var connectionInfo = new PasswordConnectionInfo(Resources.HOST, IPEndPoint.MaxPort + 1, null, null);
}
}
}
@@ -3,11 +3,28 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
namespace Renci.SshClient.Tests.Security
{
[TestClass]
public class TestPrivateKeyFile
{
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void Test_PrivateKeyFile_EmptyFileName()
{
string fileName = string.Empty;
var keyFile = new PrivateKeyFile(fileName);
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void Test_PrivateKeyFile_StreamIsNull()
{
Stream stream = null;
var keyFile = new PrivateKeyFile(stream);
}
}
}
@@ -109,20 +109,10 @@ namespace Renci.SshClient.Tests.SshClientTests
//},
(counter) =>
{
var start = DateTime.Now;
try
{
var cmd = client.CreateCommand(string.Format("wget -O- http://localhost:{0}", boundport));
var result = cmd.Execute();
var end = DateTime.Now;
Debug.WriteLine(string.Format("Length: {0}", result.Length));
}
catch (Exception exp)
{
throw;
}
var cmd = client.CreateCommand(string.Format("wget -O- http://localhost:{0}", boundport));
var result = cmd.Execute();
var end = DateTime.Now;
Debug.WriteLine(string.Format("Length: {0}", result.Length));
}
);
}
@@ -321,6 +321,48 @@ namespace Renci.SshClient.Tests.SshClientTests
}
}
[TestMethod]
public void Test_Get_Result_Without_Execution()
{
using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
{
client.Connect();
var cmd = client.CreateCommand("ls -l");
Assert.IsTrue(string.IsNullOrEmpty(cmd.Result));
client.Disconnect();
}
}
[TestMethod]
public void Test_Get_Error_Without_Execution()
{
using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
{
client.Connect();
var cmd = client.CreateCommand("ls -l");
Assert.IsTrue(string.IsNullOrEmpty(cmd.Error));
client.Disconnect();
}
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Test_EndExecute_Before_BeginExecute()
{
using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
{
client.Connect();
var cmd = client.CreateCommand("ls -l");
cmd.EndExecute(null);
client.Disconnect();
}
}
private static bool ExecuteTestCommand(Renci.SshClient.SshClient s)
{
var testValue = Guid.NewGuid().ToString();
@@ -80,6 +80,9 @@ namespace Renci.SshClient
/// <param name="connectionInfo">The connection info.</param>
public BaseClient(ConnectionInfo connectionInfo)
{
if (connectionInfo == null)
throw new ArgumentNullException("connectionInfo");
this.ConnectionInfo = connectionInfo;
this.Session = new Session(connectionInfo);
}
@@ -2,6 +2,7 @@
using System.Threading;
using Renci.SshClient.Common;
using Renci.SshClient.Messages.Connection;
using System.Globalization;
namespace Renci.SshClient.Channels
{
@@ -51,7 +52,7 @@ namespace Renci.SshClient.Channels
if (!this.IsOpen)
{
throw new SshException(string.Format("Failed to open a channel after {0} attempts.", this._failedOpenAttempts));
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Failed to open a channel after {0} attempts.", this._failedOpenAttempts));
}
}
}
@@ -79,7 +80,7 @@ namespace Renci.SshClient.Channels
{
this._failedOpenAttempts++;
Debug.WriteLine(string.Format("Local channel: {0} attempts: {1}.", this.LocalChannelNumber, this._failedOpenAttempts));
Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Local channel: {0} attempts: {1}.", this.LocalChannelNumber, this._failedOpenAttempts));
this.SessionSemaphore.Release();
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System;
using System.Globalization;
namespace Renci.SshClient
{
@@ -83,7 +84,7 @@ namespace Renci.SshClient
{
foreach (var b in bytes)
{
Debug.Write(string.Format("0x{0:x2}, ", b));
Debug.Write(string.Format(CultureInfo.CurrentCulture, "0x{0:x2}, ", b));
}
Debug.WriteLine(string.Empty);
}
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Globalization;
/// <summary>
/// PipeStream is a thread-safe read/write data stream for use between two threads in a
@@ -101,16 +102,6 @@
#region Stream overide methods
///<summary>
///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///</summary>
///<filterpriority>2</filterpriority>
public new void Dispose()
{
// clear the internal buffer
_buffer.Clear();
}
///<summary>
///When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device.
///</summary>
@@ -177,7 +168,7 @@
if (offset < 0 || count < 0)
throw new ArgumentOutOfRangeException("offset", "offset or count is negative.");
if (BlockLastReadBuffer && count >= _maxBufferLength)
throw new ArgumentException(String.Format("count({0}) > mMaxBufferLength({1})", count, _maxBufferLength));
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "count({0}) > mMaxBufferLength({1})", count, _maxBufferLength));
if (count == 0)
return 0;
@@ -4,6 +4,7 @@ using System.Linq;
using System.Numerics;
using System.Text;
using Renci.SshClient;
using System.Globalization;
namespace Renci.SshClient.Common
{
@@ -201,7 +202,7 @@ namespace Renci.SshClient.Common
if (length > int.MaxValue)
{
throw new NotSupportedException(string.Format("String that longer that {0} are not supported.", int.MaxValue));
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "String that longer that {0} are not supported.", int.MaxValue));
}
return Encoding.ASCII.GetString(this.ReadBytes(length));
@@ -217,7 +218,7 @@ namespace Renci.SshClient.Common
if (length > int.MaxValue)
{
throw new NotSupportedException(string.Format("String that longer that {0} are not supported.", int.MaxValue));
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "String that longer that {0} are not supported.", int.MaxValue));
}
return this.ReadBytes(length);
@@ -7,6 +7,7 @@ using Renci.SshClient.Messages;
using Renci.SshClient.Messages.Authentication;
using Renci.SshClient.Common;
using System.Threading;
using System.Net;
namespace Renci.SshClient
{
/// <summary>
@@ -201,6 +202,15 @@ namespace Renci.SshClient
protected ConnectionInfo(string host, int port, string username)
: this()
{
if (string.IsNullOrEmpty(host))
throw new ArgumentNullException("host");
if (port < IPEndPoint.MinPort)
throw new ArgumentOutOfRangeException("port");
if (port > IPEndPoint.MaxPort)
throw new ArgumentOutOfRangeException("port");
this.Host = host;
this.Port = port;
this.Username = username;
@@ -213,6 +223,9 @@ namespace Renci.SshClient
/// <returns>true if authenticated; otherwise false.</returns>
public bool Authenticate(Session session)
{
if (session == null)
throw new ArgumentNullException("session");
this.Session = session;
this.Session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE");
@@ -260,7 +273,7 @@ namespace Renci.SshClient
{
this.Session.WaitHandle(eventWaitHandle);
}
/// <summary>
/// Handles the UserAuthenticationFailureReceived event of the session.
/// </summary>
@@ -5,6 +5,7 @@ using Renci.SshClient.Channels;
using Renci.SshClient.Messages.Connection;
using Renci.SshClient.Common;
using System.Diagnostics;
using System.Globalization;
namespace Renci.SshClient
{
@@ -46,7 +47,7 @@ namespace Renci.SshClient
// If request failed don't handle channel opening for this request
this.Session.ChannelOpenReceived -= Session_ChannelOpening;
throw new SshException(string.Format("Port forwarding for '{0}' port '{1}' failed to start.", this.Host, this.Port));
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Port forwarding for '{0}' port '{1}' failed to start.", this.Host, this.Port));
}
else
{
@@ -113,7 +113,7 @@ namespace Renci.SshClient
{
var eventArgs = new AuthenticationPromptEventArgs(this.Username, informationRequestMessage.Instruction, informationRequestMessage.Language, informationRequestMessage.Prompts);
var eventTask = Task.Factory.StartNew(() =>
Task.Factory.StartNew(() =>
{
try
{
@@ -1,4 +1,5 @@
namespace Renci.SshClient.Messages.Connection
using System.Globalization;
namespace Renci.SshClient.Messages.Connection
{
/// <summary>
/// Base class for all channel specific SSH messages.
@@ -37,7 +38,7 @@
/// </returns>
public override string ToString()
{
return string.Format("{0} : #{1}", base.ToString(), this.LocalChannelNumber);
return string.Format(CultureInfo.CurrentCulture, "{0} : #{1}", base.ToString(), this.LocalChannelNumber);
}
}
}
@@ -1,4 +1,5 @@
using System;
using System.Globalization;
namespace Renci.SshClient.Messages.Connection
{
@@ -95,7 +96,7 @@ namespace Renci.SshClient.Messages.Connection
}
else
{
throw new NotSupportedException(string.Format("Channel type '{0}' is not supported.", channelName));
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Channel type '{0}' is not supported.", channelName));
}
this.Info.Load(bytes);
@@ -1,4 +1,5 @@
using System;
using System.Globalization;
namespace Renci.SshClient.Messages.Connection
{
@@ -116,7 +117,7 @@ namespace Renci.SshClient.Messages.Connection
}
else
{
throw new NotSupportedException(string.Format("Request '{0}' is not supported.", requestName));
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Request '{0}' is not supported.", requestName));
}
this.Info.Load(bytes);
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using Renci.SshClient.Common;
using System.Globalization;
namespace Renci.SshClient.Messages
{
@@ -17,8 +18,6 @@ namespace Renci.SshClient.Messages
/// <returns>SSH message object</returns>
internal static T Load<T>(byte[] data) where T : Message, new()
{
var messageType = data.FirstOrDefault();
T message = new T();
message.LoadBytes(data);
@@ -53,7 +52,7 @@ namespace Renci.SshClient.Messages
var messageAttribute = this.GetType().GetCustomAttributes(typeof(MessageAttribute), true).SingleOrDefault() as MessageAttribute;
if (messageAttribute == null)
throw new SshException(string.Format("Type '{0}' is not a valid message type.", this.GetType().AssemblyQualifiedName));
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Type '{0}' is not a valid message type.", this.GetType().AssemblyQualifiedName));
var data = new List<byte>(base.GetBytes());
@@ -73,7 +72,7 @@ namespace Renci.SshClient.Messages
var messageAttribute = this.GetType().GetCustomAttributes(typeof(MessageAttribute), true).SingleOrDefault() as MessageAttribute;
if (messageAttribute == null)
return string.Format("'{0}' without Message attribute.", this.GetType().FullName);
return string.Format(CultureInfo.CurrentCulture, "'{0}' without Message attribute.", this.GetType().FullName);
return messageAttribute.Name;
}
@@ -15,8 +15,9 @@ namespace Renci.SshClient
{
private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
private Exception _exception;
/// <summary>
/// Gets list of allowed authentications.
/// </summary>
public IEnumerable<string> AllowedAuthentications { get; private set; }
/// <summary>
@@ -34,7 +35,6 @@ namespace Renci.SshClient
/// </summary>
/// <param name="host">Connection host.</param>
/// <param name="username">Connection username.</param>
/// <param name="password">Connection password.</param>
public NoneConnectionInfo(string host, string username)
: this(host, 22, username)
{
@@ -47,7 +47,6 @@ namespace Renci.SshClient
/// <param name="host">Connection host.</param>
/// <param name="port">Connection port.</param>
/// <param name="username">Connection username.</param>
/// <param name="password">Connection password.</param>
public NoneConnectionInfo(string host, int port, string username)
: base(host, port, username)
{
@@ -61,11 +60,6 @@ namespace Renci.SshClient
this.SendMessage(new RequestMessageNone(ServiceNames.Connection, this.Username));
this.WaitHandle(this._authenticationCompleted);
if (this._exception != null)
{
throw this._exception;
}
}
/// <summary>
@@ -117,7 +117,7 @@ namespace Renci.SshClient
{
this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
var eventTask = Task.Factory.StartNew(() =>
Task.Factory.StartNew(() =>
{
try
{
@@ -8,6 +8,7 @@ using Renci.SshClient.Security;
using System.Security.Cryptography;
using System.Security;
using Renci.SshClient.Common;
using System.Globalization;
namespace Renci.SshClient
{
@@ -70,6 +71,9 @@ namespace Renci.SshClient
/// <param name="fileName">Name of the file.</param>
public PrivateKeyFile(string fileName)
{
if (string.IsNullOrEmpty(fileName))
throw new ArgumentNullException("fileName");
using (var keyFile = File.Open(fileName, FileMode.Open))
{
this.Open(keyFile, null);
@@ -83,6 +87,9 @@ namespace Renci.SshClient
/// <param name="passPhrase">The pass phrase.</param>
public PrivateKeyFile(string fileName, string passPhrase)
{
if (string.IsNullOrEmpty(fileName))
throw new ArgumentNullException("fileName");
using (var keyFile = File.Open(fileName, FileMode.Open))
{
this.Open(keyFile, passPhrase);
@@ -106,6 +113,9 @@ namespace Renci.SshClient
/// <param name="passPhrase">The pass phrase.</param>
private void Open(Stream privateKey, string passPhrase)
{
if (privateKey == null)
throw new ArgumentNullException("privateKey");
Match privateKeyMatch = null;
using (StreamReader sr = new StreamReader(privateKey))
@@ -174,7 +184,7 @@ namespace Renci.SshClient
}
break;
default:
throw new SshException(string.Format("Unknown private key cipher \"{0}\".", cipherName));
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Unknown private key cipher \"{0}\".", cipherName));
}
}
else
@@ -191,7 +201,7 @@ namespace Renci.SshClient
this._key = new CryptoPrivateKeyDss();
break;
default:
throw new NotSupportedException(string.Format("Key '{0}' is not supported.", keyName));
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Key '{0}' is not supported.", keyName));
}
this._key.Load(decryptedData);
@@ -1,16 +1,17 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SshClient")]
[assembly: AssemblyTitle("SshNet")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("SshClient")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyCompany("Renci")]
[assembly: AssemblyProduct("SSH.NET")]
[assembly: AssemblyCopyright("Copyright © Renci 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -34,4 +35,5 @@ using System.Runtime.CompilerServices;
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.1")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: CLSCompliant(true)]
[assembly: InternalsVisibleTo("Renci.SshClient.Tests")]
@@ -57,7 +57,6 @@ namespace Renci.SshClient.Security
/// <summary>
/// Initializes a new instance of the <see cref="CipherAESCBC"/> class.
/// </summary>
/// <param name="keyBitsSize">Size of the key bits.</param>
public CipherCast()
{
this._algorithm = new Cryptography.Cast(128);
@@ -25,7 +25,7 @@ namespace Renci.SshClient.Security.Cryptography
/// <param name="keySize">Size of the key.</param>
public Blowfish(int keySize)
{
this.KeySizeValue = 16 * 8;
this.KeySizeValue = keySize;
this.BlockSizeValue = 8 * 8;
this.FeedbackSizeValue = BlockSizeValue;
this.LegalBlockSizesValue = new KeySizes[] { new KeySizes(64, 64, 0 ) };
@@ -709,7 +709,7 @@ namespace Renci.SshClient.Security.Cryptography
for (int i = 0; i < key.Length; t++)
{
W[t >> 2, t & 3] = CipherBase.LE_To_UInt32(key, i);
W[t >> 2, t & 3] = CipherBase.LittleEndianToUInt32(key, i);
i += 4;
}
@@ -754,18 +754,18 @@ namespace Renci.SshClient.Security.Cryptography
private void UnPackBlock(byte[] bytes, int off)
{
C0 = CipherBase.LE_To_UInt32(bytes, off);
C1 = CipherBase.LE_To_UInt32(bytes, off + 4);
C2 = CipherBase.LE_To_UInt32(bytes, off + 8);
C3 = CipherBase.LE_To_UInt32(bytes, off + 12);
C0 = CipherBase.LittleEndianToUInt32(bytes, off);
C1 = CipherBase.LittleEndianToUInt32(bytes, off + 4);
C2 = CipherBase.LittleEndianToUInt32(bytes, off + 8);
C3 = CipherBase.LittleEndianToUInt32(bytes, off + 12);
}
private void PackBlock(byte[] bytes, int off)
{
CipherBase.UInt32_To_LE(C0, bytes, off);
CipherBase.UInt32_To_LE(C1, bytes, off + 4);
CipherBase.UInt32_To_LE(C2, bytes, off + 8);
CipherBase.UInt32_To_LE(C3, bytes, off + 12);
CipherBase.UInt32ToLittleEndian(C0, bytes, off);
CipherBase.UInt32ToLittleEndian(C1, bytes, off + 4);
CipherBase.UInt32ToLittleEndian(C2, bytes, off + 8);
CipherBase.UInt32ToLittleEndian(C3, bytes, off + 12);
}
private void EncryptBlock(uint[,] KW)
@@ -317,8 +317,8 @@ namespace Renci.SshClient.Security.Cryptography
if (inputCount != this.BlockSize)
throw new ArgumentException("inputCount");
uint xl = CipherBase.BE_To_UInt32(inputBuffer, inputOffset);
uint xr = CipherBase.BE_To_UInt32(inputBuffer, inputOffset + 4);
uint xl = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
uint xr = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
xl ^= P[0];
@@ -330,8 +330,8 @@ namespace Renci.SshClient.Security.Cryptography
xr ^= P[ROUNDS + 1];
CipherBase.UInt32_To_BE(xr, outputBuffer, outputOffset);
CipherBase.UInt32_To_BE(xl, outputBuffer, outputOffset + 4);
CipherBase.UInt32ToBigEndian(xr, outputBuffer, outputOffset);
CipherBase.UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
return this.BlockSize;
}
@@ -341,8 +341,8 @@ namespace Renci.SshClient.Security.Cryptography
if (inputCount != this.BlockSize)
throw new ArgumentException("inputCount");
uint xl = CipherBase.BE_To_UInt32(inputBuffer, inputOffset);
uint xr = CipherBase.BE_To_UInt32(inputBuffer, inputOffset + 4);
uint xl = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
uint xr = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
xl ^= P[ROUNDS + 1];
@@ -354,8 +354,8 @@ namespace Renci.SshClient.Security.Cryptography
xr ^= P[0];
CipherBase.UInt32_To_BE(xr, outputBuffer, outputOffset);
CipherBase.UInt32_To_BE(xl, outputBuffer, outputOffset + 4);
CipherBase.UInt32ToBigEndian(xr, outputBuffer, outputOffset);
CipherBase.UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
return this.BlockSize;
}
@@ -33,15 +33,15 @@ namespace Renci.SshClient.Security.Cryptography
// batch the units up into a 32 bit chunk and go for it
// the array is in bytes, the increment is 8x8 bits = 64
uint L0 = CipherBase.BE_To_UInt32(inputBuffer, inputOffset);
uint R0 = CipherBase.BE_To_UInt32(inputBuffer, inputOffset + 4);
uint L0 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
uint R0 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
uint[] result = new uint[2];
CAST_Encipher(L0, R0, result);
// now stuff them into the destination block
CipherBase.UInt32_To_BE(result[0], outputBuffer, outputOffset);
CipherBase.UInt32_To_BE(result[1], outputBuffer, outputOffset + 4);
CipherBase.UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
CipherBase.UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
return this.BlockSize;
}
@@ -51,15 +51,15 @@ namespace Renci.SshClient.Security.Cryptography
// process the input block
// batch the units up into a 32 bit chunk and go for it
// the array is in bytes, the increment is 8x8 bits = 64
uint L16 = CipherBase.BE_To_UInt32(inputBuffer, inputOffset);
uint R16 = CipherBase.BE_To_UInt32(inputBuffer, inputOffset + 4);
uint L16 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset);
uint R16 = CipherBase.BigEndianToUInt32(inputBuffer, inputOffset + 4);
uint[] result = new uint[2];
CAST_Decipher(L16, R16, result);
// now stuff them into the destination block
CipherBase.UInt32_To_BE(result[0], outputBuffer, outputOffset);
CipherBase.UInt32_To_BE(result[1], outputBuffer, outputOffset + 4);
CipherBase.UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
CipherBase.UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
return this.BlockSize;
}
@@ -67,124 +67,212 @@ namespace Renci.SshClient.Security.Cryptography
#region Packing functions
protected static void UInt32_To_BE(uint n, byte[] bs)
/// <summary>
/// Populates buffer with big endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
protected static void UInt32ToBigEndian(uint number, byte[] buffer)
{
bs[0] = (byte)(n >> 24);
bs[1] = (byte)(n >> 16);
bs[2] = (byte)(n >> 8);
bs[3] = (byte)(n);
buffer[0] = (byte)(number >> 24);
buffer[1] = (byte)(number >> 16);
buffer[2] = (byte)(number >> 8);
buffer[3] = (byte)(number);
}
protected static void UInt32_To_BE(uint n, byte[] bs, int off)
/// <summary>
/// Populates buffer with big endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
protected static void UInt32ToBigEndian(uint number, byte[] buffer, int offset)
{
bs[off] = (byte)(n >> 24);
bs[++off] = (byte)(n >> 16);
bs[++off] = (byte)(n >> 8);
bs[++off] = (byte)(n);
buffer[offset] = (byte)(number >> 24);
buffer[++offset] = (byte)(number >> 16);
buffer[++offset] = (byte)(number >> 8);
buffer[++offset] = (byte)(number);
}
protected static uint BE_To_UInt32(byte[] bs)
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns></returns>
protected static uint BigEndianToUInt32(byte[] buffer)
{
uint n = (uint)bs[0] << 24;
n |= (uint)bs[1] << 16;
n |= (uint)bs[2] << 8;
n |= (uint)bs[3];
uint n = (uint)buffer[0] << 24;
n |= (uint)buffer[1] << 16;
n |= (uint)buffer[2] << 8;
n |= (uint)buffer[3];
return n;
}
protected static uint BE_To_UInt32(byte[] bs, int off)
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
/// <returns></returns>
protected static uint BigEndianToUInt32(byte[] buffer, int offset)
{
uint n = (uint)bs[off] << 24;
n |= (uint)bs[++off] << 16;
n |= (uint)bs[++off] << 8;
n |= (uint)bs[++off];
uint n = (uint)buffer[offset] << 24;
n |= (uint)buffer[++offset] << 16;
n |= (uint)buffer[++offset] << 8;
n |= (uint)buffer[++offset];
return n;
}
protected static ulong BE_To_UInt64(byte[] bs)
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns></returns>
protected static ulong BigEndianToUInt64(byte[] buffer)
{
uint hi = BE_To_UInt32(bs);
uint lo = BE_To_UInt32(bs, 4);
uint hi = BigEndianToUInt32(buffer);
uint lo = BigEndianToUInt32(buffer, 4);
return ((ulong)hi << 32) | (ulong)lo;
}
protected static ulong BE_To_UInt64(byte[] bs, int off)
/// <summary>
/// Converts big endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
/// <returns></returns>
protected static ulong BigEndianToUInt64(byte[] buffer, int offset)
{
uint hi = BE_To_UInt32(bs, off);
uint lo = BE_To_UInt32(bs, off + 4);
uint hi = BigEndianToUInt32(buffer, offset);
uint lo = BigEndianToUInt32(buffer, offset + 4);
return ((ulong)hi << 32) | (ulong)lo;
}
protected static void UInt64_To_BE(ulong n, byte[] bs)
/// <summary>
/// Populates buffer with big endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
protected static void UInt64ToBigEndian(ulong number, byte[] buffer)
{
UInt32_To_BE((uint)(n >> 32), bs);
UInt32_To_BE((uint)(n), bs, 4);
UInt32ToBigEndian((uint)(number >> 32), buffer);
UInt32ToBigEndian((uint)(number), buffer, 4);
}
protected static void UInt64_To_BE(ulong n, byte[] bs, int off)
/// <summary>
/// Populates buffer with big endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
protected static void UInt64ToBigEndian(ulong number, byte[] buffer, int offset)
{
UInt32_To_BE((uint)(n >> 32), bs, off);
UInt32_To_BE((uint)(n), bs, off + 4);
UInt32ToBigEndian((uint)(number >> 32), buffer, offset);
UInt32ToBigEndian((uint)(number), buffer, offset + 4);
}
protected static void UInt32_To_LE(uint n, byte[] bs)
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
protected static void UInt32ToLittleEndian(uint number, byte[] buffer)
{
bs[0] = (byte)(n);
bs[1] = (byte)(n >> 8);
bs[2] = (byte)(n >> 16);
bs[3] = (byte)(n >> 24);
buffer[0] = (byte)(number);
buffer[1] = (byte)(number >> 8);
buffer[2] = (byte)(number >> 16);
buffer[3] = (byte)(number >> 24);
}
protected static void UInt32_To_LE(uint n, byte[] bs, int off)
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
protected static void UInt32ToLittleEndian(uint number, byte[] buffer, int offset)
{
bs[off] = (byte)(n);
bs[++off] = (byte)(n >> 8);
bs[++off] = (byte)(n >> 16);
bs[++off] = (byte)(n >> 24);
buffer[offset] = (byte)(number);
buffer[++offset] = (byte)(number >> 8);
buffer[++offset] = (byte)(number >> 16);
buffer[++offset] = (byte)(number >> 24);
}
protected static uint LE_To_UInt32(byte[] bs)
/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns></returns>
protected static uint LittleEndianToUInt32(byte[] buffer)
{
uint n = (uint)bs[0];
n |= (uint)bs[1] << 8;
n |= (uint)bs[2] << 16;
n |= (uint)bs[3] << 24;
uint n = (uint)buffer[0];
n |= (uint)buffer[1] << 8;
n |= (uint)buffer[2] << 16;
n |= (uint)buffer[3] << 24;
return n;
}
protected static uint LE_To_UInt32(byte[] bs, int off)
/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
/// <returns></returns>
protected static uint LittleEndianToUInt32(byte[] buffer, int offset)
{
uint n = (uint)bs[off];
n |= (uint)bs[++off] << 8;
n |= (uint)bs[++off] << 16;
n |= (uint)bs[++off] << 24;
uint n = (uint)buffer[offset];
n |= (uint)buffer[++offset] << 8;
n |= (uint)buffer[++offset] << 16;
n |= (uint)buffer[++offset] << 24;
return n;
}
protected static ulong LE_To_UInt64(byte[] bs)
/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <returns></returns>
protected static ulong LittleEndianToUInt64(byte[] buffer)
{
uint lo = LE_To_UInt32(bs);
uint hi = LE_To_UInt32(bs, 4);
uint lo = LittleEndianToUInt32(buffer);
uint hi = LittleEndianToUInt32(buffer, 4);
return ((ulong)hi << 32) | (ulong)lo;
}
protected static ulong LE_To_UInt64(byte[] bs, int off)
/// <summary>
/// Converts little endian bytes into number.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
/// <returns></returns>
protected static ulong LittleEndianToUInt64(byte[] buffer, int offset)
{
uint lo = LE_To_UInt32(bs, off);
uint hi = LE_To_UInt32(bs, off + 4);
uint lo = LittleEndianToUInt32(buffer, offset);
uint hi = LittleEndianToUInt32(buffer, offset + 4);
return ((ulong)hi << 32) | (ulong)lo;
}
protected static void UInt64_To_LE(ulong n, byte[] bs)
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
protected static void UInt64ToLittleEndian(ulong number, byte[] buffer)
{
UInt32_To_LE((uint)(n), bs);
UInt32_To_LE((uint)(n >> 32), bs, 4);
UInt32ToLittleEndian((uint)(number), buffer);
UInt32ToLittleEndian((uint)(number >> 32), buffer, 4);
}
protected static void UInt64_To_LE(ulong n, byte[] bs, int off)
/// <summary>
/// Populates buffer with little endian number representation.
/// </summary>
/// <param name="number">The number to convert.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The buffer offset.</param>
protected static void UInt64ToLittleEndian(ulong number, byte[] buffer, int offset)
{
UInt32_To_LE((uint)(n), bs, off);
UInt32_To_LE((uint)(n >> 32), bs, off + 4);
UInt32ToLittleEndian((uint)(number), buffer, offset);
UInt32ToLittleEndian((uint)(number >> 32), buffer, offset + 4);
}
#endregion
@@ -6,487 +6,501 @@ using System.Security.Cryptography;
namespace Renci.SshClient.Security.Cryptography
{
/// <summary>
/// Represents the class for the DES algorithm.
/// </summary>
public class DesCipher : CipherBase
{
private int[] _encryptionKey;
/// <summary>
/// Gets the encryption key.
/// </summary>
protected int[] EncryptionKey
{
get
{
if (this._encryptionKey == null)
{
this._encryptionKey = DesCipher.GenerateWorkingKey(true, this.Key);
}
return this._encryptionKey;
}
}
private int[] _decryptionKey;
/// <summary>
/// Gets the decryption key.
/// </summary>
protected int[] DecryptionKey
{
get
{
if (this._decryptionKey == null)
{
this._decryptionKey = DesCipher.GenerateWorkingKey(true, this.Key);
}
return this._decryptionKey;
}
}
#region Static tables
private static readonly short[] bytebit =
{
128, 64, 32, 16, 8, 4, 2, 1
};
private static readonly int[] bigbyte =
{
0x800000, 0x400000, 0x200000, 0x100000,
0x80000, 0x40000, 0x20000, 0x10000,
0x8000, 0x4000, 0x2000, 0x1000,
0x800, 0x400, 0x200, 0x100,
0x80, 0x40, 0x20, 0x10,
0x8, 0x4, 0x2, 0x1
};
/*
* Use the key schedule specified in the Standard (ANSI X3.92-1981).
*/
private static readonly byte[] pc1 =
{
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
};
private static readonly byte[] totrot =
{
1, 2, 4, 6, 8, 10, 12, 14,
15, 17, 19, 21, 23, 25, 27, 28
};
private static readonly byte[] pc2 =
{
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
};
private static readonly uint[] SP1 =
/// <summary>
/// Represents the class for the DES algorithm.
/// </summary>
public class DesCipher : CipherBase
{
private int[] _encryptionKey;
/// <summary>
/// Gets the encryption key.
/// </summary>
protected int[] EncryptionKey
{
0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400,
0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000,
0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004,
0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004
};
get
{
if (this._encryptionKey == null)
{
this._encryptionKey = DesCipher.GenerateWorkingKey(true, this.Key);
}
private static readonly uint[] SP2 =
return this._encryptionKey;
}
}
private int[] _decryptionKey;
/// <summary>
/// Gets the decryption key.
/// </summary>
protected int[] DecryptionKey
{
0x80108020, 0x80008000, 0x00008000, 0x00108020,
0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000,
0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000,
0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020,
0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000
};
get
{
if (this._decryptionKey == null)
{
this._decryptionKey = DesCipher.GenerateWorkingKey(true, this.Key);
}
private static readonly uint[] SP3 =
return this._decryptionKey;
}
}
#region Static tables
private static readonly short[] bytebit =
{
0x00000208, 0x08020200, 0x00000000, 0x08020008,
0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200,
0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208,
0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200,
0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200
};
128, 64, 32, 16, 8, 4, 2, 1
};
private static readonly uint[] SP4 =
private static readonly int[] bigbyte =
{
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001,
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080
};
0x800000, 0x400000, 0x200000, 0x100000,
0x80000, 0x40000, 0x20000, 0x10000,
0x8000, 0x4000, 0x2000, 0x1000,
0x800, 0x400, 0x200, 0x100,
0x80, 0x40, 0x20, 0x10,
0x8, 0x4, 0x2, 0x1
};
private static readonly uint[] SP5 =
/*
* Use the key schedule specified in the Standard (ANSI X3.92-1981).
*/
private static readonly byte[] pc1 =
{
0x00000100, 0x02080100, 0x02080000, 0x42000100,
0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000,
0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000,
0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100,
0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100
};
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
};
private static readonly uint[] SP6 =
private static readonly byte[] totrot =
{
0x20000010, 0x20400000, 0x00004000, 0x20404010,
0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000,
0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000,
0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010,
0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010
};
1, 2, 4, 6, 8, 10, 12, 14,
15, 17, 19, 21, 23, 25, 27, 28
};
private static readonly uint[] SP7 =
private static readonly byte[] pc2 =
{
0x00200000, 0x04200002, 0x04000802, 0x00000000,
0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800,
0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802,
0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000,
0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002
};
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
};
private static readonly uint[] SP8 =
private static readonly uint[] SP1 =
{
0x10001040, 0x00001000, 0x00040000, 0x10041040,
0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040,
0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000,
0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000,
0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040,
0x00001040, 0x00040040, 0x10000000, 0x10041000
};
0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400,
0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000,
0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004,
0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004
};
#endregion
private static readonly uint[] SP2 =
{
0x80108020, 0x80008000, 0x00008000, 0x00108020,
0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000,
0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000,
0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020,
0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000
};
/// <summary>
/// Gets the size of the block.
/// </summary>
/// <value>
/// The size of the block.
/// </value>
public override int BlockSize
{
get { return 8; }
}
private static readonly uint[] SP3 =
{
0x00000208, 0x08020200, 0x00000000, 0x08020008,
0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200,
0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208,
0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200,
0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200
};
/// <summary>
/// Initializes a new instance of the <see cref="DesCipher"/> class.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="iv">The iv.</param>
public DesCipher(byte[] key, byte[] iv)
: base(key, iv)
{
}
private static readonly uint[] SP4 =
{
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001,
0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080
};
/// <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)
{
if ((inputOffset + this.BlockSize) > inputBuffer.Length)
throw new IndexOutOfRangeException("input buffer too short");
private static readonly uint[] SP5 =
{
0x00000100, 0x02080100, 0x02080000, 0x42000100,
0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000,
0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000,
0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100,
0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100
};
if ((outputOffset + this.BlockSize) > outputBuffer.Length)
throw new IndexOutOfRangeException("output buffer too short");
private static readonly uint[] SP6 =
{
0x20000010, 0x20400000, 0x00004000, 0x20404010,
0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000,
0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000,
0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010,
0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010
};
DesCipher.DesFunc(this.EncryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
private static readonly uint[] SP7 =
{
0x00200000, 0x04200002, 0x04000802, 0x00000000,
0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800,
0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802,
0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000,
0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002
};
return this.BlockSize;
}
private static readonly uint[] SP8 =
{
0x10001040, 0x00001000, 0x00040000, 0x10041040,
0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040,
0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000,
0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000,
0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040,
0x00001040, 0x00040040, 0x10000000, 0x10041000
};
/// <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)
{
if ((inputOffset + this.BlockSize) > inputBuffer.Length)
throw new IndexOutOfRangeException("input buffer too short");
#endregion
if ((outputOffset + this.BlockSize) > outputBuffer.Length)
throw new IndexOutOfRangeException("output buffer too short");
/// <summary>
/// Gets the size of the block.
/// </summary>
/// <value>
/// The size of the block.
/// </value>
public override int BlockSize
{
get { return 8; }
}
DesCipher.DesFunc(this.DecryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
/// <summary>
/// Initializes a new instance of the <see cref="DesCipher"/> class.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="iv">The iv.</param>
public DesCipher(byte[] key, byte[] iv)
: base(key, iv)
{
}
return this.BlockSize;
}
/// <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)
{
if ((inputOffset + this.BlockSize) > inputBuffer.Length)
throw new IndexOutOfRangeException("input buffer too short");
protected static int[] GenerateWorkingKey(bool encrypting, byte[] key)
{
int[] newKey = new int[32];
bool[] pc1m = new bool[56];
bool[] pcr = new bool[56];
if ((outputOffset + this.BlockSize) > outputBuffer.Length)
throw new IndexOutOfRangeException("output buffer too short");
for (int j = 0; j < 56; j++)
{
int l = pc1[j];
DesCipher.DesFunc(this.EncryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
pc1m[j] = ((key[(uint)l >> 3] & bytebit[l & 07]) != 0);
}
return this.BlockSize;
}
for (int i = 0; i < 16; i++)
{
int l, m, n;
/// <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)
{
if ((inputOffset + this.BlockSize) > inputBuffer.Length)
throw new IndexOutOfRangeException("input buffer too short");
if (encrypting)
{
m = i << 1;
}
else
{
m = (15 - i) << 1;
}
if ((outputOffset + this.BlockSize) > outputBuffer.Length)
throw new IndexOutOfRangeException("output buffer too short");
n = m + 1;
newKey[m] = newKey[n] = 0;
DesCipher.DesFunc(this.DecryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
for (int j = 0; j < 28; j++)
{
l = j + totrot[i];
if (l < 28)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
return this.BlockSize;
}
for (int j = 28; j < 56; j++)
{
l = j + totrot[i];
if (l < 56)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
/// <summary>
/// Generates the working key.
/// </summary>
/// <param name="encrypting">if set to <c>true</c> [encrypting].</param>
/// <param name="key">The key.</param>
/// <returns></returns>
protected static int[] GenerateWorkingKey(bool encrypting, byte[] key)
{
int[] newKey = new int[32];
bool[] pc1m = new bool[56];
bool[] pcr = new bool[56];
for (int j = 0; j < 24; j++)
{
if (pcr[pc2[j]])
{
newKey[m] |= bigbyte[j];
}
for (int j = 0; j < 56; j++)
{
int l = pc1[j];
if (pcr[pc2[j + 24]])
{
newKey[n] |= bigbyte[j];
}
}
}
pc1m[j] = ((key[(uint)l >> 3] & bytebit[l & 07]) != 0);
}
//
// store the processed key
//
for (int i = 0; i != 32; i += 2)
{
int i1, i2;
for (int i = 0; i < 16; i++)
{
int l, m, n;
i1 = newKey[i];
i2 = newKey[i + 1];
if (encrypting)
{
m = i << 1;
}
else
{
m = (15 - i) << 1;
}
newKey[i] = (int)((uint)((i1 & 0x00fc0000) << 6) |
(uint)((i1 & 0x00000fc0) << 10) |
((uint)(i2 & 0x00fc0000) >> 10) |
((uint)(i2 & 0x00000fc0) >> 6));
n = m + 1;
newKey[m] = newKey[n] = 0;
newKey[i + 1] = (int)((uint)((i1 & 0x0003f000) << 12) |
(uint)((i1 & 0x0000003f) << 16) |
((uint)(i2 & 0x0003f000) >> 4) |
(uint)(i2 & 0x0000003f));
}
for (int j = 0; j < 28; j++)
{
l = j + totrot[i];
if (l < 28)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
return newKey;
}
for (int j = 28; j < 56; j++)
{
l = j + totrot[i];
if (l < 56)
{
pcr[j] = pc1m[l];
}
else
{
pcr[j] = pc1m[l - 28];
}
}
protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
{
uint left = CipherBase.BE_To_UInt32(input, inOff);
uint right = CipherBase.BE_To_UInt32(input, inOff + 4);
uint work;
for (int j = 0; j < 24; j++)
{
if (pcr[pc2[j]])
{
newKey[m] |= bigbyte[j];
}
work = ((left >> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
left ^= (work << 4);
work = ((left >> 16) ^ right) & 0x0000ffff;
right ^= work;
left ^= (work << 16);
work = ((right >> 2) ^ left) & 0x33333333;
left ^= work;
right ^= (work << 2);
work = ((right >> 8) ^ left) & 0x00ff00ff;
left ^= work;
right ^= (work << 8);
right = (right << 1) | (right >> 31);
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = (left << 1) | (left >> 31);
if (pcr[pc2[j + 24]])
{
newKey[n] |= bigbyte[j];
}
}
}
for (int round = 0; round < 8; round++)
{
uint fval;
//
// store the processed key
//
for (int i = 0; i != 32; i += 2)
{
int i1, i2;
work = (right << 28) | (right >> 4);
work ^= (uint)wKey[round * 4 + 0];
fval = SP7[work & 0x3f];
fval |= SP5[(work >> 8) & 0x3f];
fval |= SP3[(work >> 16) & 0x3f];
fval |= SP1[(work >> 24) & 0x3f];
work = right ^ (uint)wKey[round * 4 + 1];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >> 8) & 0x3f];
fval |= SP4[(work >> 16) & 0x3f];
fval |= SP2[(work >> 24) & 0x3f];
left ^= fval;
work = (left << 28) | (left >> 4);
work ^= (uint)wKey[round * 4 + 2];
fval = SP7[work & 0x3f];
fval |= SP5[(work >> 8) & 0x3f];
fval |= SP3[(work >> 16) & 0x3f];
fval |= SP1[(work >> 24) & 0x3f];
work = left ^ (uint)wKey[round * 4 + 3];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >> 8) & 0x3f];
fval |= SP4[(work >> 16) & 0x3f];
fval |= SP2[(work >> 24) & 0x3f];
right ^= fval;
}
i1 = newKey[i];
i2 = newKey[i + 1];
right = (right << 31) | (right >> 1);
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = (left << 31) | (left >> 1);
work = ((left >> 8) ^ right) & 0x00ff00ff;
right ^= work;
left ^= (work << 8);
work = ((left >> 2) ^ right) & 0x33333333;
right ^= work;
left ^= (work << 2);
work = ((right >> 16) ^ left) & 0x0000ffff;
left ^= work;
right ^= (work << 16);
work = ((right >> 4) ^ left) & 0x0f0f0f0f;
left ^= work;
right ^= (work << 4);
newKey[i] = (int)((uint)((i1 & 0x00fc0000) << 6) |
(uint)((i1 & 0x00000fc0) << 10) |
((uint)(i2 & 0x00fc0000) >> 10) |
((uint)(i2 & 0x00000fc0) >> 6));
CipherBase.UInt32_To_BE(right, outBytes, outOff);
CipherBase.UInt32_To_BE(left, outBytes, outOff + 4);
}
newKey[i + 1] = (int)((uint)((i1 & 0x0003f000) << 12) |
(uint)((i1 & 0x0000003f) << 16) |
((uint)(i2 & 0x0003f000) >> 4) |
(uint)(i2 & 0x0000003f));
}
return newKey;
}
/// <summary>
/// Perfoms DES function.
/// </summary>
/// <param name="wKey">The w key.</param>
/// <param name="input">The input.</param>
/// <param name="inOff">The in off.</param>
/// <param name="outBytes">The out bytes.</param>
/// <param name="outOff">The out off.</param>
protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
{
uint left = CipherBase.BigEndianToUInt32(input, inOff);
uint right = CipherBase.BigEndianToUInt32(input, inOff + 4);
uint work;
work = ((left >> 4) ^ right) & 0x0f0f0f0f;
right ^= work;
left ^= (work << 4);
work = ((left >> 16) ^ right) & 0x0000ffff;
right ^= work;
left ^= (work << 16);
work = ((right >> 2) ^ left) & 0x33333333;
left ^= work;
right ^= (work << 2);
work = ((right >> 8) ^ left) & 0x00ff00ff;
left ^= work;
right ^= (work << 8);
right = (right << 1) | (right >> 31);
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = (left << 1) | (left >> 31);
for (int round = 0; round < 8; round++)
{
uint fval;
work = (right << 28) | (right >> 4);
work ^= (uint)wKey[round * 4 + 0];
fval = SP7[work & 0x3f];
fval |= SP5[(work >> 8) & 0x3f];
fval |= SP3[(work >> 16) & 0x3f];
fval |= SP1[(work >> 24) & 0x3f];
work = right ^ (uint)wKey[round * 4 + 1];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >> 8) & 0x3f];
fval |= SP4[(work >> 16) & 0x3f];
fval |= SP2[(work >> 24) & 0x3f];
left ^= fval;
work = (left << 28) | (left >> 4);
work ^= (uint)wKey[round * 4 + 2];
fval = SP7[work & 0x3f];
fval |= SP5[(work >> 8) & 0x3f];
fval |= SP3[(work >> 16) & 0x3f];
fval |= SP1[(work >> 24) & 0x3f];
work = left ^ (uint)wKey[round * 4 + 3];
fval |= SP8[work & 0x3f];
fval |= SP6[(work >> 8) & 0x3f];
fval |= SP4[(work >> 16) & 0x3f];
fval |= SP2[(work >> 24) & 0x3f];
right ^= fval;
}
right = (right << 31) | (right >> 1);
work = (left ^ right) & 0xaaaaaaaa;
left ^= work;
right ^= work;
left = (left << 31) | (left >> 1);
work = ((left >> 8) ^ right) & 0x00ff00ff;
right ^= work;
left ^= (work << 8);
work = ((left >> 2) ^ right) & 0x33333333;
right ^= work;
left ^= (work << 2);
work = ((right >> 16) ^ left) & 0x0000ffff;
left ^= work;
right ^= (work << 16);
work = ((right >> 4) ^ left) & 0x0f0f0f0f;
left ^= work;
right ^= (work << 4);
CipherBase.UInt32ToBigEndian(right, outBytes, outOff);
CipherBase.UInt32ToBigEndian(left, outBytes, outOff + 4);
}
}
}
}
@@ -14,13 +14,27 @@ namespace Renci.SshClient.Security.Cryptography
private byte[] _pass1;
private byte[] _pass2;
/// <summary>
/// Initializes a new instance of the <see cref="TripleDesCipher"/> class.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="iv">The iv.</param>
public TripleDesCipher(byte[] key, byte[] iv)
: base(key, iv)
{
this._pass1 = new byte[this.BlockSize];
this._pass2 = new byte[this.BlockSize];
}
/// <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)
{
if ((inputOffset + this.BlockSize) > inputBuffer.Length)
@@ -29,6 +43,11 @@ namespace Renci.SshClient.Security.Cryptography
if ((outputOffset + this.BlockSize) > outputBuffer.Length)
throw new IndexOutOfRangeException("output buffer too short");
if (this._pass1 == null)
this._pass1 = new byte[this.BlockSize];
if (this._pass2 == null)
this._pass2 = new byte[this.BlockSize];
DesCipher.DesFunc(this.EncryptionKey, inputBuffer, inputOffset, this._pass1, 0);
DesCipher.DesFunc(this.EncryptionKey, this._pass1, 0, this._pass2, 0);
DesCipher.DesFunc(this.EncryptionKey, this._pass2, 0, outputBuffer, outputOffset);
@@ -36,6 +55,17 @@ namespace Renci.SshClient.Security.Cryptography
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)
{
if ((inputOffset + this.BlockSize) > inputBuffer.Length)
@@ -15,8 +15,7 @@ namespace Renci.SshClient.Security.Cryptography
/// <summary>
/// Initializes a new instance of the <see cref="Des"/> class.
/// </summary>
/// <param name="keySize">Size of the key.</param>
public Des(int keySize)
public Des()
{
this.KeySizeValue = 64;
this.BlockSizeValue = 64;
@@ -28,6 +28,10 @@ namespace Renci.SshClient.Security.Cryptography
get { return this._blockSize; }
}
/// <summary>
/// Initializes a new instance of the <see cref="CbcMode"/> class.
/// </summary>
/// <param name="cipher">The cipher.</param>
public CbcMode(CipherBase cipher)
: base(cipher)
{
@@ -36,6 +40,17 @@ namespace Renci.SshClient.Security.Cryptography
this._nextIV = new byte[this._iv.Length];
}
/// <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)
{
if (inputBuffer.Length - inputOffset < this._blockSize)
@@ -59,6 +74,17 @@ namespace Renci.SshClient.Security.Cryptography
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)
{
if (inputBuffer.Length - inputOffset < this._blockSize)
@@ -28,6 +28,10 @@ namespace Renci.SshClient.Security.Cryptography
get { return this._blockSize; }
}
/// <summary>
/// Initializes a new instance of the <see cref="CfbMode"/> class.
/// </summary>
/// <param name="cipher">The cipher.</param>
public CfbMode(CipherBase cipher)
: base(cipher)
{
+25 -22
View File
@@ -17,6 +17,7 @@ using Renci.SshClient.Messages.Authentication;
using Renci.SshClient.Messages.Connection;
using Renci.SshClient.Messages.Transport;
using Renci.SshClient.Security;
using System.Globalization;
namespace Renci.SshClient
{
@@ -385,7 +386,7 @@ namespace Renci.SshClient
internal Session(ConnectionInfo connectionInfo)
{
this.ConnectionInfo = connectionInfo;
this.ClientVersion = string.Format("SSH-2.0-Renci.SshClient.{0}", this.GetType().Assembly.GetName().Version);
this.ClientVersion = string.Format(CultureInfo.CurrentCulture, "SSH-2.0-Renci.SshClient.{0}", this.GetType().Assembly.GetName().Version);
}
/// <summary>
@@ -471,10 +472,10 @@ namespace Renci.SshClient
if (!(version.Equals("2.0") || version.Equals("1.99")))
{
throw new SshConnectionException(string.Format("Server version '{0}' is not supported.", version), DisconnectReasons.ProtocolVersionNotSupported);
throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Server version '{0}' is not supported.", version), DisconnectReasons.ProtocolVersionNotSupported);
}
this.Write(Encoding.ASCII.GetBytes(string.Format("{0}\x0D\x0A", this.ClientVersion)));
this.Write(Encoding.ASCII.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", this.ClientVersion)));
// Register Transport response messages
this.RegisterMessage("SSH_MSG_DISCONNECT");
@@ -513,24 +514,26 @@ namespace Renci.SshClient
}
// Try authenticate using none method
var noneConnectionInfo = new NoneConnectionInfo(this.ConnectionInfo.Host, this.ConnectionInfo.Port, this.ConnectionInfo.Username);
noneConnectionInfo.Authenticate(this);
this._isAuthenticated = noneConnectionInfo.IsAuthenticated;
if (!this._isAuthenticated)
using (var noneConnectionInfo = new NoneConnectionInfo(this.ConnectionInfo.Host, this.ConnectionInfo.Port, this.ConnectionInfo.Username))
{
// Ensure that authentication method is allowed
if (!noneConnectionInfo.AllowedAuthentications.Contains(this.ConnectionInfo.Name))
noneConnectionInfo.Authenticate(this);
this._isAuthenticated = noneConnectionInfo.IsAuthenticated;
if (!this._isAuthenticated)
{
throw new SshAuthenticationException("User authentication method is not supported.");
// Ensure that authentication method is allowed
if (!noneConnectionInfo.AllowedAuthentications.Contains(this.ConnectionInfo.Name))
{
throw new SshAuthenticationException("User authentication method is not supported.");
}
// In future, if more then one authentication methods are supported perform the check here.
// Authenticate using provided connection info object
this.ConnectionInfo.Authenticate(this);
this._isAuthenticated = this.ConnectionInfo.IsAuthenticated;
}
// In future, if more then one authentication methods are supported perform the check here.
// Authenticate using provided connection info object
this.ConnectionInfo.Authenticate(this);
this._isAuthenticated = this.ConnectionInfo.IsAuthenticated;
}
if (!this._isAuthenticated)
@@ -635,7 +638,7 @@ namespace Renci.SshClient
if (messageData.Length > Session.MAXIMUM_PAYLOAD_SIZE)
{
throw new InvalidOperationException(string.Format("Payload cannot be more then {0} bytes.", Session.MAXIMUM_PAYLOAD_SIZE));
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Payload cannot be more then {0} bytes.", Session.MAXIMUM_PAYLOAD_SIZE));
}
if (this._clientCompression != null)
@@ -683,7 +686,7 @@ namespace Renci.SshClient
if (packetData.Length > Session.MAXIMUM_PACKET_SIZE)
{
throw new InvalidOperationException(string.Format("Packet is too big. Maximum packet size is {0} bytes.", Session.MAXIMUM_PACKET_SIZE));
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Packet is too big. Maximum packet size is {0} bytes.", Session.MAXIMUM_PACKET_SIZE));
}
if (this._clientMac == null)
@@ -731,7 +734,7 @@ namespace Renci.SshClient
// Test packet minimum and maximum boundaries
if (packetLength < Math.Max((byte)16, blockSize) - 4 || packetLength > Session.MAXIMUM_PACKET_SIZE - 4)
throw new SshConnectionException(string.Format("Bad packet length {0}", packetLength), DisconnectReasons.ProtocolError);
throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Bad packet length {0}", packetLength), DisconnectReasons.ProtocolError);
// Read rest of the packet data
int bytesToRead = (int)(packetLength - (blockSize - 4));
@@ -1521,7 +1524,7 @@ namespace Renci.SshClient
var messageMetadata = (from m in this._messagesMetadata where m.Number == messageType && m.Enabled && m.Activated select m).SingleOrDefault();
if (messageMetadata == null)
throw new SshException(string.Format("Message type {0} is not valid.", messageType));
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageType));
var message = messageMetadata.Type.CreateInstance<Message>();
@@ -2,6 +2,7 @@
using System.Linq;
using Renci.SshClient.Common;
using Renci.SshClient.Sftp.Messages;
using System.Globalization;
namespace Renci.SshClient.Sftp
{
@@ -46,11 +47,11 @@ namespace Renci.SshClient.Sftp
base.OnName(files);
var seperator = "/";
if (this._path.EndsWith(seperator))
if (this._path[this._path.Length - 1] == '/')
seperator = string.Empty;
var sftpFiles = from f in files
select new SftpFile(this.SftpSession, string.Format("{0}{1}{2}", this._path, seperator, f.Key), f.Value);
select new SftpFile(this.SftpSession, string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", this._path, seperator, f.Key), f.Value);
this._files.AddRange(sftpFiles);
@@ -63,7 +64,7 @@ namespace Renci.SshClient.Sftp
if (statusCode == StatusCodes.NoSuchFile)
{
throw new SshFileNotFoundException(string.Format("Path '{0}' is not found.", this._path));
throw new SshFileNotFoundException(string.Format(CultureInfo.CurrentCulture, "Path '{0}' is not found.", this._path));
}
if (statusCode == StatusCodes.Eof)
@@ -25,7 +25,7 @@ namespace Renci.SshClient.Sftp.Messages
for (int i = 0; i < this.Count; i++)
{
var fileName = this.ReadString();
var fullName = this.ReadString(); // This field value has meaningless information
this.ReadString(); // This field value has meaningless information
var attributes = this.ReadAttributes();
this.Files.Add(fileName, attributes);
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Renci.SshClient.Common;
using System.Globalization;
namespace Renci.SshClient.Sftp.Messages
{
@@ -166,14 +167,12 @@ namespace Renci.SshClient.Sftp.Messages
}
else
{
throw new NotSupportedException(string.Format("Message type '{0}' is not registered.", messageType));
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Message type '{0}' is not registered.", messageType));
}
}
private static T Load<T>(byte[] data) where T : SftpMessage, new()
{
var messageType = (SftpMessageTypes)data[0];
T message = new T();
message.LoadBytes(data);
@@ -187,7 +186,7 @@ namespace Renci.SshClient.Sftp.Messages
public override string ToString()
{
return string.Format("SFTP Message : {0}", this.SftpMessageType);
return string.Format(CultureInfo.CurrentCulture, "SFTP Message : {0}", this.SftpMessageType);
}
}
}
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Security;
using Renci.SshClient.Sftp.Messages;
using System.Globalization;
namespace Renci.SshClient.Sftp
{
@@ -350,7 +351,7 @@ namespace Renci.SshClient.Sftp
/// <param name="mode">The mode.</param>
public void SetPermissions(ushort mode)
{
var modeBytes = mode.ToString().ToArray();
var modeBytes = mode.ToString(CultureInfo.InvariantCulture).ToArray();
var permission = (modeBytes[0] & 0x0F) * 8 * 8 + (modeBytes[1] & 0x0F) * 8 + (modeBytes[2] & 0x0F);
@@ -518,7 +519,7 @@ namespace Renci.SshClient.Sftp
/// </returns>
public override string ToString()
{
return string.Format("Name {0}, Size {1}, User ID {2}, Group ID {3}, Accessed {4}, Modified {5}", this.Name, this.Size, this.UserId, this.GroupId, this.LastAccessTime, this.LastWriteTime);
return string.Format(CultureInfo.CurrentCulture, "Name {0}, Size {1}, User ID {2}, Group ID {3}, Accessed {4}, Modified {5}", this.Name, this.Size, this.UserId, this.GroupId, this.LastAccessTime, this.LastWriteTime);
}
}
}
@@ -8,6 +8,7 @@ using Renci.SshClient.Common;
using Renci.SshClient.Sftp.Messages;
using System.Diagnostics;
using System.Collections.Generic;
using System.Globalization;
namespace Renci.SshClient.Sftp
{
@@ -112,15 +113,15 @@ namespace Renci.SshClient.Sftp
{
var fullPath = path;
if (!path.StartsWith("/") && this.WorkingDirectory != null)
if (path[0] == '/' && this.WorkingDirectory != null)
{
if (this.WorkingDirectory.EndsWith("/"))
if (this.WorkingDirectory[this.WorkingDirectory.Length - 1] == '/')
{
fullPath = string.Format("{0}{1}", this.WorkingDirectory, path);
fullPath = string.Format(CultureInfo.InvariantCulture, "{0}{1}", this.WorkingDirectory, path);
}
else
{
fullPath = string.Format("{0}/{1}", this.WorkingDirectory, path);
fullPath = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", this.WorkingDirectory, path);
}
}
@@ -151,7 +152,7 @@ namespace Renci.SshClient.Sftp
var slash = string.Empty;
if (!canonizedPath.EndsWith("/"))
slash = "/";
return string.Format("{0}{1}{2}", canonizedPath, slash, pathParts[pathParts.Length - 1]);
return string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", canonizedPath, slash, pathParts[pathParts.Length - 1]);
}
}
@@ -229,7 +230,7 @@ namespace Renci.SshClient.Sftp
}
else
{
throw new NotSupportedException(string.Format("Server SFTP version {0} is not supported.", message.Version));
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Server SFTP version {0} is not supported.", message.Version));
}
}
@@ -323,7 +324,7 @@ namespace Renci.SshClient.Sftp
else if (index > 1)
{
// throw time out error
throw new SshOperationTimeoutException(string.Format("Sftp operation has timed out."));
throw new SshOperationTimeoutException(string.Format(CultureInfo.CurrentCulture, "Sftp operation has timed out."));
}
}
+57 -2
View File
@@ -14,7 +14,7 @@ namespace Renci.SshClient
/// <summary>
/// Represents instance of the SSH shell object
/// </summary>
public class Shell
public class Shell : IDisposable
{
private readonly Session _session;
@@ -129,7 +129,7 @@ namespace Renci.SshClient
this._session.ErrorOccured += Session_ErrorOccured;
this._channel.Open();
this._channel.SendPseudoTerminalRequest(this._terminalName, this._columns, this._columns, this._width, this._height, this._terminalMode);
this._channel.SendPseudoTerminalRequest(this._terminalName, this._columns, this._rows, this._width, this._height, this._terminalMode);
this._channel.SendShellRequest();
this._channelClosedWaitHandle = new AutoResetEvent(false);
@@ -257,5 +257,60 @@ namespace Renci.SshClient
this._channel = null;
}
#region IDisposable Members
private bool _disposed = false;
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param>
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this._disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged ResourceMessages.
if (disposing)
{
if (this._channelClosedWaitHandle != null)
{
this._channelClosedWaitHandle.Dispose();
this._channelClosedWaitHandle = null;
}
}
// Note disposing has been done.
this._disposed = true;
}
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="Session"/> is reclaimed by garbage collection.
/// </summary>
~Shell()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
#endregion
}
}
+70 -5
View File
@@ -190,7 +190,7 @@ namespace Renci.SshClient
}
/// <summary>
/// Creates the shell. (not complete)
/// Creates the shell.
/// </summary>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
@@ -201,8 +201,9 @@ namespace Renci.SshClient
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="terminalMode">The terminal mode.</param>
/// <param name="bufferSize">Size of the internal read buffer.</param>
/// <returns></returns>
public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName = "", uint columns = 0, uint rows = 0, uint width = 0, uint height = 0, string terminalMode = "", int bufferSize = 1024)
public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, string terminalMode, int bufferSize)
{
// Ensure that connection is established.
this.EnsureConnection();
@@ -211,7 +212,7 @@ namespace Renci.SshClient
}
/// <summary>
/// Creates the shell. (not complete)
/// Creates the shell.
/// </summary>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
@@ -223,7 +224,39 @@ namespace Renci.SshClient
/// <param name="height">The height.</param>
/// <param name="terminalMode">The terminal mode.</param>
/// <returns></returns>
public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName = "", uint columns = 0, uint rows = 0, uint width = 0, uint height = 0, string terminalMode = "", int bufferSize = 1024)
public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, string terminalMode)
{
return this.CreateShell(input, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, 1024);
}
/// <summary>
/// Creates the shell.
/// </summary>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
/// <param name="extendedOutput">The extended output.</param>
/// <returns></returns>
public Shell CreateShell(Stream input, Stream output, Stream extendedOutput)
{
return this.CreateShell(input, output, extendedOutput, string.Empty, 0, 0, 0, 0, string.Empty, 1024);
}
/// <summary>
/// Creates the shell.
/// </summary>
/// <param name="encoding">The encoding to use to send the input.</param>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
/// <param name="extendedOutput">The extended output.</param>
/// <param name="terminalName">Name of the terminal.</param>
/// <param name="columns">The columns.</param>
/// <param name="rows">The rows.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="terminalMode">The terminal mode.</param>
/// <param name="bufferSize">Size of the internal read buffer.</param>
/// <returns></returns>
public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width , uint height , string terminalMode, int bufferSize)
{
// Ensure that connection is established.
this.EnsureConnection();
@@ -232,7 +265,39 @@ namespace Renci.SshClient
new StreamWriter(inputStream, encoding).Write(input);
inputStream.Seek(0, SeekOrigin.Begin);
return new Shell(this.Session, inputStream, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, bufferSize);
return this.CreateShell(inputStream, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, bufferSize);
}
/// <summary>
/// Creates the shell.
/// </summary>
/// <param name="encoding">The encoding.</param>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
/// <param name="extendedOutput">The extended output.</param>
/// <param name="terminalName">Name of the terminal.</param>
/// <param name="columns">The columns.</param>
/// <param name="rows">The rows.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="terminalMode">The terminal mode.</param>
/// <returns></returns>
public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, string terminalMode)
{
return this.CreateShell(encoding, input, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, 1024);
}
/// <summary>
/// Creates the shell.
/// </summary>
/// <param name="encoding">The encoding.</param>
/// <param name="input">The input.</param>
/// <param name="output">The output.</param>
/// <param name="extendedOutput">The extended output.</param>
/// <returns></returns>
public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput)
{
return this.CreateShell(encoding, input, output, extendedOutput, string.Empty, 0, 0, 0, 0, string.Empty, 1024);
}
}
+18 -25
View File
@@ -9,6 +9,7 @@ using Renci.SshClient.Common;
using Renci.SshClient.Messages;
using Renci.SshClient.Messages.Connection;
using Renci.SshClient.Messages.Transport;
using System.Globalization;
namespace Renci.SshClient
{
@@ -17,14 +18,6 @@ namespace Renci.SshClient
/// </summary>
public class SshCommand : IDisposable
{
//private StreamReader _outputSteamReader;
//private StreamReader _extendedOutputSteamReader;
//private StreamWriter _outputSteamWriter;
//private StreamWriter _extendedOutputSteamWriter;
private Encoding _encoding;
private Session _session;
@@ -82,7 +75,7 @@ namespace Renci.SshClient
this._result = new StringBuilder();
}
if (this.OutputStream.Length > 0)
if (this.OutputStream != null && this.OutputStream.Length > 0)
{
using (var sr = new StreamReader(this.OutputStream, this._encoding))
{
@@ -109,7 +102,7 @@ namespace Renci.SshClient
this._error = new StringBuilder();
}
if (this.ExtendedOutputStream.Length > 0)
if (this.ExtendedOutputStream != null && this.ExtendedOutputStream.Length > 0)
{
using (var sr = new StreamReader(this.ExtendedOutputStream, this._encoding))
{
@@ -132,6 +125,9 @@ namespace Renci.SshClient
/// <param name="encoding">The encoding.</param>
internal SshCommand(Session session, string commandText, Encoding encoding)
{
if (session == null)
throw new ArgumentNullException("session");
this._encoding = encoding;
this._session = session;
this.CommandText = commandText;
@@ -154,7 +150,7 @@ namespace Renci.SshClient
// Prevent from executing BeginExecute before calling EndExecute
if (this._asyncResult != null)
{
throw new InvalidOperationException("");
throw new InvalidOperationException("Asynchronous operation is already in progress.");
}
// Create new AsyncResult object
@@ -204,11 +200,14 @@ namespace Renci.SshClient
/// <summary>
/// Waits for the pending asynchronous command execution to complete.
/// </summary>
/// <param name="asynchResult">The reference to the pending asynchronous request to finish.</param>
/// <param name="asyncResult">The reference to the pending asynchronous request to finish.</param>
/// <returns></returns>
public string EndExecute(IAsyncResult asynchResult)
public string EndExecute(IAsyncResult asyncResult)
{
CommandAsyncResult channelAsyncResult = asynchResult as CommandAsyncResult;
CommandAsyncResult channelAsyncResult = asyncResult as CommandAsyncResult;
if (channelAsyncResult == null)
throw new ArgumentException("Not valid 'asynchResult' parameter.");
channelAsyncResult.ValidateCommand(this);
@@ -235,13 +234,12 @@ namespace Renci.SshClient
return this.EndExecute(this.BeginExecute(null, null));
}
/// <summary>
/// Cancels command execution in asynchronous scenarios. CURRENTLY NOT IMPLEMENTED.
/// </summary>
public void Cancel()
{
if (this._channel != null && this._channel.IsOpen)
{
this._session.SendMessage(new ChannelEofMessage(this._channel.RemoteChannelNumber));
this._session.SendMessage(new ChannelCloseMessage(this._channel.RemoteChannelNumber));
}
throw new NotImplementedException();
}
/// <summary>
@@ -266,11 +264,6 @@ namespace Renci.SshClient
this._channel.Closed += Channel_Closed;
this.OutputStream = new PipeStream();
this.ExtendedOutputStream = new PipeStream();
//this._outputSteamReader = new StreamReader(this.OutputStream);
//this._extendedOutputSteamReader = new StreamReader(this.ExtendedOutputStream);
//this._outputSteamWriter = new StreamWriter(this.OutputStream);
//this._extendedOutputSteamWriter = new StreamWriter(this.ExtendedOutputStream);
}
private void Session_Disconnected(object sender, EventArgs e)
@@ -381,7 +374,7 @@ namespace Renci.SshClient
else if (index > 1)
{
// throw time out error
throw new SshOperationTimeoutException(string.Format("Command '{0}' has timed out.", this.CommandText));
throw new SshOperationTimeoutException(string.Format(CultureInfo.CurrentCulture, "Command '{0}' has timed out.", this.CommandText));
}
}