在SSH.NET中使用PPK密钥进行身份validation

我正在创建一个窗口服务,用于从SFTP服务器下载文件。 为此,我使用的是Renci.SshNetRenci.SshNet.CommonRenci.SshNet.Sftp

我有这个代码:

 String Host = "HostName"; int Port = 22; String RemoteFileDirectory = Convert.ToString(ConfigurationManager.AppSettings["SourcePath"]); String Username = "UserName"; String Password = "*******"; var KeybasedMethod = new KeyboardInteractiveAuthenticationMethod(Username); KeybasedMethod.AuthenticationPrompt += (sender, e) => { e.Prompts.First().Response = password; }; AuthenticationMethod[] methods = new AuthenticationMethod[] { new PrivateKeyAuthenticationMethod(Username, new PrivateKeyFile(@"Z:\SFTP SETUP\CJ22")), KeybasedMethod }; ConnectionInfo connectionInfo = new ConnectionInfo(hostname, username, methods); using (var sftp = new SftpClient(connectionInfo)) { sftp.Connect(); // ... } 

我得到例外。

私钥文件无效。

我无法弄清楚我的代码中缺少的是什么。

下面是我使用FileZilla从客户端计算机登录服务器时获得的日志文件。

 2017-04-03 16:25:19 8120 3 Status: Connecting to abc.domainname.com... 2017-04-03 16:25:19 8120 3 Trace: Going to execute "C:\Program Files\FileZilla FTP Client\fzsftp.exe" 2017-04-03 16:25:19 8120 3 Response: fzSftp started 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectParseResponse(fzSftp started) 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectSend() 2017-04-03 16:25:19 8120 3 Command: keyfile "Z:\SFTP SETUP\CJ21_PVT.ppk" 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectParseResponse() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectSend() 2017-04-03 16:25:19 8120 3 Command: keyfile "Z:\SFTP SETUP\CJ22_PVT.ppk" 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectParseResponse() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectSend() 2017-04-03 16:25:19 8120 3 Command: keyfile "Z:\SFTP SETUP\CJ24_PVT.ppk" 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectParseResponse() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectSend() 2017-04-03 16:25:19 8120 3 Command: keyfile "Z:\SFTP SETUP\CJ90_PVT.ppk" 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectParseResponse() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:19 8120 3 Trace: CSftpControlSocket::ConnectSend() 2017-04-03 16:25:19 8120 3 Command: open "CJ22@abc.domainname.com" 22 2017-04-03 16:25:19 8120 3 Trace: Looking up host "abc.domainname.com" 2017-04-03 16:25:19 8120 3 Trace: Connecting to xxx.xxx.163.74 port 22 2017-04-03 16:25:23 8120 3 Trace: Server version: SSH-2.0-1.82_sshlib Globalscape 2017-04-03 16:25:23 8120 3 Trace: Using SSH protocol version 2 2017-04-03 16:25:23 8120 3 Trace: We claim version: SSH-2.0-PuTTY_Local:_Mar_28_2014_10:34:48 2017-04-03 16:25:24 8120 3 Trace: Doing Diffie-Hellman group exchange 2017-04-03 16:25:24 8120 3 Trace: Doing Diffie-Hellman key exchange with hash SHA-1 2017-04-03 16:25:25 8120 3 Trace: Host key fingerprint is: 2017-04-03 16:25:25 8120 3 Trace: ssh-rsa 2048 6b:80:2c:5e:af:3f:2c:c7:f7:ef:4b:dd:85:55:32:fe 2017-04-03 16:25:25 8120 3 Trace: Initialised AES-256 SDCTR client->server encryption 2017-04-03 16:25:25 8120 3 Trace: Initialised HMAC-SHA1 client->server MAC algorithm 2017-04-03 16:25:25 8120 3 Trace: Initialised AES-256 SDCTR server->client encryption 2017-04-03 16:25:25 8120 3 Trace: Initialised HMAC-SHA1 server->client MAC algorithm 2017-04-03 16:25:25 8120 3 Trace: Successfully loaded 4 key pairs from file 2017-04-03 16:25:26 8120 3 Trace: Offered public key from "Z:\SFTP SETUP\CJ21_PVT.ppk" 2017-04-03 16:25:26 8120 3 Trace: Server refused public key 2017-04-03 16:25:26 8120 3 Trace: Offered public key from "Z:\SFTP SETUP\CJ22_PVT.ppk" 2017-04-03 16:25:26 8120 3 Trace: Offer of public key accepted, trying to authenticate using it. 2017-04-03 16:25:29 8120 3 Trace: Further authentication required 2017-04-03 16:25:30 8120 3 Trace: Using keyboard-interactive authentication. inst_len: 0, num_prompts: 1 2017-04-03 16:25:30 8120 3 Command: Pass: ********* 2017-04-03 16:25:30 8120 3 Trace: Access granted 2017-04-03 16:25:30 8120 3 Trace: Opened channel for session 2017-04-03 16:25:31 8120 3 Trace: Started a shell/command 2017-04-03 16:25:31 8120 3 Status: Connected to abc.domainname.com 2017-04-03 16:25:33 8120 3 Trace: CSftpControlSocket::ConnectParseResponse() 2017-04-03 16:25:33 8120 3 Trace: CSftpControlSocket::ResetOperation(0) 2017-04-03 16:25:33 8120 3 Trace: CControlSocket::ResetOperation(0) 2017-04-03 16:25:33 8120 3 Trace: CFileZillaEnginePrivate::ResetOperation(0) 2017-04-03 16:25:33 8120 3 Status: Retrieving directory listing... 2017-04-03 16:25:33 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:33 8120 3 Trace: CSftpControlSocket::ChangeDirSend() 2017-04-03 16:25:33 8120 3 Command: cd "/" 2017-04-03 16:25:34 8120 3 Response: New directory is: "/" 2017-04-03 16:25:34 8120 3 Trace: CSftpControlSocket::ResetOperation(0) 2017-04-03 16:25:34 8120 3 Trace: CControlSocket::ResetOperation(0) 2017-04-03 16:25:34 8120 3 Trace: CSftpControlSocket::ParseSubcommandResult(0) 2017-04-03 16:25:34 8120 3 Trace: CSftpControlSocket::ListSubcommandResult() 2017-04-03 16:25:34 8120 3 Trace: state = 1 2017-04-03 16:25:34 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:34 8120 3 Trace: CSftpControlSocket::ListSend() 2017-04-03 16:25:34 8120 3 Trace: state = 2 2017-04-03 16:25:34 8120 3 Command: ls 2017-04-03 16:25:34 8120 3 Status: Listing directory / 2017-04-03 16:25:36 8120 3 Listing: drwxrw-rw- 1 user group 0 Mar 24 2015 JKOB1 2017-04-03 16:25:36 8120 3 Listing: drwxrw-rw- 1 user group 0 Apr 3 10:40 JKOB 2017-04-03 16:25:36 8120 3 Trace: CSftpControlSocket::ListParseResponse() 2017-04-03 16:25:36 8120 3 Trace: CSftpControlSocket::SendNextCommand() 2017-04-03 16:25:36 8120 3 Trace: CSftpControlSocket::ListSend() 2017-04-03 16:25:36 8120 3 Trace: state = 3 2017-04-03 16:25:36 8120 3 Status: Calculating timezone offset of server... 2017-04-03 16:25:36 8120 3 Command: mtime "JKOB" 2017-04-03 16:25:37 8120 3 Response: 1491216040 2017-04-03 16:25:37 8120 3 Trace: CSftpControlSocket::ListParseResponse(1491216040) 2017-04-03 16:25:37 8120 3 Status: Timezone offsets: Server: 0 seconds. Local: 19800 seconds. Difference: 19800 seconds. 2017-04-03 16:25:37 8120 3 Trace: CSftpControlSocket::ResetOperation(0) 2017-04-03 16:25:37 8120 3 Trace: CControlSocket::ResetOperation(0) 2017-04-03 16:25:37 8120 3 Status: Directory listing successful 2017-04-03 16:25:37 8120 3 Trace: CFileZillaEnginePrivate::ResetOperation(0) 2017-04-03 16:27:24 8120 3 Status: Disconnected from server 2017-04-03 16:27:24 8120 3 Trace: CControlSocket::DoClose(64) 2017-04-03 16:27:24 8120 3 Trace: CSftpControlSocket::ResetOperation(66) 2017-04-03 16:27:24 8120 3 Trace: CControlSocket::ResetOperation(66) 2017-04-03 16:27:24 8120 3 Trace: CFileZillaEnginePrivate::ResetOperation(66) 2017-04-03 16:27:24 8120 3 Trace: CControlSocket::DoClose(64) 2017-04-03 16:27:24 8120 3 Trace: CControlSocket::DoClose(64) 2017-04-03 16:27:24 8120 3 Trace: CFileZillaEnginePrivate::ResetOperation(0) 

我已经尝试了从这里和其他来源的多个解决方案一个接一个,但没有一个工作。 如果您有任何建议,那么非常欢迎。

SSH.NET不支持.ppk密钥文件。 您必须使用PuTTYgen将.ppk密钥转换为OpenSSH格式。

请参见如何将使用PuTTYgen(Windows)生成的SSH密钥对转换为ssh-agent和Keychain(Linux)使用的密钥对 。


问题编辑前的原始答案:

您正在FileZilla中使用多重私钥和键盘交互式身份validation:

2017-04-03 16:25:26 8120 3跟踪:从“Z:\ SFTP SETUP \ CJ22_PVT.ppk”提供公钥
2017-04-03 16:25:26 8120 3跟踪:接受公钥提供,尝试使用它进行身份validation。
2017-04-03 16:25:29 8120 3跟踪:需要进一步的身份validation
2017-04-03 16:25:30 8120 3跟踪:使用键盘交互式身份validation。 inst_len:0,num_prompts:1
2017-04-03 16:25:30 8120 3命令:通过:*********
2017-04-03 16:25:30 8120 3跟踪:授予访问权限

同时,您在代码中使用简单的密码validation:

 using (var sftp = new SftpClient(Host, Port, Username, Password)) 

你怎么能期望这个工作?


要实现多路复用器身份validation,您必须使用ConnectionInfo

 var keybInterMethod = new KeyboardInteractiveAuthenticationMethod(username); keybInterMethod.AuthenticationPrompt += (sender, e) => { e.Prompts.First().Response = password; }; AuthenticationMethod[] methods = new AuthenticationMethod[] { new PrivateKeyAuthenticationMethod(username, new PrivateKeyFile(privateKey)), keybInterMethod }; ConnectionInfo connectionInfo = new ConnectionInfo(hostname, username, methods); using (var sftp = new SftpClient(connectionInfo)) { sftp.Connect(); // ... }