Search code examples
phpphpseclib

PHP PHPSECLIB SFTP using private key giving error on RSA Cannot instantiate abstract class


I worked through getting phplibsec v3 installed using composer. I got the pathing right and it now does not give any errors until it hits $rsa = new RSA(). It then errors and says: PHP Fatal error: Uncaught Error: Cannot instantiate abstract class phpseclib3\C rypt\RSA in C:\Temp\PHPSCRIPTS\mmax_send_gl_file.php:6 Stack trace: #0 {main} thrown in C:\Temp\PHPSCRIPTS\mmax_send_gl_file.php on line 6

Here is my code:

require 'c:\temp\php\vendor\autoload.php';
use phpseclib3\Net\SSH2;
use phpseclib3\Crypt\RSA;
use phpseclib3\Net\SFTP;
$rsa = new RSA();
$rsa->loadKey(file_get_contents('C:\temp\phpscripts\mmax.ppk'));
$sftp = new SFTP('sftp.server.com');
echo $sftp->get('test.txt');

If I take the $rsa lines out, the new SFTP does not blow up, but I need the private key. I have tried several variations, read every post on this and worked on this for hours. I cannot get it to work. Can anyone tell me what I am doing wrong?

Also, I can log in to the ftp site with filezilla with sftp and it works fine. I just put the host in and selected key file for login type and loaded the ppk contents into it and no problems.

I found out that I needed to do:

$rsa = PublicKeyLoader::load(file_get_contents('C:\temp\phpscripts\mmax.ppk'));

Now my code is:

require 'c:\temp\php\vendor\autoload.php';
use phpseclib3\Net\SSH2;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Net\SFTP;
$rsa = PublicKeyLoader::load(file_get_contents('C:\temp\phpscripts\mmax.ppk'));
$sftp = new SFTP('sftp.server.com');
if (!$sftp->login('username', $rsa)) {
   exit('Login Failed');
}
echo $sftp->get('test.txt');

It is not logging in and I can't find documentation on how to use the login part with a private key. Also, I do not need a username.


Solution

  • I was able to get through this. For more background, see neubert's link. As discussed above, I used phpseclib v3. The rsa things have changed and now use PublicKeyLoader::load.

    It still would not connect because I was not provided a username and I was not sure what to do with the 'username' in the:

    if (!$sftp->login('username', $rsa)) {
    

    statement. I checked the filezilla logs and it was sending what was in my ppk file on the comment: line which although not apparent was the username.

    I changed username to the value in the comment field and that fixed it. Not sure if this is "normal", but filezilla knew what to do with it.

    Here is the final working script without the actual server destination:

    $arr = getopt("f:");
    $file = $arr['f'];
    require 'c:\temp\php\vendor\autoload.php';
    use phpseclib3\Net\SSH2;
    use phpseclib3\Crypt\PublicKeyLoader;
    use phpseclib3\Net\SFTP;
    $rsa = PublicKeyLoader::load(file_get_contents('C:\temp\keys\mmax.ppk'));
    $sftp = new SFTP('sftp.server.com');
    if (!$sftp->login('username_from_ppk_comment_line', $rsa)) {
      exit('Login Failed');
    }
    $sftp->put($file,'c:\\temp\\EXPORT\\'.$file, SFTP::SOURCE_LOCAL_FILE);
    echo 'done';
    

    This is on a windows server running this from a command prompt. Hope this saves someone else some time. It is always that "one" thing that takes the longest.