SshSharp 1.0.0

dotnet add package SshSharp --version 1.0.0
                    
NuGet\Install-Package SshSharp -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SshSharp" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SshSharp" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="SshSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SshSharp --version 1.0.0
                    
#r "nuget: SshSharp, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SshSharp@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SshSharp&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=SshSharp&version=1.0.0
                    
Install as a Cake Tool

<img src="https://raw.githubusercontent.com/zcsizmadia/SshSharp/main/assets/logo/sshsharp-512.png" alt="SshSharp logo" width="96">

SshSharp

CI NuGet .NET License: MIT

A managed, async-first SSH client library for .NET, with OpenSSH ssh_config and known_hosts support. Connect to a host by its ssh_config alias and get the same host name, user, keys, agent, jump hosts and host key policy that ssh would use.

await using var client = await SshClient.ConnectAsync("prod-db");   // an alias from ~/.ssh/config
var result = await client.RunCommandAsync("uptime");
Console.WriteLine(result.StandardOutputText);

Status: 1.0: the public API follows semantic versioning, so breaking changes wait for a major version. The managed cryptography has had an internal constant-time review but not yet an outside one. See SECURITY.md.

Features

  • Pure managed C#, no native dependencies; .NET 8 and .NET 10, tested on Windows and Linux (x64 and Arm64) and macOS (Arm64); trimming- and Native AOT-compatible, with an AOT-compiled smoke test against a real server in CI.
  • Async all the way: CancellationToken on every network operation, IAsyncDisposable, System.IO.Pipelines I/O with zero-copy packet handling.
  • OpenSSH configuration: ssh_config (Host, Match, Include, tokens) and known_hosts (hashed hosts, @cert-authority, @revoked), resolved like ssh -G.
  • Authentication: password, public keys (OpenSSH, PKCS#8, PKCS#1/SEC1 and PuTTY .ppk formats, encrypted too), OpenSSH user certificates, ssh-agent (Unix sockets, the Windows OpenSSH agent and PuTTY's Pageant), FIDO security keys held by the agent, agent forwarding, keyboard-interactive (one-time codes, PAM), and multi-factor chains. Key generation, saved as ssh-keygen does; signing and verifying files and git commits with SSH keys (ssh-keygen -Y).
  • Host verification: StrictHostKeyChecking policies, host certificates, UpdateHostKeys, key pinning, or your own verifier. There is no "accept anything" default. Host key scanning, as ssh-keyscan does it.
  • Connections: ProxyJump chains, ProxyCommand, HTTP and SOCKS proxies, connect over any Stream or from a chosen local address (BindAddress, BindInterface), keep-alive and dead-connection detection; HttpClient through the SSH connection; TCP and Unix-socket tunnels; local, remote and dynamic (SOCKS) port forwarding (ssh -L, -R, -D) and remote dynamic and Unix-socket forwarding (-R port, -R /socket:target), also started from ssh_config.
  • Sessions: run commands, stream stdin/stdout/stderr, interactive shells with a pseudo-terminal, environment variables, signals and window resizing; subsystems (ssh -s) such as netconf; expect-style scripting of shells.
  • Modern algorithms: post-quantum mlkem768x25519-sha256, and the FIPS-compatible mlkem768nistp256-sha256 and mlkem1024nistp384-sha384 (on .NET 10 where the platform has ML-KEM), and sntrup761x25519-sha512 (managed, on every platform), curve25519-sha256, ECDH and DH group 14/16 key exchange; ChaCha20-Poly1305, AES-GCM and AES-CTR with HMAC-SHA2 ETM; Ed25519, ECDSA and RSA (SHA-2) keys; strict key exchange (Terrapin) always on; a FIPS mode.
  • File transfer: SFTP (version 3 with OpenSSH's extensions: pipelined uploads and downloads, seekable remote file streams, directories, links and attributes), and SCP uploads and downloads of files, streams and directories, with progress, kept times, and checks that stop a hostile server from writing outside the target.
  • Files for the rest of .NET: SshSharp.IO.Abstractions implements System.IO.Abstractions' IFileSystem over SFTP (code written against IFileSystem reads and writes the server unchanged), and SshSharp.FileProviders serves a directory as an IFileProvider, for ASP.NET Core static files, Razor views and configuration; nothing is mounted, so only your application sees the files.
  • Dependency injection: SshSharp.Extensions.DependencyInjection registers named endpoints from configuration, with a factory for new connections, a shared connection that is opened again when it drops, and a health check.
  • Observability: ILogger logging, ActivitySource tracing and Meter metrics, with no secrets recorded.

Why not SSH.NET?

SSH.NET is the established .NET SSH library, and for some projects it is the better choice (see below). SshSharp is for applications that should behave like OpenSSH's ssh: connect by ssh_config alias, trust what known_hosts says, sign with the user's agent, hop through jump hosts, and do all of it asynchronously.

SshSharp SSH.NET 2026.0
Target frameworks .NET 8, .NET 10 .NET Framework 4.6.2+, .NET Standard 2.0, .NET 8+
API Async-only network API; CancellationToken on every network operation Mostly synchronous; async connect, commands and SFTP
ssh_config (Host, Match with localnetwork, sessiontype and command, Include; connect by alias; KnownHostsCommand, RefuseConnection) ✅ ❌
known_hosts verification (hashed hosts, @cert-authority, @revoked, StrictHostKeyChecking) ✅ ❌ (verify in a HostKeyReceived handler)
Revoked host keys (RevokedHostKeys: OpenSSH KRLs from ssh-keygen -k, or key lists) ✅ ❌
UpdateHostKeys (key rotation) ✅ ❌
Host key scanning (ssh-keyscan) ✅ ❌
ProxyJump chains, ProxyCommand ✅ ❌
HTTP and SOCKS 4/5 proxies ✅ ✅
Connect over any Stream (WebSocket, named pipe, your own tunnel) ✅ ❌
Connect from a chosen local address or interface (BindAddress, BindInterface) ✅ ❌
Keep-alive that detects a dead server (ServerAliveCountMax) ✅ ❌ (keep-alives get no reply)
Round-trip ping (client.PingAsync, OpenSSH's ping@openssh.com) ✅ ❌
Channel idle timeouts by channel type (ChannelTimeout, OpenSSH 9.2+) ✅ ❌
Hide keystroke timing in terminal sessions (ObscureKeystrokeTiming, OpenSSH 9.5+) ✅ ❌
Stop a program's output early without killing it (eow@openssh.com), refuse further sessions on a connection (no-more-sessions@openssh.com) ✅ ❌
SSH agent (ssh-agent, Windows OpenSSH agent, PuTTY's Pageant) ✅ ❌
Agent forwarding ✅ ❌
FIDO security keys through the agent (sk-ssh-ed25519@openssh.com, sk-ecdsa-sha2-nistp256@openssh.com, and their certificates) ✅ ❌
Agent key management (ssh-add: add with lifetime, confirmation or destination constraints (-h), remove, lock; AddKeysToAgent), and signing with destination-constrained keys ✅ ❌
Password, public key, keyboard-interactive, multi-factor ✅ ✅
Kerberos (GSSAPI, gssapi-with-mic; .NET 10) ✅ ❌
OpenSSH certificates User and host User (authentication)
Private key formats OpenSSH, PKCS#1/#8, SEC1, PuTTY .ppk OpenSSH, PKCS#1/#8, PuTTY .ppk, ssh.com
Key generation (Ed25519, ECDSA, RSA; saved in the OpenSSH format) ✅ ❌
Signing and verifying files and git commits (ssh-keygen -Y, SSHSIG, allowed-signers files) ✅ ❌
Post-quantum key exchange sntrup761x25519-sha512 (OpenSSH 8.5+, also as @openssh.com) ✅ (managed: every platform, .NET 8 too) ✅
Post-quantum key exchange mlkem768x25519-sha256 (OpenSSH 9.9+) ✅ (.NET 10 with platform ML-KEM) ✅
FIPS-compatible post-quantum key exchange (mlkem768nistp256-sha256, mlkem1024nistp384-sha384) ✅ (.NET 10 with platform ML-KEM) ❌
Strict key exchange (Terrapin fix) ✅ ✅
Legacy algorithms (CBC, 3DES, SHA-1, ssh-rsa, DH group 1, zlib) — (by design) ✅
Commands, shells with a terminal, expect-style scripting ✅ ✅
Environment variables for a session (env requests, as ssh's SetEnv and SendEnv) ✅ ❌
Any signal to a running session, including extension signals (INFO@openssh.com) ✅ ❌ (TERM or KILL, when cancelling a command)
BREAK (RFC 4335, for serial consoles) ✅ ❌
Any subsystem (ssh -s) ✅ ❌ (SFTP and NETCONF only)
Local, remote and dynamic port forwarding ✅ (also started from ssh_config) ✅
Remote dynamic forwarding (ssh -R port, a SOCKS proxy on the client side) ✅ ❌
Unix-socket tunnels (Docker or database sockets on the server) ✅ ❌
Remote Unix-socket forwarding (ssh -R /remote.sock:target, for example gpg-agent forwarding) ✅ ❌
HttpClient through the SSH connection (SocketsHttpHandler.ConnectCallback) ✅ ❌
FIPS mode (FIPS-approved algorithms only) ✅ ❌
SCP ✅ ✅
SFTP ✅ (version 3 with OpenSSH extensions, pipelined transfers) ✅
Segmented SFTP downloads (one file in parallel ranges over several sessions) ✅ ❌
SFTP fsync@openssh.com (durable uploads), hardlink@openssh.com and limits@openssh.com ✅ ❌
Remote files as an IFileSystem (System.IO.Abstractions: File, Directory, Path, streams) ✅ (SshSharp.IO.Abstractions) ❌
Remote files as an IFileProvider (ASP.NET Core static files, Razor, configuration) ✅ (SshSharp.FileProviders) ❌
Native AOT ✅ (an AOT-compiled binary connects to a real server in CI) ✅ (AOT-compatible; an AOT publish is checked in CI)
Diagnostics ILogger, ActivitySource tracing, Meter metrics (OpenTelemetry semantic conventions) ILogger
Fuzzing ✅ (coverage-guided, nightly; every parser in each test run) ❌
Fault-injection tests against real servers (cuts at any byte, either way; silent or one-way stalled networks; latency, tiny segments, low bandwidth; sessions killed on the server) ✅ Partial (sessions killed on the server)
Mutation testing ✅ (Stryker.NET, weekly) ❌
Maturity New (1.0); managed crypto awaiting an outside review More than a decade of production use

Use SSH.NET instead when you need .NET Framework or .NET Standard, servers that only speak legacy algorithms, or a long track record. Moving from SSH.NET? See the migration guide.

Install

dotnet add package SshSharp
dotnet add package SshSharp.IO.Abstractions # optional: an IFileSystem over SFTP
dotnet add package SshSharp.FileProviders   # optional: an IFileProvider over SFTP
dotnet add package SshSharp.Extensions.DependencyInjection # optional: named endpoints, a shared connection, health checks

Examples

Connect with a key and verify the host against ~/.ssh/known_hosts:

using SshSharp;
using SshSharp.Config;

using var key = await SshPrivateKey.LoadAsync("/home/me/.ssh/id_ed25519");
await using var client = await SshClient.ConnectAsync("example.com", 22, new SshClientOptions
{
    UserName = "deploy",
    PrivateKeys = [key],
    HostKeyVerifier = KnownHostsVerifier.ForCurrentUser(StrictHostKeyChecking.Yes),
});

var result = await client.RunCommandAsync("df -h /");
Console.WriteLine($"exit {result.ExitStatus}: {result.StandardOutputText}");

Stream a long-running command:

await using var session = await client.StartCommandAsync("tail -f /var/log/syslog");
using var reader = new StreamReader(session.StandardOutput);
while (await reader.ReadLineAsync() is { } line)
{
    Console.WriteLine(line);
}

Use the keys in ssh-agent:

var agent = SshAgent.FromEnvironment();
var keys = agent is null ? [] : await agent.GetKeysAsync();

Documentation

zcsizmadia.github.io/SshSharp: the guides below and the full API reference, for the latest release.

Testing

Every pull request runs about 1,300 unit tests on Linux, Windows and macOS (x64 and Arm64), each on .NET 8 and .NET 10, and the interop tests against real servers: OpenSSH old and new on Linux and Windows, Dropbear, AsyncSSH, Apache MINA SSHD, Erlang/OTP, and SFTP-only servers. The cryptography is checked against reference vectors and about 6,400 Project Wycheproof edge cases. A fault-injection proxy cuts, stalls and slows connections at any point, the parsers are fuzzed nightly, and stress runs loop the whole suite with an instrumented build that catches buffer misuse. Testing and validation has the details, what the testing found, and what is not covered yet.

Building

  • .NET SDK 10.0.401 or later (see global.json).
  • Build: dotnet build -c Release
  • Test (TUnit): dotnet test --project tests/SshSharp.Tests -c Release. Tests against real servers run when SSHSHARP_TEST_SSHD and related variables are set; CI sets them up on Linux, and . ./scripts/test-server.ps1 starts the same server in Docker locally (-Server dropbear for Dropbear, -Stop to remove it).
  • Coverage report: ./scripts/coverage.ps1 (target 95%+, not enforced in CI).
  • Mutation testing (Stryker.NET, weekly in CI): dotnet tool restore, then in tests/SshSharp.Tests: dotnet stryker --test-runner mtp --project SshSharp.csproj --target-framework net10.0 -m "**/Crypto/X25519.cs".
  • Releases: pushing a v* tag on main publishes to nuget.org (.github/workflows/publish.yml).

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on SshSharp:

Package Downloads
SshSharp.FileProviders

An IFileProvider over SFTP (SshSharp): serve files from an SSH server to ASP.NET Core static files, Razor, configuration and anything else that reads through Microsoft.Extensions.FileProviders.

SshSharp.IO.Abstractions

An IFileSystem (System.IO.Abstractions) over SFTP (SshSharp): code written against IFileSystem reads and writes a directory on an SSH server, with nothing mounted.

SshSharp.Extensions.DependencyInjection

Dependency injection for SshSharp: named SSH endpoints from configuration, a factory for new connections, a shared connection that reconnects, and a health check.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 306 10/17/2026
0.6.0 1,475 10/16/2026
0.5.0 3,302 10/14/2026
0.4.0 44 10/14/2026
0.3.0 731 10/14/2026