SshSharp 0.3.0
See the version list below for details.
dotnet add package SshSharp --version 0.3.0
NuGet\Install-Package SshSharp -Version 0.3.0
<PackageReference Include="SshSharp" Version="0.3.0" />
<PackageVersion Include="SshSharp" Version="0.3.0" />
<PackageReference Include="SshSharp" />
paket add SshSharp --version 0.3.0
#r "nuget: SshSharp, 0.3.0"
#:package SshSharp@0.3.0
#addin nuget:?package=SshSharp&version=0.3.0
#tool nuget:?package=SshSharp&version=0.3.0
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: pre-1.0 (0.x releases). The API may still change before 1.0, and 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 and the Windows OpenSSH agent) and agent forwarding, keyboard-interactive (one-time codes, PAM), and multi-factor chains. - Host verification:
StrictHostKeyCheckingpolicies, host certificates,UpdateHostKeys, key pinning, or your own verifier. There is no "accept anything" default. - Connections: ProxyJump chains, ProxyCommand, connect over any
Stream, keep-alive and dead-connection detection; TCP and Unix-socket tunnels; local, remote and dynamic (SOCKS) port forwarding (ssh -L,-R,-D), also started fromssh_config. - Sessions: run commands, stream stdin/stdout/stderr, interactive shells with a pseudo-terminal, environment variables, signals and window resizing.
- Modern algorithms: post-quantum
mlkem768x25519-sha256(on .NET 10 where the platform has ML-KEM),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: 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.
- Observability:
ILoggerlogging,ActivitySourcetracing andMetermetrics, with no secrets recorded.
Coming next: SFTP, as a separate package.
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, Include; connect by alias) |
✅ | ❌ |
known_hosts verification (hashed hosts, @cert-authority, @revoked, StrictHostKeyChecking) |
✅ | ❌ (verify in a HostKeyReceived handler) |
UpdateHostKeys (key rotation) |
✅ | ❌ |
| ProxyJump chains, ProxyCommand | ✅ | ❌ (SOCKS4/5 and HTTP proxies) |
SSH agent (ssh-agent, Windows OpenSSH agent) |
✅ | ❌ |
| Agent forwarding | ✅ | ❌ |
| Password, public key, keyboard-interactive, multi-factor | ✅ | ✅ |
| 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 |
| Post-quantum key exchange | mlkem768x25519-sha256 (.NET 10 with platform ML-KEM) |
mlkem768x25519-sha256, sntrup761x25519-sha512 |
| Strict key exchange (Terrapin fix) | ✅ | ✅ |
Legacy algorithms (CBC, 3DES, SHA-1, ssh-rsa, DH group 1, zlib) |
— (by design) | ✅ |
| Commands, shells with a terminal | ✅ | ✅ |
| Local, remote and dynamic port forwarding | ✅ (also Unix-socket tunnels, and from ssh_config) |
✅ |
| SCP | ✅ | ✅ |
| SFTP | Planned (SshSharp.Sftp) |
✅ |
| 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 |
ILogger |
| Fuzzing | ✅ (coverage-guided, nightly; every parser in each test run) | ❌ |
| Mutation testing | ✅ (Stryker.NET, weekly) | ❌ |
| Maturity | New, pre-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, SFTP today, servers that only speak legacy algorithms, a connection through an HTTP or SOCKS proxy, or a long track record. Moving from SSH.NET? See the migration guide.
Install
dotnet add package SshSharp
Examples
Connect with a key and verify the host against ~/.ssh/known_hosts:
using SshSharp;
using SshSharp.Config;
using var key = await SshPrivateKey.LoadFileAsync("/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
- 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 (SCP)
- Configuration files
- Errors and diagnostics: exceptions, logging, tracing, metrics
- Migrating from SSH.NET: the same tasks, side by side
- Samples: a small
ssh-like tool (commands, streaming, shell, port forwarding, SOCKS, SCP) - API reference: generated from the XML documentation with DocFX (
dotnet tool restore, thendotnet docfx docs/docfx.json --serve); every public member is documented, and IntelliSense shows the same text. - Design notes, threat model, cryptography review
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 (>= 10.0.12)
- System.IO.Pipelines (>= 10.0.12)
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.