- I am using phpseclib v3.0.12 using composer.
- PHP code is being run on a CPanel control panel managed CentOS server where RSA 2048 bit SSH keys with passphrase are generated and keys are saved in the following paths.
- private key (/home/cccv3/.ssh/id_rsa), public key (/home/cccv3/.ssh/id_rsa.pub)
- public key is copied to target server over putty client and while I am able to connect over ssh on putty, I get error loading the private key irrespective of private key’s absolute path or relative path when I try using key based authentication (https://phpseclib.com/docs/auth#public-key),
PHP Fatal error: Uncaught phpseclib3\Exception\NoKeyLoadedException: Unable to read key in /home/cccv3/public_html/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php:64
Stack trace:
#0 /home/cccv3/public_html/test-ssh-sftp2.php(23): phpseclib3\Crypt\PublicKeyLoader::load(false, 'gIoNocxIp08y')
#1 {main}
thrown in /home/cccv3/public_html/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php on line 64
include 'vendor/autoload.php';
//$key = \phpseclib3\Crypt\PublicKeyLoader::load('/home/cccv3/.ssh/id_rsa', 'gIoNocxIp08y');
//$key = \phpseclib3\Crypt\PublicKeyLoader::load('.ssh/id_rsa', 'gIoNocxIp08y');
$key = \phpseclib3\Crypt\PublicKeyLoader::load('../.ssh/id_rsa', 'gIoNocxIp08y');
$ssh = new \phpseclib3\Net\SSH2('167.71.83.55');
echo "getserveridentification: " . $ssh->getServerIdentification() . "<br>";
print_r($ssh->getServerAlgorithms());
print_r($ssh->getAlgorithmsNegotiated());
if (!$ssh->login('root', $key)) {
exit('Login Failed');
}
echo $ssh->read('root@root:~$');
$ssh->write("ls -la\n");
echo $ssh->read('root@root:~$');
getserveridentification: SSH-2.0-OpenSSH_8.0
Array ( [kex] => Array ( [0] => curve25519-sha256 [1] => curve25519-sha256@libssh.org [2] => ecdh-sha2-nistp256 [3] => ecdh-sha2-nistp384 [4] => ecdh-sha2-nistp521 [5] => diffie-hellman-group-exchange-sha256 [6] => diffie-hellman-group14-sha256 [7] => diffie-hellman-group16-sha512 [8] => diffie-hellman-group18-sha512 [9] => diffie-hellman-group-exchange-sha1 [10] => diffie-hellman-group14-sha1 ) [hostkey] => Array ( [0] => rsa-sha2-512 [1] => rsa-sha2-256 [2] => ssh-rsa [3] => ecdsa-sha2-nistp256 [4] => ssh-ed25519 ) [client_to_server] => Array ( [crypt] => Array ( [0] => aes256-gcm@openssh.com [1] => chacha20-poly1305@openssh.com [2] => aes256-ctr [3] => aes256-cbc [4] => aes128-gcm@openssh.com [5] => aes128-ctr [6] => aes128-cbc ) [mac] => Array ( [0] => hmac-sha2-256-etm@openssh.com [1] => hmac-sha1-etm@openssh.com [2] => umac-128-etm@openssh.com [3] => hmac-sha2-512-etm@openssh.com [4] => hmac-sha2-256 [5] => hmac-sha1 [6] => umac-128@openssh.com [7] => hmac-sha2-512 ) [comp] => Array ( [0] => none [1] => zlib@openssh.com ) [lang] => Array ( [0] => ) ) [server_to_client] => Array ( [crypt] => Array ( [0] => aes256-gcm@openssh.com [1] => chacha20-poly1305@openssh.com [2] => aes256-ctr [3] => aes256-cbc [4] => aes128-gcm@openssh.com [5] => aes128-ctr [6] => aes128-cbc ) [mac] => Array ( [0] => hmac-sha2-256-etm@openssh.com [1] => hmac-sha1-etm@openssh.com [2] => umac-128-etm@openssh.com [3] => hmac-sha2-512-etm@openssh.com [4] => hmac-sha2-256 [5] => hmac-sha1 [6] => umac-128@openssh.com [7] => hmac-sha2-512 ) [comp] => Array ( [0] => none [1] => zlib@openssh.com ) [lang] => Array ( [0] => ) ) )
Array ( [kex] => curve25519-sha256 [hostkey] => ssh-ed25519 [client_to_server] => Array ( [crypt] => aes256-gcm@openssh.com [mac] => hmac-sha2-256-etm@openssh.com [comp] => none ) [server_to_client] => Array ( [crypt] => aes256-gcm@openssh.com [mac] => hmac-sha2-256-etm@openssh.com [comp] => none ) )
So one interesting thing about encrypted OpenSSH keys is that node.js can do them super fast:
https://gist.githubusercontent.com/haythemhammami/83e60a81d6066b5652bc57876947c7a3/raw/b4da272983a63687b8931aa6a5cf83524fb677ce/crawlerByTimos_node_modules_bcrypt-pbkdf_index.js
So what I’ve been mulling over is to just port that instead of trying to come up with a brand new green field implementation. If even that doesn’t yield an acceptably fast OpenSSH encrypted key I should at least be able to share a small code samples showing Javascript’s speed vs PHP’s speed. Like right now the best I can do is share one big program vs another big program and that’s not as convincing a demonstration as a small 3 line code snippet would be.
I mean, just considering the history of Javascript vs PHP it isn’t all that surprising that Javascript would be loads faster. Javascript has big money behind it. The PHP Foundation has an annual budget of $600k per https://opencollective.com/phpfoundation#category-BUDGET . Google’s V8 engine probably has whole teams of devs working on it, of which prob 25% of the devs make $500k+ a year. PHP can’t compete with that.
So is there no chance of phpseclib ever supporting ed25519 SSH key passphrases? That seems to be the most recommended key type these days and my use case requires a passphrase. I currently use RSA keys but ed25519 is theoretically faster.
Waiting 30-60s doing it with pure PHP is obviously a non-starter. I am thinking that maybe there is some 3rd party library that supports it or will in the future.
https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bcrypt_pbkdf.c
@terrafrost
I have an update, “it worked”.
While I tried using file_get_contents in one of the manually managed server setup on ubuntu/centos, I somehow replaced that code with private key path directly, as posted in the sample code in this github issue, when keys are created and code was later uploaded on this cpanel control panel managed centos server.
replaced:
$key = \phpseclib3\Crypt\PublicKeyLoader::load('/home/cccv3/.ssh/id_rsa', 'gIoNocxIp08y');with:
$key = \phpseclib3\Crypt\PublicKeyLoader::load(file_get_contents('/home/cccv3/.ssh/id_rsa'), 'gIoNocxIp08y');while commenting the key reading line of code inwhich I had copied private key content directly.
key takeaways:
thank you
It’s possible that PHP is running as a different user (say www-data) than the user that owns the key. This would be a problem because OpenSSH won’t use the key if the permissions are too open.
A few ideas:
It depends more on the version of OpenSSH being used. Looking at the changelog’s it looks like it was OpenSSH 7.8 that introduced the change:
Got it - I’ll take a look later today!
That’s not an OpenSSH formatted key. An encrypted OpenSSH key starts off with
-----BEGIN OPENSSH PRIVATE KEY-----. Apologies for assuming that it was.Private keys of the format you posted are supported.
If you can generate a private key that’ll duplicate the issue - or are willing to share that private key with me - could you do so so that I might be able to reproduce the key? You can email it to terrafrost@php.net if you want!