The manual doesn't indicate such, but some Googling returns pages from the turn of the decade (such as this) suggesting that this at least used to be the case. We have code like this:
var privateKeyAuthenticationMethod =
new PrivateKeyAuthenticationMethod(userName, new PrivateKeyFile(privateKeyLocation));
var connInfo =
new ConnectionInfo(
ftpSettings.HostAddress, ftpSettings.UserName, privateKeyAuthenticationMethod);
using (var client = new SftpClient(connInfo))
{
client.Connect();
client.UploadFile(memStreamData, destination);
}
This hooks into a private key that we have used successfully via SCP2 (Secure Copy 2 as detailed here) - it is 2048 DSA, which is listed as valid in the SSH.NET documentation. The key uses an ssh.com format like:
---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
Subject: <FID name>
Comment: "2048-bit dsa, <FID name>@<Server name>, Mon Apr 24 201\
7 15:49:36 +0100"
<ENCRYPTED KEY>
---- END SSH2 ENCRYPTED PRIVATE KEY ----
However, there is a Regex
within the private key handling portion of SSH.NET that fails to match our private key, and so throws an exception:
ERROR 2017-05-10 15:31:43 UTC [T: 474] – Invalid private key file.
ERROR 2017-05-10 15:31:43 UTC [T: 474] – at Renci.SshNet.PrivateKeyFile.Open(Stream privateKey, String passPhrase)
It does however match if we convert the key to OpenSSH format, but this is not necessarily something that we can use in production due to business constraints.
Does anyone know exactly what the restrictions are on Private Key format for SSH.NET please? We are not sure if this time if we need to abandon SSH.NET for some other SFTP wrapper library, write our own, or what.
As the in-code documentation for PrivateKeyFile
type says:
Supports RSA and DSA private key in both OpenSSH and ssh.com format.
I have generated new ssh.com private key:
---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
Comment: "dsa-key-20170511"
P2/56wAAA4IAAAAmZGwtbW9kcHtzaWdue2RzYS1uaXN0LXNoYTF9LGRoe3BsYWlufX0AAA
AEbm9uZQAAA0QAAANAAAAAAAAACACOT7SBNaNYmT13gDCCFyE/3yEs6oVbmmGVM6dIesTC
iwY26oHL2JKNLh2gHYfwa9iwDESAH6CIUR+Jf19KXLyNMLQgsoEhfZRS35mDC0pyoYgD77
N2VXt7hkEYFYuJK459HmmoJ2DABdZ9Anb6twDwfY7XhRdLz2H44OOifd1qKjYd/qzsm9MQ
4qUDHYsJpfCly2DFjcFy915fPW4IrTguCRRv545B949iZD/9VcysVe5Cs5DKe1zQybgs2L
qRgMXVS8eHIx4ASNRP6Z9gllkPK2CqWMeLL7P0oR6fNuC8T02xy0CTNh9s041mB7zN5Sfy
kuTzqh6Wkj3t9Z9Fv8YxAAAH/iadRhuaJzO7c9oA4+Z/aPwcTQZQiyeZ0jzTzKUZsyOUiV
PDGxsAuBAcMapskELDdWy0n0S0im4HyxouQrQxqIHBtzucuD4YznIdsCCjs8S0NiBLXEE1
DYyiIpnAgpoC1j6b00L3LosaI2szOAp2fGB2dtXizX6fIkUZssNZthEbpOKGvItor7JUv8
urcbl56S9B+mdyTm/a+zKP+Q5rC9mjd/N6X+9+pZxPoSfEzgclUOLxC+zJigpUEZ9UcqGR
eCT881CKmd0HRrVG3uzgVvsnnzX7wyTnOqg2CXuESB3NvvlzM2Vsa3UuBU1AjBj1++0h5Q
VJ83MZmlp2seG0m3MAAACg22bQYT6jD8GG9XaeoHXwnaPCB8kAAAgAh5QuiehV7IZN9G0R
V4t/sdnhA8M5X7YXw9iQUu08TYmPomZATI/7OlUYySPsjuf5IbRWSKXVP1x2Rku8gJQnAI
lbS6jhxHjx61fwD4jctaCZdI1MzXgW/PtIv3Sc6JyJdnD1dqKieUuRG6PhTFqoG3F1YHyy
VydaIhB1vKi90sTJ5AXXEZG81Q7yRBItJqr46XBz0W4CqQS6aguzzO9ZEdcadJGfDF6Bp8
Ymxzf58lYNrCJem4p7axM7P/9HaNW4xzRb5N0hyBYjFXAFa/mo2jARWHQTGeQy7KbdfUKE
vkxd96qK3InQHijWelnKAT5KgFaM9P1AEsgLnNRlQdn/fwAAAJ4qvy/nqPvqBwotQLLE0I
M9rbFIdA==
---- END SSH2 ENCRYPTED PRIVATE KEY ----
The SSH.NET 2016.0.0 PrivateKeyFile
can load it without any problem.
One thing with your key, that the PrivateKeyFile
cannot handle, is the Subject:
header. Remove it.
If you need the key file intact, just remove it on-the-fly, while reading:
string key = File.ReadAllText(@"C:\path\key");
Regex removeSubjectRegex = new Regex("Subject:.*[\r\n]+", RegexOptions.IgnoreCase);
key = removeSubjectRegex.Replace(key, "");
MemoryStream buf = new MemoryStream(Encoding.UTF8.GetBytes(key));
PrivateKeyFile privateKeyFile = new PrivateKeyFile(buf);