none
SFTP Communications in C# using Private - Public key

    Question

  • Hi everyone,

    I need a sample C# code for following:

    I need to download certain files from a server with Secure FTP connection using username, password & private -public key as authentication mode. Private key will reside in my m/c and public key in server. Hostname, port, username & password have to be provided same like plain FTP connection.

    I need a sample code for above case. I can not use any commercial version, I have to use some free / opne source copy.

    Please help me in urgent basis.


    Best Regards, Arka Mitra.
    Tuesday, July 06, 2010 11:52 AM

All replies

  • Hi,

     

    You can use http://www.tamirgal.com/blog/page/SharpSSH.aspx

    For the private SSH key you should convert it to OpenSSH format.

     

    Regards,

     

    Tuesday, July 06, 2010 3:32 PM
  • Hi Link,

    Thanks for ur guidance. Downloaded the code and tried but with little success.

    I noticed a few things:

    1. In my case port is not default 22, its some other port.

    2. How to convert private SSH key to OpenSSH format? Its showing invalid private key.

    3. I also have a password which is required for login.

    What I have understand, in my case, combining private key, password & public key, a composite key is generated and it is used for authentication. Very similar how WinSCP.exe works.

    Can you please extend your help again.


    Best Regards, Arka Mitra.
    Thursday, July 08, 2010 7:19 AM
  • Hello, Arka

    Tamir Gal has uploaded a project for SFTP Communications using public key and private key. And he also wrote an article talking about this.

    See this link http://www.codeproject.com/KB/IP/sharpssh.aspx

    Thanks

    Chao

    Friday, July 09, 2010 10:57 AM
    Moderator
  • Hi,

     

    1. you can specify the port as you want.

    2. Use PuttyGen to generate and convert the key (Conversion -> export OpenSSH Key)

    3. You can also add a user and password.

    I wrote an SftPlugin class with a sample that uses Tamir.SharpSssh, You can customize it as you want and add the methods that you want :

     

    namespace Test.SFTP
    {
      using System;
      using System.Linq;
      using Tamir.SharpSsh;
    
      class Program
      {
        static void Main(string[] args)
        {
          string host = "192.xx.xx.xx";
          int port = 455;
          string user = "user";
          string pass = "pass";
          string privateKey = @"C:\key.ppk";
    
          SftpPlugin sftp = new SftpPlugin(host, port, user, pass, privateKey);
    
          // uplload a file
          bool done = sftp.UploadFile(@"C:\test.xml", "dir/");
    
        }
      }
    
      public class SftpPlugin
      {
        // Private fields
        private int _port;
        private string _privateSshKeyPath;
        private Tamir.SharpSsh.Sftp _tamirSftp;
    
        // Constructors
        public SftpPlugin(string host, string username, string password)
        {
          this._tamirSftp = new Sftp(host, username, password);
          this._port = 22; // default Port 22
        }
    
        public SftpPlugin(string host, int port, string username, string password)
        {
          this._tamirSftp = new Sftp(host, username, password);
          this._port = port;   // Specific port
        }
    
        public SftpPlugin(string host, int port, string username, string password, string privateSshKeyPath)
        {
          this._tamirSftp = new Sftp(host, username, password);
          this._port = port;
          this._privateSshKeyPath = privateSshKeyPath;
        }
    
        // Private Methods
        private void Connect()
        {
          this._tamirSftp.Connect(this._port);
    
          // add the private Key if it is specified
          if (!string.IsNullOrEmpty(this._privateSshKeyPath))
          {
            this._tamirSftp.AddIdentityFile(this._privateSshKeyPath);
          }
        }
    
        // Public Methods
    
        // upload a list of files to a remote path
        public bool UploadFiles(string[] files, string toRemotePath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          try
          {
            this._tamirSftp.Put(files, toRemotePath);
            return true;
          }
          catch (Exception ex)
          {
            // You can also log the exception
            // Or use a timeout to repeat the operation
            // several times
            return false;
          }
          finally
          {
            this._tamirSftp.Close();
          }
        }
    
        // upload a file to a remote path
        public bool UploadFile(string file, string toRemotePath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          try
          {
            this._tamirSftp.Put(file, toRemotePath);
            return true;
          }
          catch (Exception ex)
          {
            // You can also log the exception
            // Or use a timeout to repeat the operation
            // several times
            return false;
          }
          finally
          {
            this._tamirSftp.Close();
          }
        }
    
        // download a list of files to a local path
        public bool DownloadFiles(string[] files, string toLocalPath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          try
          {
            this._tamirSftp.Get(files, toLocalPath);
            return true;
          }
          catch (Exception ex)
          {
            // You can also log the exception
            // Or use a timeout to repeat the operation
            // several times
            return false;
          }
          finally
          {
            this._tamirSftp.Close();
          }
        }
    
        // download a file to a localPath
        public bool DownloadFile(string file, string toLocalPath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          try
          {
            this._tamirSftp.Get(file, toLocalPath);
            return true;
          }
          catch (Exception ex)
          {
            // You can also log the exception
            // Or use a timeout to repeat the operation
            // several times
            return false;
          }
          finally
          {
            this._tamirSftp.Close();
          }
        }
    
        // list the files of a remote location
        public string[] ListFiles(string remotePath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          string[] files = new string[] { };
          try
          {
            files = this._tamirSftp.GetFileList(remotePath).Cast<string>().ToArray();
          }
          catch (Exception ex)
          {
            // You can also log the exception
            // Or use a timeout to repeat the operation
            // several times
          }
          finally
          {
            this._tamirSftp.Close();
          }
          return files;
        }
    
        //
        // You can add other methods, Just explore the class Tamir.SharpSsh.Sftp
        //
      }
    }
    

    Regards,

    • Marked as answer by Chao KuoModerator Monday, July 12, 2010 12:16 PM
    • Unmarked as answer by Arka Mitra Tuesday, July 13, 2010 7:42 AM
    • Proposed as answer by Link.fr Saturday, August 21, 2010 9:32 PM
    Saturday, July 10, 2010 1:34 PM
  • Hi Link,

    Thanks for sample code. I copy-paste your exact code. I got exception in:

        private void Connect()
        {
          this._tamirSftp.Connect(this._port);   //error in this line
    
          // add the private Key if it is specified
          .....
         }
    

    Following is the error log:

    Tamir.SharpSsh.jsch.JSchException: Auth fail
       at Tamir.SharpSsh.jsch.Session.connect(Int32 connectTimeout)
       at Tamir.SharpSsh.jsch.Session.connect()
       at Tamir.SharpSsh.SshBase.ConnectSession(Int32 tcpPort)
       at Tamir.SharpSsh.SshBase.Connect(Int32 tcpPort)
       at Tamir_OpenSource.SftpPlugin.Connect() in D:\Demo\SFTPTest\Tamir_OpenSource\Program.cs:line 64

     

     

     


    Best Regards, Arka Mitra.
    Monday, July 12, 2010 5:51 AM
  • Hi,

    This error means that the authentication to the sftp server failed.

    Could you test the connection with WinSCP

    Winscp use the PuttyGen Format and Tamir the OpenSSH Format.

    Make sure that the private key is in the right format.

     

    Regards,

    • Marked as answer by Chao KuoModerator Monday, July 12, 2010 12:17 PM
    • Unmarked as answer by Arka Mitra Tuesday, July 13, 2010 7:42 AM
    • Proposed as answer by Link.fr Saturday, August 21, 2010 9:33 PM
    Monday, July 12, 2010 11:18 AM
  • Hi Link,

    I have tesed the connection with WinSCP and able to connect sucessfully.

    Can you please help me to convert the private key from PuttyGen format to OpenSSH format.

    I have used one trial DLL by Rebex. They also use host ip, port no., username, password and private key , all 5 to authenticate and login into the SFTP server. Am able to login and download/upload file successfully, but I need some open source code. I can not use their DLL, Tamir's code is open source.


    Best Regards, Arka Mitra.
    Tuesday, July 13, 2010 7:42 AM
  • Hi,

     

    1. Load the private key generated by PuttyGen

    2. Conversion -> Export OpenSSH Key (Menu bar of PuttyGen) to convert the key to OpenSSH format

     

    Also, you should put the AddIdentity in the connect method before the connect.

     

    Regrads,

    • Proposed as answer by Link.fr Saturday, August 21, 2010 9:33 PM
    Tuesday, July 13, 2010 12:50 PM
  • Hi Link,

    Thanks very much , but am yet to break through.

    Just followed what you have told and used all 3 algo (SSH-1 RSA, SSH-2 RSA, SSH-2 DSA) one by one and generated the private key in OpenSSH format. Also used AddIdentityFile, but all in vein.

    Code am using : 

    private void Connect()
    {
       try
       {
    
         this._tamirSftp.AddIdentityFile(this._privateSshKeyPath);
    
         this._tamirSftp.Connect(this._port);   //error here
    
         .....
       }
       ....
    }      
    

    The error log reads:

    Tamir.SharpSsh.jsch.JSchException: Auth fail
       at Tamir.SharpSsh.jsch.Session.connect(Int32 connectTimeout)
       at Tamir.SharpSsh.jsch.Session.connect()
       at Tamir.SharpSsh.SshBase.ConnectSession(Int32 tcpPort)
       at Tamir.SharpSsh.SshBase.Connect(Int32 tcpPort)
       at Tamir_OpenSource.SftpPlugin.Connect() in D:\Demo\SFTPTest\Tamir_OpenSource\Program.cs:line 67

    Really don't know where am going wrong.

    Am pasting my full code. Just try in your m/c.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Tamir.SharpSsh;
    
    namespace Tamir_OpenSource
    {
      class Program
      {
        static void Main(string[] args)
        {
          try
          {
            string host = "xxxxx";
            int port = 9019;
            string user = "xxxxx";
            string pass = "xxxxx";
            string privateKey = @"C:\private_OpenSSH.ppk";
    
            SftpPlugin sftp = new SftpPlugin(host, port, user, pass, privateKey);
    
            string[] files = sftp.ListFiles("pwcjv06i_20100712.dat");
    
            //download a file
            bool done1 = sftp.DownloadFile("pwcjv06i_20100712.dat", @"C:\pwcjv06i_20100712.dat");
    
            // uplload a file
            //bool done2 = sftp.UploadFile(@"C:\ArkaMitra.log", "/");
          }
          catch (Exception ex)
          {
            .....
          }
        }
      }
    
      public class SftpPlugin
      {
        // Private fields
        private int _port;
        private string _privateSshKeyPath;
        private Tamir.SharpSsh.Sftp _tamirSftp;
    
        public SftpPlugin(string host, int port, string username, string password, string privateSshKeyPath)
        {
          this._tamirSftp = new Sftp(host, username, password);
          this._port = port;
          this._privateSshKeyPath = privateSshKeyPath;
        }
    
        // Private Methods
        private void Connect()
        {
          try
          {
            // add the private Key if it is specified
            if (!string.IsNullOrEmpty(this._privateSshKeyPath))
            {
              this._tamirSftp.AddIdentityFile(this._privateSshKeyPath);
              //this._tamirSftp.AddIdentityFile(this._privateSshKeyPath, "pa$$%phr@se");
            }
    
            this._tamirSftp.Connect(this._port);
          }
          catch (Exception ex)
          {
            throw ex;
          }
        }
    
        // Public Methods
    
        // upload a file to a remote path
        public bool UploadFile(string file, string toRemotePath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          try
          {
            this._tamirSftp.Put(file, toRemotePath);
            return true;
          }
          catch (Exception ex)
          {
            throw new Exception(ex.Message);
          }
          finally
          {
            this._tamirSftp.Close();
          }
        }
    
        // download a file to a localPath
        public bool DownloadFile(string file, string toLocalPath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          try
          {
            this._tamirSftp.Get(file, toLocalPath);
            return true;
          }
          catch (Exception ex)
          {
            throw new Exception(ex.Message);
          }
          finally
          {
            this._tamirSftp.Close();
          }
        }
    
        // list the files of a remote location
        public string[] ListFiles(string remotePath)
        {
          if (!this._tamirSftp.Connected)
          {
            this.Connect();
          }
    
          string[] files = new string[] { };
          try
          {
            files = this._tamirSftp.GetFileList(remotePath).Cast<string>().ToArray();
          }
          catch (Exception ex)
          {
            throw new Exception(ex.Message);
          }
          finally
          {
            this._tamirSftp.Close();
          }
          return files;
        }
      }
    }
    
    

     


    Best Regards, Arka Mitra.
    Wednesday, July 14, 2010 6:10 AM
  • Hi Arka,

    I've just tested the connection on an SFTP server that requires a private key and it works. The format supported is SSH-2-RSA.

    As the exception mention, it is linked to the connection to your sftp server. I advise you to follow the steps below to make sure that the connection works :

    1. Generate an SSH-2-RSA public key by PuttyGen
    2. Register the public key on the SFTP server
    3. Save the private key in putty Format
    4. Use WinSCP to connect to the sftp server using the private key generated in the step 3
    5. If the connection works, You will have to load the private key generated in the step 3 and  convert it to OpenSSh format.
    6. Use the private key generated in step 5, make sure that the authentication parameters are right, then test the tamirSftp connection.
    7. Make sure that you have a reference to the three DLL (DiffieHelman, OrgMantalis and TamirSharpSSH )
    Regards,
    Wednesday, July 14, 2010 12:31 PM
  • Hi Link.fr,

     

       I followed your code and everything is working properly. I am able to send the file to the remote server through SFTP with the public key authentication.

    Now my issue is, the user is requesting to send the file to a different remote SFTP path and now I need to change directory and then send the file to the parent directory.

    i.e when I log in, it takes me to HOME directory, from there I need to do the following

    Home>cd ..

    >cd Test

    Test>

    I don't know how to change directory and upload the file to the new directory. Need your help ASAP.


    Nick
    Thursday, August 05, 2010 12:14 AM
  • Hi Nick,

    You should simply put your server path in the upload method :

          string serverPath = "Test/";
    
          // uplload a file
          bool done = sftp.UploadFile(@"C:\test.xml", serverPath);

    Best regards.

    Saturday, August 21, 2010 9:29 PM
  • If you are using public/key private key to connect you need to move the AddIdentityFile call to before the Connect call, like so:

     

     private void Connect()
     {
        // add the private Key if it is specified
        if (!string.IsNullOrEmpty(this._privateSshKeyPath))
        {
          this._tamirSftp.AddIdentityFile(this._privateSshKeyPath);
        }
    
        this._tamirSftp.Connect(this._port);
     }
    
    If you use it the way it is, it will authenticate correctly if you use a password, but you will receive the 'Auth Fail' exception if you don't provide a password.

    Monday, January 10, 2011 9:06 PM
  • Hi Link,

     

    Thanks for the plugin

    I am using the above code

     

    string host = "sftp.xxxx.xxx.xxxxx.edu";

     

    int port = 22;

     

    string user = "xxxxxxxxx";

     

    string pass = "xxxxxxx";

     

    SftpPlugin sftp = new SftpPlugin(host, port, user, pass);

     

    //SftpPlugin sftp = new SftpPlugin(host, port, user, pass, privateKey);

     

    // uplload a file

    I am able to connect to the server and when i download its giving false

    bool done = sftp.DownloadFile("data/xxxxxxxx/processed/1_09_38182.txt", @"C:\");

    Please correct me if i am wrong anywhere

    Thanks in advance for any help

     

    Thanks

    Venkat

     

    Thursday, January 20, 2011 6:03 AM
  • Hi,

    You should put the name of file @"C:\yourfile.txt" instead @"C:\".

    Regards,

    Friday, January 21, 2011 7:19 PM
  • Hello,

     

    I am using SharpSSH-1.1.1.13 version application. I am getting the private key error while running the project. I used the keys which is generated through SmartFTP software in my application.

     

    Our application is working fine by the time when i generated keys using CoreFTP and use those keys in our application.

     

    So please let me know, Is there any way to use the keys generated through SmartFTP. If so how we can achieve that? (or) Is there any tool to convert the SmartFTP keys to the format which is to be supported by our SharpSSh application?

     

    Please do the needful to let me know the result as soon as possible.

     

    I also followed the way using the above mail.

    * Created Private/public key by the way of putty key generator

    * Converted the private file into OpenSSH format using putty software

    * Placed the .pub  file in CoreFTP Server and converted private file into client s place

    * Used the SharpSSH application by adding the private key file through AddIdentityFile method

     

    But i am getting following authentication error

     

    "Connecting...ee: Tamir.SharpSsh.jsch.JSchException: SSH_MSG_DISCONNECT: 2 key ch

    eck failed"

     

    So how could i use this application with the keys generated through various softwares like SmartFtp,Putty etc.

    What are the steps need to follow for converting and using the converted file in the application

     

    -Thanks

     

    Wednesday, January 26, 2011 3:22 PM
  • Hello Tamirgal,

    Is there any possiblity to use the keys generated through SmartFTP within our application. Is there any tool to convert the SmartFTP keys to the format which is to be supported by our SharpSSh application?

     

    I am using the SshFileTransferTest class to commuicate with remote server using SFTP. But i am getting the "Invalid Private key" error while i am try to communicate with the server through SmartFTP keys.

     

    So it would be greatful, if i could know how to resolve the issue as soon as possible.

     

    -Thanks

     

    Friday, January 28, 2011 11:40 AM
  • Hi,

    Use puttygen.

    Refere to answers below.

    Regards,

    Thursday, February 03, 2011 10:45 PM
  • Hello Link.fr

    The puttygen could not make sense, when i try to import the SmartFTP key to conversion it notifies error message like "could'not load private key".

    So please let me know some other way to resolve the issue.

     

    -thanks

    Tuesday, February 08, 2011 9:03 AM
  • Hi, 

     

    I have the private key in putty format that works fine when i'm connecting to the server so i did steps 5-7 but when trying to connect it throws me reject HostKey i found that in a blog that i should try this: 

     

    Hashtable config=new Hashtable();
    config.Add("StrictHostKeyChecking", "no");
    m_session.setConfig(config);

    m_session.connect();}
    I did that and now I get the "Auth Fail" error.. 

    Any suggestions??? thanks.

    Wednesday, February 23, 2011 9:56 PM
  • I got error "Cannot load script for excution."  Any ideas what missing?  Thanks!
    Ash_
    Friday, June 03, 2011 12:12 AM
  • Hello,

    Could you provide more informations about the error you are having ?

    is it in relation with ssis ?

    Kind regards,


    aelassas.free.fr
    Friday, June 03, 2011 4:19 PM
  • In SSIS, I created a script task which I copied the above code and changed the sftp info.  When executed the task, I get error.

    Error: Cannot load script for execution.

    Task Script Task failed


    Ash_
    Friday, June 03, 2011 4:38 PM
  • Hi,

    There is a similar answered post related to this error : here

    If you still face the same problem, I advise you to open a new post in the ssis forums.

    Kind regards,


    aelassas.free.fr
    Friday, June 03, 2011 5:10 PM
  • Hi,

    We are also facing same issue.Please let us know if you got any solution. Please provide us your contact number.

    Thursday, June 16, 2011 3:01 PM
  • Hi,

    I tried this but seems some sftp class is missing.Please let me know where can I get latest code.

    Really appreciate your quick response.

    Thursday, June 16, 2011 3:03 PM
  • Hi Mam,

    mam, I am also facing the same problem as in your code. I am facing prot is not connected.

    in this line of code----

    <p>this._tamirSftp.Connect(this._port);</p><pre style="padding:0px; border:none; font-size:14.399999618530273px; vertical-align:baseline; list-style-type:none; word-wrap:break-word; line-height:16.799999237060547px"><span style="margin:0px; padding:0px; border:0px; vertical-align:baseline; color:blue">private</span> <span style="margin:0px; padding:0px; border:0px; vertical-align:baseline; color:blue">void</span> Connect()
        {
          <span style="margin:0px; padding:0px; border:0px; vertical-align:baseline; color:blue">this</span>._tamirSftp.Connect(<span style="margin:0px; padding:0px; border:0px; vertical-align:baseline; color:blue">this</span>._port);   <span style="margin:0px; padding:0px; border:0px; vertical-align:baseline; color:green">//error in this line</span>
    
          <span style="margin:0px; padding:0px; border:0px; vertical-align:baseline; color:green">// add the private Key if it is specified</span>
          .....
         }
    

    if u hv solution then plz send me. i converted the private key in Open SSH format for tamir dll by PuTTY gen.

    with regard--avinash mishra

    Tuesday, June 04, 2013 11:05 AM