SSH uses various cryptographic algorithms for key exchange, encryption, message authentication, and compression. NullOpsDevs.LibSsh allows you to configure which algorithms to prefer and in what order during the SSH handshake.
Why Configure Algorithms?
By default, libssh2 negotiates algorithms automatically. However, you might want to customize preferences to:
Enforce strong security standards - Reject weak or deprecated algorithms
Ensure compatibility - Support specific server requirements
Meet compliance requirements - Satisfy security policies or regulations
The easiest way to use strong algorithms is to apply the secure defaults:
using NullOpsDevs.LibSsh;
var session = new SshSession();
// Apply secure algorithm preferences before connecting
session.SetSecureMethodPreferences();
session.Connect("example.com", 22);
This configures:
Key Exchange: Curve25519, ECDH with NIST curves, DH group exchange
Host Keys: Ed25519, ECDSA, RSA-SHA2 (no DSA)
Ciphers: ChaCha20-Poly1305, AES-GCM, AES-CTR
MACs: HMAC-SHA2-256/512 with encrypt-then-MAC
Compression: None
SSH Method Types
SSH uses different algorithm types for different purposes:
Configure specific algorithms for any method type before connecting:
using NullOpsDevs.LibSsh.Core;
var session = new SshSession();
// Only accept Ed25519 and ECDSA host keys (no RSA or DSA)
session.SetMethodPreferences(
SshMethod.HostKey,
"ssh-ed25519,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256"
);
// Use only ChaCha20 or AES-GCM ciphers
session.SetMethodPreferences(
SshMethod.CryptCs,
"[email protected],[email protected],[email protected]"
);
session.SetMethodPreferences(
SshMethod.CryptSc,
"[email protected],[email protected],[email protected]"
);
session.Connect("example.com", 22);
Preference Format
Algorithm preferences are specified as comma-separated lists in priority order:
First algorithm is most preferred
Last algorithm is least preferred
Server and client negotiate the first mutually-supported algorithm
// Most preferred → Least preferred
session.SetMethodPreferences(
SshMethod.Kex,
"curve25519-sha256,ecdh-sha2-nistp521,ecdh-sha2-nistp256,diffie-hellman-group14-sha256"
);
Checking Negotiated Algorithms
After connecting, verify which algorithms were actually negotiated:
try
{
session.Connect("example.com", 22);
}
catch (SshException ex) when (ex.Error == SshError.KexFailure)
{
Console.WriteLine("Key exchange failed - no common algorithms");
Console.WriteLine("Try adding more algorithms to your preferences");
}
Solution: Add more algorithms to support older servers:
var session = new SshSession();
session.SetSecureMethodPreferences();
session.Connect("example.com", 22);
// Verify only strong algorithms were negotiated
var kex = session.GetNegotiatedMethod(SshMethod.Kex);
var hostKey = session.GetNegotiatedMethod(SshMethod.HostKey);
if (kex?.Contains("sha1") == true || hostKey == "ssh-rsa")
{
Console.WriteLine("WARNING: Weak algorithms detected!");
session.Dispose();
return;
}
Console.WriteLine("Strong algorithms confirmed ✓");
Best Practices
Always set preferences before connecting:
session.SetSecureMethodPreferences(); // Must be before Connect()
session.Connect("example.com", 22);
Use secure defaults unless you have specific needs:
// Start with this
session.SetSecureMethodPreferences();
// Only customize if necessary
Log negotiated algorithms in production:
logger.LogInformation($"Connected with KEX: {session.GetNegotiatedMethod(SshMethod.Kex)}");
logger.LogInformation($"Host key: {session.GetNegotiatedMethod(SshMethod.HostKey)}");
Test with your target servers:
Different servers support different algorithms
Test your configuration before deploying
Prefer modern algorithms:
Ed25519 over RSA for host keys
Curve25519 over DH for key exchange
ChaCha20-Poly1305 or AES-GCM for ciphers
Disable weak algorithms:
Never include SHA-1 based algorithms in production
Avoid CBC-mode ciphers
Never use DSA keys
Complete Example
using NullOpsDevs.LibSsh;
using NullOpsDevs.LibSsh.Core;
using NullOpsDevs.LibSsh.Credentials;
using NullOpsDevs.LibSsh.Exceptions;
public class SecureConnection
{
public void ConnectWithStrongAlgorithms(string host, int port)
{
var session = new SshSession();
try
{
// Apply secure algorithm preferences
session.SetSecureMethodPreferences();
Console.WriteLine("Connecting with secure algorithms...");
session.Connect(host, port);
// Verify what was negotiated
Console.WriteLine("\nNegotiated Algorithms:");
Console.WriteLine($" Key Exchange: {session.GetNegotiatedMethod(SshMethod.Kex)}");
Console.WriteLine($" Host Key: {session.GetNegotiatedMethod(SshMethod.HostKey)}");
Console.WriteLine($" Cipher (C→S): {session.GetNegotiatedMethod(SshMethod.CryptCs)}");
Console.WriteLine($" Cipher (S→C): {session.GetNegotiatedMethod(SshMethod.CryptSc)}");
Console.WriteLine($" MAC (C→S): {session.GetNegotiatedMethod(SshMethod.MacCs)}");
Console.WriteLine($" MAC (S→C): {session.GetNegotiatedMethod(SshMethod.MacSc)}");
// Authenticate and use the connection
var credential = SshCredential.FromPublicKeyFile(
"username",
"~/.ssh/id_ed25519.pub",
"~/.ssh/id_ed25519"
);
if (session.Authenticate(credential))
{
Console.WriteLine("\nAuthentication successful!");
var result = session.ExecuteCommand("whoami");
Console.WriteLine($"Logged in as: {result.Stdout.Trim()}");
}
}
catch (SshException ex)
{
Console.WriteLine($"SSH error: {ex.Message}");
}
finally
{
session.Dispose();
}
}
}
See Also
SshSession.SetMethodPreferences() (SshSession.cs:215) - Set custom algorithm preferences