phpseclib: libssh2 vs phpseclib

Download phpseclib

Compared to libssh2, phpseclib:

Whether or not the API is better to libssh2 is debatable. This comparison looks at more objective criteria.

Portability

phpseclib is designed to be ultra-portable, even to the point of working on PHP4. Not a single extension is required, either (although if they're available they'll be used, for speed).

libssh2, in contrast... if you're on a shared host that doesn't have it installed (and most don't) you're S.O.L. And even if your server is running on a dedicated box it's still one extra step you have to do to install it. As if migrating to a new server wasn't enough of a challenge do you really want to compound the challenge by adding an additional server dependency like libssh2?

Speed

The following table shows how long, in seconds, it took to transfer a 1mb file via phpseclib and libssh2 to localhost and to a remote host.

Upload remote host libssh2 13.0037
phpseclib 11.1086
localhost libssh2 1.1250
phpseclib 0.3380
Download remote host libssh2 4.8302
phpseclib 2.4311
localhost libssh2 0.7680
phpseclib 0.4400

This test was conducted on an Intel Core i5-3320M CPU @ 2.6GHz running Windows 7 64-bit and PHP 5.4.19 and libssh 0.12 and the latest Git version of phpseclib with the gmp and mcrypt extensions installed.

The connection to the remote host was done with a 1MB upload speed. Here's the speedtest.net results:

speed test

The code used to conduct these tests is at upload.phps and download.phps.

The motivation for doing a separate test for remote hosts and localhosts was to compare the speeds with different bottlenecks. ie. with the remote host the bandwidth is the bottleneck. With localhost bandwidth is eliminated as a bottleneck. This shows that phpseclib performs better under a multitude of conditions.

Public Key Support

How you do it with libssh2:

<?php
$ssh = ssh2_connect('domain.tld');
ssh2_auth_pubkey_file($ssh, 'username', '/home/ubuntu/pubkey', '/home/ubuntu/privkey'/*, 'password'*/);

$stream = ssh2_exec($ssh, 'ls -la');
echo stream_get_contents($stream);

Both have to be of the right format too. If you didn't use ssh-keygen to generate your keys good luck in converting them.

<?php
include('Net/SSH2.php');
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();
//$rsa->setPassword('password');
$rsa->loadKey('...');

$ssh = new Net_SSH2('domain.tld');
$ssh->login('username', $rsa);

echo $ssh->exec('ls -la');

Ignoring the API for the time being there are a few clear ways phpseclib comes out on top here:

Diagnosing Problems

Why didn't top or sudo work? With phpseclib you can get logs. They look like this:

http://phpseclib.sourceforge.net/ssh/log.txt

You can also do print_r($ssh->getErrors()) or echo $ssh->getLastError()

Changing Directories

I don't see any cd or chdir functions at http://php.net/ssh2. phpseclib, however, has it - Net_SFTP::chdir(...)

Interactive Shell

Let's try to do sudo on the remote system.

With phpseclib: examples.html#sudo

With libssh2? I have no clue. My best guess (doesn't work):

<?php
$ssh = ssh2_connect('domain.tld'); 
ssh2_auth_password($ssh, 'username', 'password');

$shell = ssh2_shell($ssh);
echo fread($shell, 1024*1024);
fwrite($shell, "sudo ls -la\n");
$output = fread($shell, 1024*1024);
echo $output;
if (preg_match('#[pP]assword[^:]*:#', $output)) {
    fwrite($shell, "password\n");
}
echo fread($shell, 1024*1024);

It is additionally unclear how to get top working with libssh2 but it works perfectly fine with phpseclib: examples.html#top.