From e3557220d7b4f10b4b8420ba71845e88b3b69c50 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Wed, 13 Nov 2019 23:47:16 -0600 Subject: [PATCH 1/2] SSH2: sodium_compat doesn't support memzero --- phpseclib/Net/SSH2.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index fae64fc5..84104fc2 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -1713,7 +1713,14 @@ class SSH2 return false; } $key = new BigInteger(sodium_crypto_scalarmult($x, $fBytes), 256); - sodium_memzero($x); + // sodium_compat doesn't emulate sodium_memzero + // also, with v1 of libsodium API the extension identifies itself as + // libsodium whereas v2 of the libsodium API (what PHP 7.2+ includes) + // identifies itself as sodium. sodium_compat uses the v1 API to + // emulate the v2 API if it's the v1 API that's available + if (extension_loaded('sodium') || extension_loaded('libsodium')) { + sodium_memzero($x); + } } else { $f = new BigInteger($fBytes, -256); $key = $f->modPow($x, $prime); From ea27295c8f3d0c584adf184273d8a2f7b2089917 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sat, 23 Nov 2019 00:58:12 -0600 Subject: [PATCH 2/2] SSH2: ssh-ed25519 keys didn't work --- phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php | 2 +- phpseclib/Crypt/EC/PrivateKey.php | 18 ++++++++++-------- phpseclib/Crypt/EC/PublicKey.php | 13 +++++++++++-- tests/Unit/Crypt/EC/KeyTest.php | 2 ++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php b/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php index ee8a60d8..9f973dbc 100644 --- a/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php +++ b/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php @@ -153,7 +153,7 @@ abstract class OpenSSH extends Progenitor if ($curve instanceof Ed25519) { $key = Strings::packSSH2('ss', 'ssh-ed25519', $curve->encodePoint($publicKey)); - if (self::$binary) { + if (isset($options['binary']) ? $options['binary'] : self::$binary) { return $key; } diff --git a/phpseclib/Crypt/EC/PrivateKey.php b/phpseclib/Crypt/EC/PrivateKey.php index 4c22a6ed..601fab55 100644 --- a/phpseclib/Crypt/EC/PrivateKey.php +++ b/phpseclib/Crypt/EC/PrivateKey.php @@ -24,6 +24,7 @@ use phpseclib\Crypt\EC\Curves\Curve25519; use phpseclib\Crypt\EC\Formats\Keys\PKCS1; use phpseclib\Crypt\Common; use phpseclib\Exception\UnsupportedOperationException; +use phpseclib\Common\Functions\Strings; /** * EC Private Key @@ -98,9 +99,16 @@ class PrivateKey extends EC implements Common\PrivateKey $order = $this->curve->getOrder(); + $shortFormat = $this->shortFormat; + $format = $this->format; + if ($format === false) { + return false; + } + if ($this->curve instanceof TwistedEdwardsCurve) { if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) { - return sodium_crypto_sign_detached($message, $this->toString('libsodium')); + $result = sodium_crypto_sign_detached($message, $this->toString('libsodium')); + return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) : $result; } // contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not. @@ -133,13 +141,7 @@ class PrivateKey extends EC implements Common\PrivateKey $S = $k->multiply($dA)->add($r); list(, $S) = $S->divide($order); $S = str_pad(strrev($S->toBytes()), $curve::SIZE, "\0"); - return $R . $S; - } - - $shortFormat = $this->shortFormat; - $format = $this->format; - if ($format === false) { - return false; + return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $R . $S) : $R . $S; } if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { diff --git a/phpseclib/Crypt/EC/PublicKey.php b/phpseclib/Crypt/EC/PublicKey.php index d88dc1bb..b60585eb 100644 --- a/phpseclib/Crypt/EC/PublicKey.php +++ b/phpseclib/Crypt/EC/PublicKey.php @@ -23,6 +23,7 @@ use phpseclib\Crypt\EC\Curves\Ed25519; use phpseclib\Crypt\EC\Formats\Keys\PKCS1; use phpseclib\Crypt\Common; use phpseclib\Exception\UnsupportedOperationException; +use phpseclib\Common\Functions\Strings; /** * EC Public Key @@ -50,9 +51,19 @@ class PublicKey extends EC implements Common\PublicKey throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures'); } + $shortFormat = $this->shortFormat; + $format = $this->format; + if ($format === false) { + return false; + } + $order = $this->curve->getOrder(); if ($this->curve instanceof TwistedEdwardsCurve) { + if ($shortFormat == 'SSH2') { + list(, $signature) = Strings::unpackSSH2('ss', $signature); + } + if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) { return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium')); } @@ -105,8 +116,6 @@ class PublicKey extends EC implements Common\PublicKey return $lhs[0]->equals($rhs[0]) && $lhs[1]->equals($rhs[1]); } - $format = $this->format; - $params = $format::load($signature); if ($params === false || count($params) != 2) { return false; diff --git a/tests/Unit/Crypt/EC/KeyTest.php b/tests/Unit/Crypt/EC/KeyTest.php index a327c40e..b8d14042 100644 --- a/tests/Unit/Crypt/EC/KeyTest.php +++ b/tests/Unit/Crypt/EC/KeyTest.php @@ -480,10 +480,12 @@ lEIq93iMVzIArjGaKrFDAAAADHJvb3RAdmFncmFudAE= $key = PublicKeyLoader::load($key); $sig = $key->sign('zzz'); + $sig2 = $key->withSignatureFormat('SSH2')->sign('zzz'); $key = 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKGEJnCqQiHjcB9RE86BvJh5lEIq93iMVzIArjGaKrFD root@vagrant'; $key = PublicKeyLoader::load($key); $this->assertTrue($key->verify('zzz', $sig)); + $this->assertTrue($key->withSignatureFormat('SSH2')->verify('zzz', $sig2)); } }