SshSharp 1.0.0
dotnet add package SshSharp --version 1.0.0
NuGet\Install-Package SshSharp -Version 1.0.0
<PackageReference Include="SshSharp" Version="1.0.0" />
<PackageVersion Include="SshSharp" Version="1.0.0" />
<PackageReference Include="SshSharp" />
paket add SshSharp --version 1.0.0
#r "nuget: SshSharp, 1.0.0"
#:package SshSharp@1.0.0
#addin nuget:?package=SshSharp&version=1.0.0
#tool nuget:?package=SshSharp&version=1.0.0
<img src="https://raw.githubusercontent.com/zcsizmadia/SshSharp/main/assets/logo/sshsharp-512.png" alt="SshSharp logo" width="96">
SshSharp
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:
CancellationTokenon every network operation,IAsyncDisposable,System.IO.PipelinesI/O with zero-copy packet handling. - OpenSSH configuration:
ssh_config(Host,Match,Include, tokens) andknown_hosts(hashed hosts,@cert-authority,@revoked), resolved likessh -G. - Authentication: password, public keys (OpenSSH, PKCS#8, PKCS#1/SEC1 and PuTTY
.ppkformats, 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 asssh-keygendoes; signing and verifying files and git commits with SSH keys (ssh-keygen -Y). - Host verification:
StrictHostKeyCheckingpolicies, host certificates,UpdateHostKeys, key pinning, or your own verifier. There is no "accept anything" default. Host key scanning, asssh-keyscandoes it. - Connections: ProxyJump chains, ProxyCommand, HTTP and SOCKS proxies, connect over any
Streamor from a chosen local address (BindAddress,BindInterface), keep-alive and dead-connection detection;HttpClientthrough 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 fromssh_config. - Sessions: run commands, stream stdin/stdout/stderr, interactive shells with a pseudo-terminal, environment variables,
signals and window resizing; subsystems (
ssh -s) such asnetconf;expect-style scripting of shells. - Modern algorithms: post-quantum
mlkem768x25519-sha256, and the FIPS-compatiblemlkem768nistp256-sha256andmlkem1024nistp384-sha384(on .NET 10 where the platform has ML-KEM), andsntrup761x25519-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.Abstractionsimplements System.IO.Abstractions'IFileSystemover SFTP (code written againstIFileSystemreads and writes the server unchanged), andSshSharp.FileProvidersserves a directory as anIFileProvider, for ASP.NET Core static files, Razor views and configuration; nothing is mounted, so only your application sees the files. - Dependency injection:
SshSharp.Extensions.DependencyInjectionregisters 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:
ILoggerlogging,ActivitySourcetracing andMetermetrics, 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.
- Getting started
- Connecting: TCP, streams,
ssh_configaliases, ProxyJump, keep-alive, algorithms - Authentication: passwords, keys, certificates, the agent, keyboard-interactive
- Host keys:
known_hosts, policies, pinning - Commands and shells
- File transfer (SFTP)
- File transfer (SCP)
- Signing files and commits: SSH signatures
(
ssh-keygen -Y) and allowed-signers files - Configuration files
- Dependency injection: named endpoints, a shared reconnecting connection, health checks
- Errors and diagnostics: exceptions, logging, tracing, metrics
- Migrating from SSH.NET: the same tasks, side by side
- Samples: an
ssh-like tool (commands, streaming, shell, port forwarding, SOCKS, SCP, SFTP,IFileSystem, a Windows CNG key), ASP.NET Core with dependency injection, static files and a health check, and a worker service that survives dropped connections - API reference: generated from the XML documentation with DocFX
(to build it locally:
dotnet tool restore, thendotnet docfx docs/docfx.json --serve); every public member is documented, and IntelliSense shows the same text. - Design notes, testing and validation, threat model, cryptography review, benchmarks
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 whenSSHSHARP_TEST_SSHDand related variables are set; CI sets them up on Linux, and. ./scripts/test-server.ps1starts the same server in Docker locally (-Server dropbearfor Dropbear,-Stopto remove it). - Coverage report:
./scripts/coverage.ps1(target 95%+, not enforced in CI). - Mutation testing (Stryker.NET, weekly in CI):
dotnet tool restore, then intests/SshSharp.Tests:dotnet stryker --test-runner mtp --project SshSharp.csproj --target-framework net10.0 -m "**/Crypto/X25519.cs". - Releases: pushing a
v*tag onmainpublishes to nuget.org (.github/workflows/publish.yml).
License
| Product | Versions 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. |
-
net10.0
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.12)
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- System.IO.Pipelines (>= 8.0.0)
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.