2023.0.0
版本发布时间: 2023-10-11 03:26:25
sshnet/SSH.NET最新发布版本:2024.1.0(2024-06-28 15:06:08)
New features:
- Support for .NET 6, 7, and .NET Standard 2.1
- Support for RSA-SHA256/512 signature algorithms
- Support for parsing OpenSSH keys with ECDSA 256/384/521 and RSA
- Support for SHA256 and MD5 fingerprints for host key validation
- Added async support to
SftpClient
andSftpFileStream
- Added
ISftpFile
interface toSftpFile
- Removed support for old target frameworks
- Improved performance and stability
- Added the ability to set the last write and access time for Sftp files
The list of changes:
- Assets/logos by @Filini in https://github.com/sshnet/SSH.NET/pull/782
- OPENSSH KeyReader for more keys by @darinkes in https://github.com/sshnet/SSH.NET/pull/614
- Add interface to SftpFile #120 by @wxtsxt in https://github.com/sshnet/SSH.NET/pull/812
- Start MessageListener with ThreadAbstraction.ExecuteThreadLongRunning #2 by @IgorMilavec in https://github.com/sshnet/SSH.NET/pull/902
- Add async support to SftpClient and SftpFileStream by @IgorMilavec in https://github.com/sshnet/SSH.NET/pull/819
- Fix virus false-positive by Defender on Renci.SSHNet.Tests.dll by @zybexXL in https://github.com/sshnet/SSH.NET/pull/867
- Add unit tests for task-based asynchronous API by @IgorMilavec in https://github.com/sshnet/SSH.NET/pull/906
- correct 'Documenation' to 'Documentation' by @maxijabase in https://github.com/sshnet/SSH.NET/pull/838
- Agent auth and Keygen by @darinkes in https://github.com/sshnet/SSH.NET/pull/794
- Add IBaseClient for BaseClient and ISftpClient to inherit from by @Owen-Krueger in https://github.com/sshnet/SSH.NET/pull/975
- Fix typo by @psh9508 in https://github.com/sshnet/SSH.NET/pull/999
- Fix Seek Operations in SftpFileStream by @lemonyte in https://github.com/sshnet/SSH.NET/pull/910
- Add back copyright to license by @drieseng in https://github.com/sshnet/SSH.NET/pull/1060
- Removing old target frameworks by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1109
- Remove old features [Part 1] by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1117
- Remove FEATURE_DIRECTORYINFO_ENUMERATEFILES by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1119
- Fix some (lots of) issues reported by analyzers. by @drieseng in https://github.com/sshnet/SSH.NET/pull/1125
- Round 2 of analyzer fixes and general cleanup. by @drieseng in https://github.com/sshnet/SSH.NET/pull/1132
- Analyzer fixes round 3. by @drieseng in https://github.com/sshnet/SSH.NET/pull/1135
- Replace Array<T>.Empty with Array.Empty<T>() by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1137
- Replace IsNullOrWhiteSpace extension by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1142
- Use License Expression for NuGet Package by @mus65 in https://github.com/sshnet/SSH.NET/pull/1146
- MSTest Integration tests by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1148
- ListDirectoryAsync return IAsyncEnumerable by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1126
- Fix the assembly resolution build warning by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1165
- Delete performance/longrunning tests by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1143
- Move Integration tests by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1173
- Add a benchmarks project by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1151
- Use ExceptionDispatchInfo to retain call stack in Session.WaitOnHandle() by @IgorMilavec in https://github.com/sshnet/SSH.NET/pull/936
- Support SHA256 fingerprints for host key validation by @DavisNT in https://github.com/sshnet/SSH.NET/pull/1098
- Add support for RSA SHA-2 public key algorithms by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1177
- Improvements after #1177 by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1180
- Use ExceptionDispatchInfo in more places by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1182
- Try to "fix" the flaky test by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1185
- Enable DSA tests by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1181
- FingerPrints improvements by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1186
- Use OS-agnostic socket error codes to allow tests run on different OSes by @dimhotepus in https://github.com/sshnet/SSH.NET/pull/1179
- Fix for channel session semaphore from thread blocking by @patrick-yates-redgate in https://github.com/sshnet/SSH.NET/pull/1071
- Update ISftpClient by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1193
- Implement set last write and access time by @WojciechNagorski in https://github.com/sshnet/SSH.NET/pull/1194
- Add/migrate hmac+cipher integration tests by @Rob-Hague in https://github.com/sshnet/SSH.NET/pull/1189
- Improve tests for (Get|Set)LastAccessTime(Utc) by @drieseng in https://github.com/sshnet/SSH.NET/pull/1198
New Contributors
- @wxtsxt made their first contribution in https://github.com/sshnet/SSH.NET/pull/812
- @IgorMilavec made their first contribution in https://github.com/sshnet/SSH.NET/pull/902
- @zybexXL made their first contribution in https://github.com/sshnet/SSH.NET/pull/867
- @maxijabase made their first contribution in https://github.com/sshnet/SSH.NET/pull/838
- @Owen-Krueger made their first contribution in https://github.com/sshnet/SSH.NET/pull/975
- @psh9508 made their first contribution in https://github.com/sshnet/SSH.NET/pull/999
- @lemonyte made their first contribution in https://github.com/sshnet/SSH.NET/pull/910
- @WojciechNagorski made their first contribution in https://github.com/sshnet/SSH.NET/pull/1109
- @Rob-Hague made their first contribution in https://github.com/sshnet/SSH.NET/pull/1137
- @mus65 made their first contribution in https://github.com/sshnet/SSH.NET/pull/1146
- @DavisNT made their first contribution in https://github.com/sshnet/SSH.NET/pull/1098
- @dimhotepus made their first contribution in https://github.com/sshnet/SSH.NET/pull/1179
- @patrick-yates-redgate made their first contribution in https://github.com/sshnet/SSH.NET/pull/1071
Thank you to all of our contributors for making SSH.NET the best SSH library for .NET!
Full Changelog: https://github.com/sshnet/SSH.NET/compare/2020.0.1...2023.0.0
API listing follows standard diff formatting. Lines preceded by a '+' are additions and a '-' indicates removal.
Renci.SshNet
namespace Renci.SshNet {
- public abstract class BaseClient : IDisposable {
+ public abstract class BaseClient : IBaseClient, IDisposable {
+ public Task ConnectAsync(CancellationToken cancellationToken);
}
+ public interface IBaseClient
+ public interface IPrivateKeySource
- public interface ISftpClient {
+ public interface ISftpClient : IBaseClient, IDisposable {
+ Task DeleteFileAsync(string path, CancellationToken cancellationToken);
- IEnumerable<SftpFile> EndListDirectory(IAsyncResult asyncResult);
+ IEnumerable<ISftpFile> EndListDirectory(IAsyncResult asyncResult);
- SftpFile Get(string path);
+ ISftpFile Get(string path);
+ Task<SftpFileSytemInformation> GetStatusAsync(string path, CancellationToken cancellationToken);
- IEnumerable<SftpFile> ListDirectory(string path, Action<int> listCallback = null);
+ IEnumerable<ISftpFile> ListDirectory(string path, Action<int> listCallback = null);
+ IAsyncEnumerable<ISftpFile> ListDirectoryAsync(string path, CancellationToken cancellationToken);
+ Task<SftpFileStream> OpenAsync(string path, FileMode mode, FileAccess access, CancellationToken cancellationToken);
+ Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken);
+ void SetLastAccessTime(string path, DateTime lastAccessTime);
+ void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc);
+ void SetLastWriteTime(string path, DateTime lastWriteTime);
+ void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc);
}
public class NetConfClient : BaseClient {
+ public NetConfClient(string host, int port, string username, params IPrivateKeySource[] keyFiles);
- public NetConfClient(string host, int port, string username, params PrivateKeyFile[] keyFiles);
+ public NetConfClient(string host, string username, params IPrivateKeySource[] keyFiles);
- public NetConfClient(string host, string username, params PrivateKeyFile[] keyFiles);
}
public class PrivateKeyAuthenticationMethod : AuthenticationMethod, IDisposable {
+ public PrivateKeyAuthenticationMethod(string username, params IPrivateKeySource[] keyFiles);
- public PrivateKeyAuthenticationMethod(string username, params PrivateKeyFile[] keyFiles);
- public ICollection<PrivateKeyFile> KeyFiles { get; private set; }
+ public ICollection<IPrivateKeySource> KeyFiles { get; private set; }
}
public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable {
+ public PrivateKeyConnectionInfo(string host, int port, string username, params IPrivateKeySource[] keyFiles);
- public PrivateKeyConnectionInfo(string host, int port, string username, params PrivateKeyFile[] keyFiles);
+ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params IPrivateKeySource[] keyFiles);
- public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles);
+ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params IPrivateKeySource[] keyFiles);
- public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles);
+ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params IPrivateKeySource[] keyFiles);
- public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles);
+ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params IPrivateKeySource[] keyFiles);
- public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles);
+ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params IPrivateKeySource[] keyFiles);
- public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles);
+ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params IPrivateKeySource[] keyFiles);
- public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles);
- public ICollection<PrivateKeyFile> KeyFiles { get; private set; }
+ public ICollection<IPrivateKeySource> KeyFiles { get; private set; }
}
- public class PrivateKeyFile : IDisposable {
+ public class PrivateKeyFile : IDisposable, IPrivateKeySource {
+ public PrivateKeyFile(Key key);
- public HostAlgorithm HostKey { get; private set; }
+ public IReadOnlyCollection<HostAlgorithm> HostKeyAlgorithms { get; }
+ public Key Key { get; }
}
public class ScpClient : BaseClient {
+ public ScpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles);
- public ScpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles);
+ public ScpClient(string host, string username, params IPrivateKeySource[] keyFiles);
- public ScpClient(string host, string username, params PrivateKeyFile[] keyFiles);
}
public class Session : IDisposable, ISession {
+ public Task ConnectAsync(CancellationToken cancellationToken);
}
- public class SftpClient : BaseClient, ISftpClient {
+ public class SftpClient : BaseClient, IBaseClient, IDisposable, ISftpClient {
+ public SftpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles);
- public SftpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles);
+ public SftpClient(string host, string username, params IPrivateKeySource[] keyFiles);
- public SftpClient(string host, string username, params PrivateKeyFile[] keyFiles);
+ public Task DeleteFileAsync(string path, CancellationToken cancellationToken);
- public IEnumerable<SftpFile> EndListDirectory(IAsyncResult asyncResult);
+ public IEnumerable<ISftpFile> EndListDirectory(IAsyncResult asyncResult);
- public SftpFile Get(string path);
+ public ISftpFile Get(string path);
+ public Task<SftpFileSytemInformation> GetStatusAsync(string path, CancellationToken cancellationToken);
- public IEnumerable<SftpFile> ListDirectory(string path, Action<int> listCallback = null);
+ public IEnumerable<ISftpFile> ListDirectory(string path, Action<int> listCallback = null);
+ public IAsyncEnumerable<ISftpFile> ListDirectoryAsync(string path, CancellationToken cancellationToken);
+ public Task<SftpFileStream> OpenAsync(string path, FileMode mode, FileAccess access, CancellationToken cancellationToken);
+ public Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken);
}
public class SshClient : BaseClient {
+ public SshClient(string host, int port, string username, params IPrivateKeySource[] keyFiles);
- public SshClient(string host, int port, string username, params PrivateKeyFile[] keyFiles);
+ public SshClient(string host, string username, params IPrivateKeySource[] keyFiles);
- public SshClient(string host, string username, params PrivateKeyFile[] keyFiles);
}
}
Renci.SshNet.Common
namespace Renci.SshNet.Common {
public struct BigInteger : IComparable, IComparable<BigInteger>, IEquatable<BigInteger>, IFormattable {
- public string ToString(string format, IFormatProvider provider);
+ public string ToString(string format, IFormatProvider formatProvider);
}
public class HostKeyEventArgs : EventArgs {
+ public string FingerPrintMD5 { get; }
+ public string FingerPrintSHA256 { get; }
}
public class NetConfServerException : SshException {
- protected NetConfServerException(SerializationInfo info, StreamingContext context);
}
public class ProxyException : SshException {
- protected ProxyException(SerializationInfo info, StreamingContext context);
}
public class ScpException : SshException {
- protected ScpException(SerializationInfo info, StreamingContext context);
}
public class SemaphoreLight : IDisposable {
- ~SemaphoreLight();
}
public class SftpPathNotFoundException : SshException {
- protected SftpPathNotFoundException(SerializationInfo info, StreamingContext context);
}
public class SftpPermissionDeniedException : SshException {
- protected SftpPermissionDeniedException(SerializationInfo info, StreamingContext context);
}
public class SshAuthenticationException : SshException {
- protected SshAuthenticationException(SerializationInfo info, StreamingContext context);
}
public class SshConnectionException : SshException {
- protected SshConnectionException(SerializationInfo info, StreamingContext context);
}
public class SshException : Exception {
- protected SshException(SerializationInfo info, StreamingContext context);
}
public class SshOperationTimeoutException : SshException {
- protected SshOperationTimeoutException(SerializationInfo info, StreamingContext context);
}
public class SshPassPhraseNullOrEmptyException : SshException {
- protected SshPassPhraseNullOrEmptyException(SerializationInfo info, StreamingContext context);
}
}
Renci.SshNet.Messages.Connection
namespace Renci.SshNet.Messages.Connection {
public class ChannelDataMessage : ChannelMessage {
- public int Offset { get; set; }
+ public int Offset { get; private set; }
- public int Size { get; set; }
+ public int Size { get; private set; }
}
}
Renci.SshNet.Security
namespace Renci.SshNet.Security {
public class DsaKey : Key, IDisposable {
- protected override DigitalSignature DigitalSignature { get; }
+ protected internal override DigitalSignature DigitalSignature { get; }
}
public class EcdsaKey : Key, IDisposable {
- protected override DigitalSignature DigitalSignature { get; }
+ protected internal override DigitalSignature DigitalSignature { get; }
- public CngAlgorithm HashAlgorithm { get; }
+ public HashAlgorithmName HashAlgorithm { get; }
+ public byte[] PrivateKey { get; private set; }
}
public class ED25519Key : Key, IDisposable {
+ public ED25519Key(byte[] pk);
- protected override DigitalSignature DigitalSignature { get; }
+ protected internal override DigitalSignature DigitalSignature { get; }
}
public abstract class Key {
+ public string Comment { get; set; }
- protected abstract DigitalSignature DigitalSignature { get; }
+ protected internal abstract DigitalSignature DigitalSignature { get; }
}
public class KeyHostAlgorithm : HostAlgorithm {
+ public KeyHostAlgorithm(string name, Key key, DigitalSignature digitalSignature);
+ public KeyHostAlgorithm(string name, Key key, byte[] data, DigitalSignature digitalSignature);
+ public DigitalSignature DigitalSignature { get; private set; }
}
public class RsaKey : Key, IDisposable {
- protected override DigitalSignature DigitalSignature { get; }
+ protected internal override DigitalSignature DigitalSignature { get; }
+ public override string ToString();
}
}
Renci.SshNet.Security.Cryptography
namespace Renci.SshNet.Security.Cryptography {
public abstract class BlockCipher : SymmetricCipher {
- public override byte[] Decrypt(byte[] data);
+ public override byte[] Decrypt(byte[] input);
- public override byte[] Decrypt(byte[] data, int offset, int length);
+ public override byte[] Decrypt(byte[] input, int offset, int length);
- public override byte[] Encrypt(byte[] data, int offset, int length);
+ public override byte[] Encrypt(byte[] input, int offset, int length);
}
public class RsaDigitalSignature : CipherDigitalSignature, IDisposable {
+ public RsaDigitalSignature(RsaKey rsaKey, HashAlgorithmName hashAlgorithmName);
}
}
Renci.SshNet.Security.Cryptography.Ciphers
namespace Renci.SshNet.Security.Cryptography.Ciphers {
public class RsaCipher : AsymmetricCipher {
- public override byte[] Decrypt(byte[] data);
+ public override byte[] Decrypt(byte[] input);
- public override byte[] Decrypt(byte[] data, int offset, int length);
+ public override byte[] Decrypt(byte[] input, int offset, int length);
- public override byte[] Encrypt(byte[] data, int offset, int length);
+ public override byte[] Encrypt(byte[] input, int offset, int length);
}
}
Renci.SshNet.Sftp
namespace Renci.SshNet.Sftp {
+ public interface ISftpFile
- public class SftpFile
+ public sealed class SftpFile : ISftpFile
public class SftpFileStream : Stream {
+ public override Task FlushAsync(CancellationToken cancellationToken);
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken);
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken);
}
}