github sshnet/SSH.NET 2023.0.0

latest releases: 2024.0.0, 2023.0.1
6 months ago

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 and SftpFileStream
  • Added ISftpFile interface to SftpFile
  • 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:

New Contributors

Thank you to all of our contributors for making SSH.NET the best SSH library for .NET!

Full Changelog: 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);
     }
 }

Don't miss a new SSH.NET release

NewReleases is sending notifications on new releases.