SSH.NET是否只接受OpenSSH格式的私钥?如果没有,有什么限制?

时间:2017-05-11 12:15:25

标签: c# .net ssh sftp ssh.net

手册并没有表明这一点,但是一些谷歌搜索从十年之交返回页面(例如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);
}

这挂钩到我们通过SCP2成功使用的私钥(Secure Copy 2详细here) - 它是2048 DSA,在SSH.NET文档中列为有效。密钥使用ssh.com格式,如:

---- 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 ----

但是,SSH.NET的私钥处理部分中有Regex无法匹配我们的私钥,因此抛出异常:

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)

如果我们将密钥转换为OpenSSH格式,它确实匹配,但由于业务限制,这不一定是我们可以在生产中使用的东西。

有没有人确切知道SSH.NET的私钥格式有哪些限制?我们不确定这次是否需要放弃SSH.NET用于其他SFTP包装器库,编写我们自己的或者什么。

1 个答案:

答案 0 :(得分:6)

正如PrivateKeyFile类型的代码内文档所示:

  

支持OpenSSH和ssh.com格式的RSA和DSA私钥。

我已经生成了新的ssh.com私钥:

---- 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 ----

SSH.NET 2016.0.0 PrivateKeyFile可以毫无问题地加载它。

PrivateKeyFile无法处理的关键是Subject:标题。删除它。

如果您需要完整的密钥文件,只需在运行时将其删除,同时阅读:

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);