使用SSH.NET字符串密钥认证SFTP时报Invalid private key file错误
SSH.NET使用私钥连接SFTP报错问题排查
问题背景
我开发的程序需要连接SFTP服务器做文件上传和拉取,服务器要求用私钥完成连接。我参考了相关技术帖子尝试实现,做了如下操作:
- 用PuTTYgen把拿到的.ppk格式私钥转换成OpenSSH格式
- 把转换得到的私钥内容复制到代码里,尝试基于该私钥创建
SftpClient实例
我写的代码如下:
SftpClient sftp = null; if (bHost.Equals("sftp.sftpHost.com")) { var keyStr = @"-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,15BEAB6C0B73F39A ***private key*** -----END RSA PRIVATE KEY-----"; using (var keystrm = new MemoryStream(Encoding.UTF8.GetBytes(keyStr))) { var privateKey = new PrivateKeyFile(keystrm, "passPhrase"); sftp = new SftpClient(bHost, bUser, new[] { privateKey }); } } else { sftp = new SftpClient(bHost, bPort, bUser, bPw); } return sftp;
现在运行报错提示私钥文件无效,我发现其他示例的密钥字符串里都没有如下内容:
Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,15BEAB6C0B73F39A
请问是代码有问题还是生成OpenSSH格式密钥的方式有误?
问题排查与解决方案
你遇到的问题和密钥的特殊头信息无关,这两行是加密RSA私钥的标准PEM头,其他示例没有是因为那些示例用的是未加密的私钥,本身是合法内容,不属于错误。
问题出在以下两个地方:
- 私钥字符串存在多余缩进
你用了C#的逐字字符串@"",字符串内每一行开头的缩进空格会被完整保留到keyStr中,而SSH私钥对格式校验非常严格,行首多余的空格会直接导致解析失败。 - 若你使用的是2016年之前的旧版本SSH.NET,对加密PEM格式的RSA私钥兼容存在已知bug。
修正方案
- 首先去掉私钥字符串里所有行的开头缩进,保证私钥内容顶格书写:
// 修正后的私钥字符串,无多余缩进 var keyStr = @"-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,15BEAB6C0B73F39A ***private key*** -----END RSA PRIVATE KEY-----";
- 升级SSH.NET到最新稳定版本,避免旧版本的兼容问题。
- 如果你不需要对私钥做加密保护,可以在PuTTYgen导出私钥时清除密钥密码,导出的OpenSSH格式私钥就不会包含
Proc-Type和DEK-Info这两行头信息,创建PrivateKeyFile实例时也不需要传入密码参数。
内容的提问来源于stack exchange,提问作者MERNboy
相关产品推荐
相关产品推荐

