Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot connect with OpenSSH password protected RSA private key #1490

Closed
rafaeldsousa opened this issue Jul 16, 2020 · 3 comments
Closed

Cannot connect with OpenSSH password protected RSA private key #1490

rafaeldsousa opened this issue Jul 16, 2020 · 3 comments

Comments

@rafaeldsousa
Copy link

rafaeldsousa commented Jul 16, 2020

I'm trying to connect to a remote SFTP server using a private RSA (PRIVATE_FORMAT_OPENSSH) key, which is password protected but the connection is never stablished. Debugging it, it seems that the connection isn't ever attempted as the key modulus isn't loaded.
This happens for both 2.0.25 version and 2.0.27

/**
     * Attempts to connect to server
     *
     * @return void
     */
    public function connect(): void
    {
        if (!$this->canExecute()) {
            $private_key = file_get_contents($this->ssh_auth_key);
            $key = new RSA();
            $key->setPassword($this->ssh_auth_pwd);
            $key->loadKey($private_key);

            //Remote server's ip address or hostname
            $this->connection = new SFTP($this->ssh_host);

            if (!$this->connection->login($this->ssh_auth_user, $key)) {
                SFTPErrorHandler::logError($this->connection, SFTPErrorHandler::AUTHERROR);
            }
        }
    }

Debugging it step by step I get to _parseKey() line 1484 (in this case $options is equals to aes256-ctr bcrypt) on RSA.php file, which check the key options and in this case the key has an encryption, not meeting the criteria for this check.

After that, and going through a few more checks, I get to _privatekey_login() line 2548 on SSH2.php, which tries to get the publicKey for the private key I'm using, that goes back to RSA.php which checks if we have $this->modules loaded and nothing has been loaded, returning false and login process failing prematurely.

If I try login in with a private key that isn't pwd protect the process works just fine.

Could anyone help me bring some light to this, I'm pretty much stuck at this point and don't know what to search for to try and workaround/resolve this issue.

I'm running OpenSSL 1.1.1 on Mac High Sierra

@rafaeldsousa rafaeldsousa changed the title Not being able to establish connection with Pwd protected RSA Private Key Pwd protected RSA Private Key not working Jul 16, 2020
@rafaeldsousa rafaeldsousa changed the title Pwd protected RSA Private Key not working Password protected RSA private key not working Jul 16, 2020
@rafaeldsousa rafaeldsousa changed the title Password protected RSA private key not working Cannot connect with Password protected RSA private key Jul 16, 2020
@terrafrost
Copy link
Member

Encrypted OpenSSH private keys are, sadly, not supported. Based on my experiments, to date, it seems that PHP is just waaay too slow to do the bcrypt-inspired password derivation.

The following comment (from the 3.0 branch) elaborates:

/*
OpenSSH private keys use a customized version of bcrypt. specifically, instead of encrypting
OrpheanBeholderScryDoubt 64 times OpenSSH's bcrypt variant encrypts
OxychromaticBlowfishSwatDynamite 64 times. so we can't use crypt().
bcrypt is basically Blowfish with an altered key expansion. whereas Blowfish just runs the
key through the key expansion bcrypt interleaves the key expansion with the salt and
password. this renders openssl / mcrypt unusuable. this forces us to use a pure-PHP implementation
of bcrypt. the problem with that is that pure-PHP is too slow to be practically useful.
in addition to encrypting a different string 64 times the OpenSSH implementation also performs bcrypt
from scratch $rounds times. calling crypt() 64x with bcrypt takes 0.7s. PHP is going to be naturally
slower. pure-PHP is 215x slower than OpenSSL for AES and pure-PHP is 43x slower for bcrypt.
43 * 0.7 = 30s. no one wants to wait 30s to load a private key.
another way to think about this.. according to wikipedia's article on Blowfish,
"Each new key requires pre-processing equivalent to encrypting about 4 kilobytes of text".
key expansion is done (9+64*2)*160 times. multiply that by 4 and it turns out that Blowfish,
OpenSSH style, is the equivalent of encrypting ~80mb of text.
more supporting evidence: sodium_compat does not implement Argon2 (another password hashing
algorithm) because "It's not feasible to polyfill scrypt or Argon2 into PHP and get reasonable
performance. Users would feel motivated to select parameters that downgrade security to avoid
denial of service (DoS) attacks. The only winning move is not to play"
-- https://github.com/paragonie/sodium_compat/blob/master/README.md
*/

Maybe PHP8's JIT will make it more feasible idk.

@rafaeldsousa
Copy link
Author

rafaeldsousa commented Jul 18, 2020

Hi @terrafrost that makes total sense. I kept trying my private OpenSSH key and that kept failing, but with a suggestion tried generating a key using PEM and that worked as expected.
Hopefully PHP8 will get this sorted for this to work there.

Thanks a lot for your reply.

@rafaeldsousa rafaeldsousa changed the title Cannot connect with Password protected RSA private key Cannot connect with OpenSSH password protected RSA private key Jul 18, 2020
@terrafrost
Copy link
Member

Encrypted OpenSSH private keys are now supported as of this commit:

0c8994b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants