SshNet.Agent
2026.0.0
dotnet add package SshNet.Agent --version 2026.0.0
NuGet\Install-Package SshNet.Agent -Version 2026.0.0
<PackageReference Include="SshNet.Agent" Version="2026.0.0" />
<PackageVersion Include="SshNet.Agent" Version="2026.0.0" />
<PackageReference Include="SshNet.Agent" />
paket add SshNet.Agent --version 2026.0.0
#r "nuget: SshNet.Agent, 2026.0.0"
#:package SshNet.Agent@2026.0.0
#addin nuget:?package=SshNet.Agent&version=2026.0.0
#tool nuget:?package=SshNet.Agent&version=2026.0.0
SshNet.Agent
SSH.NET Extension to authenticate via OpenSSH Agent and PuTTY Pageant
.NET Frameworks
- .NET 4.8
- netstandard 2.0
- netstandard 2.1
- .NET 8.0
Note: Only the netstandard 2.1 and .NET 8.0 builds contain support for Unix Domain Sockets to use ssh-agent on Linux.
Keys
- ssh-ed25519
- ecdsa-sha2-nistp256
- ecdsa-sha2-nistp384
- ecdsa-sha2-nistp521
- ssh-rsa with 2048, 3072, 4096 or 8192 KeyLength
- sk-ssh-ed25519@openssh.com (FIDO/security key)
- sk-ecdsa-sha2-nistp256@openssh.com (FIDO/security key)
FIDO / security keys
FIDO identities (ssh-keygen -t ed25519-sk / -t ecdsa-sk) held by the agent
are offered to the server automatically. The agent drives the authenticator, so
touch (and, for verify-required keys, the PIN) is prompted at sign time; the
private key never leaves the hardware. These identities have no SSH.NET Key,
so SshAgentPrivateKey.Key is null for them; their comment is still available
via SshAgentPrivateKey.Comment, which every identity carries.
RSA and legacy ssh-rsa
RSA identities are offered as rsa-sha2-512 and rsa-sha2-256 (RFC 8332). The
legacy SHA-1 ssh-rsa signature algorithm is only offered when explicitly
enabled: it is needed solely for servers without RFC 8332 support (OpenSSH
older than 7.2), OpenSSH 8.8+ rejects it, and every offered algorithm costs one
of the server's MaxAuthTries.
var agent = new SshAgent { IncludeLegacySshRsa = true };
Features
- Auth
- Auth with OpenSSH Certificates
- Adding Keys
- Adding Keys with Constraints (lifetime, confirm)
- Adding and Removing PKCS#11 / Smartcard Keys
- Getting Keys
- Removing Keys
- Removing all Keys
- Locking and Unlocking the Agent
- Async API
Agent Protocol Documentation
Usage
OpenSSH Agent
var agent = new SshAgent();
var keyFile = new PrivateKeyFile("test.key");
agent.AddIdentity(keyFile);
var keys = agent.RequestIdentities();
using var client = new SshClient("ssh.foo.com", "root", keys);
client.Connect();
Console.WriteLine(client.RunCommand("hostname").Result);
PuTTY Pageant
var agent = new Pageant();
var keyFile = new PrivateKeyFile("test.key");
agent.AddIdentity(keyFile);
var keys = agent.RequestIdentities();
using var client = new SshClient("ssh.foo.com", "root", keys);
client.Connect();
Console.WriteLine(client.RunCommand("hostname").Result);
Pageant automatically talks to Pageant 0.77+ over its OpenSSH named pipe when
one is available (real async I/O, no WM_COPYDATA 8 KB message limit), and falls
back to the legacy WM_COPYDATA interface otherwise. No code change is needed.
The Pageant class is Windows only (its transports, WM_COPYDATA and the Windows
named pipe, do not exist elsewhere). On Linux, PuTTY's pageant serves the
standard agent protocol on a unix socket, so use SshAgent instead: pageant
sets SSH_AUTH_SOCK, which new SshAgent() picks up, or pass the socket path to
new SshAgent(path, null).
OpenSSH Certificates
Certificate identities held by the agent (*-cert-v01@openssh.com) are offered
to the server automatically; the agent signs with the matching private key. To
add a key together with its certificate, load the certificate alongside the
private key:
var agent = new SshAgent();
// test.key + the certificate signed by your CA (test-cert.pub)
agent.AddIdentity(new PrivateKeyFile("test.key", null, "test-cert.pub"));
var keys = agent.RequestIdentities();
// works against servers that trust the CA (TrustedUserCAKeys)
using var client = new SshClient("ssh.foo.com", "root", keys);
client.Connect();
Minting Certificates with SshNet.Keygen
The certificate above can be produced in .NET with
SshNet.Keygen, so the whole
short-lived-certificate flow - mint, load into the agent, authenticate - stays
in one process without shelling out to ssh-keygen:
// mint a short-lived user certificate for test.key, signed by your CA
var userKey = new PrivateKeyFile("test.key");
var certificate = new SshCertificateBuilder(userKey)
.WithKeyId("root@example.com")
.WithPrincipal("root")
.WithValidity(DateTime.UtcNow, DateTime.UtcNow.AddHours(8))
.SignWith(new PrivateKeyFile("ca"));
File.WriteAllText("test-cert.pub", certificate.ToOpenSshPublicFormat());
// load the key together with the freshly minted certificate ...
var agent = new SshAgent();
agent.AddIdentity(new PrivateKeyFile("test.key", null, "test-cert.pub"));
// ... and authenticate against a server that trusts the CA
using var client = new SshClient("ssh.foo.com", "root", agent.RequestIdentities());
client.Connect();
The same certificate can be served through an agent server, or used directly with SSH.NET without an agent.
Async
All agent operations are also available asynchronously and take an optional
CancellationToken:
var agent = new SshAgent();
await agent.AddIdentityAsync(new PrivateKeyFile("test.key"), cancellationToken);
var keys = await agent.RequestIdentitiesAsync(cancellationToken);
await agent.RemoveAllIdentitiesAsync(cancellationToken);
Note: Signing during authentication stays synchronous, since SSH.NET calls it
through its synchronous DigitalSignature contract.
Key Constraints
Keys can be added with the constraints known from ssh-add -t and ssh-add -c:
var agent = new SshAgent();
// the agent removes the key after 10 minutes and asks for
// confirmation on every use
agent.AddIdentity(new PrivateKeyFile("test.key"), TimeSpan.FromMinutes(10), confirm: true);
Locking and Unlocking
A locked agent hides its identities and refuses signing until it is unlocked
again, like ssh-add -x/ssh-add -X:
var agent = new SshAgent();
agent.Lock("passphrase");
// agent.RequestIdentities() is empty now
agent.Unlock("passphrase");
PKCS#11 / Smartcard Keys
Keys held on a PKCS#11 token can be added to and removed from the agent, like
ssh-add -s/ssh-add -e. The agent loads the key through the PKCS#11 provider
(a shared library path) and unlocks the token with the PIN; the private key
never leaves the token.
var agent = new SshAgent();
// ssh-add -s /usr/lib/opensc-pkcs11.so
agent.AddSmartcardIdentity("/usr/lib/opensc-pkcs11.so", "1234");
var keys = agent.RequestIdentities();
// ssh-add -e /usr/lib/opensc-pkcs11.so
agent.RemoveSmartcardIdentity("/usr/lib/opensc-pkcs11.so");
Smartcard keys can be added with the same lifetime/confirm constraints as regular keys:
agent.AddSmartcardIdentity("/usr/lib/opensc-pkcs11.so", "1234", TimeSpan.FromMinutes(10), confirm: true);
Resharper Warning
If you want to avoid the Resharper Warning "Co-variant array conversion": https://www.jetbrains.com/help/resharper/CoVariantArrayConversion.html
var agent = new Pageant();
var keyFile = new PrivateKeyFile("test.key");
agent.AddIdentity(keyFile);
var keys = agent.RequestIdentities();
using var client = new SshClient("ssh.foo.com", "root", keys.ToArray<IPrivateKeySource>());
client.Connect();
Console.WriteLine(client.RunCommand("hostname").Result);
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 is compatible. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
NuGet packages (3)
Showing the top 3 NuGet packages that depend on SshNet.Agent:
| Package | Downloads |
|---|---|
|
RoyalApps.RoyalTerminal.Terminal.Transport.Ssh.SshNet.Agent
Optional SSH.NET agent authentication adapter for terminal SSH transport. |
|
|
RoyalApps.RoyalTerminal.Avalonia.App
Reusable RoyalTerminal Avalonia application shell with window chrome, native menus, settings, capture replay UI, and multi-session terminal workflows. |
|
|
DplTools
Package Description |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on SshNet.Agent:
| Repository | Stars |
|---|---|
|
duplicati/duplicati
Store securely encrypted backups in the cloud!
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.0.0 | 5,178 | 8/14/2026 |
| 2024.2.0.5 | 675 | 7/21/2026 |
| 2024.2.0.4 | 144 | 7/16/2026 |
| 2024.2.0.4-beta | 122 | 7/14/2026 |
| 2024.2.0.3-beta | 552 | 5/14/2025 |
| 2024.2.0.2-beta | 349 | 5/14/2025 |
| 2024.2.0.1 | 90,047 | 12/3/2024 |
| 2024.2.0 | 12,638 | 12/2/2024 |
| 2024.0.0.2 | 475 | 10/18/2024 |
| 2024.0.0.2-beta | 449 | 3/25/2024 |
| 2024.0.0.1-beta | 234 | 3/24/2024 |
| 2024.0.0-beta | 219 | 3/16/2024 |
| 0.4.0-beta | 286 | 11/29/2023 |
| 0.3.0-beta | 218 | 11/29/2023 |
| 0.2.0-beta | 228 | 11/29/2023 |
| 0.1.0-beta | 707 | 3/7/2021 |