diff --git a/Web/composer.lock b/Web/composer.lock index 8175aae..e9a2231 100644 --- a/Web/composer.lock +++ b/Web/composer.lock @@ -125,16 +125,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.43", + "version": "3.0.57", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02" + "reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4", + "reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4", "shasum": "" }, "require": { @@ -215,7 +215,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.57" }, "funding": [ { @@ -231,16 +231,16 @@ "type": "tidelift" } ], - "time": "2024-12-14T21:12:59+00:00" + "time": "2026-08-26T12:13:21+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.6.0" + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.9.0" } diff --git a/Web/vendor/autoload.php b/Web/vendor/autoload.php index f449ecd..09453dc 100644 --- a/Web/vendor/autoload.php +++ b/Web/vendor/autoload.php @@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) { echo $err; } } - trigger_error( - $err, - E_USER_ERROR - ); + throw new RuntimeException($err); } require_once __DIR__ . '/composer/autoload_real.php'; diff --git a/Web/vendor/composer/InstalledVersions.php b/Web/vendor/composer/InstalledVersions.php index 51e734a..2052022 100644 --- a/Web/vendor/composer/InstalledVersions.php +++ b/Web/vendor/composer/InstalledVersions.php @@ -26,12 +26,23 @@ use Composer\Semver\VersionParser; */ class InstalledVersions { + /** + * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to + * @internal + */ + private static $selfDir = null; + /** * @var mixed[]|null * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null */ private static $installed; + /** + * @var bool + */ + private static $installedIsLocalDir; + /** * @var bool|null */ @@ -309,6 +320,24 @@ class InstalledVersions { self::$installed = $data; self::$installedByVendor = array(); + + // when using reload, we disable the duplicate protection to ensure that self::$installed data is + // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, + // so we have to assume it does not, and that may result in duplicate data being returned when listing + // all installed packages for example + self::$installedIsLocalDir = false; + } + + /** + * @return string + */ + private static function getSelfDir() + { + if (self::$selfDir === null) { + self::$selfDir = strtr(__DIR__, '\\', '/'); + } + + return self::$selfDir; } /** @@ -322,19 +351,27 @@ class InstalledVersions } $installed = array(); + $copiedLocalDir = false; if (self::$canGetVendors) { + $selfDir = self::getSelfDir(); foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + $vendorDir = strtr($vendorDir, '\\', '/'); if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (is_file($vendorDir.'/composer/installed.php')) { /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ $required = require $vendorDir.'/composer/installed.php'; - $installed[] = self::$installedByVendor[$vendorDir] = $required; - if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { - self::$installed = $installed[count($installed) - 1]; + self::$installedByVendor[$vendorDir] = $required; + $installed[] = $required; + if (self::$installed === null && $vendorDir.'/composer' === $selfDir) { + self::$installed = $required; + self::$installedIsLocalDir = true; } } + if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) { + $copiedLocalDir = true; + } } } @@ -350,7 +387,7 @@ class InstalledVersions } } - if (self::$installed !== array()) { + if (self::$installed !== array() && !$copiedLocalDir) { $installed[] = self::$installed; } diff --git a/Web/vendor/composer/LICENSE b/Web/vendor/composer/LICENSE index 62ecfd8..f27399a 100644 --- a/Web/vendor/composer/LICENSE +++ b/Web/vendor/composer/LICENSE @@ -1,3 +1,4 @@ + Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy @@ -17,3 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/Web/vendor/composer/autoload_static.php b/Web/vendor/composer/autoload_static.php index c86619d..db0e2a1 100644 --- a/Web/vendor/composer/autoload_static.php +++ b/Web/vendor/composer/autoload_static.php @@ -11,22 +11,22 @@ class ComposerStaticInita702940bbf24a822224611db5c22942b ); public static $prefixLengthsPsr4 = array ( - 'p' => + 'p' => array ( 'phpseclib3\\' => 11, ), - 'P' => + 'P' => array ( 'ParagonIE\\ConstantTime\\' => 23, ), ); public static $prefixDirsPsr4 = array ( - 'phpseclib3\\' => + 'phpseclib3\\' => array ( 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib', ), - 'ParagonIE\\ConstantTime\\' => + 'ParagonIE\\ConstantTime\\' => array ( 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src', ), diff --git a/Web/vendor/composer/installed.json b/Web/vendor/composer/installed.json index ffdc855..1fe75cc 100644 --- a/Web/vendor/composer/installed.json +++ b/Web/vendor/composer/installed.json @@ -125,17 +125,17 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.43", - "version_normalized": "3.0.43.0", + "version": "3.0.57", + "version_normalized": "3.0.57.0", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02" + "reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4", + "reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4", "shasum": "" }, "require": { @@ -153,7 +153,7 @@ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." }, - "time": "2024-12-14T21:12:59+00:00", + "time": "2026-08-26T12:13:21+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -218,7 +218,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.57" }, "funding": [ { diff --git a/Web/vendor/composer/installed.php b/Web/vendor/composer/installed.php index 4d908a1..c39b365 100644 --- a/Web/vendor/composer/installed.php +++ b/Web/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => '__root__', - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => null, + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'reference' => '6f6e2e6c92dba1cabd61ab6e3dd0c13ae52f161a', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -11,9 +11,9 @@ ), 'versions' => array( '__root__' => array( - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => null, + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'reference' => '6f6e2e6c92dba1cabd61ab6e3dd0c13ae52f161a', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -38,9 +38,9 @@ 'dev_requirement' => false, ), 'phpseclib/phpseclib' => array( - 'pretty_version' => '3.0.43', - 'version' => '3.0.43.0', - 'reference' => '709ec107af3cb2f385b9617be72af8cf62441d02', + 'pretty_version' => '3.0.57', + 'version' => '3.0.57.0', + 'reference' => 'd17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4', 'type' => 'library', 'install_path' => __DIR__ . '/../phpseclib/phpseclib', 'aliases' => array(), diff --git a/Web/vendor/composer/platform_check.php b/Web/vendor/composer/platform_check.php index adfb472..a70ba47 100644 --- a/Web/vendor/composer/platform_check.php +++ b/Web/vendor/composer/platform_check.php @@ -19,8 +19,7 @@ if ($issues) { echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; } } - trigger_error( - 'Composer detected issues in your platform: ' . implode(' ', $issues), - E_USER_ERROR + throw new \RuntimeException( + 'Composer detected issues in your platform: ' . implode(' ', $issues) ); } diff --git a/Web/vendor/phpseclib/phpseclib/BACKERS.md b/Web/vendor/phpseclib/phpseclib/BACKERS.md index cafcf60..04ed50e 100644 --- a/Web/vendor/phpseclib/phpseclib/BACKERS.md +++ b/Web/vendor/phpseclib/phpseclib/BACKERS.md @@ -4,6 +4,7 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co ## Backers +- [HeroDevs](https://www.herodevs.com/sustainability-fund) - Allan Simon - [ChargeOver](https://chargeover.com/) - Raghu Veer Dendukuri @@ -16,4 +17,6 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co - [istiak-tridip](https://github.com/istiak-tridip) - [Anna Filina](https://github.com/afilina) - [blakemckeeby](https://github.com/blakemckeeby) -- [ssddanbrown](https://github.com/ssddanbrown) \ No newline at end of file +- [ssddanbrown](https://github.com/ssddanbrown) +- Stefan Beck +- [Greg Mayes](https://github.com/GregMayes) \ No newline at end of file diff --git a/Web/vendor/phpseclib/phpseclib/README.md b/Web/vendor/phpseclib/phpseclib/README.md index 37cbcb9..8d8515b 100644 --- a/Web/vendor/phpseclib/phpseclib/README.md +++ b/Web/vendor/phpseclib/phpseclib/README.md @@ -29,6 +29,17 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 / * Unstable API * Do not use in production +### 4.0 + +* Expected Release Date: September 2026 +* Long term support (LTS) release +* X509 split into separate X509, CRL, CSR and SPKAC classes +* PFX and CMS classes added +* All ASN1 classes are lazy loaded by default +* Minimum PHP version: 8.1.0 +* PSR-4 autoloading with namespace rooted at `\phpseclib4` +* Install via Composer: `composer require phpseclib/phpseclib:4.0.x-dev` + ### 3.0 * Long term support (LTS) release @@ -51,7 +62,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 / * PHP4 compatible * Composer compatible (PSR-0 autoloading) * Install using Composer: `composer require phpseclib/phpseclib:~1.0` -* [Download 1.0.23 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.23.zip/download) +* [Download 1.0.25 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.30.zip/download) ## Security contact information @@ -63,14 +74,23 @@ Need Support? * [Checkout Questions and Answers on Stack Overflow](http://stackoverflow.com/questions/tagged/phpseclib) * [Create a Support Ticket on GitHub](https://github.com/phpseclib/phpseclib/issues/new) -* [Browse the Support Forum](http://www.frostjedi.com/phpbb/viewforum.php?f=46) (no longer in use) ## Special Thanks -Special Thanks to our $50+ sponsors!: +

+ + Sovereign Tech Agency + +

+## Additional Thanks + +- [HeroDevs](https://www.herodevs.com/sustainability-fund) - Allan Simon +- [Anna Filina](https://afilina.com/) +- delovelady - [ChargeOver](https://chargeover.com/) +- ## Contributing diff --git a/Web/vendor/phpseclib/phpseclib/SECURITY.md b/Web/vendor/phpseclib/phpseclib/SECURITY.md new file mode 100644 index 0000000..f8368b6 --- /dev/null +++ b/Web/vendor/phpseclib/phpseclib/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 1.0.x | :white_check_mark: | +| 2.0.x | :white_check_mark: | +| 3.0.x | :white_check_mark: | + +## Reporting a Vulnerability + +To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. \ No newline at end of file diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php index fa750ba..7a56f7c 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php @@ -126,7 +126,9 @@ abstract class Strings // 64-bit floats can be used to get larger numbers then 32-bit signed ints would allow // for. sure, you're not gonna get the full precision of 64-bit numbers but just because // you need > 32-bit precision doesn't mean you need the full 64-bit precision - extract(unpack('Nupper/Nlower', self::shift($data, 8))); + $unpacked = unpack('Nupper/Nlower', self::shift($data, 8)); + $upper = $unpacked['upper']; + $lower = $unpacked['lower']; $temp = $upper ? 4294967296 * $upper : 0; $temp += $lower < 0 ? ($lower & 0x7FFFFFFFF) + 0x80000000 : $lower; // $temp = hexdec(bin2hex(self::shift($data, 8))); @@ -354,9 +356,11 @@ abstract class Strings // from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits $p1 = ($b * 0x0802) & 0x22110; $p2 = ($b * 0x8020) & 0x88440; - $r .= chr( - (($p1 | $p2) * 0x10101) >> 16 - ); + $temp = ($p1 | $p2) * 0x10101; + if (is_float($temp)) { + $temp = (int) fmod($temp, 0x7FFFFFFF); + } + $r .= chr(($temp >> 16) & 0xFF); } } return $r; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php index 4038716..270986d 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php @@ -59,7 +59,7 @@ class AES extends Rijndael * * Since \phpseclib3\Crypt\AES extends \phpseclib3\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything. * - * @see \phpseclib3\Crypt\Rijndael::setBlockLength() + * @see Rijndael::setBlockLength() * @param int $length * @throws \BadMethodCallException anytime it's called */ diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php index 3cb2b30..38df513 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php @@ -129,7 +129,7 @@ class Blowfish extends BlockCipher /** * Block Length of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size + * @see Common\SymmetricKey::block_size * @var int */ protected $block_size = 8; @@ -137,7 +137,7 @@ class Blowfish extends BlockCipher /** * The mcrypt specific name of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt + * @see Common\SymmetricKey::cipher_name_mcrypt * @var string */ protected $cipher_name_mcrypt = 'blowfish'; @@ -145,7 +145,7 @@ class Blowfish extends BlockCipher /** * Optimizing value while CFB-encrypting * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len + * @see Common\SymmetricKey::cfb_init_len * @var int */ protected $cfb_init_len = 500; @@ -325,7 +325,7 @@ class Blowfish extends BlockCipher * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu * of that, we'll just precompute it once.} * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength() + * @see Common\SymmetricKey::setKeyLength() * @var int */ protected $key_length = 16; @@ -368,7 +368,7 @@ class Blowfish extends BlockCipher * * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() + * @see Common\SymmetricKey::isValidEngine() * @param int $engine * @return bool */ @@ -394,7 +394,7 @@ class Blowfish extends BlockCipher /** * Setup the key (expansion) * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey() + * @see Common\SymmetricKey::_setupKey() */ protected function setupKey() { @@ -448,8 +448,8 @@ class Blowfish extends BlockCipher protected static function initialize_static_variables() { if (is_float(self::$sbox[0x200])) { - self::$sbox = array_map('intval', self::$sbox); - self::$parray = array_map('intval', self::$parray); + self::$sbox = array_map([self::class, 'safe_intval'], self::$sbox); + self::$parray = array_map([self::class, 'safe_intval'], self::$parray); } parent::initialize_static_variables(); @@ -755,7 +755,7 @@ class Blowfish extends BlockCipher /** * Setup the performance-optimized function for de/encrypt() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt() + * @see Common\SymmetricKey::_setupInlineCrypt() */ protected function setupInlineCrypt() { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php index b2691b5..88c4b5d 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php @@ -35,7 +35,7 @@ class ChaCha20 extends Salsa20 * * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * @see SymmetricKey::__construct() * @param int $engine * @return bool */ @@ -73,7 +73,7 @@ class ChaCha20 extends Salsa20 /** * Encrypts a message. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * @see SymmetricKey::decrypt() * @see self::crypt() * @param string $plaintext * @return string $ciphertext @@ -95,7 +95,7 @@ class ChaCha20 extends Salsa20 * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). * At least if the continuous buffer is disabled. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() + * @see SymmetricKey::encrypt() * @see self::crypt() * @param string $ciphertext * @return string $plaintext @@ -279,10 +279,10 @@ class ChaCha20 extends Salsa20 // xor'ing and rotation are all on the same line so i'm keeping it on the same // line here as well // @codingStandardsIgnoreStart - $a+= $b; $d = self::leftRotate(intval($d) ^ intval($a), 16); - $c+= $d; $b = self::leftRotate(intval($b) ^ intval($c), 12); - $a+= $b; $d = self::leftRotate(intval($d) ^ intval($a), 8); - $c+= $d; $b = self::leftRotate(intval($b) ^ intval($c), 7); + $a+= $b; $d = self::leftRotate(self::safe_intval($d) ^ self::safe_intval($a), 16); + $c+= $d; $b = self::leftRotate(self::safe_intval($b) ^ self::safe_intval($c), 12); + $a+= $b; $d = self::leftRotate(self::safe_intval($d) ^ self::safe_intval($a), 8); + $c+= $d; $b = self::leftRotate(self::safe_intval($b) ^ self::safe_intval($c), 7); // @codingStandardsIgnoreEnd } @@ -357,424 +357,424 @@ class ChaCha20 extends Salsa20 // @codingStandardsIgnoreStart // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // columnRound - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12); - $x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8); - $x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12); + $x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8); + $x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12); - $x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8); - $x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12); + $x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8); + $x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12); - $x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8); - $x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12); + $x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8); + $x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12); - $x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8); - $x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12); + $x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8); + $x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7); // rowRound - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12); - $x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8); - $x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12); + $x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8); + $x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12); - $x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8); - $x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12); + $x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8); + $x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12); - $x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8); - $x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12); + $x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8); + $x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12); - $x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8); - $x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12); + $x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8); + $x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7); // @codingStandardsIgnoreEnd $x0 += $z0; @@ -794,6 +794,6 @@ class ChaCha20 extends Salsa20 $x14 += $z14; $x15 += $z15; - return pack('V*', $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15); + return pack('V*', self::safe_intval($x0), self::safe_intval($x1), self::safe_intval($x2), self::safe_intval($x3), self::safe_intval($x4), self::safe_intval($x5), self::safe_intval($x6), self::safe_intval($x7), self::safe_intval($x8), self::safe_intval($x9), self::safe_intval($x10), self::safe_intval($x11), self::safe_intval($x12), self::safe_intval($x13), self::safe_intval($x14), self::safe_intval($x15)); } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php index a380e43..a8074cb 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php @@ -78,13 +78,6 @@ abstract class AsymmetricKey */ private static $invisiblePlugins = []; - /** - * Available Engines - * - * @var boolean[] - */ - protected static $engines = []; - /** * Key Comment * @@ -92,6 +85,14 @@ abstract class AsymmetricKey */ private $comment; + /** + * OpenSSL configuration file name. + * + * @see self::createKey() + * @var ?string + */ + protected static $configFile; + /** * @param string $type * @return array|string @@ -119,6 +120,10 @@ abstract class AsymmetricKey self::$one = new BigInteger(1); } + if (!isset(self::$configFile)) { + self::$configFile = dirname(__FILE__) . '/../../openssl.cnf'; + } + self::loadPlugins('Keys'); if (static::ALGORITHM != 'RSA' && static::ALGORITHM != 'DH') { self::loadPlugins('Signature'); @@ -363,6 +368,18 @@ abstract class AsymmetricKey return self::$plugins[static::ALGORITHM]['Keys']; } + /** + * Sets the OpenSSL config file path + * + * Set to the empty string to use the default config file + * + * @param string $val + */ + public static function setOpenSSLConfigPath($val) + { + self::$configFile = $val; + } + /** * Add a fileformat plugin * @@ -419,34 +436,28 @@ abstract class AsymmetricKey } /** - * Tests engine validity - * + * Force engine (useful for unit testing) */ - public static function useBestEngine() + public static function forceEngine($engine = null) { - static::$engines = [ - 'PHP' => true, - 'OpenSSL' => extension_loaded('openssl'), - // this test can be satisfied by either of the following: - // http://php.net/manual/en/book.sodium.php - // https://github.com/paragonie/sodium_compat - 'libsodium' => function_exists('sodium_crypto_sign_keypair') - ]; - - return static::$engines; + if (!isset($engine)) { + static::$forcedEngine = null; + return; + } + switch ($engine) { + case 'PHP': + case 'OpenSSL': + case 'libsodium': + static::$forcedEngine = $engine; + break; + default: + throw new \InvalidArgumentException('Valid engines are null, PHP, OpenSSL or libsodium'); + } } - /** - * Flag to use internal engine only (useful for unit testing) - * - */ - public static function useInternalEngine() + public static function getForcedEngine() { - static::$engines = [ - 'PHP' => true, - 'OpenSSL' => false, - 'libsodium' => false - ]; + return static::$forcedEngine; } /** diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/JWK.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/JWK.php index 4c761b8..98b8dac 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/JWK.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/JWK.php @@ -50,6 +50,14 @@ abstract class JWK return $key; } + if (!is_object($key)) { + throw new \RuntimeException('invalid JWK: not an object'); + } + + if (!isset($key->keys)) { + throw new \RuntimeException('invalid JWK: object has no property "keys"'); + } + if (count($key->keys) != 1) { throw new \RuntimeException('Although the JWK key format supports multiple keys phpseclib does not'); } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php index ab7f050..6673ac5 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php @@ -118,7 +118,7 @@ abstract class OpenSSH return compact('type', 'publicKey', 'paddedKey'); } - $parts = explode(' ', $key, 3); + $parts = preg_split("#[\t ]+#", $key, 3); if (!isset($parts[1])) { $key = base64_decode($parts[0]); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php index 6c9a650..8971a80 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php @@ -361,7 +361,9 @@ abstract class PKCS8 extends PKCS if (!$temp) { throw new \RuntimeException('Unable to decode BER'); } - extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP)); + $map = ASN1::asn1map($temp[0], Maps\PBEParameter::MAP); + $salt = $map['salt']; + $iterationCount = $map['iterationCount']; $iterationCount = (int) $iterationCount->toString(); $cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount); $key = $cipher->decrypt($decrypted['encryptedData']); @@ -379,7 +381,8 @@ abstract class PKCS8 extends PKCS throw new \RuntimeException('Unable to decode BER'); } $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); - extract($temp); + $keyDerivationFunc = $temp['keyDerivationFunc']; + $encryptionScheme = $temp['encryptionScheme']; $cipher = self::getPBES2EncryptionObject($encryptionScheme['algorithm']); $meta['meta']['cipher'] = $encryptionScheme['algorithm']; @@ -389,7 +392,8 @@ abstract class PKCS8 extends PKCS throw new \RuntimeException('Unable to decode BER'); } $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP); - extract($temp); + $keyDerivationFunc = $temp['keyDerivationFunc']; + $encryptionScheme = $temp['encryptionScheme']; if (!$cipher instanceof RC2) { $cipher->setIV($encryptionScheme['parameters']['octetString']); @@ -398,7 +402,9 @@ abstract class PKCS8 extends PKCS if (!$temp) { throw new \RuntimeException('Unable to decode BER'); } - extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP)); + $map = ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP); + $rc2ParametersVersion = $map['rc2ParametersVersion']; + $iv = $map['iv']; $effectiveKeyLength = (int) $rc2ParametersVersion->toString(); switch ($effectiveKeyLength) { case 160: @@ -423,9 +429,13 @@ abstract class PKCS8 extends PKCS if (!$temp) { throw new \RuntimeException('Unable to decode BER'); } - $prf = ['algorithm' => 'id-hmacWithSHA1']; $params = ASN1::asn1map($temp[0], Maps\PBKDF2params::MAP); - extract($params); + if (empty($params['prf'])) { + $params['prf'] = ['algorithm' => 'id-hmacWithSHA1']; + } + $salt = $params['salt']; + $iterationCount = $params['iterationCount']; + $prf = $params['prf']; $meta['meta']['prf'] = $prf['algorithm']; $hash = str_replace('-', '/', substr($prf['algorithm'], 11)); $params = [ @@ -555,7 +565,7 @@ abstract class PKCS8 extends PKCS ], 'privateKey' => $key ]; - if ($oid != 'id-Ed25519' && $oid != 'id-Ed448') { + if ($oid != 'id-Ed25519' && $oid != 'id-Ed448' && $oid != 'id-X25519' && $oid != 'id-X448') { $key['privateKeyAlgorithm']['parameters'] = $params; } if (!empty($attr)) { @@ -672,7 +682,7 @@ abstract class PKCS8 extends PKCS 'publicKey' => "\0" . $key ]; - if ($oid != 'id-Ed25519' && $oid != 'id-Ed448') { + if ($oid != 'id-Ed25519' && $oid != 'id-Ed448' && $oid != 'id-X25519' && $oid != 'id-X448') { $key['publicKeyAlgorithm']['parameters'] = $params; } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php index 85da83a..ff4a95a 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php @@ -199,7 +199,7 @@ abstract class PuTTY $source = Strings::packSSH2('ssss', $type, $encryption, $components['comment'], $public); - extract(unpack('Nlength', Strings::shift($public, 4))); + $length = unpack('Nlength', Strings::shift($public, 4))['length']; $newtype = Strings::shift($public, $length); if ($newtype != $type) { throw new \RuntimeException('The binary type does not match the human readable type field'); @@ -227,7 +227,10 @@ abstract class PuTTY $parallelism = trim(preg_replace('#Argon2-Parallelism: (\d+)#', '$1', $key[$offset++])); $salt = Strings::hex2bin(trim(preg_replace('#Argon2-Salt: ([0-9a-f]+)#', '$1', $key[$offset++]))); - extract(self::generateV3Key($password, $flavour, $memory, $passes, $salt)); + $v3key = self::generateV3Key($password, $flavour, $memory, $passes, $salt); + $symkey = $v3key['symkey']; + $symiv = $v3key['symiv']; + $hashkey = $v3key['hashkey']; break; case 2: @@ -323,7 +326,10 @@ abstract class PuTTY $key .= "Argon2-Passes: 13\r\n"; $key .= "Argon2-Parallelism: 1\r\n"; $key .= "Argon2-Salt: " . Strings::bin2hex($salt) . "\r\n"; - extract(self::generateV3Key($password, 'Argon2id', 8192, 13, $salt)); + $v3key = self::generateV3Key($password, 'Argon2id', 8192, 13, $salt); + $symkey = $v3key['symkey']; + $symiv = $v3key['symiv']; + $hashkey = $v3key['hashkey']; $hash = new Hash('sha256'); $hash->setKey($hashkey); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php index 0d96908..e44f5c8 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php @@ -26,7 +26,7 @@ abstract class StreamCipher extends SymmetricKey * * Stream ciphers do not have a block size * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size + * @see SymmetricKey::block_size * @var int */ protected $block_size = 0; @@ -34,7 +34,7 @@ abstract class StreamCipher extends SymmetricKey /** * Default Constructor. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * @see SymmetricKey::__construct() * @return StreamCipher */ public function __construct() diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php index 35d7a7d..b24a194 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php @@ -60,76 +60,76 @@ abstract class SymmetricKey * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. * * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_CTR = -1; /** * Encrypt / decrypt using the Electronic Code Book mode. * * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_ECB = 1; /** * Encrypt / decrypt using the Code Book Chaining mode. * * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_CBC = 2; /** * Encrypt / decrypt using the Cipher Feedback mode. * * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_CFB = 3; /** * Encrypt / decrypt using the Cipher Feedback mode (8bit) * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_CFB8 = 7; /** * Encrypt / decrypt using the Output Feedback mode (8bit) * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_OFB8 = 8; /** * Encrypt / decrypt using the Output Feedback mode. * * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_OFB = 4; /** * Encrypt / decrypt using Galois/Counter mode. * * @link https://en.wikipedia.org/wiki/Galois/Counter_Mode - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_GCM = 5; /** * Encrypt / decrypt using streaming mode. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * SymmetricKey::encrypt() + * SymmetricKey::decrypt() */ const MODE_STREAM = 6; /** * Mode Map * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * SymmetricKey::__construct() */ const MODE_MAP = [ 'ctr' => self::MODE_CTR, @@ -146,44 +146,44 @@ abstract class SymmetricKey /** * Base value for the internal implementation $engine switch * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * SymmetricKey::__construct() */ const ENGINE_INTERNAL = 1; /** * Base value for the eval() implementation $engine switch * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * SymmetricKey::__construct() */ const ENGINE_EVAL = 2; /** * Base value for the mcrypt implementation $engine switch * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * SymmetricKey::__construct() */ const ENGINE_MCRYPT = 3; /** * Base value for the openssl implementation $engine switch * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * SymmetricKey::__construct() */ const ENGINE_OPENSSL = 4; /** * Base value for the libsodium implementation $engine switch * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * SymmetricKey::__construct() */ const ENGINE_LIBSODIUM = 5; /** * Base value for the openssl / gcm implementation $engine switch * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * SymmetricKey::__construct() */ const ENGINE_OPENSSL_GCM = 6; /** * Engine Reverse Map * - * @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine() + * SymmetricKey::getEngine() */ const ENGINE_MAP = [ self::ENGINE_INTERNAL => 'PHP', @@ -666,6 +666,11 @@ abstract class SymmetricKey { if (!isset(self::$use_reg_intval)) { switch (true) { + // PHP 8.5, per https://www.php.net/manual/en/migration85.incompatible.php, now emits a warning + // "when casting floats (or strings that look like floats) to int if they cannot be represented as one" + case PHP_VERSION_ID >= 80500 && PHP_INT_SIZE == 4: + self::$use_reg_intval = false; + break; // PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster case (PHP_OS & "\xDF\xDF\xDF") === 'WIN': case !function_exists('php_uname'): @@ -1265,7 +1270,7 @@ abstract class SymmetricKey if ($this->continuousBuffer) { $this->encryptIV = $iv; } - break; + return $ciphertext; case self::MODE_OFB: return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer); } @@ -2591,7 +2596,7 @@ abstract class SymmetricKey $length = ord($text[strlen($text) - 1]); - if (!$length || $length > $this->block_size) { + if (!$length | ($length > $this->block_size)) { throw new BadDecryptionException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})"); } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php index 3b03830..6123f18 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php @@ -53,22 +53,22 @@ class DES extends BlockCipher /** * Contains $keys[self::ENCRYPT] * - * @see \phpseclib3\Crypt\DES::setupKey() - * @see \phpseclib3\Crypt\DES::processBlock() + * @see DES::setupKey() + * @see DES::processBlock() */ const ENCRYPT = 0; /** * Contains $keys[self::DECRYPT] * - * @see \phpseclib3\Crypt\DES::setupKey() - * @see \phpseclib3\Crypt\DES::processBlock() + * @see DES::setupKey() + * @see DES::processBlock() */ const DECRYPT = 1; /** * Block Length of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size + * @see Common\SymmetricKey::block_size * @var int */ protected $block_size = 8; @@ -76,7 +76,7 @@ class DES extends BlockCipher /** * Key Length (in bytes) * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength() + * @see Common\SymmetricKey::setKeyLength() * @var int */ protected $key_length = 8; @@ -84,7 +84,7 @@ class DES extends BlockCipher /** * The mcrypt specific name of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt + * @see Common\SymmetricKey::cipher_name_mcrypt * @var string */ protected $cipher_name_mcrypt = 'des'; @@ -92,7 +92,7 @@ class DES extends BlockCipher /** * The OpenSSL names of the cipher / modes * - * @see \phpseclib3\Crypt\Common\SymmetricKey::openssl_mode_names + * @see Common\SymmetricKey::openssl_mode_names * @var array */ protected $openssl_mode_names = [ @@ -106,7 +106,7 @@ class DES extends BlockCipher /** * Optimizing value while CFB-encrypting * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len + * @see Common\SymmetricKey::cfb_init_len * @var int */ protected $cfb_init_len = 500; @@ -586,7 +586,7 @@ class DES extends BlockCipher * * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() + * @see Common\SymmetricKey::isValidEngine() * @param int $engine * @return bool */ @@ -615,7 +615,7 @@ class DES extends BlockCipher * * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey() + * @see Common\SymmetricKey::setKey() * @param string $key */ public function setKey($key) @@ -631,8 +631,8 @@ class DES extends BlockCipher /** * Encrypts a block * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() + * @see Common\SymmetricKey::encryptBlock() + * @see Common\SymmetricKey::encrypt() * @see self::encrypt() * @param string $in * @return string @@ -645,8 +645,8 @@ class DES extends BlockCipher /** * Decrypts a block * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * @see Common\SymmetricKey::decryptBlock() + * @see Common\SymmetricKey::decrypt() * @see self::decrypt() * @param string $in * @return string @@ -673,14 +673,14 @@ class DES extends BlockCipher { static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip; if (!$sbox1) { - $sbox1 = array_map('intval', self::$sbox1); - $sbox2 = array_map('intval', self::$sbox2); - $sbox3 = array_map('intval', self::$sbox3); - $sbox4 = array_map('intval', self::$sbox4); - $sbox5 = array_map('intval', self::$sbox5); - $sbox6 = array_map('intval', self::$sbox6); - $sbox7 = array_map('intval', self::$sbox7); - $sbox8 = array_map('intval', self::$sbox8); + $sbox1 = array_map([self::class, 'safe_intval'], self::$sbox1); + $sbox2 = array_map([self::class, 'safe_intval'], self::$sbox2); + $sbox3 = array_map([self::class, 'safe_intval'], self::$sbox3); + $sbox4 = array_map([self::class, 'safe_intval'], self::$sbox4); + $sbox5 = array_map([self::class, 'safe_intval'], self::$sbox5); + $sbox6 = array_map([self::class, 'safe_intval'], self::$sbox6); + $sbox7 = array_map([self::class, 'safe_intval'], self::$sbox7); + $sbox8 = array_map([self::class, 'safe_intval'], self::$sbox8); /* Merge $shuffle with $[inv]ipmap */ for ($i = 0; $i < 256; ++$i) { $shuffleip[] = self::$shuffle[self::$ipmap[$i]]; @@ -747,7 +747,7 @@ class DES extends BlockCipher /** * Creates the key schedule * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() + * @see Common\SymmetricKey::setupKey() */ protected function setupKey() { @@ -1243,9 +1243,9 @@ class DES extends BlockCipher $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF]; // Reorder: odd bytes/even bytes. Push the result in key schedule. - $val1 = ( $cp & intval(0xFF000000)) | (($cp << 8) & 0x00FF0000) | + $val1 = ( $cp & self::safe_intval(0xFF000000)) | (($cp << 8) & 0x00FF0000) | (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF); - $val2 = (($cp << 8) & intval(0xFF000000)) | (($cp << 16) & 0x00FF0000) | + $val2 = (($cp << 8) & self::safe_intval(0xFF000000)) | (($cp << 16) & 0x00FF0000) | (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF); $keys[$des_round][self::ENCRYPT][ ] = $val1; $keys[$des_round][self::DECRYPT][$ki - 1] = $val1; @@ -1281,7 +1281,7 @@ class DES extends BlockCipher /** * Setup the performance-optimized function for de/encrypt() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt() + * @see Common\SymmetricKey::setupInlineCrypt() */ protected function setupInlineCrypt() { @@ -1292,14 +1292,14 @@ class DES extends BlockCipher $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip; if (!$sbox1) { - $sbox1 = array_map("intval", self::$sbox1); - $sbox2 = array_map("intval", self::$sbox2); - $sbox3 = array_map("intval", self::$sbox3); - $sbox4 = array_map("intval", self::$sbox4); - $sbox5 = array_map("intval", self::$sbox5); - $sbox6 = array_map("intval", self::$sbox6); - $sbox7 = array_map("intval", self::$sbox7); - $sbox8 = array_map("intval", self::$sbox8);' + $sbox1 = array_map(["' . self::class . '", "safe_intval"], self::$sbox1); + $sbox2 = array_map(["' . self::class . '", "safe_intval"], self::$sbox2); + $sbox3 = array_map(["' . self::class . '", "safe_intval"], self::$sbox3); + $sbox4 = array_map(["' . self::class . '", "safe_intval"], self::$sbox4); + $sbox5 = array_map(["' . self::class . '", "safe_intval"], self::$sbox5); + $sbox6 = array_map(["' . self::class . '", "safe_intval"], self::$sbox6); + $sbox7 = array_map(["' . self::class . '", "safe_intval"], self::$sbox7); + $sbox8 = array_map(["' . self::class . '", "safe_intval"], self::$sbox8);' /* Merge $shuffle with $[inv]ipmap */ . ' for ($i = 0; $i < 256; ++$i) { $shuffleip[] = self::$shuffle[self::$ipmap[$i]]; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php index b230198..6e95381 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php @@ -28,6 +28,7 @@ use phpseclib3\Crypt\Common\AsymmetricKey; use phpseclib3\Crypt\DH\Parameters; use phpseclib3\Crypt\DH\PrivateKey; use phpseclib3\Crypt\DH\PublicKey; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Exception\NoKeyLoadedException; use phpseclib3\Exception\UnsupportedOperationException; use phpseclib3\Math\BigInteger; @@ -295,21 +296,64 @@ abstract class DH extends AsymmetricKey } if ($private instanceof EC\PrivateKey) { + $privateCurve = $private->getCurve(); switch (true) { case $public instanceof EC\PublicKey: + if ($privateCurve !== $public->getCurve()) { + throw new \InvalidArgumentException("The public key curve (" . $public->getCurve() . ") and private key curve ($privateCurve) need to match"); + } + $orig = $public; $public = $public->getEncodedCoordinates(); // fall-through case is_string($public): - $point = $private->multiply($public); - switch ($private->getCurve()) { - case 'Curve25519': - case 'Curve448': - $secret = $point; - break; - default: - // according to https://www.secg.org/sec1-v2.pdf#page=33 only X is returned - $secret = substr($point, 1, (strlen($point) - 1) >> 1); + $forcedEngine = EC::getForcedEngine(); + if ($forcedEngine === 'libsodium' && $privateCurve !== 'Curve25519') { + throw new BadConfigurationException('Engine libsodium is forced but can only used with Curve25519 for ECDH'); } + if (!isset($forcedEngine) || $forcedEngine === 'OpenSSL') { + // PHP 7.3.0 introduced the openssl_pkey_derive() function + // openssl_dh_computee_key() has been around since PHP 5.3.0+ BUT it did not support ECDH + // until PHP 8.1.0 / OpenSSL 3.0.0 + if ($forcedEngine === 'OpenSSL' && !function_exists('openssl_pkey_derive')) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for ECDH'); + } + if (function_exists('openssl_pkey_derive')) { + $privateStr = (string) $private->withPassword(); + $publicStr = (string) (isset($orig) ? $orig : EC::convertPointToPublicKey($private->getCurve(), $public)); + $result = openssl_pkey_derive($publicStr, $privateStr); + if ($result) { + return $result; + } + if ($forcedEngine === 'OpenSSL') { + // i suppose we _could_ try openssl_dh_compute_key() at this point + // quoting https://www.php.net/openssl-dh-compute-key "ECDH is only supported as of PHP 8.1.0 and OpenSSL 3.0.0". ie. + // PHP_VERSION_ID >= 80100 && OPENSSL_VERSION_NUMBER >= 0x3000000f + // but i think that's overkill. if openssl_pkey_derive() doesn't work it seems doubtful to me that openssl_dh_compute_key() would + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to perform ECDH because of ' . openssl_error_string()); + } + } + } + $curveName = $private->getCurve(); + $isMontgomeryCurve = $curveName == 'Curve25519' || $curveName == 'Curve448'; + if (!$isMontgomeryCurve) { + $public = EC::convertPointToPublicKey($curveName, $public, false); + } + $point = $private->multiply($public); + if ($isMontgomeryCurve) { + /* + "Both MAY check, without leaking extra information about the value of K, + whether K is the all-zero value and abort if so" + -- https://datatracker.ietf.org/doc/html/rfc7748#section-6.1 (and #section-6.2) + */ + $size = $curveName == 'Curve25519' ? 32 : 56; + // throw exception if hash_equals is false, otherwise, return $point + if (hash_equals(str_repeat("\0", $size), $point)) { + throw new \UnexpectedValueException('All-zero shared secret detected (points order is too small)'); + } + return $point; + } + // according to https://www.secg.org/sec1-v2.pdf#page=33 only X is returned + $secret = substr($point, 1, (strlen($point) - 1) >> 1); /* if (($secret[0] & "\x80") === "\x80") { $secret = "\0$secret"; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php index 92c777d..23c54df 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php @@ -33,6 +33,7 @@ use phpseclib3\Crypt\Common\AsymmetricKey; use phpseclib3\Crypt\DSA\Parameters; use phpseclib3\Crypt\DSA\PrivateKey; use phpseclib3\Crypt\DSA\PublicKey; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Exception\InsufficientSetupException; use phpseclib3\Math\BigInteger; @@ -87,6 +88,14 @@ abstract class DSA extends AsymmetricKey */ protected $sigFormat; + /** + * Forced Engine + * + * @var ?string + * @see parent::forceEngine() + */ + protected static $forcedEngine = null; + /** * Signature Format (Short) * @@ -110,10 +119,6 @@ abstract class DSA extends AsymmetricKey throw new \RuntimeException('createParameters() should not be called from final classes (' . static::class . ')'); } - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - switch (true) { case $N == 160: /* @@ -185,15 +190,19 @@ abstract class DSA extends AsymmetricKey { self::initialize_static_variables(); + if (self::$forcedEngine == 'libsodium') { + throw new BadConfigurationException('Engine ' . self::$forcedEngine . ' is forced but unsupported for DSA'); + } + + if (self::$forcedEngine == 'OpenSSL' && !defined('OPENSSL_KEYTYPE_DSA')) { + throw new BadConfigurationException("Engine OpenSSL is forced but unsupported for DSA"); + } + $class = new \ReflectionClass(static::class); if ($class->isFinal()) { throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')'); } - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) { $params = self::createParameters($args[0], $args[1]); } elseif (count($args) == 1 && $args[0] instanceof Parameters) { @@ -204,6 +213,33 @@ abstract class DSA extends AsymmetricKey throw new InsufficientSetupException('Valid parameters are either two integers (L and N), a single DSA object or no parameters at all.'); } + // at this point the only two supported values for self::$forcedEngine are OpenSSL, PHP and null + // if it's either OpenSSL or null we'll use OpenSSL (if it's available) + if (self::$forcedEngine !== 'PHP' && defined('OPENSSL_KEYTYPE_DSA')) { + $config = []; + if (self::$configFile) { + $config['config'] = self::$configFile; + } + $dsa = openssl_pkey_new($config + [ + 'private_key_type' => OPENSSL_KEYTYPE_DSA, + 'p' => $params->p, + 'q' => $params->q, + 'g' => $params->g, + ]); + if ($dsa && openssl_pkey_export($dsa, $privatekeystr, null, $config)) { + // clear the buffer of error strings stemming from a minimalistic openssl.cnf + // https://github.com/php/php-src/issues/11054 talks about other errors this'll pick up + while (openssl_error_string() !== false) { + } + + return DSA::load($privatekeystr) + ->withHash($params->hash->getHash()) + ->withSignatureFormat($params->shortFormat); + } elseif (isset(self::$forcedEngine)) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for DSA'); + } + } + $private = new PrivateKey(); $private->p = $params->p; $private->q = $params->q; @@ -227,10 +263,6 @@ abstract class DSA extends AsymmetricKey */ protected static function onLoad(array $components) { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - if (!isset($components['x']) && !isset($components['y'])) { $new = new Parameters(); } elseif (isset($components['x'])) { @@ -276,22 +308,6 @@ abstract class DSA extends AsymmetricKey return ['L' => $this->p->getLength(), 'N' => $this->q->getLength()]; } - /** - * Returns the current engine being used - * - * @see self::useInternalEngine() - * @see self::useBestEngine() - * @return string - */ - public function getEngine() - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? - 'OpenSSL' : 'PHP'; - } - /** * Returns the parameters * diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php index 800cfb3..2d06336 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php @@ -63,13 +63,28 @@ abstract class PKCS1 extends Progenitor $key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP); if (is_array($key)) { + if ($key['version']->toString() !== '0') { + throw new \UnexpectedValueException('Version number is not valid'); + } return $key; } - $key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP); - if (is_array($key)) { - return $key; - } + // PKCS1 DSA public keys are not supported by phpseclib since they can't be used to do + // anything on their own. in order to verify a signature with DSA you need p, q, g and y. + // a PKCS1 DSA public key only has y. to verify a signature with a PKCS1 DSA public key + // you'd also need to load a PKCS1 DSA parameters file separately. like you'd need to + // load two files instead of just one. there's no other key format that phpseclib supports + // that has that requirement so building it in for PKCS1 DSA public keys seems excessive. + // + // the whole thing would be rather like an RSA public key having the modulo live in + // a separate file than the exponent. + // + // this isn't an issue for PKCS8 DSA public keys because those keys have the parameters + // included. eg. \phpseclib3\File\ASN1\Maps\SubjectPublicKeyInfo has "algorithm" and + // "subjectPublicKey" and "algorithm", in turn, has "algorithm" and "parameters". y + // is saved as "subjectPublicKey" and p, q and g are saved as "parameters". + + //$key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP); throw new \RuntimeException('Unable to perform ASN1 mapping'); } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php index f6177f4..8549a2e 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php @@ -56,7 +56,10 @@ abstract class PuTTY extends Progenitor if (!isset($components['private'])) { return $components; } - extract($components); + $type = $components['type']; + $comment = $components['comment']; + $public = $components['public']; + $private = $components['private']; unset($components['public'], $components['private']); list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $public); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php index 87cd77a..0b1a24c 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php @@ -14,6 +14,7 @@ namespace phpseclib3\Crypt\DSA; use phpseclib3\Crypt\Common; use phpseclib3\Crypt\DSA; use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Math\BigInteger; /** @@ -79,18 +80,34 @@ final class PrivateKey extends DSA implements Common\PrivateKey { $format = $this->sigFormat; - if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { - $signature = ''; - $result = openssl_sign($message, $signature, $this->toString('PKCS8'), $this->hash->getHash()); + if (self::$forcedEngine === 'libsodium') { + throw new BadConfigurationException('Engine libsodium is forced but unsupported for DSA'); + } - if ($result) { - if ($this->shortFormat == 'ASN1') { - return $signature; + if (self::$forcedEngine === 'OpenSSL' && !function_exists('openssl_get_md_methods')) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for DSA'); + } + + if (function_exists('openssl_get_md_methods') && self::$forcedEngine !== 'PHP') { + if (in_array($this->hash->getHash(), openssl_get_md_methods())) { + $signature = ''; + $result = openssl_sign($message, $signature, $this->withPassword()->toString('PKCS8'), $this->hash->getHash()); + + if ($result) { + if ($this->shortFormat == 'ASN1') { + return $signature; + } + + $loaded = ASN1Signature::load($signature); + $r = $loaded['r']; + $s = $loaded['s']; + + return $format::save($r, $s); + } elseif (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to create signature because of ' . openssl_error_string()); } - - extract(ASN1Signature::load($signature)); - - return $format::save($r, $s); + } elseif (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for DSA / ' . $this->hash->getHash()); } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php index c14ffbd..e7e7d7e 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php @@ -14,6 +14,7 @@ namespace phpseclib3\Crypt\DSA; use phpseclib3\Crypt\Common; use phpseclib3\Crypt\DSA; use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature; +use phpseclib3\Exception\BadConfigurationException; /** * DSA Public Key @@ -34,21 +35,34 @@ final class PublicKey extends DSA implements Common\PublicKey */ public function verify($message, $signature) { + if (self::$forcedEngine === 'libsodium') { + throw new BadConfigurationException('Engine libsodium is forced but unsupported for DSA'); + } + + if (self::$forcedEngine === 'OpenSSL' && !function_exists('openssl_get_md_methods')) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for DSA'); + } + $format = $this->sigFormat; $params = $format::load($signature); if ($params === false || count($params) != 2) { return false; } - extract($params); + $r = $params['r']; + $s = $params['s']; - if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { - $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; + if (function_exists('openssl_get_md_methods') && self::$forcedEngine !== 'PHP') { + if (in_array($this->hash->getHash(), openssl_get_md_methods())) { + $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; - $result = openssl_verify($message, $sig, $this->toString('PKCS8'), $this->hash->getHash()); + $result = openssl_verify($message, $sig, $this->toString('PKCS8'), $this->hash->getHash()); - if ($result != -1) { - return (bool) $result; + if ($result != -1) { + return (bool) $result; + } + } elseif (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for DSA / ' . $this->hash->getHash()); } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php index dc82dd0..5393085 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php @@ -33,12 +33,15 @@ use phpseclib3\Crypt\Common\AsymmetricKey; use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; use phpseclib3\Crypt\EC\Curves\Curve25519; +use phpseclib3\Crypt\EC\Curves\Curve448; use phpseclib3\Crypt\EC\Curves\Ed25519; use phpseclib3\Crypt\EC\Curves\Ed448; use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; +use phpseclib3\Crypt\EC\Formats\Keys\PKCS8; use phpseclib3\Crypt\EC\Parameters; use phpseclib3\Crypt\EC\PrivateKey; use phpseclib3\Crypt\EC\PublicKey; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Exception\UnsupportedAlgorithmException; use phpseclib3\Exception\UnsupportedCurveException; use phpseclib3\Exception\UnsupportedOperationException; @@ -74,13 +77,6 @@ abstract class EC extends AsymmetricKey */ protected $curve; - /** - * Signature Format - * - * @var string - */ - protected $format; - /** * Signature Format (Short) * @@ -130,6 +126,14 @@ abstract class EC extends AsymmetricKey */ protected $sigFormat; + /** + * Forced Engine + * + * @var ?string + * @see parent::forceEngine() + */ + protected static $forcedEngine = null; + /** * Create public / private key pair. * @@ -145,31 +149,7 @@ abstract class EC extends AsymmetricKey throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')'); } - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - $curve = strtolower($curve); - if (self::$engines['libsodium'] && $curve == 'ed25519' && function_exists('sodium_crypto_sign_keypair')) { - $kp = sodium_crypto_sign_keypair(); - - $privatekey = EC::loadFormat('libsodium', sodium_crypto_sign_secretkey($kp)); - //$publickey = EC::loadFormat('libsodium', sodium_crypto_sign_publickey($kp)); - - $privatekey->curveName = 'Ed25519'; - //$publickey->curveName = $curve; - - return $privatekey; - } - - $privatekey = new PrivateKey(); - - $curveName = $curve; - if (preg_match('#(?:^curve|^ed)\d+$#', $curveName)) { - $curveName = ucfirst($curveName); - } elseif (substr($curveName, 0, 10) == 'brainpoolp') { - $curveName = 'brainpoolP' . substr($curveName, 10); - } + $curveName = self::getCurveCase($curve); $curve = '\phpseclib3\Crypt\EC\Curves\\' . $curveName; if (!class_exists($curve)) { @@ -180,6 +160,54 @@ abstract class EC extends AsymmetricKey $curveName = $reflect->isFinal() ? $reflect->getParentClass()->getShortName() : $reflect->getShortName(); + $curveEngineName = self::getOpenSSLCurveName(strtolower($curveName)); + + switch ($curveName) { + case 'Ed25519': + $providers = [ + 'libsodium' => function_exists('sodium_crypto_sign_keypair'), + // OPENSSL_KEYTYPE_ED25519 introduced in PHP 8.4.0 + 'OpenSSL' => defined('OPENSSL_KEYTYPE_ED25519'), + ]; + break; + case 'Ed448': + // OPENSSL_KEYTYPE_ED448 introduced in PHP 8.4.0 + $providers = ['OpenSSL' => defined('OPENSSL_KEYTYPE_ED448')]; + break; + case 'Curve25519': + $providers = [ + 'libsodium' => function_exists('sodium_crypto_box_publickey_from_secretkey'), + // OPENSSL_KEYTYPE_X25519 introduced in PHP 8.4.0 + 'OpenSSL' => defined('OPENSSL_KEYTYPE_X25519'), + ]; + break; + // OPENSSL_KEYTYPE_X448 introduced in PHP 8.4.0 + case 'Curve448': + $providers = ['OpenSSL' => defined('OPENSSL_KEYTYPE_X448')]; + break; + default: + // openssl_get_curve_names() was introduced in PHP 7.1.0 + // exclude curve25519 and curve448 from testing + $providers = ['OpenSSL' => function_exists('openssl_get_curve_names') && substr($curveEngineName, 0, 5) != 'curve' && in_array($curveEngineName, openssl_get_curve_names())]; + }; + + foreach ($providers as $engine => $isSupported) { + // if an engine is being forced and the forced engine doesn't match $engine, skip it + if (isset(self::$forcedEngine) && self::$forcedEngine !== $engine) { + continue; + } + if ($isSupported) { + $result = self::generateWithEngine($engine, $curveEngineName); + if (isset($result)) { + return $result; + } + } + if (self::$forcedEngine === $engine) { + throw new BadConfigurationException("EC::createKey: Engine $engine is forced but unsupported for $curve"); + } + } + + $privatekey = new PrivateKey(); $curve = new $curve(); if ($curve instanceof TwistedEdwardsCurve) { @@ -189,21 +217,14 @@ abstract class EC extends AsymmetricKey } else { $privatekey->dA = $dA = $curve->createRandomMultiplier(); } - if ($curve instanceof Curve25519 && self::$engines['libsodium']) { - //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000'); - //$QA = sodium_crypto_scalarmult($dA->toBytes(), $r); - $QA = sodium_crypto_box_publickey_from_secretkey($dA->toBytes()); - $privatekey->QA = [$curve->convertInteger(new BigInteger(strrev($QA), 256))]; - } else { - $privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA); - } $privatekey->curve = $curve; + $privatekey->curveName = $curveName; + $privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA); //$publickey = clone $privatekey; //unset($publickey->dA); //unset($publickey->x); - $privatekey->curveName = $curveName; //$publickey->curveName = $curveName; if ($privatekey->curve instanceof TwistedEdwardsCurve) { @@ -213,6 +234,130 @@ abstract class EC extends AsymmetricKey return $privatekey; } + /** + * Returns the actual case of the curve + * + * Useful for initializing the curve class + * + * @param string $curveName + * @return string + */ + private static function getCurveCase($curveName) + { + $curveName = strtolower($curveName); + if (preg_match('#(?:^curve|^ed)\d+$#', $curveName)) { + return ucfirst($curveName); + } + if (substr($curveName, 0, 10) == 'brainpoolp') { + return 'brainpoolP' . substr($curveName, 10); + } + return $curveName; + } + + /** + * Return the OpenSSL name for a curve + * + * @param string $curve + * @return string + */ + private static function getOpenSSLCurveName($curve) + { + switch ($curve) { + case 'secp256r1': + return 'prime256v1'; + case 'secp192r1': + return 'prime192v1'; + } + return $curve; + } + + /** + * Generate the key for a given curve / engine combo + * + * @param string $engine + * @param string $curve + * @return ?PrivateKey + */ + private static function generateWithEngine($engine, $curve) + { + if ($engine == 'libsodium') { + if ($curve == 'ed25519') { + $kp = sodium_crypto_sign_keypair(); + + $privatekey = EC::loadFormat('libsodium', sodium_crypto_sign_secretkey($kp)); + //$publickey = EC::loadFormat('libsodium', sodium_crypto_sign_publickey($kp)); + + $privatekey->curveName = 'Ed25519'; + //$publickey->curveName = $curve; + + return $privatekey; + } else { // $curve == 'curve25519 + $privatekey = new PrivateKey(); + $privatekey->curve = new Curve25519(); + $privatekey->curveName = 'Curve25519'; + $privatekey->dA = $privatekey->curve->createRandomMultiplier(); + $dA = str_pad($privatekey->dA->toBytes(), 32, "\0", STR_PAD_LEFT); + //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000'); + //$QA = sodium_crypto_scalarmult($dA, $r); + $QA = sodium_crypto_box_publickey_from_secretkey($dA); + $privatekey->QA = [$privatekey->curve->convertInteger(new BigInteger(strrev($QA), 256))]; + return $privatekey; + } + } + + // at this point $engine == 'OpenSSL' + + $curveName = self::getCurveCase($curve); + + $config = []; + if (self::$configFile) { + $config['config'] = self::$configFile; + } + $params = $config; + switch ($curve) { + case 'ed25519': + $params['private_key_type'] = OPENSSL_KEYTYPE_ED25519; + break; + case 'ed448': + $params['private_key_type'] = OPENSSL_KEYTYPE_ED448; + break; + case 'curve25519': + $params['private_key_type'] = OPENSSL_KEYTYPE_X25519; + break; + case 'curve448': + $params['private_key_type'] = OPENSSL_KEYTYPE_X448; + break; + default: + $params['private_key_type'] = OPENSSL_KEYTYPE_EC; + $params['curve_name'] = $curveName; + } + + $key = openssl_pkey_new($params); + if (!$key) { + return null; + } + $privateKeyStr = ''; + if (!openssl_pkey_export($key, $privateKeyStr, null, $config)) { + return null; + } + // clear the buffer of error strings + while (openssl_error_string() !== false) { + } + // some versions of OpenSSL / PHP return PKCS1 keys, others return PKCS8 keys + $privatekey = EC::load($privateKeyStr); + switch ($curveName) { + case 'prime256v1': + $privatekey->curveName = 'secp256r1'; + break; + case 'prime192v1': + $privatekey->curveName = 'secp192r1'; + break; + default: + $privatekey->curveName = $curveName; + } + return $privatekey; + } + /** * OnLoad Handler * @@ -220,10 +365,6 @@ abstract class EC extends AsymmetricKey */ protected static function onLoad(array $components) { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - if (!isset($components['dA']) && !isset($components['QA'])) { $new = new Parameters(); $new->curve = $components['curve']; @@ -320,27 +461,6 @@ abstract class EC extends AsymmetricKey return $this->curve->getLength(); } - /** - * Returns the current engine being used - * - * @see self::useInternalEngine() - * @see self::useBestEngine() - * @return string - */ - public function getEngine() - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - if ($this->curve instanceof TwistedEdwardsCurve) { - return $this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context) ? - 'libsodium' : 'PHP'; - } - - return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? - 'OpenSSL' : 'PHP'; - } - /** * Returns the public key coordinates as a string * @@ -359,6 +479,48 @@ abstract class EC extends AsymmetricKey return "\4" . $this->QA[0]->toBytes(true) . $this->QA[1]->toBytes(true); } + /** + * Convert point to public key + * + * For Weierstrass curves, if only the x coordinate is present (as is the case after doing a round of ECDH) + * then we'll guess at the y coordinate. There are only two possible y values and, atleast in-so-far as + * multiplication is concerned, neither value affects the resultant x value + * + * If $toPublicKey is set to false then a string will be returned - a kind of public key precursor + * + * @param string $curveName + * @param string $secret + * @param bool $toPublicKey optional + * @return PublicKey|string + */ + public static function convertPointToPublicKey($curveName, $secret, $toPublicKey = true) + { + $curveName = self::getCurveCase($curveName); + $curve = '\phpseclib3\Crypt\EC\Curves\\' . $curveName; + + if (!class_exists($curve)) { + throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported'); + } + + $curve = new $curve(); + if (!$curve instanceof TwistedEdwardsCurve) { + if ($curve instanceof MontgomeryCurve) { + $secret = strrev($secret); + } elseif ($curve->getLengthInBytes() == strlen($secret)) { + $secret = "\3$secret"; + } + if (!$toPublicKey) { + return $secret; + } + $secret = "\0$secret"; + } elseif (!$toPublicKey) { + return $secret; + } + $QA = PKCS8::extractPoint($secret, $curve); + $key = PKCS8::savePublicKey($curve, $QA); + return EC::loadFormat('PKCS8', $key); + } + /** * Returns the parameters * @@ -380,7 +542,7 @@ abstract class EC extends AsymmetricKey /** * Determines the signature padding mode * - * Valid values are: ASN1, SSH2, Raw + * Valid values are: ASN1, IEEE, SSH2, Raw * * @param string $format */ @@ -463,18 +625,4 @@ abstract class EC extends AsymmetricKey return parent::withHash($hash); } - - /** - * __toString() magic method - * - * @return string - */ - public function __toString() - { - if ($this->curve instanceof MontgomeryCurve) { - return ''; - } - - return parent::__toString(); - } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php index b792e16..30ca623 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php @@ -223,6 +223,9 @@ class Montgomery extends Base $p2 = $this->convertToInternal($p); $x = $p[0]; + $r = $this->randomInteger(); + $p2 = [$p2[0]->multiply($r), $p2[1]->multiply($r)]; + $b = $d->toBits(); $b = str_pad($b, 256, '0', STR_PAD_LEFT); for ($i = 0; $i < strlen($b); $i++) { @@ -246,7 +249,7 @@ class Montgomery extends Base * * x=X/Z * - * @return \phpseclib3\Math\PrimeField\Integer[] + * @return PrimeInteger[] */ public function convertToInternal(array $p) { @@ -266,7 +269,7 @@ class Montgomery extends Base /** * Returns the affine point * - * @return \phpseclib3\Math\PrimeField\Integer[] + * @return PrimeInteger[] */ public function convertToAffine(array $p) { @@ -274,6 +277,9 @@ class Montgomery extends Base return $p; } list($x, $z) = $p; + if ($z->equals($this->zero)) { + return [clone $this->zero]; + } return [$x->divide($z)]; } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php index 6200401..b197055 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php @@ -751,7 +751,7 @@ class Prime extends Base * To convert a Jacobian Coordinate to an Affine Point * you do (x / z^2, y / z^3) * - * @return \phpseclib3\Math\PrimeField\Integer[] + * @return PrimeInteger[] */ public function convertToAffine(array $p) { @@ -770,7 +770,7 @@ class Prime extends Base /** * Converts an affine point to a jacobian coordinate * - * @return \phpseclib3\Math\PrimeField\Integer[] + * @return PrimeInteger[] */ public function convertToInternal(array $p) { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php index 004406a..99aa38b 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php @@ -171,7 +171,7 @@ class TwistedEdwards extends Base /** * Returns the affine point * - * @return PrimeField\Integer[] + * @return PrimeInteger[] */ public function convertToAffine(array $p) { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php index 0f3f4d8..0aa81c8 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php @@ -18,6 +18,8 @@ use phpseclib3\Math\BigInteger; class Curve25519 extends Montgomery { + const SIZE = 32; + public function __construct() { // 2^255 - 19 @@ -47,10 +49,12 @@ class Curve25519 extends Montgomery */ public function multiplyPoint(array $p, BigInteger $d) { - //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes()))); + $d = $d->toBytes(); + $d = str_pad($d, 32, "\0", STR_PAD_LEFT); + + //$r = strrev(sodium_crypto_scalarmult($d, strrev($p[0]->toBytes()))); //return [$this->factory->newInteger(new BigInteger($r, 256))]; - $d = $d->toBytes(); $d &= "\xF8" . str_repeat("\xFF", 30) . "\x7F"; $d = strrev($d); $d |= "\x40"; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php index f4a4423..3a042e5 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php @@ -18,6 +18,8 @@ use phpseclib3\Math\BigInteger; class Curve448 extends Montgomery { + const SIZE = 56; + public function __construct() { // 2^448 - 2^224 - 1 @@ -58,10 +60,12 @@ class Curve448 extends Montgomery */ public function multiplyPoint(array $p, BigInteger $d) { - //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes()))); + $d = $d->toBytes(); + $d = str_pad($d, 56, "\0", STR_PAD_LEFT); + + //$r = strrev(sodium_crypto_scalarmult($d, strrev($p[0]->toBytes()))); //return [$this->factory->newInteger(new BigInteger($r, 256))]; - $d = $d->toBytes(); $d[0] = $d[0] & "\xFC"; $d = strrev($d); $d |= "\x80"; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php index 743c07c..df6ac12 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php @@ -14,10 +14,14 @@ namespace phpseclib3\Crypt\EC\Formats\Keys; use phpseclib3\Common\Functions\Strings; +use phpseclib3\Crypt\EC; use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; use phpseclib3\Crypt\EC\BaseCurves\Binary as BinaryCurve; +use phpseclib3\Crypt\EC\BaseCurves\Montgomery; use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve; use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; +use phpseclib3\Crypt\EC\Curves\Curve25519; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Exception\UnsupportedCurveException; use phpseclib3\File\ASN1; use phpseclib3\File\ASN1\Maps; @@ -274,6 +278,9 @@ trait Common */ public static function extractPoint($str, BaseCurve $curve) { + if ($curve instanceof Montgomery) { + return [new BigInteger($str, 256)]; + } if ($curve instanceof TwistedEdwardsCurve) { // first step of point deciding as discussed at the following URL's: // https://tools.ietf.org/html/rfc8032#section-5.1.3 @@ -524,6 +531,54 @@ trait Common throw new UnsupportedCurveException('Curve cannot be serialized'); } + private static function deriveMontgomeryPublicKey(array $components) + { + $curve = $components['curve']; + $dA = $components['dA']; + $forcedEngine = EC::getForcedEngine(); + + $useLibsodium = !isset($forcedEngine) && $curve instanceof Curve25519 && function_exists('sodium_crypto_box_publickey_from_secretkey'); + if ($forcedEngine === 'libsodium') { + $useLibsodium = true; + if (!$curve instanceof Curve25519) { + throw new \RuntimeException('Engine libsodium is forced but is not supported for Curve448'); + } + if (!function_exists('sodium_crypto_box_publickey_from_secretkey')) { + throw new BadConfigurationException('Engine libsodium is forced but not available'); + } + } + + if ($useLibsodium) { + //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000'); + //$QA = sodium_crypto_scalarmult($dA->toBytes(), $r); + $QA = sodium_crypto_box_publickey_from_secretkey(str_pad($dA->toBytes(), 32, chr(0), STR_PAD_LEFT)); + return [$components['curve']->convertInteger(new BigInteger(strrev($QA), 256))]; + } + + $useOpenSSL = !isset($forcedEngine) && function_exists('openssl_pkey_get_private'); + if ($forcedEngine == 'OpenSSL') { + $useOpenSSL = true; + if (!function_exists('openssl_pkey_get_private')) { + throw new BadConfigurationException('Engine OpenSSL is forced but is not available'); + } + } + + if ($useOpenSSL) { + $pem = PKCS8::savePrivateKey($dA, $curve, []); + $res = openssl_pkey_get_private($pem); + if ($res !== false && ($details = openssl_pkey_get_details($res)) !== false) { + $index = $curve instanceof Curve25519 ? 'x25519' : 'x448'; + return isset($details[$index]['pub_key']) ? + [$curve->convertInteger(new BigInteger(strrev($details[$index]['pub_key']), 256))] : + PKCS8::load($details['key'])['QA']; + } elseif ($forcedEngine == 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to derive the public key because of ' . openssl_error_string()); + } + } + + return [$components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA'])[0]]; + } + /** * Use Specified Curve * diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php index aa64f79..0277c86 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php @@ -33,6 +33,8 @@ use phpseclib3\Math\BigInteger; */ abstract class MontgomeryPrivate { + use Common; + /** * Is invisible flag * @@ -59,11 +61,11 @@ abstract class MontgomeryPrivate throw new \LengthException('The only supported lengths are 32 and 56'); } - $components = ['curve' => $curve]; - $components['dA'] = new BigInteger($key, 256); - $curve->rangeCheck($components['dA']); - // note that EC::getEncodedCoordinates does some additional "magic" (it does strrev on the result) - $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); + $components = [ + 'curve' => $curve, + 'dA' => new BigInteger($key, 256) + ]; + $components['QA'] = self::deriveMontgomeryPublicKey($components); return $components; } @@ -96,6 +98,6 @@ abstract class MontgomeryPrivate throw new UnsupportedFormatException('MontgomeryPrivate private keys do not support encryption'); } - return $privateKey->toBytes(); + return str_pad($privateKey->toBytes(), $curve::SIZE, "\0", STR_PAD_RIGHT); } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php index 0ef1160..5310d5a 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php @@ -111,6 +111,9 @@ abstract class OpenSSH extends Progenitor $reflect = new \ReflectionClass($curve); $name = $reflect->getShortName(); + if (!isset(self::$curveOIDs[$name])) { + throw new UnsupportedCurveException($name . ' is not a curve that the OpenSSH plugin supports'); + } $oid = self::$curveOIDs[$name]; $aliases = array_filter(self::$curveOIDs, function ($v) use ($oid) { return $v == $oid; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php index 756ffb9..e67e68b 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php @@ -132,8 +132,8 @@ abstract class PKCS1 extends Progenitor $components = []; $components['curve'] = self::loadCurveByParam($key['parameters']); $components['dA'] = new BigInteger($key['privateKey'], 256); - $components['QA'] = isset($ecPrivate['publicKey']) ? - self::extractPoint($ecPrivate['publicKey'], $components['curve']) : + $components['QA'] = isset($key['publicKey']) ? + self::extractPoint($key['publicKey'], $components['curve']) : $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']); return $components; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php index 9fc8405..6df0c91 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php @@ -27,12 +27,14 @@ use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor; use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve; use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve; use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve; +use phpseclib3\Crypt\EC\Curves\Curve25519; +use phpseclib3\Crypt\EC\Curves\Curve448; use phpseclib3\Crypt\EC\Curves\Ed25519; use phpseclib3\Crypt\EC\Curves\Ed448; -use phpseclib3\Exception\UnsupportedCurveException; use phpseclib3\File\ASN1; use phpseclib3\File\ASN1\Maps; use phpseclib3\Math\BigInteger; +use phpseclib3\Math\Common\FiniteField\Integer; /** * PKCS#8 Formatted EC Key Handler @@ -48,14 +50,14 @@ abstract class PKCS8 extends Progenitor * * @var array */ - const OID_NAME = ['id-ecPublicKey', 'id-Ed25519', 'id-Ed448']; + const OID_NAME = ['id-ecPublicKey', 'id-Ed25519', 'id-Ed448', 'id-X25519', 'id-X448']; /** * OID Value * * @var string */ - const OID_VALUE = ['1.2.840.10045.2.1', '1.3.101.112', '1.3.101.113']; + const OID_VALUE = ['1.2.840.10045.2.1', '1.3.101.112', '1.3.101.113', '1.3.101.110', '1.3.101.111']; /** * Break a public or private key down into its constituent components @@ -81,6 +83,9 @@ abstract class PKCS8 extends Progenitor case 'id-Ed25519': case 'id-Ed448': return self::loadEdDSA($key); + case 'id-X25519': + case 'id-X448': + return self::loadECDH($key); } $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element); @@ -158,20 +163,57 @@ abstract class PKCS8 extends Progenitor return $components; } + private static function loadECDH(array $key) + { + $components = []; + + if (isset($key['privateKey'])) { + $components['curve'] = $key['privateKeyAlgorithm']['algorithm'] == 'id-X25519' ? new Curve25519() : new Curve448(); + $expected = chr(ASN1::TYPE_OCTET_STRING) . ASN1::encodeLength($components['curve']::SIZE); + $privateKey = (string) $key['privateKey']; + if (substr($privateKey, 0, 2) != $expected) { + throw new \RuntimeException( + 'The first two bytes of the ' . + $key['privateKeyAlgorithm']['algorithm'] . + ' private key field should be 0x' . bin2hex($expected) + ); + } + $components['dA'] = new BigInteger(substr($privateKey, 2), 256); + } + + if (isset($key['publicKey'])) { + if (!isset($components['curve'])) { + $components['curve'] = $key['publicKeyAlgorithm']['algorithm'] == 'id-X25519' ? new Curve25519() : new Curve448(); + } + + $components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key['publicKey']), 256))]; + } + + if (isset($key['privateKey']) && !isset($components['QA'])) { + $components['QA'] = self::deriveMontgomeryPublicKey($components); + } + + return $components; + } + /** * Convert an EC public key to the appropriate format * * @param BaseCurve $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey + * @param Integer[] $publicKey * @param array $options optional * @return string */ public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = []) { self::initialize_static_variables(); - if ($curve instanceof MontgomeryCurve) { - throw new UnsupportedCurveException('Montgomery Curves are not supported'); + return self::wrapPublicKey( + str_pad(strrev($publicKey[0]->toBytes()), $curve::SIZE, "\0", STR_PAD_RIGHT), + null, + $curve instanceof Curve25519 ? 'id-X25519' : 'id-X448', + $options + ); } if ($curve instanceof TwistedEdwardsCurve) { @@ -195,7 +237,7 @@ abstract class PKCS8 extends Progenitor * * @param BigInteger $privateKey * @param BaseCurve $curve - * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey + * @param Integer[] $publicKey * @param string $secret optional * @param string $password optional * @param array $options optional @@ -206,7 +248,13 @@ abstract class PKCS8 extends Progenitor self::initialize_static_variables(); if ($curve instanceof MontgomeryCurve) { - throw new UnsupportedCurveException('Montgomery Curves are not supported'); + return self::wrapPrivateKey( + chr(ASN1::TYPE_OCTET_STRING) . ASN1::encodeLength($curve::SIZE) . str_pad($privateKey->toBytes(), $curve::SIZE, "\0", STR_PAD_LEFT), + [], + null, + $password, + $curve instanceof Curve25519 ? 'id-X25519' : 'id-X448' + ); } if ($curve instanceof TwistedEdwardsCurve) { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php index b0cb126..7f6cf63 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php @@ -71,6 +71,10 @@ abstract class XML $use_errors = libxml_use_internal_errors(true); + if (substr($key, 0, 5) != '' . $key . ''; + } + $temp = self::isolateNamespace($key, 'http://www.w3.org/2009/xmldsig11#'); if ($temp) { $key = $temp; @@ -82,9 +86,6 @@ abstract class XML } $dom = new \DOMDocument(); - if (substr($key, 0, 5) != '' . $key . ''; - } if (!$dom->loadXML($key)) { libxml_use_internal_errors($use_errors); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php index 91253b8..b786222 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php @@ -21,6 +21,7 @@ use phpseclib3\Crypt\EC\Curves\Ed25519; use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature; use phpseclib3\Crypt\Hash; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Exception\UnsupportedOperationException; use phpseclib3\Math\BigInteger; @@ -59,18 +60,40 @@ final class PrivateKey extends EC implements Common\PrivateKey */ public function multiply($coordinates) { - if ($this->curve instanceof MontgomeryCurve) { - if ($this->curve instanceof Curve25519 && self::$engines['libsodium']) { - return sodium_crypto_scalarmult($this->dA->toBytes(), $coordinates); - } + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is not supported for the multiplication operation'); + } + if (self::$forcedEngine === 'libsodium' && !$this->curve instanceof Curve25519) { + throw new BadConfigurationException('Engine libsodium is only supported for Curve25519'); + } + + if ($this->curve instanceof Curve25519 && self::$forcedEngine !== 'PHP') { + if (self::$forcedEngine === 'libsodium' && !function_exists('sodium_crypto_scalarmult')) { + throw new BadConfigurationException('Engine libsodium is forced but unsupported for Curve25519'); + } + if (function_exists('sodium_crypto_scalarmult')) { + $dA = str_pad($this->dA->toBytes(), 32, "\0", STR_PAD_LEFT); + try { + return sodium_crypto_scalarmult($dA, $coordinates); + } catch (\SodiumException $e) { + if (self::$forcedEngine == 'libsodium') { + throw new BadConfigurationException('Engine libsodium is forced but was unable to perform multiplication because of ' . $e->getMessage()); + } + } + } + } + + if ($this->curve instanceof MontgomeryCurve) { $point = [$this->curve->convertInteger(new BigInteger(strrev($coordinates), 256))]; $point = $this->curve->multiplyPoint($point, $this->dA); return strrev($point[0]->toBytes(true)); } + if (!$this->curve instanceof TwistedEdwardsCurve) { $coordinates = "\0$coordinates"; } + $point = PKCS1::extractPoint($coordinates, $this->curve); $point = $this->curve->multiplyPoint($point, $this->dA); if ($this->curve instanceof TwistedEdwardsCurve) { @@ -104,11 +127,56 @@ final class PrivateKey extends EC implements Common\PrivateKey return false; } - if ($this->curve instanceof TwistedEdwardsCurve) { - if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) { + if (self::$forcedEngine === 'libsodium' && !$this->curve instanceof Ed25519) { + throw new BadConfigurationException('Engine libsodium is only supported for Ed25519'); + } + + // at this point either self::$forcedEngine is NOT libsodium or the curve is Ed25519 + + if ($this->curve instanceof Ed25519 && self::$forcedEngine !== 'PHP' && self::$forcedEngine !== 'OpenSSL') { + if (self::$forcedEngine === 'libsodium') { + if (!function_exists('sodium_crypto_sign_detached')) { + throw new BadConfigurationException('Engine libsodium is forced but unsupported for Ed25519 / Ed448'); + } + if (isset($this->context)) { + throw new BadConfigurationException('Engine libsodium is forced but unsupported for Ed25519ctx (context)'); + } + } + if (function_exists('sodium_crypto_sign_detached') && !isset($this->context)) { $result = sodium_crypto_sign_detached($message, $this->withPassword()->toString('libsodium')); return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) : $result; } + } + + // at this point self::$forcedEngine CAN'T be libsodium so we won't check for it henceforth + + if ($this->curve instanceof TwistedEdwardsCurve) { + if (self::$forcedEngine !== 'PHP') { + $keyTypeConstant = $this->curve instanceof Ed25519 ? 'OPENSSL_KEYTYPE_ED25519' : 'OPENSSL_KEYTYPE_ED448'; + if (self::$forcedEngine === 'OpenSSL') { + if (!defined($keyTypeConstant)) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for Ed25519 / Ed448'); + } + // OpenSSL supports Ed25519/Ed448 but not Ed25519ctx (context), so skip if context is set + if (isset($this->context)) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for Ed25519 / Ed448 curves with context\'s'); + } + } + if (defined($keyTypeConstant) && !isset($this->context)) { + $result = ''; + // algorithm 0 is used because EdDSA has a built-in hash + openssl_sign($message, $result, $this->withPassword()->toString('PKCS8'), 0); + if ($result) { + $signature = $shortFormat == 'SSH2' + ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) + : $result; + return $signature; + } + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to create signature because of ' . openssl_error_string()); + } + } + } // contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not. // quoting https://tools.ietf.org/html/rfc8032#section-8.5 , @@ -143,23 +211,37 @@ final class PrivateKey extends EC implements Common\PrivateKey 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())) { - $signature = ''; - // altho PHP's OpenSSL bindings only supported EC key creation in PHP 7.1 they've long - // supported signing / verification - // we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve; - // doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even - // has curve-specific optimizations - $result = openssl_sign($message, $signature, $this->withPassword()->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); + if (self::$forcedEngine === 'OpenSSL' && !function_exists('openssl_get_md_methods')) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for ECDSA'); + } - if ($result) { - if ($shortFormat == 'ASN1') { - return $signature; + // at this point $forcedEngine is either PHP or null. either that OR openssl_get_md_methods() exists + + if (self::$forcedEngine !== 'PHP') { + if (in_array($this->hash->getHash(), openssl_get_md_methods())) { + $signature = ''; + // altho PHP's OpenSSL bindings only supported EC key creation in PHP 7.1 they've long + // supported signing / verification + // we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve; + // doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even + // has curve-specific optimizations + $result = openssl_sign($message, $signature, $this->withPassword()->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); + + if ($result) { + if ($shortFormat == 'ASN1') { + return $signature; + } + + $loaded = ASN1Signature::load($signature); + $r = $loaded['r']; + $s = $loaded['s']; + + return $this->formatSignature($r, $s); + } elseif (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to create signature because of ' . openssl_error_string()); } - - extract(ASN1Signature::load($signature)); - - return $this->formatSignature($r, $s); + } elseif (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for ECDSA / ' . $this->hash->getHash()); } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php index 4558ce3..2201497 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php @@ -20,6 +20,7 @@ use phpseclib3\Crypt\EC\Curves\Ed25519; use phpseclib3\Crypt\EC\Formats\Keys\PKCS1; use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature; use phpseclib3\Crypt\Hash; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Exception\UnsupportedOperationException; use phpseclib3\Math\BigInteger; @@ -52,17 +53,62 @@ final class PublicKey extends EC implements Common\PublicKey return false; } - $order = $this->curve->getOrder(); + if (self::$forcedEngine === 'libsodium' && !$this->curve instanceof Ed25519) { + throw new BadConfigurationException('Engine libsodium is only supported for Ed25519'); + } + + // at this point either self::$forcedEngine is NOT libsodium or the curve is Ed25519 + + if ($this->curve instanceof Ed25519 && self::$forcedEngine !== 'PHP' && self::$forcedEngine !== 'OpenSSL') { + if (self::$forcedEngine === 'libsodium') { + if (!function_exists('sodium_crypto_sign_verify_detached')) { + throw new BadConfigurationException('Engine libsodium is forced but unsupported for Ed25519 / Ed448'); + } + if (isset($this->context)) { + throw new BadConfigurationException('Engine libsodium is forced but unsupported for Ed25519ctx (context)'); + } + } + if (function_exists('sodium_crypto_sign_verify_detached') && !isset($this->context)) { + if ($shortFormat == 'SSH2') { + list(, $signature) = Strings::unpackSSH2('ss', $signature); + } + + return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium')); + } + } + + // at this point self::$forcedEngine CAN'T be libsodium so we won't check for it henceforth 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')); + if (self::$forcedEngine !== 'PHP') { + $keyTypeConstant = $this->curve instanceof Ed25519 ? 'OPENSSL_KEYTYPE_ED25519' : 'OPENSSL_KEYTYPE_ED448'; + if (self::$forcedEngine === 'OpenSSL') { + if (!defined($keyTypeConstant)) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for Ed25519 / Ed448'); + } + // OpenSSL supports Ed25519/Ed448 but not Ed25519ctx (context), so skip if context is set + if (isset($this->context)) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for Ed25519 / Ed448 curves with context\'s'); + } + } + if (defined($keyTypeConstant) && !isset($this->context)) { + // algorithm 0 is used because EdDSA has a built-in hash + $result = openssl_verify($message, $signature, $this->toString('PKCS8'), 0) === 1; + if ($result !== -1 && $result !== false) { + return (bool) $result; + } + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to create signature because of ' . openssl_error_string()); + } + } } + $order = $this->curve->getOrder(); + $curve = $this->curve; if (strlen($signature) != 2 * $curve::SIZE) { return false; @@ -115,18 +161,34 @@ final class PublicKey extends EC implements Common\PublicKey if ($params === false || count($params) != 2) { return false; } - extract($params); + $r = $params['r']; + $s = $params['s']; - if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) { - $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; + if (self::$forcedEngine === 'OpenSSL' && !function_exists('openssl_get_md_methods')) { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for ECDSA'); + } - $result = openssl_verify($message, $sig, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); + // at this point $forcedEngine is either PHP or null. either that OR openssl_get_md_methods() exists - if ($result != -1) { - return (bool) $result; + if (self::$forcedEngine !== 'PHP') { + if (in_array($this->hash->getHash(), openssl_get_md_methods())) { + $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature; + + $result = openssl_verify($message, $sig, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash()); + + if ($result !== -1 && $result !== false) { + return (bool) $result; + } + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to verify signature because of ' . openssl_error_string()); + } + } elseif (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for ECDSA / ' . $this->hash->getHash()); } } + $order = $this->curve->getOrder(); + $n_1 = $order->subtract(self::$one); if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) { return false; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php index 09e48f9..f1105ca 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php @@ -194,6 +194,15 @@ class Hash private static $maxwordrange128; /**#@-*/ + /**#@+ + * AES_CMAC variables + * + * @var string + */ + private $k1; + private $k2; + /**#@-*/ + /** * Default Constructor. * @@ -286,7 +295,7 @@ class Hash public function setHash($hash) { $oldHash = $this->hashParam; - $this->hashParam = $hash = strtolower($hash); + $this->hashParam = $hash = strtolower(str_replace('/', '-', $hash)); switch ($hash) { case 'umac-32': case 'umac-64': @@ -299,6 +308,14 @@ class Hash $this->length = abs(substr($hash, -3)) >> 3; $this->algo = 'umac'; return; + case 'aes_cmac': + if ($oldHash != $this->hashParam) { + $this->recomputeAESKey = true; + } + $this->blockSize = 128; + $this->length = 16; + $this->algo = 'aes_cmac'; + return; case 'md2-96': case 'md5-96': case 'sha1-96': @@ -306,8 +323,8 @@ class Hash case 'sha256-96': case 'sha384-96': case 'sha512-96': - case 'sha512/224-96': - case 'sha512/256-96': + case 'sha512-224-96': + case 'sha512-256-96': $hash = substr($hash, 0, -3); $this->length = 12; // 96 / 8 = 12 break; @@ -319,7 +336,7 @@ class Hash $this->length = 20; break; case 'sha224': - case 'sha512/224': + case 'sha512-224': case 'sha3-224': $this->length = 28; break; @@ -327,7 +344,7 @@ class Hash $this->paddingType = self::PADDING_KECCAK; // fall-through case 'sha256': - case 'sha512/256': + case 'sha512-256': case 'sha3-256': $this->length = 32; break; @@ -407,12 +424,12 @@ class Hash } } - if ($hash == 'sha512/224' || $hash == 'sha512/256') { + if ($hash == 'sha512-224' || $hash == 'sha512-256') { // PHP 7.1.0 introduced sha512/224 and sha512/256 support: // http://php.net/ChangeLog-7.php#7.1.0 if (version_compare(PHP_VERSION, '7.1.0') < 0) { // from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24 - $initial = $hash == 'sha512/256' ? + $initial = $hash == 'sha512-256' ? [ '22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD', '96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2' @@ -442,6 +459,15 @@ class Hash $this->opad = str_repeat(chr(0x5C), $b); } + // PHP's built in hash function does sha3-256 but sha512/256 so we'll update those accordingly + switch ($hash) { + case 'sha512-224': + $hash = 'sha512/224'; + break; + case 'sha512-256': + $hash = 'sha512/256'; + } + $this->algo = $hash; $this->computeKey(); @@ -977,6 +1003,69 @@ class Hash public function hash($text) { $algo = $this->algo; + // https://www.rfc-editor.org/rfc/rfc4493.html + // https://en.wikipedia.org/wiki/One-key_MAC + if ($algo == 'aes_cmac') { + $constZero = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + if ($this->recomputeAESKey) { + if (!is_string($this->key)) { + throw new InsufficientSetupException('No key has been set'); + } + if (strlen($this->key) != 16) { + throw new \LengthException('Key must be 16 bytes long'); + } + // Algorithm Generate_Subkey + $constRb = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x87"; + $this->c = new AES('ecb'); + $this->c->setKey($this->key); + $this->c->disablePadding(); + $l = $this->c->encrypt($constZero); + $msb = ($l & "\x80") == "\x80"; + $l = new BigInteger($l, 256); + $l->setPrecision(128); + $l = $l->bitwise_leftShift(1)->toBytes(); + // make it constant time + $k1 = $msb ? $l ^ $constRb : $l | $constZero; + + $msb = ($k1 & "\x80") == "\x80"; + $k2 = new BigInteger($k1, 256); + $k2->setPrecision(128); + $k2 = $k2->bitwise_leftShift(1)->toBytes(); + // make it constant time + $k2 = $msb ? $k2 ^ $constRb : $k2 | $constZero; + + $this->k1 = $k1; + $this->k2 = $k2; + } + + $len = strlen($text); + $const_Bsize = 16; + $M = strlen($text) ? str_split($text, $const_Bsize) : ['']; + + // Step 2 + $n = ceil($len / $const_Bsize); + // Step 3 + if ($n == 0) { + $n = 1; + $flag = false; + } else { + $flag = $len % $const_Bsize == 0; + } + // Step 4 + $M_last = $flag ? + $M[$n - 1] ^ $k1 : + self::OMAC_padding($M[$n - 1], $const_Bsize) ^ $k2; + // Step 5 + $x = $constZero; + // Step 6 + $c = &$this->c; + for ($i = 0; $i < $n - 1; $i++) { + $y = $x ^ $M[$i]; + $x = $c->encrypt($y); + } + $y = $M_last ^ $x; + return $c->encrypt($y); + } if ($algo == 'umac') { if ($this->recomputeAESKey) { if (!is_string($this->nonce)) { @@ -1790,6 +1879,17 @@ class Hash return pack('J*', ...$hash); } + /** + * OMAC Padding + * + * @link https://www.rfc-editor.org/rfc/rfc4493.html#section-2.4 + */ + private static function OMAC_padding($m, $length) + { + $count = $length - strlen($m) - 1; + return "$m\x80" . str_repeat("\0", $count); + } + /** * __toString() magic method */ diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php index 61afbae..3626408 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php @@ -32,6 +32,7 @@ abstract class PublicKeyLoader * @return AsymmetricKey * @param string|array $key * @param string $password optional + * @throws NoKeyLoadedException if key is not valid */ public static function load($key, $password = false) { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php index 654c906..f6b1676 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php @@ -45,7 +45,7 @@ class RC2 extends BlockCipher /** * Block Length of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size + * @see Common\SymmetricKey::block_size * @var int */ protected $block_size = 8; @@ -53,7 +53,7 @@ class RC2 extends BlockCipher /** * The Key * - * @see \phpseclib3\Crypt\Common\SymmetricKey::key + * @see Common\SymmetricKey::key * @see self::setKey() * @var string */ @@ -62,7 +62,7 @@ class RC2 extends BlockCipher /** * The Original (unpadded) Key * - * @see \phpseclib3\Crypt\Common\SymmetricKey::key + * @see Common\SymmetricKey::key * @see self::setKey() * @see self::encrypt() * @see self::decrypt() @@ -73,7 +73,7 @@ class RC2 extends BlockCipher /** * Key Length (in bytes) * - * @see \phpseclib3\Crypt\RC2::setKeyLength() + * @see RC2::setKeyLength() * @var int */ protected $key_length = 16; // = 128 bits @@ -81,7 +81,7 @@ class RC2 extends BlockCipher /** * The mcrypt specific name of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt + * @see Common\SymmetricKey::cipher_name_mcrypt * @var string */ protected $cipher_name_mcrypt = 'rc2'; @@ -89,7 +89,7 @@ class RC2 extends BlockCipher /** * Optimizing value while CFB-encrypting * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len + * @see Common\SymmetricKey::cfb_init_len * @var int */ protected $cfb_init_len = 500; @@ -261,7 +261,7 @@ class RC2 extends BlockCipher * * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * @see Common\SymmetricKey::__construct() * @param int $engine * @return bool */ @@ -323,7 +323,7 @@ class RC2 extends BlockCipher * has more then 128 bytes in it, and set $key to a single null byte if * it is empty. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey() + * @see Common\SymmetricKey::setKey() * @param string $key * @param int|boolean $t1 optional Effective key length in bits. * @throws \LengthException if the key length isn't supported @@ -426,8 +426,8 @@ class RC2 extends BlockCipher /** * Encrypts a block * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() + * @see Common\SymmetricKey::encryptBlock() + * @see Common\SymmetricKey::encrypt() * @param string $in * @return string */ @@ -470,8 +470,8 @@ class RC2 extends BlockCipher /** * Decrypts a block * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock() - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * @see Common\SymmetricKey::decryptBlock() + * @see Common\SymmetricKey::decrypt() * @param string $in * @return string */ @@ -514,7 +514,7 @@ class RC2 extends BlockCipher /** * Creates the key schedule * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() + * @see Common\SymmetricKey::setupKey() */ protected function setupKey() { @@ -534,7 +534,7 @@ class RC2 extends BlockCipher /** * Setup the performance-optimized function for de/encrypt() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt() + * @see Common\SymmetricKey::setupInlineCrypt() */ protected function setupInlineCrypt() { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php index 5f3bff2..c31efc1 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php @@ -52,19 +52,19 @@ use phpseclib3\Crypt\Common\StreamCipher; class RC4 extends StreamCipher { /** - * @see \phpseclib3\Crypt\RC4::_crypt() + * @see RC4::_crypt() */ const ENCRYPT = 0; /** - * @see \phpseclib3\Crypt\RC4::_crypt() + * @see RC4::_crypt() */ const DECRYPT = 1; /** * Key Length (in bytes) * - * @see \phpseclib3\Crypt\RC4::setKeyLength() + * @see RC4::setKeyLength() * @var int */ protected $key_length = 128; // = 1024 bits @@ -72,7 +72,7 @@ class RC4 extends StreamCipher /** * The mcrypt specific name of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt + * @see Common\SymmetricKey::cipher_name_mcrypt * @var string */ protected $cipher_name_mcrypt = 'arcfour'; @@ -98,7 +98,7 @@ class RC4 extends StreamCipher * * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * @see Common\SymmetricKey::__construct() * @param int $engine * @return bool */ @@ -159,7 +159,7 @@ class RC4 extends StreamCipher /** * Encrypts a message. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * @see Common\SymmetricKey::decrypt() * @see self::crypt() * @param string $plaintext * @return string $ciphertext @@ -178,7 +178,7 @@ class RC4 extends StreamCipher * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). * At least if the continuous buffer is disabled. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() + * @see Common\SymmetricKey::encrypt() * @see self::crypt() * @param string $ciphertext * @return string $plaintext @@ -214,7 +214,7 @@ class RC4 extends StreamCipher /** * Setup the key (expansion) * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey() + * @see Common\SymmetricKey::_setupKey() */ protected function setupKey() { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php index 9cbe6bf..30ad153 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php @@ -57,6 +57,7 @@ use phpseclib3\Crypt\Common\AsymmetricKey; use phpseclib3\Crypt\RSA\Formats\Keys\PSS; use phpseclib3\Crypt\RSA\PrivateKey; use phpseclib3\Crypt\RSA\PublicKey; +use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Exception\InconsistentSetupException; use phpseclib3\Exception\UnsupportedAlgorithmException; use phpseclib3\Math\BigInteger; @@ -228,12 +229,11 @@ abstract class RSA extends AsymmetricKey protected static $enableBlinding = true; /** - * OpenSSL configuration file name. + * Enable automatic salt length determination * - * @see self::createKey() - * @var ?string + * @var bool */ - protected static $configFile; + protected static $autoSaltLength = true; /** * Smallest Prime @@ -256,6 +256,14 @@ abstract class RSA extends AsymmetricKey */ protected $publicExponent; + /** + * Forced Engine + * + * @var ?string + * @see parent::forceEngine() + */ + protected static $forcedEngine = null; + /** * Sets the public exponent for key generation * @@ -280,18 +288,6 @@ abstract class RSA extends AsymmetricKey self::$smallestPrime = $val; } - /** - * Sets the OpenSSL config file path - * - * Set to the empty string to use the default config file - * - * @param string $val - */ - public static function setOpenSSLConfigPath($val) - { - self::$configFile = $val; - } - /** * Create a private key * @@ -309,6 +305,10 @@ abstract class RSA extends AsymmetricKey throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')'); } + if (self::$forcedEngine == 'libsodium' || (self::$forcedEngine == 'OpenSSL' && !function_exists('openssl_pkey_new'))) { + throw new BadConfigurationException('Engine ' . self::$forcedEngine . ' is forced but unsupported for RSA'); + } + $regSize = $bits >> 1; // divide by two to see how many bits P and Q would be if ($regSize > self::$smallestPrime) { $num_primes = floor($bits / self::$smallestPrime); @@ -318,25 +318,27 @@ abstract class RSA extends AsymmetricKey } if ($num_primes == 2 && $bits >= 384 && self::$defaultExponent == 65537) { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - - // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum - if (self::$engines['OpenSSL']) { + // at this point the only two supported values for self::$forcedEngine are OpenSSL, PHP and null + // if it's either OpenSSL or null we'll use OpenSSL (if it's available) + if (self::$forcedEngine !== 'PHP' && function_exists('openssl_pkey_new')) { $config = []; if (self::$configFile) { $config['config'] = self::$configFile; } + // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum $rsa = openssl_pkey_new(['private_key_bits' => $bits] + $config); - openssl_pkey_export($rsa, $privatekeystr, null, $config); + if (!$rsa || !openssl_pkey_export($rsa, $privatekeystr, null, $config)) { + if (isset(self::$forcedEngine)) { + throw new BadConfigurationException('Engine OpenSSL is forced but produced an error - ' . openssl_error_string()); + } + } else { + // clear the buffer of error strings stemming from a minimalistic openssl.cnf + // https://github.com/php/php-src/issues/11054 talks about other errors this'll pick up + while (openssl_error_string() !== false) { + } - // clear the buffer of error strings stemming from a minimalistic openssl.cnf - // https://github.com/php/php-src/issues/11054 talks about other errors this'll pick up - while (openssl_error_string() !== false) { + return RSA::load($privatekeystr); } - - return RSA::load($privatekeystr); } } @@ -345,22 +347,21 @@ abstract class RSA extends AsymmetricKey $e = new BigInteger(self::$defaultExponent); } - $n = clone self::$one; - $exponents = $coefficients = $primes = []; - $lcm = [ - 'top' => clone self::$one, - 'bottom' => false - ]; - do { + $n = clone self::$one; + $exponents = $coefficients = $primes = []; + $lcm = [ + 'top' => clone self::$one, + 'bottom' => false + ]; + for ($i = 1; $i <= $num_primes; $i++) { if ($i != $num_primes) { $primes[$i] = BigInteger::randomPrime($regSize); } else { - extract(BigInteger::minMaxBits($bits)); - /** @var BigInteger $min - * @var BigInteger $max - */ + $minMax = BigInteger::minMaxBits($bits); + $min = $minMax['min']; + $max = $minMax['max']; list($min) = $min->divide($n); $min = $min->add(self::$one); list($max) = $max->divide($n); @@ -479,18 +480,6 @@ abstract class RSA extends AsymmetricKey return $key; } - /** - * Initialize static variables - */ - protected static function initialize_static_variables() - { - if (!isset(self::$configFile)) { - self::$configFile = dirname(__FILE__) . '/../openssl.cnf'; - } - - parent::initialize_static_variables(); - } - /** * Constructor * @@ -582,6 +571,22 @@ abstract class RSA extends AsymmetricKey break; case 'sha512/256': $t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x05\x00\x04\x20"; + break; + // the following 3x algorithms are not specified in PKCS1 v2.2, however, some standards none-the-less do use them: + // https://sk-eid.github.io/smart-id-documentation/rp-api/changes.html#_security_enhancements + // the OIDs are from this URL: + // https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration#Hash + case 'sha3/224': + $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x07\x05\x00\x04\x1c"; + break; + case 'sha3/256': + $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x08\x05\x00\x04\x20"; + break; + case 'sha3/384': + $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x09\x05\x00\x04\x30"; + break; + case 'sha3/512': + $t = "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x0A\x05\x00\x04\x40"; } $t .= $h; $tLen = strlen($t); @@ -639,6 +644,22 @@ abstract class RSA extends AsymmetricKey case 'sha512/256': $t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x04\x20"; break; + // the following 3x algorithms are not specified in PKCS1 v2.2, however, some standards none-the-less do use them: + // https://sk-eid.github.io/smart-id-documentation/rp-api/changes.html#_security_enhancements + // the OIDs are from this URL: + // https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration#Hash + case 'sha3/224': + $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x07\x04\x1c"; + break; + case 'sha3/256': + $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x08\x04\x20"; + break; + case 'sha3/384': + $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x09\x04\x30"; + break; + case 'sha3/512': + $t = "\x30\x2b\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x0A\x04\x40"; + break; default: throw new UnsupportedAlgorithmException('md2 and md5 require NULLs'); } @@ -714,11 +735,15 @@ abstract class RSA extends AsymmetricKey case 'sha224': case 'sha512/224': case 'sha512/256': + case 'sha3/224': + case 'sha3/256': + case 'sha3/384': + case 'sha3/512': $new->hash = new Hash($hash); break; default: throw new UnsupportedAlgorithmException( - 'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256' + "The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256 - $hash provided" ); } $new->hLen = $new->hash->getLengthInBytes(); @@ -749,11 +774,15 @@ abstract class RSA extends AsymmetricKey case 'sha224': case 'sha512/224': case 'sha512/256': + case 'sha3/224': + case 'sha3/256': + case 'sha3/384': + case 'sha3/512': $new->mgfHash = new Hash($hash); break; default: throw new UnsupportedAlgorithmException( - 'The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256' + "The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256 - $hash provided" ); } $new->mgfHLen = $new->mgfHash->getLengthInBytes(); @@ -763,7 +792,6 @@ abstract class RSA extends AsymmetricKey /** * Returns the MGF hash algorithm currently being used - * */ public function getMGFHash() { @@ -892,28 +920,6 @@ abstract class RSA extends AsymmetricKey return $this->signaturePadding | $this->encryptionPadding; } - /** - * Returns the current engine being used - * - * OpenSSL is only used in this class (and it's subclasses) for key generation - * Even then it depends on the parameters you're using. It's not used for - * multi-prime RSA nor is it used if the key length is outside of the range - * supported by OpenSSL - * - * @see self::useInternalEngine() - * @see self::useBestEngine() - * @return string - */ - public function getEngine() - { - if (!isset(self::$engines['PHP'])) { - self::useBestEngine(); - } - return self::$engines['OpenSSL'] && self::$defaultExponent == 65537 ? - 'OpenSSL' : - 'PHP'; - } - /** * Enable RSA Blinding * @@ -931,4 +937,241 @@ abstract class RSA extends AsymmetricKey { static::$enableBlinding = false; } + + public static function enableSaltLengthDiscovery() + { + static::$autoSaltLength = true; + } + + public static function disableSaltLengthDiscovery() + { + static::$autoSaltLength = false; + } + + /** + * Handles OpenSSL encryption / decryption / signature creation / verification + * + * @param string $func + * @param string $message + * @param ?string $signature + * @return bool|string|null + */ + protected function handleOpenSSL($func, $message, $signature = null) + { + switch ($func) { + case 'openssl_verify': + case 'openssl_sign': + $paddingType = 'signaturePadding'; + break; + case 'openssl_public_encrypt': + case 'openssl_private_decrypt': + $paddingType = 'encryptionPadding'; + } + + if (self::$forcedEngine === 'libsodium') { + throw new BadConfigurationException('Engine libsodium is not supported for RSA'); + } + + if ((isset(self::$forcedEngine) && self::$forcedEngine !== 'PHP') && $this->$paddingType === self::SIGNATURE_RELAXED_PKCS1) { + throw new BadConfigurationException('Only the PHP engine can be used with relaxed PKCS1 padding'); + } + + if (self::$forcedEngine !== 'PHP') { + if (self::$forcedEngine === 'OpenSSL' && !function_exists($func)) { + throw new BadConfigurationException('Engine OpenSSL is forced but unavailable for RSA'); + } + if ($this->$paddingType === self::SIGNATURE_PSS) { + $create = $func === 'openssl_sign'; + switch (true) { + case !defined('OPENSSL_PKCS1_PSS_PADDING'): + $error = 'Engine OpenSSL is forced but PSS encryption requires PHP >= 8.5.0'; + break; + case $this->hash->getHash() !== $this->mgfHash->getHash(): + $error = 'Engine OpenSSL is forced but can\'t be used because the Hash and MGF Hash do not match'; + break; + case !$create && !static::$autoSaltLength: + $error = 'Engine OpenSSL is forced but auto calculation of the salt length is disabled'; + break; + case $create && $this->getSaltLength() !== $this->hLen: + $error = 'Engine OpenSSL is forced but can\'t be used because the salt length doesn\'t match the hash length'; + break; + case $create && $this->getLength() < 8 * (2 * $this->getSaltLength() + 2): + $error = 'Engine OpenSSL is forced but can\'t be used for PSS signing because the key is too small for OpenSSL to use the configured salt length'; + break; + case $create && OPENSSL_VERSION_NUMBER < 0x30100000: + $error = 'Engine OpenSSL is forced but can\'t be used for PSS signing because OpenSSL < 3.1.0 defaults to the maximum salt length instead of the hash length'; + break; + } + } + /* + https://datatracker.ietf.org/doc/html/rfc4055#page-6 says the following: + + There are two possible encodings for the AlgorithmIdentifier + parameters field associated with these object identifiers. The two + alternatives arise from the loss of the OPTIONAL associated with the + algorithm identifier parameters when the 1988 syntax for + AlgorithmIdentifier was translated into the 1997 syntax. Later the + OPTIONAL was recovered via a defect report, but by then many people + thought that algorithm parameters were mandatory. Because of this + history some implementations encode parameters as a NULL element + while others omit them entirely. The correct encoding is to omit the + parameters field; however, when RSASSA-PSS and RSAES-OAEP were + defined, it was done using the NULL parameters rather than absent + parameters. + + All implementations MUST accept both NULL and absent parameters as + legal and equivalent encodings. + + OpenSSL does NOT accept both - it REQUIRES NULL be present. phpseclib, however, + DOES accept both. at first, it didn't. at first, not knowing why some small number + of PKCS1 signatures omitted NULL, i added the SIGNATURE_RELAXED_PKCS1 mode on + 2015-08-26. https://phpseclib.com/docs/rsa#rsasignature_relaxed_pkcs1 talks more + about that mode. later, on 2021-04-05, there was CVE-2021-30130. consequently, + the SIGNATURE_PKCS1 mode was updated to accept either NULL or non-NULL. + + because phpseclib accepts PKCS1 signatures that OpenSSL doesn't, OpenSSL isn't + used for PKCS1. if the OpenSSL extension is installed then it'll be used to perform + unpadded RSA (ie. modular exponentiation), however, the actual PKCS1 construction + takes place in PHP code vs OpenSSL. + + see https://security.stackexchange.com/questions/110330/encoding-of-optional-null-in-der + for an additional reference + */ + if ($this->$paddingType === self::SIGNATURE_PKCS1 && $func === 'openssl_verify') { + $error = 'Engine OpenSSL is forced but can\'t be used with PKCS1 signature verification because OpenSSL requires NULL be present whereas phpseclib doesn\'t'; + } + if ($this->$paddingType === self::ENCRYPTION_OAEP) { + switch (true) { + case $this->hash->getHash() !== $this->mgfHash->getHash(): + $error = 'Engine OpenSSL is forced but can\'t be used because the Hash and MGF Hash do not match'; + break; + case $this->hash->getHash() !== 'sha1' && PHP_VERSION_ID < 80500: + $error = 'Engine OpenSSL is forced but non-sha1 hashes are only supported on PHP 8.5.0+'; + break; + case strlen($this->label): + $error = 'Engine OpenSSL is forced but can\'t be used because the label is not the empty string'; + } + } + if (isset($error)) { + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException($error); + } + } elseif ($paddingType === 'signaturePadding') { + switch (true) { + case $this->signaturePadding === self::SIGNATURE_PSS && defined('OPENSSL_PKCS1_PSS_PADDING'): + case $this->signaturePadding !== self::SIGNATURE_PSS && function_exists($func): + $key = $this instanceof PrivateKey ? + $this->withPassword()->toString('PKCS8') : + $this->toString('PKCS8'); + if ($func === 'openssl_sign' && strpos($key, 'PUBLIC') !== false) { + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but cannot be used because the private key does not have the prime components within it'); + } + break; + } + $hash = $this->hash->getHash(); + + // on github actions, php 7.0 and 7.1 on windows emit the following warning: + // openssl_sign(): supplied key param cannot be coerced into a private key + set_error_handler(function ($errno, $errstr) { + throw new BadConfigurationException("Engine OpenSSL is forced but got error: $errstr"); + }); + try { + $result = $this->signaturePadding === self::SIGNATURE_PSS ? + $func($message, $signature, $key, $hash, OPENSSL_PKCS1_PSS_PADDING) : + $func($message, $signature, $key, $hash); + } catch (BadConfigurationException $e) { + if (self::$forcedEngine === 'OpenSSL') { + throw $e; + } + $result = false; + } finally { + restore_error_handler(); + } + + if ($func === 'openssl_verify') { + if ($result === -1 || $result === false) { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to verify signature because of ' . openssl_error_string()); + } + return (bool) $result; + } + if ($result) { + return $signature; + } + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but was unable to create signature because of ' . openssl_error_string()); + } + } + } else { + if ($this->encryptionPadding !== self::ENCRYPTION_OAEP || PHP_VERSION_ID >= 80500) { + $key = $this instanceof PrivateKey ? + $this->withPassword()->toString('PKCS8') : + $this->toString('PKCS8'); + if ($func === 'openssl_private_decrypt' && strpos($key, 'PUBLIC') !== false) { + if ($this->encryptionPadding === self::ENCRYPTION_OAEP) { + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but cannot be used because openssl_public_decrypt() doesn\'t have a hash parameter like openssl_private_decrypt() does'); + } + return null; + } + $func = 'openssl_public_decrypt'; + } + if ($this->encryptionPadding === self::ENCRYPTION_PKCS1 && OPENSSL_VERSION_NUMBER >= 0x30200000) { + // quoting https://docs.openssl.org/3.4/man3/RSA_public_encrypt/#return-values : + // + // "Since version 3.2.0, the default provider in OpenSSL does not return an error when padding checks fail. + // Instead it generates a random message" + // + // the idea is that even a perfect implementation of PKCS1 padding can be used to conduct a Bleichenbacher + // padding oracle attack. + // + // so like if $rsa->decrypt() doesn't throw an exception it's liable to run additional code that'll take + // longer to run than it'd take if an exception would be thrown and in theory, with PKCS1, in particular, + // you can use that fact to guess at successive bits of the private key until you've figured it out. it's + // why you should use OAEP padding vs PKCS1 padding BUT if you need PKCS1 padding for interoperability then + // you're stuck with it. + // + // with the OpenSSL 3.2.0+ behavior they're making it harder to do the attack by making it harder to use PKCS1 + // in the real world. this isn't a design philosophy i agree with. like phpseclib lets you DES encryption. you + // shouldn't use DES encryption but if you need to you need to and phpseclib isn't here to judge. that's a big + // difference between phpseclib and stuff like libsodium. + if (self::$forcedEngine === 'OpenSSL') { + throw new BadConfigurationException('Engine OpenSSL is forced but cannot be used to decrypt PKCS1 encrypted strings with OpenSSL 3.2.0+'); + } + return null; + } + $hash = $this->hash->getHash(); + $output = ''; + switch ($this->encryptionPadding) { + case self::ENCRYPTION_NONE: + case self::ENCRYPTION_PKCS1: + $padding = $this->encryptionPadding === self::ENCRYPTION_NONE ? OPENSSL_NO_PADDING : OPENSSL_PKCS1_PADDING; + // on github actions, php 7.0 and 7.1 on windows emit the following warning: + // openssl_private_decrypt(): key parameter is not a valid private key + set_error_handler(function ($errno, $errstr) { + throw new BadConfigurationException("Engine OpenSSL is forced but got error: $errstr"); + }); + try { + $result = $func($message, $output, $key, $padding); + } catch (BadConfigurationException $e) { + if (self::$forcedEngine === 'OpenSSL') { + throw $e; + } + $result = false; + } finally { + restore_error_handler(); + } + break; + //case self::ENCRYPTION_OAEP: + default: + $result = $func($message, $output, $key, OPENSSL_PKCS1_OAEP_PADDING, $hash); + } + if ($result) { + return $output; + } + } + } + return null; + } + } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php index b60e48e..035fc8c 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php @@ -88,13 +88,11 @@ abstract class MSBLOB // PUBLICKEYSTRUC publickeystruc // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx - extract(unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8))); - /** - * @var string $type - * @var string $version - * @var integer $reserved - * @var integer $algo - */ + $unpacked = unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8)); + $type = $unpacked['type']; + $version = $unpacked['version']; + $reserved = $unpacked['reserved']; + $algo = $unpacked['algo']; switch (ord($type)) { case self::PUBLICKEYBLOB: case self::PUBLICKEYBLOBEX: @@ -121,12 +119,10 @@ abstract class MSBLOB // RSAPUBKEY rsapubkey // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx // could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit - extract(unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12))); - /** - * @var integer $magic - * @var integer $bitlen - * @var string $pubexp - */ + $unpacked = unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12)); + $magic = $unpacked['magic']; + $bitlen = $unpacked['bitlen']; + $pubexp = $unpacked['pubexp']; switch ($magic) { case self::RSA2: $components['isPublicKey'] = false; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php index 7633556..56f2143 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php @@ -65,6 +65,9 @@ abstract class PKCS1 extends Progenitor $key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP); if (is_array($key)) { + if ($key['version'] === false) { + throw new \UnexpectedValueException('Version number is not valid'); + } $components += [ 'modulus' => $key['modulus'], 'publicExponent' => $key['publicExponent'], @@ -96,6 +99,20 @@ abstract class PKCS1 extends Progenitor $components['isPublicKey'] = true; } + $components = $components + $key; + foreach ($components as &$val) { + if ($val instanceof BigInteger) { + $val = self::makePositive($val); + } + if (is_array($val)) { + foreach ($val as &$subval) { + if ($subval instanceof BigInteger) { + $subval = self::makePositive($subval); + } + } + } + } + return $components + $key; } @@ -157,4 +174,17 @@ abstract class PKCS1 extends Progenitor return self::wrapPublicKey($key, 'RSA'); } + + /** + * Negative numbers make no sense in RSA so convert them to positive + * + * @param BigInteger $x + * @return string + */ + private static function makePositive(BigInteger $x) + { + return $x->isNegative() ? + new BigInteger($x->toBytes(true), 256) : + $x; + } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php index bf51bcf..ee9b992 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php @@ -141,7 +141,7 @@ abstract class PSS extends Progenitor $result['hash'] = str_replace('id-', '', $params['hashAlgorithm']['algorithm']); $result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']); if (isset($params['saltLength'])) { - $result['saltLength'] = (int) $params['saltLength']->toString(); + $result['saltLength'] = (int) "$params[saltLength]"; } if (isset($key['meta'])) { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php index 293903c..8416758 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php @@ -56,7 +56,10 @@ abstract class PuTTY extends Progenitor if (!isset($components['private'])) { return $components; } - extract($components); + $type = $components['type']; + $comment = $components['comment']; + $public = $components['public']; + $private = $components['private']; unset($components['public'], $components['private']); $isPublicKey = false; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php index 8c828b3..62a13a4 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php @@ -216,7 +216,7 @@ final class PrivateKey extends RSA implements Common\PrivateKey $db = $ps . chr(1) . $salt; $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); // ie. stlren($db) $maskedDB = $db ^ $dbMask; - $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0]; + $maskedDB[0] = ~chr(256 - (1 << ($emBits & 7))) & $maskedDB[0]; $em = $maskedDB . $h . chr(0xBC); return $em; @@ -288,6 +288,11 @@ final class PrivateKey extends RSA implements Common\PrivateKey */ public function sign($message) { + $result = $this->handleOpenSSL('openssl_sign', $message); + if ($result !== null) { + return $result; + } + switch ($this->signaturePadding) { case self::SIGNATURE_PKCS1: case self::SIGNATURE_RELAXED_PKCS1: @@ -434,6 +439,11 @@ final class PrivateKey extends RSA implements Common\PrivateKey */ public function decrypt($ciphertext) { + $result = $this->handleOpenSSL('openssl_private_decrypt', $ciphertext); + if ($result !== null) { + return $result; + } + switch ($this->encryptionPadding) { case self::ENCRYPTION_NONE: return $this->raw_encrypt($ciphertext); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php index ff80ae7..63563d7 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php @@ -116,7 +116,7 @@ final class PublicKey extends RSA implements Common\PublicKey } // Compare - return $r1 || $r2; + return boolval($r1 | $r2); } /** @@ -228,7 +228,11 @@ final class PublicKey extends RSA implements Common\PublicKey // be output. $emLen = ($emBits + 7) >> 3; // ie. ceil($emBits / 8); - $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; + if (static::$autoSaltLength) { + $sLen = 0; + } else { + $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; + } $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { @@ -241,18 +245,24 @@ final class PublicKey extends RSA implements Common\PublicKey $maskedDB = substr($em, 0, -$this->hLen - 1); $h = substr($em, -$this->hLen - 1, $this->hLen); - $temp = chr(0xFF << ($emBits & 7)); + $temp = chr(256 - (1 << ($emBits & 7))); if ((~$maskedDB[0] & $temp) != $temp) { return false; } $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); $db = $maskedDB ^ $dbMask; - $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; - $temp = $emLen - $this->hLen - $sLen - 2; - if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) { + $db[0] = ~chr(256 - (1 << ($emBits & 7))) & $db[0]; + + // PS is a run of zero bytes terminated by a single 0x01 + $psLen = strspn($db, "\0"); + if ($psLen == strlen($db) || $db[$psLen] != chr(0x01)) { return false; } - $salt = substr($db, $temp + 1); // should be $sLen long + if (!static::$autoSaltLength && $psLen != $emLen - $this->hLen - $sLen - 2) { + return false; + } + + $salt = substr($db, $psLen + 1); // should be $sLen long $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; $h2 = $this->hash->hash($m2); return hash_equals($h, $h2); @@ -301,6 +311,11 @@ final class PublicKey extends RSA implements Common\PublicKey */ public function verify($message, $signature) { + $result = $this->handleOpenSSL('openssl_verify', $message, $signature); + if ($result !== null) { + return $result; + } + switch ($this->signaturePadding) { case self::SIGNATURE_RELAXED_PKCS1: return $this->rsassa_pkcs1_v1_5_relaxed_verify($message, $signature); @@ -450,6 +465,11 @@ final class PublicKey extends RSA implements Common\PublicKey */ public function encrypt($plaintext) { + $result = $this->handleOpenSSL('openssl_public_encrypt', $plaintext); + if ($result !== null) { + return $result; + } + switch ($this->encryptionPadding) { case self::ENCRYPTION_NONE: return $this->raw_encrypt($plaintext); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php index ff31f9c..3638adb 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php @@ -74,8 +74,8 @@ class Rijndael extends BlockCipher * or not for the current $block_size/$key_length. * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt - * @see \phpseclib3\Crypt\Common\SymmetricKey::engine + * @see Common\SymmetricKey::cipher_name_mcrypt + * @see Common\SymmetricKey::engine * @see self::isValidEngine() * @var string */ @@ -262,7 +262,7 @@ class Rijndael extends BlockCipher * * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * Common\SymmetricKey::__construct() * @param int $engine * @return bool */ @@ -378,7 +378,7 @@ class Rijndael extends BlockCipher $k = $c[2]; $l = $c[3]; while ($i < $Nb) { - $temp[$i] = ($state[$i] & intval(0xFF000000)) ^ + $temp[$i] = ($state[$i] & (PHP_INT_SIZE == 8 ? 0xFF000000 : -16777216)) ^ ($state[$j] & 0x00FF0000) ^ ($state[$k] & 0x0000FF00) ^ ($state[$l] & 0x000000FF) ^ @@ -452,7 +452,7 @@ class Rijndael extends BlockCipher $l = $Nb - $c[3]; while ($i < $Nb) { - $word = ($state[$i] & intval(0xFF000000)) | + $word = ($state[$i] & (PHP_INT_SIZE == 8 ? 0xFF000000 : -16777216)) | ($state[$j] & 0x00FF0000) | ($state[$k] & 0x0000FF00) | ($state[$l] & 0x000000FF); @@ -511,7 +511,7 @@ class Rijndael extends BlockCipher /** * Setup the key (expansion) * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() + * Common\SymmetricKey::setupKey() */ protected function setupKey() { @@ -528,7 +528,7 @@ class Rijndael extends BlockCipher 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000, 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 ]; - $rcon = array_map('intval', $rcon); + $rcon = array_map([self::class, 'safe_intval'], $rcon); } if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) { @@ -568,7 +568,9 @@ class Rijndael extends BlockCipher // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine, // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and' // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is. - $temp = (($temp << 8) & intval(0xFFFFFF00)) | (($temp >> 24) & 0x000000FF); // rotWord + $temp = PHP_INT_SIZE == 8 ? // rotWord + (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF) : + ($temp << 8) | (($temp >> 24) & 0x000000FF); $temp = $this->subWord($temp) ^ $rcon[$i / $this->Nk]; } elseif ($this->Nk > 6 && $i % $this->Nk == 4) { $temp = $this->subWord($temp); @@ -659,7 +661,7 @@ class Rijndael extends BlockCipher // according to (section 5.2.1), // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so // those are the names we'll use. - $t3 = array_map('intval', [ + $t3 = array_map([self::class, 'safe_intval'], [ // with array_map('intval', ...) we ensure we have only int's and not // some slower floats converted by php automatically on high values 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, @@ -697,9 +699,9 @@ class Rijndael extends BlockCipher ]); foreach ($t3 as $t3i) { - $t0[] = (($t3i << 24) & intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF); - $t1[] = (($t3i << 16) & intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF); - $t2[] = (($t3i << 8) & intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF); + $t0[] = (($t3i << 24) & self::safe_intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF); + $t1[] = (($t3i << 16) & self::safe_intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF); + $t2[] = (($t3i << 8) & self::safe_intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF); } $tables = [ @@ -744,7 +746,7 @@ class Rijndael extends BlockCipher { static $tables; if (empty($tables)) { - $dt3 = array_map('intval', [ + $dt3 = array_map([self::class, 'safe_intval'], [ 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, @@ -779,11 +781,19 @@ class Rijndael extends BlockCipher 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 ]); - foreach ($dt3 as $dt3i) { - $dt0[] = (($dt3i << 24) & intval(0xFF000000)) | (($dt3i >> 8) & 0x00FFFFFF); - $dt1[] = (($dt3i << 16) & intval(0xFFFF0000)) | (($dt3i >> 16) & 0x0000FFFF); - $dt2[] = (($dt3i << 8) & intval(0xFFFFFF00)) | (($dt3i >> 24) & 0x000000FF); - }; + if (PHP_INT_SIZE === 8) { + foreach ($dt3 as $dt3i) { + $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF); + $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF); + $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF); + }; + } else { + foreach ($dt3 as $dt3i) { + $dt0[] = ($dt3i << 24) | (($dt3i >> 8) & 0x00FFFFFF); + $dt1[] = ($dt3i << 16) | (($dt3i >> 16) & 0x0000FFFF); + $dt2[] = ($dt3i << 8) | (($dt3i >> 24) & 0x000000FF); + }; + } $tables = [ // The Precomputed inverse mixColumns tables dt0 - dt3 @@ -818,7 +828,7 @@ class Rijndael extends BlockCipher /** * Setup the performance-optimized function for de/encrypt() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt() + * Common\SymmetricKey::setupInlineCrypt() */ protected function setupInlineCrypt() { @@ -879,7 +889,7 @@ class Rijndael extends BlockCipher $encrypt_block .= '$in = pack("N*"' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= ', - ($' . $e . $i . ' & ' . ((int)0xFF000000) . ') ^ + ($' . $e . $i . ' & ' . (PHP_INT_SIZE == 8 ? 0xFF000000 : -16777216) . ') ^ ($' . $e . (($i + $c[1]) % $Nb) . ' & 0x00FF0000 ) ^ ($' . $e . (($i + $c[2]) % $Nb) . ' & 0x0000FF00 ) ^ ($' . $e . (($i + $c[3]) % $Nb) . ' & 0x000000FF ) ^ @@ -935,7 +945,7 @@ class Rijndael extends BlockCipher $decrypt_block .= '$in = pack("N*"' . "\n"; for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= ', - ($' . $e . $i . ' & ' . ((int)0xFF000000) . ') ^ + ($' . $e . $i . ' & ' . (PHP_INT_SIZE == 8 ? 0xFF000000 : -16777216) . ') ^ ($' . $e . (($Nb + $i - $c[1]) % $Nb) . ' & 0x00FF0000 ) ^ ($' . $e . (($Nb + $i - $c[2]) % $Nb) . ' & 0x0000FF00 ) ^ ($' . $e . (($Nb + $i - $c[3]) % $Nb) . ' & 0x000000FF ) ^ diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php index 785e7aa..6a79436 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php @@ -47,12 +47,12 @@ class Salsa20 extends StreamCipher protected $key_length = 32; // = 256 bits /** - * @see \phpseclib3\Crypt\Salsa20::crypt() + * @see Salsa20::crypt() */ const ENCRYPT = 0; /** - * @see \phpseclib3\Crypt\Salsa20::crypt() + * @see Salsa20::crypt() */ const DECRYPT = 1; @@ -236,7 +236,7 @@ class Salsa20 extends StreamCipher /** * Encrypts a message. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * @see SymmetricKey::decrypt() * @see self::crypt() * @param string $plaintext * @return string $ciphertext @@ -256,7 +256,7 @@ class Salsa20 extends StreamCipher * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). * At least if the continuous buffer is disabled. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() + * @see SymmetricKey::encrypt() * @see self::crypt() * @param string $ciphertext * @return string $plaintext @@ -411,7 +411,7 @@ class Salsa20 extends StreamCipher $r1 &= 0xFFFFFFFF; $r2 = ($x & 0xFFFFFFFF) >> (32 - $n); } else { - $x = (int) $x; + $x = self::safe_intval($x); $r1 = $x << $n; $r2 = $x >> (32 - $n); $r2 &= (1 << $n) - 1; @@ -482,7 +482,7 @@ class Salsa20 extends StreamCipher } for ($i = 1; $i <= 16; $i++) { - $x[$i] += $z[$i]; + $x[$i] = self::safe_intval($x[$i] + $z[$i]); } return pack('V*', ...$x); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php index 1ff5ed0..bbe3139 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php @@ -58,7 +58,7 @@ class TripleDES extends DES /** * Key Length (in bytes) * - * @see \phpseclib3\Crypt\TripleDES::setKeyLength() + * @see TripleDES::setKeyLength() * @var int */ protected $key_length = 24; @@ -66,8 +66,8 @@ class TripleDES extends DES /** * The mcrypt specific name of the cipher * - * @see \phpseclib3\Crypt\DES::cipher_name_mcrypt - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt + * @see DES::cipher_name_mcrypt + * @see Common\SymmetricKey::cipher_name_mcrypt * @var string */ protected $cipher_name_mcrypt = 'tripledes'; @@ -75,7 +75,7 @@ class TripleDES extends DES /** * Optimizing value while CFB-encrypting * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len + * @see Common\SymmetricKey::cfb_init_len * @var int */ protected $cfb_init_len = 750; @@ -84,7 +84,7 @@ class TripleDES extends DES * max possible size of $key * * @see self::setKey() - * @see \phpseclib3\Crypt\DES::setKey() + * @see DES::setKey() * @var string */ protected $key_length_max = 24; @@ -126,8 +126,8 @@ class TripleDES extends DES * * - cbc3 (same as cbc) * - * @see \phpseclib3\Crypt\DES::__construct() - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * @see Crypt\DES::__construct() + * @see Common\SymmetricKey::__construct() * @param string $mode */ public function __construct($mode) @@ -169,7 +169,7 @@ class TripleDES extends DES * * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() + * @see Common\SymmetricKey::__construct() * @param int $engine * @return bool */ @@ -189,7 +189,7 @@ class TripleDES extends DES * * SetIV is not required when \phpseclib3\Crypt\Common\SymmetricKey::MODE_ECB is being used. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::setIV() + * @see Common\SymmetricKey::setIV() * @param string $iv */ public function setIV($iv) @@ -209,7 +209,7 @@ class TripleDES extends DES * * If you want to use a 64-bit key use DES.php * - * @see \phpseclib3\Crypt\Common\SymmetricKey:setKeyLength() + * @see Common\SymmetricKey:setKeyLength() * @throws \LengthException if the key length is invalid * @param int $length */ @@ -233,8 +233,8 @@ class TripleDES extends DES * * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. * - * @see \phpseclib3\Crypt\DES::setKey() - * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey() + * @see DES::setKey() + * @see Common\SymmetricKey::setKey() * @throws \LengthException if the key length is invalid * @param string $key */ @@ -270,7 +270,7 @@ class TripleDES extends DES /** * Encrypts a message. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt() + * @see Common\SymmetricKey::encrypt() * @param string $plaintext * @return string $cipertext */ @@ -296,7 +296,7 @@ class TripleDES extends DES /** * Decrypts a message. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt() + * @see Common\SymmetricKey::decrypt() * @param string $ciphertext * @return string $plaintext */ @@ -351,7 +351,7 @@ class TripleDES extends DES * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), * however, they are also less intuitive and more likely to cause you problems. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::enableContinuousBuffer() + * @see Common\SymmetricKey::enableContinuousBuffer() * @see self::disableContinuousBuffer() */ public function enableContinuousBuffer() @@ -369,7 +369,7 @@ class TripleDES extends DES * * The default behavior. * - * @see \phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer() + * @see Common\SymmetricKey::disableContinuousBuffer() * @see self::enableContinuousBuffer() */ public function disableContinuousBuffer() @@ -385,8 +385,8 @@ class TripleDES extends DES /** * Creates the key schedule * - * @see \phpseclib3\Crypt\DES::setupKey() - * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey() + * @see DES::setupKey() + * @see Common\SymmetricKey::setupKey() */ protected function setupKey() { @@ -419,8 +419,8 @@ class TripleDES extends DES /** * Sets the internal crypt engine * - * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct() - * @see \phpseclib3\Crypt\Common\SymmetricKey::setPreferredEngine() + * @see Common\SymmetricKey::__construct() + * @see Common\SymmetricKey::setPreferredEngine() * @param int $engine */ public function setPreferredEngine($engine) diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php index bf76563..e89a776 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php @@ -49,7 +49,7 @@ class Twofish extends BlockCipher /** * The mcrypt specific name of the cipher * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt + * @see Common\SymmetricKey::cipher_name_mcrypt * @var string */ protected $cipher_name_mcrypt = 'twofish'; @@ -57,7 +57,7 @@ class Twofish extends BlockCipher /** * Optimizing value while CFB-encrypting * - * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len + * @see Common\SymmetricKey::cfb_init_len * @var int */ protected $cfb_init_len = 800; @@ -373,12 +373,12 @@ class Twofish extends BlockCipher protected static function initialize_static_variables() { if (is_float(self::$m3[0])) { - self::$m0 = array_map('intval', self::$m0); - self::$m1 = array_map('intval', self::$m1); - self::$m2 = array_map('intval', self::$m2); - self::$m3 = array_map('intval', self::$m3); - self::$q0 = array_map('intval', self::$q0); - self::$q1 = array_map('intval', self::$q1); + self::$m0 = array_map([self::class, 'safe_intval'], self::$m0); + self::$m1 = array_map([self::class, 'safe_intval'], self::$m1); + self::$m2 = array_map([self::class, 'safe_intval'], self::$m2); + self::$m3 = array_map([self::class, 'safe_intval'], self::$m3); + self::$q0 = array_map([self::class, 'safe_intval'], self::$q0); + self::$q1 = array_map([self::class, 'safe_intval'], self::$q1); } parent::initialize_static_variables(); @@ -431,7 +431,7 @@ class Twofish extends BlockCipher /** * Setup the key (expansion) * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey() + * @see Common\SymmetricKey::_setupKey() */ protected function setupKey() { @@ -700,7 +700,7 @@ class Twofish extends BlockCipher /** * Setup the performance-optimized function for de/encrypt() * - * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt() + * @see Common\SymmetricKey::_setupInlineCrypt() */ protected function setupInlineCrypt() { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php b/Web/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php index c4b06a5..aea426e 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php @@ -131,6 +131,8 @@ abstract class ASN1 */ private static $encoded; + private static $use64BitOIDHandling; + /** * Type mapping table for the ANY type. * @@ -190,6 +192,7 @@ abstract class ASN1 * * @param Element|string $encoded * @return ?array + * @changed in phpseclib 4.0.0 */ public static function decodeBER($encoded) { @@ -273,8 +276,7 @@ abstract class ASN1 // tags of indefinte length don't really have a header length; this length includes the tag $current += ['headerlength' => $length + 2]; $start += $length; - extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4))); - /** @var integer $length */ + $length = unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4))['length']; } else { $current += ['headerlength' => 2]; } @@ -515,6 +517,7 @@ abstract class ASN1 * @param array $mapping * @param array $special * @return array|bool|Element|string|null + * @changed in phpseclib 4.0.0 */ public static function asn1map(array $decoded, $mapping, $special = []) { @@ -537,7 +540,7 @@ abstract class ASN1 case $mapping['type'] == self::TYPE_CHOICE: foreach ($mapping['children'] as $key => $option) { switch (true) { - case isset($option['constant']) && $option['constant'] == $decoded['constant']: + case isset($option['constant']) && isset($decoded['constant']) && $option['constant'] == $decoded['constant']: case !isset($option['constant']) && $option['type'] == $decoded['type']: $value = self::asn1map($decoded, $option, $special); break; @@ -621,6 +624,13 @@ abstract class ASN1 // Can only match if no constant expected and type matches or is generic. $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false; } + } elseif (isset($child['constant'])) { + // a CHOICE that is itself tagged is identified by that tag. its alternatives + // can't be used to tell it apart from a sibling with the same CHOICE definition + // (eg. issuerLogo [1] / subjectLogo [2] in RFC 9399's LogotypeExtn). + $maymatch = isset($temp['constant']) && + $child['constant'] == $temp['constant'] && + $temp['type'] == self::CLASS_CONTEXT_SPECIFIC; } } @@ -693,6 +703,11 @@ abstract class ASN1 // Can only match if no constant expected and type matches or is generic. $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false; } + } elseif (isset($child['constant'])) { + // see the comment in the TYPE_SEQUENCE case + $maymatch = isset($temp['constant']) && + $child['constant'] == $temp['constant'] && + $tempClass == self::CLASS_CONTEXT_SPECIFIC; } if ($maymatch) { @@ -790,10 +805,17 @@ abstract class ASN1 case self::TYPE_ENUMERATED: $temp = $decoded['content']; if (isset($mapping['implicit'])) { - $temp = new BigInteger($decoded['content'], -256); + $temp = new BigInteger($temp, -256); + } + if (!$temp instanceof BigInteger) { + return false; } if (isset($mapping['mapping'])) { - $temp = (int) $temp->toString(); + $temp = $temp->toString(); + if (strlen($temp) > 1) { + return false; + } + $temp = (int) $temp; return isset($mapping['mapping'][$temp]) ? $mapping['mapping'][$temp] : false; @@ -834,6 +856,7 @@ abstract class ASN1 * @param array $mapping * @param array $special * @return string + * @changed in phpseclib 4.0.0 */ public static function encodeDER($source, $mapping, $special = []) { @@ -931,7 +954,19 @@ abstract class ASN1 an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)." */ if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) { - $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']); + if ($child['constant'] <= 30) { + $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']); + } else { + $constant = $child['constant']; + $subtag = ''; + while ($constant > 0) { + $subtagvalue = $constant & 0x7F; + $subtag = (chr(0x80 | $subtagvalue)) . $subtag; + $constant = $constant >> 7; + } + $subtag[strlen($subtag) - 1] = $subtag[strlen($subtag) - 1] & chr(0x7F); + $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | 0x1f) . $subtag; + } $temp = $subtag . self::encodeLength(strlen($temp)) . $temp; } else { $subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']); @@ -1130,6 +1165,19 @@ abstract class ASN1 return chr($tag) . self::encodeLength(strlen($value)) . $value; } + public static function enable64BitOIDHandling() + { + if (PHP_INT_SIZE === 4) { + throw new \RuntimeException('64-bit OID handling is unavailable on 32-bit PHP installs'); + } + self::$use64BitOIDHandling = true; + } + + public static function disable64BitOIDHandling() + { + self::$use64BitOIDHandling = false; + } + /** * BER-decode the OID * @@ -1137,20 +1185,27 @@ abstract class ASN1 * * @param string $content * @return string + * @changed in phpseclib 4.0.0 */ public static function decodeOID($content) { + // BigInteger's are used because of OIDs like 2.25.329800735698586629295641978511506172918 + // https://healthcaresecprivacy.blogspot.com/2011/02/creating-and-using-unique-id-uuid-oid.html elaborates. static $eighty; if (!$eighty) { $eighty = new BigInteger(80); } + if (!isset(self::$use64BitOIDHandling)) { + self::$use64BitOIDHandling = PHP_INT_SIZE === 8; + } + $oid = []; $pos = 0; $len = strlen($content); // see https://github.com/openjdk/jdk/blob/2deb318c9f047ec5a4b160d66a4b52f93688ec42/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java#L55 - if ($len > 4096) { - //throw new \RuntimeException("Object identifier size is limited to 4096 bytes ($len bytes present)"); + if ($len > 128) { + //throw new \RuntimeException("Object identifier size is limited to 128 bytes ($len bytes present)"); return false; } @@ -1159,13 +1214,50 @@ abstract class ASN1 } $n = new BigInteger(); - while ($pos < $len) { - $temp = ord($content[$pos++]); - $n = $n->bitwise_leftShift(7); - $n = $n->bitwise_or(new BigInteger($temp & 0x7F)); - if (~$temp & 0x80) { - $oid[] = $n; - $n = new BigInteger(); + $subn = $numBytes = 0; + if (self::$use64BitOIDHandling) { + $prefix = ''; + while ($pos < $len) { + $temp = ord($content[$pos++]); + $subn <<= 7; + $subn |= ($temp & 0x7F); + $numBytes++; + $endByte = ~$temp & 0x80; + if ($numBytes === PHP_INT_SIZE) { + $prefix .= substr(pack('J', $subn), 1); // we're basically left shifting by 7 bytes + $subn = $numBytes = 0; + if ($endByte) { + $oid[] = new BigInteger($prefix, 256); + $prefix = ''; + } + } elseif ($endByte) { + if (strlen($prefix)) { + $arc = new BigInteger($prefix, 256); + $arc = $arc->bitwise_leftShift($numBytes * 7); + $oid[] = $arc->bitwise_or(new BigInteger($subn)); + $prefix = ''; + } else { + $oid[] = new BigInteger($subn); + } + $subn = $numBytes = 0; + } + } + } else { + while ($pos < $len) { + $temp = ord($content[$pos++]); + $subn <<= 7; + $subn |= ($temp & 0x7F); + $numBytes++; + $endByte = ~$temp & 0x80; + if ($numBytes === PHP_INT_SIZE || $endByte) { + $n = $n->bitwise_leftShift($numBytes * 7); + $n = $n->bitwise_or(new BigInteger($subn)); + $subn = $numBytes = 0; + if ($endByte) { + $oid[] = $n; + $n = new BigInteger(); + } + } } } $part1 = array_shift($oid); @@ -1252,6 +1344,7 @@ abstract class ASN1 * @param string $content * @param int $tag * @return \DateTime|false + * @changed in phpseclib 4.0.0 */ private static function decodeTime($content, $tag) { @@ -1297,6 +1390,7 @@ abstract class ASN1 * Sets the time / date format for asn1map(). * * @param string $format + * @removed in phpseclib 4.0.0 */ public static function setTimeFormat($format) { @@ -1310,6 +1404,7 @@ abstract class ASN1 * Previously loaded OIDs are retained. * * @param array $oids + * @changed in phpseclib 4.0.0 */ public static function loadOIDs(array $oids) { @@ -1324,6 +1419,7 @@ abstract class ASN1 * Previously loaded filters are not retained. * * @param array $filters + * @removed in phpseclib 4.0.0 */ public static function setFilters(array $filters) { @@ -1340,6 +1436,7 @@ abstract class ASN1 * @param int $from * @param int $to * @return string + * @removed in phpseclib 4.0.0 */ public static function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING) { @@ -1505,6 +1602,7 @@ abstract class ASN1 * * @param string $name * @return string + * @removed in phpseclib 4.0.0 */ public static function getOID($name) { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/File/X509.php b/Web/vendor/phpseclib/phpseclib/phpseclib/File/X509.php index 00504f1..70f6fa3 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/File/X509.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/File/X509.php @@ -57,37 +57,37 @@ class X509 /** * Return internal array representation * - * @see \phpseclib3\File\X509::getDN() + * @see X509::getDN() */ const DN_ARRAY = 0; /** * Return string * - * @see \phpseclib3\File\X509::getDN() + * @see X509::getDN() */ const DN_STRING = 1; /** * Return ASN.1 name string * - * @see \phpseclib3\File\X509::getDN() + * @see X509::getDN() */ const DN_ASN1 = 2; /** * Return OpenSSL compatible array * - * @see \phpseclib3\File\X509::getDN() + * @see X509::getDN() */ const DN_OPENSSL = 3; /** * Return canonical ASN.1 RDNs string * - * @see \phpseclib3\File\X509::getDN() + * @see X509::getDN() */ const DN_CANON = 4; /** * Return name hash for file indexing * - * @see \phpseclib3\File\X509::getDN() + * @see X509::getDN() */ const DN_HASH = 5; @@ -96,25 +96,25 @@ class X509 * * ie. a base64-encoded PEM with a header and a footer * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() + * @see X509::saveX509() + * @see X509::saveCSR() + * @see X509::saveCRL() */ const FORMAT_PEM = 0; /** * Save as DER * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() + * @see X509::saveX509() + * @see X509::saveCSR() + * @see X509::saveCRL() */ const FORMAT_DER = 1; /** * Save as a SPKAC * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() + * @see X509::saveX509() + * @see X509::saveCSR() + * @see X509::saveCRL() * * Only works on CSRs. Not currently supported. */ @@ -124,9 +124,9 @@ class X509 * * Used only by the load*() functions * - * @see \phpseclib3\File\X509::saveX509() - * @see \phpseclib3\File\X509::saveCSR() - * @see \phpseclib3\File\X509::saveCRL() + * @see X509::saveX509() + * @see X509::saveCSR() + * @see X509::saveCRL() */ const FORMAT_AUTO_DETECT = 3; @@ -269,10 +269,18 @@ class X509 */ private $domains = null; + /** + * URL fetch callback + * + * @var string|array|null + */ + private static $urlFetchCallback = null; + /** * Default Constructor. * * @return X509 + * @changed in phpseclib 4.0.0 */ public function __construct() { @@ -315,6 +323,7 @@ class X509 'id-at-uniqueIdentifier' => '2.5.4.45', 'id-at-role' => '2.5.4.72', 'id-at-postalAddress' => '2.5.4.16', + 'id-at-organizationIdentifier' => '2.5.4.97', 'jurisdictionOfIncorporationCountryName' => '1.3.6.1.4.1.311.60.2.1.3', 'jurisdictionOfIncorporationStateOrProvinceName' => '1.3.6.1.4.1.311.60.2.1.2', 'jurisdictionLocalityName' => '1.3.6.1.4.1.311.60.2.1.1', @@ -428,6 +437,7 @@ class X509 * @param array|string $cert * @param int $mode * @return mixed + * @removed in phpseclib 4.0.0 */ public function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT) { @@ -501,6 +511,7 @@ class X509 * @param array $cert * @param int $format optional * @return string + * @removed in phpseclib 4.0.0 */ public function saveX509(array $cert, $format = self::FORMAT_PEM) { @@ -626,7 +637,9 @@ class X509 $extensions = &$this->subArray($root, $path, !empty($this->extensionValues)); foreach ($this->extensionValues as $id => $data) { - extract($data); + $critical = $data['critical']; + $replace = $data['replace']; + $value = $data['value']; $newext = [ 'extnId' => $id, 'extnValue' => $value, @@ -956,6 +969,7 @@ class X509 * * @param string $cert * @return bool + * @removed in phpseclib 4.0.0 */ public function loadCA($cert) { @@ -1082,6 +1096,7 @@ class X509 * * @param \DateTimeInterface|string $date optional * @return bool + * @removed in phpseclib 4.0.0 */ public function validateDate($date = null) { @@ -1112,6 +1127,10 @@ class X509 /** * Fetches a URL * + * If a fetch callback is set via setURLFetchCallback(), the host is resolved + * once and the connection is pinned to that IP (the callback judges the + * resolved IP, preventing DNS-rebinding bypass). + * * @param string $url * @return bool|string */ @@ -1122,25 +1141,58 @@ class X509 } $parts = parse_url($url); + if ($parts === false || !isset($parts['scheme']) || !isset($parts['host'])) { + return false; + } + $host = $parts['host']; + $port = isset($parts['port']) ? $parts['port'] : 80; + + if (isset(self::$urlFetchCallback)) { + if (filter_var($host, FILTER_VALIDATE_IP)) { + $ip = $host; + // unwrap IPv4-mapped IPv6 so the callback judges the real v4 address + if (preg_match('/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i', $ip, $m)) { + $ip = $m[1]; + } + } else { + $records = dns_get_record($host, DNS_A | DNS_AAAA); + if (!$records) { + return false; + } + if (isset($records[0]['ip'])) { + $ip = $records[0]['ip']; + } elseif (isset($records[0]['ipv6'])) { + $ip = $records[0]['ipv6']; + } else { + return false; + } + } + if (!call_user_func(self::$urlFetchCallback, $host, $ip, $port, $parts['scheme'])) { + return false; + } + $target = strpos($ip, ':') !== false ? "[$ip]" : $ip; + } else { + $target = $host; + } + $data = ''; switch ($parts['scheme']) { case 'http': - $fsock = @fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80); + $fsock = @fsockopen($target, $port); if (!$fsock) { return false; } - $path = $parts['path']; + $path = isset($parts['path']) ? $parts['path'] : '/'; if (isset($parts['query'])) { $path .= '?' . $parts['query']; } fputs($fsock, "GET $path HTTP/1.0\r\n"); - fputs($fsock, "Host: $parts[host]\r\n\r\n"); + fputs($fsock, "Host: $host\r\n\r\n"); $line = fgets($fsock, 1024); - if (strlen($line) < 3) { + if ($line === false || strlen($line) < 3) { return false; } - preg_match('#HTTP/1.\d (\d{3})#', $line, $temp); - if ($temp[1] != '200') { + if (!preg_match('#HTTP/1.\d (\d{3})#', $line, $temp) || $temp[1] != '200') { return false; } @@ -1159,7 +1211,8 @@ class X509 break; //case 'ftp': //case 'ldap': - //default: + default: + return false; } return $data; @@ -1239,6 +1292,7 @@ class X509 * * @param bool $caonly optional * @return mixed + * @changed in phpseclib 4.0.0 */ public function validateSignature($caonly = true) { @@ -1470,6 +1524,7 @@ class X509 /** * Prevents URIs from being automatically retrieved * + * @removed in phpseclib 4.0.0 */ public static function disableURLFetch() { @@ -1479,6 +1534,7 @@ class X509 /** * Allows URIs to be automatically retrieved * + * @removed in phpseclib 4.0.0 */ public static function enableURLFetch() { @@ -1492,6 +1548,7 @@ class X509 * * @param string $ip * @return string + * @removed in phpseclib 4.0.0 */ public static function decodeIP($ip) { @@ -1505,6 +1562,7 @@ class X509 * * @param string $ip * @return array + * @removed in phpseclib 4.0.0 */ public static function decodeNameConstraintIP($ip) { @@ -1521,6 +1579,7 @@ class X509 * * @param string|array $ip * @return string + * @removed in phpseclib 4.0.0 */ public static function encodeIP($ip) { @@ -1610,6 +1669,9 @@ class X509 case 'organizationalunitname': case 'ou': return 'id-at-organizationalUnitName'; + case 'id-at-organizationidentifier': + case 'organizationIdentifier': + return 'id-at-organizationIdentifier'; case 'id-at-pseudonym': case 'pseudonym': return 'id-at-pseudonym'; @@ -1641,6 +1703,7 @@ class X509 * @param mixed $propValue * @param string $type optional * @return bool + * @removed in phpseclib 4.0.0 */ public function setDNProp($propName, $propValue, $type = 'utf8String') { @@ -1671,6 +1734,7 @@ class X509 * Remove Distinguished Name properties * * @param string $propName + * @removed in phpseclib 4.0.0 */ public function removeDNProp($propName) { @@ -1704,6 +1768,7 @@ class X509 * @param array $dn optional * @param bool $withType optional * @return mixed + * @removed in phpseclib 4.0.0 */ public function getDNProp($propName, $dn = null, $withType = false) { @@ -1768,6 +1833,7 @@ class X509 * @param bool $merge optional * @param string $type optional * @return bool + * @changed in phpseclib 4.0.0 */ public function setDN($dn, $merge = false, $type = 'utf8String') { @@ -1809,6 +1875,7 @@ class X509 * @param mixed $format optional * @param array $dn optional * @return array|bool|string + * @changed in phpseclib 4.0.0 */ public function getDN($format = self::DN_ARRAY, $dn = null) { @@ -1858,7 +1925,7 @@ class X509 $dn = $this->getDN(self::DN_CANON, $dn); $hash = new Hash('sha1'); $hash = $hash->hash($dn); - extract(unpack('Vhash', $hash)); + $hash = unpack('Vhash', $hash)['hash']; return strtolower(Strings::bin2hex(pack('N', $hash))); } @@ -1950,6 +2017,7 @@ class X509 * * @param int $format optional * @return mixed + * @changed in phpseclib 4.0.0 */ public function getIssuerDN($format = self::DN_ARRAY) { @@ -1971,6 +2039,7 @@ class X509 * * @param int $format optional * @return mixed + * @changed in phpseclib 4.0.0 */ public function getSubjectDN($format = self::DN_ARRAY) { @@ -1994,6 +2063,7 @@ class X509 * @param string $propName * @param bool $withType optional * @return mixed + * @removed in phpseclib 4.0.0 */ public function getIssuerDNProp($propName, $withType = false) { @@ -2015,6 +2085,7 @@ class X509 * @param string $propName * @param bool $withType optional * @return mixed + * @removed in phpseclib 4.0.0 */ public function getSubjectDNProp($propName, $withType = false) { @@ -2036,6 +2107,7 @@ class X509 * Get the certificate chain for the current cert * * @return mixed + * @removed in phpseclib 4.0.0 */ public function getChain() { @@ -2077,6 +2149,7 @@ class X509 * Returns the current cert * * @return array|bool + * @removed in phpseclib 4.0.0 */ public function &getCurrentCert() { @@ -2102,6 +2175,7 @@ class X509 * Key needs to be a \phpseclib3\Crypt\RSA object * * @param PrivateKey $key + * @removed in phpseclib 4.0.0 */ public function setPrivateKey(PrivateKey $key) { @@ -2114,6 +2188,7 @@ class X509 * Used for SPKAC CSR's * * @param string $challenge + * @removed in phpseclib 4.0.0 */ public function setChallenge($challenge) { @@ -2174,6 +2249,7 @@ class X509 * @param string $csr * @param int $mode * @return mixed + * @removed in phpseclib 4.0.0 */ public function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT) { @@ -2248,6 +2324,7 @@ class X509 * @param array $csr * @param int $format optional * @return string + * @removed in phpseclib 4.0.0 */ public function saveCSR(array $csr, $format = self::FORMAT_PEM) { @@ -2293,6 +2370,7 @@ class X509 * * @param string $spkac * @return mixed + * @removed in phpseclib 4.0.0 */ public function loadSPKAC($spkac) { @@ -2357,6 +2435,7 @@ class X509 * @param array $spkac * @param int $format optional * @return string + * @removed in phpseclib 4.0.0 */ public function saveSPKAC(array $spkac, $format = self::FORMAT_PEM) { @@ -2394,6 +2473,7 @@ class X509 * @param string $crl * @param int $mode * @return mixed + * @removed in phpseclib 4.0.0 */ public function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT) { @@ -2460,6 +2540,7 @@ class X509 * @param array $crl * @param int $format optional * @return string + * @removed in phpseclib 4.0.0 */ public function saveCRL(array $crl, $format = self::FORMAT_PEM) { @@ -2540,6 +2621,7 @@ class X509 * a CSR or something with the DN and public key explicitly set. * * @return mixed + * @removed in phpseclib 4.0.0 */ public function sign(X509 $issuer, X509 $subject) { @@ -2722,6 +2804,7 @@ class X509 * Sign a CSR * * @return mixed + * @removed in phpseclib 4.0.0 */ public function signCSR() { @@ -2777,6 +2860,7 @@ class X509 * Sign a SPKAC * * @return mixed + * @removed in phpseclib 4.0.0 */ public function signSPKAC() { @@ -2839,6 +2923,7 @@ class X509 * $issuer's private key needs to be loaded. * * @return mixed + * @removed in phpseclib 4.0.0 */ public function signCRL(X509 $issuer, X509 $crl) { @@ -3389,6 +3474,7 @@ class X509 * @param array $cert optional * @param string $path optional * @return array + * @removed in phpseclib 4.0.0 */ public function getExtensions($cert = null, $path = null) { @@ -3415,6 +3501,7 @@ class X509 * @param string $id * @param int $disposition optional * @return bool + * @removed in phpseclib 4.0.0 */ public function removeAttribute($id, $disposition = self::ATTR_ALL) { @@ -3465,6 +3552,7 @@ class X509 * @param int $disposition optional * @param array $csr optional * @return mixed + * @removed in phpseclib 4.0.0 */ public function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null) { @@ -3506,6 +3594,7 @@ class X509 * * @param array $csr optional * @return mixed + * @removed in phpseclib 4.0.0 */ public function getRequestedCertificateExtensions($csr = null) { @@ -3526,6 +3615,7 @@ class X509 * * @param array $csr optional * @return array + * @removed in phpseclib 4.0.0 */ public function getAttributes($csr = null) { @@ -3552,6 +3642,7 @@ class X509 * @param mixed $value * @param int $disposition optional * @return bool + * @removed in phpseclib 4.0.0 */ public function setAttribute($id, $value, $disposition = self::ATTR_ALL) { @@ -3633,6 +3724,7 @@ class X509 * @param mixed $key optional * @param int $method optional * @return string binary key identifier + * @removed in phpseclib 4.0.0 */ public function computeKeyIdentifier($key = null, $method = 1) { @@ -3729,6 +3821,7 @@ class X509 * * @param mixed ...$domains * @return void + * @removed in phpseclib 4.0.0 */ public function setDomain(...$domains) { @@ -3741,6 +3834,7 @@ class X509 * Set the IP Addresses's which the cert is to be valid for * * @param mixed[] ...$ipAddresses + * @removed in phpseclib 4.0.0 */ public function setIPAddress(...$ipAddresses) { @@ -3837,6 +3931,7 @@ class X509 * * @param string $serial * @return bool + * @removed in phpseclib 4.0.0 */ public function unrevoke($serial) { @@ -3856,6 +3951,7 @@ class X509 * * @param string $serial * @return mixed + * @removed in phpseclib 4.0.0 */ public function getRevoked($serial) { @@ -3873,6 +3969,7 @@ class X509 * * @param array $crl optional * @return array|bool + * @removed in phpseclib 4.0.0 */ public function listRevoked($crl = null) { @@ -3901,6 +3998,7 @@ class X509 * @param string $serial * @param string $id * @return bool + * @removed in phpseclib 4.0.0 */ public function removeRevokedCertificateExtension($serial, $id) { @@ -3922,6 +4020,7 @@ class X509 * @param string $id * @param array $crl optional * @return mixed + * @removed in phpseclib 4.0.0 */ public function getRevokedCertificateExtension($serial, $id, $crl = null) { @@ -3969,6 +4068,7 @@ class X509 * @param bool $critical optional * @param bool $replace optional * @return bool + * @removed in phpseclib 4.0.0 */ public function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true) { @@ -4019,9 +4119,20 @@ class X509 * @param mixed $value * @param bool $critical * @param bool $replace + * @removed in phpseclib 4.0.0 */ public function setExtensionValue($id, $value, $critical = false, $replace = false) { $this->extensionValues[$id] = compact('critical', 'replace', 'value'); } + + /** + * Returns the OID corresponding to a name + * + * @param ?callable $callback + */ + public static function setURLFetchCallback($callback) + { + self::$urlFetchCallback = $callback; + } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php index 2a9cc0b..e6d420d 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php @@ -143,6 +143,11 @@ class BigInteger implements \JsonSerializable ['PHP64', ['DefaultEngine']], ['PHP32', ['DefaultEngine']] ]; + // per https://phpseclib.com/docs/speed PHP 8.4.0+ _significantly_ sped up BCMath + if (version_compare(PHP_VERSION, '8.4.0') >= 0) { + $engines[1][0] = 'BCMath'; + $engines[2][0] = 'PHP64'; + } foreach ($engines as $engine) { try { @@ -317,6 +322,7 @@ class BigInteger implements \JsonSerializable * * @param BigInteger $n * @return BigInteger + * @changed in phpseclib 4.0.0 */ public function modInverse(BigInteger $n) { @@ -333,12 +339,10 @@ class BigInteger implements \JsonSerializable */ public function extendedGCD(BigInteger $n) { - extract($this->value->extendedGCD($n->value)); - /** - * @var BigInteger $gcd - * @var BigInteger $x - * @var BigInteger $y - */ + $extended = $this->value->extendedGCD($n->value); + $gcd = $extended['gcd']; + $x = $extended['x']; + $y = $extended['y']; return [ 'gcd' => new static($gcd), 'x' => new static($x), @@ -399,7 +403,7 @@ class BigInteger implements \JsonSerializable * * Will be called, automatically, when serialize() is called on a BigInteger object. * - * __sleep() / __wakeup() have been around since PHP 4.0 + * __sleep() / __wakeup() have been around since PHP 4.0 but were deprecated in PHP 8.5 * * \Serializable was introduced in PHP 5.1 and deprecated in PHP 8.1: * https://wiki.php.net/rfc/phase_out_serializable @@ -434,6 +438,38 @@ class BigInteger implements \JsonSerializable } } + /** + * __serialize() magic method + * + * @see self::__unserialize() + * @return array + * @access public + */ + public function __serialize() + { + $result = ['hex' => $this->toHex(true)]; + if ($this->getPrecision() > 0) { + $result['precision'] = $this->getPrecision(); + } + return $result; + } + + /** + * __unserialize() magic method + * + * @see self::__serialize() + * @access public + */ + public function __unserialize(array $data) + { + $temp = new static($data['hex'], -16); + $this->value = $temp->value; + if (isset($data['precision']) && $data['precision'] > 0) { + // recalculate $this->bitmask + $this->setPrecision($data['precision']); + } + } + /** * JSON Serialize * @@ -617,10 +653,9 @@ class BigInteger implements \JsonSerializable self::initialize_static_variables(); $class = self::$mainEngine; - extract($class::minMaxBits($bits)); - /** @var BigInteger $min - * @var BigInteger $max - */ + $minMax = $class::minMaxBits($bits); + $min = $minMax['min']; + $max = $minMax['max']; return [ 'min' => new static($min), 'max' => new static($max) diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php index e3a4990..5fd78ec 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php @@ -38,6 +38,11 @@ class BCMath extends Engine */ const ENGINE_DIR = 'BCMath'; + /** + * Test to see if bcmod() accepts 2 or 3 parameters + */ + const BCMOD_THREE_PARAMS = PHP_VERSION_ID >= 72000; + /** * Test for engine validity * @@ -148,8 +153,8 @@ class BCMath extends Engine } while (bccomp($current, '0', 0) > 0) { - $temp = bcmod($current, '16777216'); - $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value; + $temp = self::BCMOD_THREE_PARAMS ? bcmod($current, '16777216', 0) : bcmod($current, '16777216'); + $value = chr($temp >> 16) . chr(($temp >> 8) & 0xFF) . chr($temp & 0xFF) . $value; $current = bcdiv($current, '16777216', 0); } @@ -167,7 +172,7 @@ class BCMath extends Engine public function add(BCMath $y) { $temp = new self(); - $temp->value = bcadd($this->value, $y->value); + $temp->value = bcadd($this->value, $y->value, 0); return $this->normalize($temp); } @@ -181,7 +186,7 @@ class BCMath extends Engine public function subtract(BCMath $y) { $temp = new self(); - $temp->value = bcsub($this->value, $y->value); + $temp->value = bcsub($this->value, $y->value, 0); return $this->normalize($temp); } @@ -195,7 +200,7 @@ class BCMath extends Engine public function multiply(BCMath $x) { $temp = new self(); - $temp->value = bcmul($this->value, $x->value); + $temp->value = bcmul($this->value, $x->value, 0); return $this->normalize($temp); } @@ -217,7 +222,7 @@ class BCMath extends Engine $remainder = new self(); $quotient->value = bcdiv($this->value, $y->value, 0); - $remainder->value = bcmod($this->value, $y->value); + $remainder->value = self::BCMOD_THREE_PARAMS ? bcmod($this->value, $y->value, 0) : bcmod($this->value, $y->value); if ($remainder->value[0] == '-') { $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0); @@ -297,8 +302,7 @@ class BCMath extends Engine */ public function gcd(BCMath $n) { - extract($this->extendedGCD($n)); - /** @var BCMath $gcd */ + $gcd = $this->extendedGCD($n)['gcd']; return $gcd; } @@ -475,7 +479,7 @@ class BCMath extends Engine $result->bitmask = $this->bitmask; if ($result->bitmask !== false) { - $result->value = bcmod($result->value, $result->bitmask->value); + $result->value = self::BCMOD_THREE_PARAMS ? bcmod($result->value, $result->bitmask->value, 0) : bcmod($result->value, $result->bitmask->value); } return $result; @@ -523,7 +527,7 @@ class BCMath extends Engine protected function make_odd() { if (!$this->isOdd()) { - $this->value = bcadd($this->value, '1'); + $this->value = bcadd($this->value, '1', 0); } } @@ -547,7 +551,7 @@ class BCMath extends Engine $value = $this->value; foreach (self::PRIMES as $prime) { - $r = bcmod($this->value, $prime); + $r = self::BCMOD_THREE_PARAMS ? bcmod($this->value, $prime, 0) : bcmod($this->value, $prime); if ($r == '0') { return $this->value == $prime; } @@ -587,7 +591,7 @@ class BCMath extends Engine public function pow(BCMath $n) { $temp = new self(); - $temp->value = bcpow($this->value, $n->value); + $temp->value = bcpow($this->value, $n->value, 0); return $this->normalize($temp); } @@ -656,8 +660,9 @@ class BCMath extends Engine */ public function testBit($x) { + $divisor = bcpow('2', $x + 1, 0); return bccomp( - bcmod($this->value, bcpow('2', $x + 1, 0)), + self::BCMOD_THREE_PARAMS ? bcmod($this->value, $divisor, 0) : bcmod($this->value, $divisor), bcpow('2', $x, 0), 0 ) >= 0; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php index fe21e04..88cd93e 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php @@ -91,7 +91,7 @@ abstract class Base extends BCMath */ protected static function multiplyReduce($x, $y, $n, $class) { - return static::reduce(bcmul($x, $y), $n); + return static::reduce(bcmul($x, $y, 0), $n); } /** @@ -105,6 +105,6 @@ abstract class Base extends BCMath */ protected static function squareReduce($x, $n, $class) { - return static::reduce(bcmul($x, $x), $n); + return static::reduce(bcmul($x, $x, 0), $n); } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php index b7ca8a2..f8bbcfa 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php @@ -33,7 +33,7 @@ abstract class BuiltIn extends BCMath protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n) { $temp = new BCMath(); - $temp->value = bcpowmod($x->value, $e->value, $n->value); + $temp->value = bcpowmod($x->value, $e->value, $n->value, 0); return $x->normalize($temp); } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php index 9e01bf0..1bec0a1 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php @@ -67,7 +67,7 @@ abstract class Barrett extends Base $m_length = strlen($m); if (strlen($n) > 2 * $m_length) { - return bcmod($n, $m); + return self::BCMOD_THREE_PARAMS ? bcmod($n, $m, 0) : bcmod($n, $m); } // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced @@ -89,14 +89,16 @@ abstract class Barrett extends Base $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1)); $u = bcdiv($lhs, $m, 0); - $m1 = bcsub($lhs, bcmul($u, $m)); + $m1 = bcsub($lhs, bcmul($u, $m, 0), 0); $cache[self::DATA][] = [ 'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1) 'm1' => $m1 // m.length ]; } else { - extract($cache[self::DATA][$key]); + $cacheValues = $cache[self::DATA][$key]; + $u = $cacheValues['u']; + $m1 = $cacheValues['m1']; } $cutoff = $m_length + ($m_length >> 1); @@ -104,8 +106,8 @@ abstract class Barrett extends Base $lsd = substr($n, -$cutoff); $msd = substr($n, 0, -$cutoff); - $temp = bcmul($msd, $m1); // m.length + (m.length >> 1) - $n = bcadd($lsd, $temp); // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers) + $temp = bcmul($msd, $m1, 0); // m.length + (m.length >> 1) + $n = bcadd($lsd, $temp, 0); // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers) //if ($m_length & 1) { // return self::regularBarrett($n, $m); //} @@ -114,31 +116,31 @@ abstract class Barrett extends Base $temp = substr($n, 0, -$m_length + 1); // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2 // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1 - $temp = bcmul($temp, $u); + $temp = bcmul($temp, $u, 0); // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1 // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) $temp = substr($temp, 0, -($m_length >> 1) - 1); // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1 // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1) - $temp = bcmul($temp, $m); + $temp = bcmul($temp, $m, 0); // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop // following this comment would loop a lot (hence our calling _regularBarrett() in that situation). - $result = bcsub($n, $temp); + $result = bcsub($n, $temp, 0); //if (bccomp($result, '0') < 0) { if ($result[0] == '-') { $temp = '1' . str_repeat('0', $m_length + 1); - $result = bcadd($result, $temp); + $result = bcadd($result, $temp, 0); } - while (bccomp($result, $m) >= 0) { - $result = bcsub($result, $m); + while (bccomp($result, $m, 0) >= 0) { + $result = bcsub($result, $m, 0); } - return $correctionNeeded ? substr($result, 0, -1) : $result; + return $correctionNeeded && $result != '0' ? substr($result, 0, -1) : $result; } /** @@ -161,7 +163,7 @@ abstract class Barrett extends Base $n_length = strlen($n); if (strlen($x) > 2 * $n_length) { - return bcmod($x, $n); + return self::BCMOD_THREE_PARAMS ? bcmod($x, $n, 0) : bcmod($x, $n); } if (($key = array_search($n, $cache[self::VARIABLE])) === false) { @@ -172,21 +174,21 @@ abstract class Barrett extends Base } $temp = substr($x, 0, -$n_length + 1); - $temp = bcmul($temp, $cache[self::DATA][$key]); + $temp = bcmul($temp, $cache[self::DATA][$key], 0); $temp = substr($temp, 0, -$n_length - 1); $r1 = substr($x, -$n_length - 1); - $r2 = substr(bcmul($temp, $n), -$n_length - 1); + $r2 = substr(bcmul($temp, $n, 0), -$n_length - 1); $result = bcsub($r1, $r2); //if (bccomp($result, '0') < 0) { if ($result[0] == '-') { $q = '1' . str_repeat('0', $n_length + 1); - $result = bcadd($result, $q); + $result = bcadd($result, $q, 0); } - while (bccomp($result, $n) >= 0) { - $result = bcsub($result, $n); + while (bccomp($result, $n, 0) >= 0) { + $result = bcsub($result, $n, 0); } return $result; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php index e033ba5..040d7b5 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php @@ -58,7 +58,7 @@ abstract class EvalBarrett extends Base $m_length = strlen($m); if ($m_length < 5) { - $code = 'return bcmod($x, $n);'; + $code = 'return self::BCMOD_THREE_PARAMS ? bcmod($x, $n, 0) : bcmod($x, $n);'; eval('$func = function ($n) { ' . $code . '};'); self::$custom_reduction = $func; return; @@ -66,7 +66,7 @@ abstract class EvalBarrett extends Base $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1)); $u = bcdiv($lhs, $m, 0); - $m1 = bcsub($lhs, bcmul($u, $m)); + $m1 = bcsub($lhs, bcmul($u, $m, 0), 0); $cutoff = $m_length + ($m_length >> 1); @@ -78,23 +78,23 @@ abstract class EvalBarrett extends Base $lsd = substr($n, -' . $cutoff . '); $msd = substr($n, 0, -' . $cutoff . '); - $temp = bcmul($msd, ' . $m1 . '); - $n = bcadd($lsd, $temp); + $temp = bcmul($msd, ' . $m1 . ', 0); + $n = bcadd($lsd, $temp, 0); $temp = substr($n, 0, ' . (-$m_length + 1) . '); - $temp = bcmul($temp, ' . $u . '); + $temp = bcmul($temp, ' . $u . ', 0); $temp = substr($temp, 0, ' . (-($m_length >> 1) - 1) . '); - $temp = bcmul($temp, ' . $m . '); + $temp = bcmul($temp, ' . $m . ', 0); - $result = bcsub($n, $temp); + $result = bcsub($n, $temp, 0); if ($result[0] == \'-\') { $temp = \'1' . str_repeat('0', $m_length + 1) . '\'; - $result = bcadd($result, $temp); + $result = bcadd($result, $temp, 0); } while (bccomp($result, ' . $m . ') >= 0) { - $result = bcsub($result, ' . $m . '); + $result = bcsub($result, ' . $m . ', 0); } return $result;'; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php index 474abe1..e845acf 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php @@ -316,11 +316,9 @@ abstract class Engine implements \JsonSerializable return $this->normalize($n->subtract($temp)); } - extract($this->extendedGCD($n)); - /** - * @var Engine $gcd - * @var Engine $x - */ + $extended = $this->extendedGCD($n); + $gcd = $extended['gcd']; + $x = $extended['x']; if (!$gcd->equals(static::$one[static::class])) { return false; @@ -366,6 +364,44 @@ abstract class Engine implements \JsonSerializable } } + /** + * __serialize() magic method + * + * __sleep / __wakeup were depreciated in PHP 8.5 + * Will be called, automatically, when serialize() is called on a Math_BigInteger object. + * + * @see self::__unserialize() + * @access public + */ + public function __serialize() + { + $result = ['hex' => $this->toHex(true)]; + if ($this->precision > 0) { + $result['precision'] = $this->precision; + } + return $result; + } + + /** + * __unserialize() magic method + * + * __sleep / __wakeup were depreciated in PHP 8.5 + * Will be called, automatically, when unserialize() is called on a Math_BigInteger object. + * + * @see self::__serialize() + * @access public + */ + public function __unserialize(array $data) + { + $temp = new static($data['hex'], -16); + $this->value = $temp->value; + $this->is_negative = $temp->is_negative; + if (isset($data['precision']) && $data['precision'] > 0) { + // recalculate $this->bitmask + $this->setPrecision($data['precision']); + } + } + /** * JSON Serialize * @@ -513,8 +549,8 @@ abstract class Engine implements \JsonSerializable $carry = 0; for ($i = strlen($x) - 1; $i >= 0; --$i) { - $temp = ord($x[$i]) << $shift | $carry; - $x[$i] = chr($temp); + $temp = (ord($x[$i]) << $shift) | $carry; + $x[$i] = chr($temp & 0xFF); $carry = $temp >> 8; } $carry = ($carry != 0) ? chr($carry) : ''; @@ -644,7 +680,7 @@ abstract class Engine implements \JsonSerializable return $this->normalize($temp->powModInner($e, $n)); } - if ($this->compare($n) > 0) { + if ($this->compare($n) > 0 || $this->isNegative()) { list(, $temp) = $this->divide($n); return $temp->powModInner($e, $n); } @@ -740,11 +776,9 @@ abstract class Engine implements \JsonSerializable */ public static function random($size) { - extract(static::minMaxBits($size)); - /** - * @var BigInteger $min - * @var BigInteger $max - */ + $minMax = static::minMaxBits($size); + $min = $minMax['min']; + $max = $minMax['max']; return static::randomRange($min, $max); } @@ -758,11 +792,9 @@ abstract class Engine implements \JsonSerializable */ public static function randomPrime($size) { - extract(static::minMaxBits($size)); - /** - * @var static $min - * @var static $max - */ + $minMax = static::minMaxBits($size); + $min = $minMax['min']; + $max = $minMax['max']; return static::randomRangePrime($min, $max); } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php index f616362..30ad4be 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php @@ -120,8 +120,7 @@ class GMP extends Engine public function toBits($twos_compliment = false) { $hex = $this->toHex($twos_compliment); - - $bits = gmp_strval(gmp_init($hex, 16), 2); + $bits = strlen($hex) ? gmp_strval(gmp_init($hex, 16), 2) : ''; if ($this->precision > 0) { $bits = substr($bits, -$this->precision); @@ -296,7 +295,10 @@ class GMP extends Engine */ public function extendedGCD(GMP $n) { - extract(gmp_gcdext($this->value, $n->value)); + $extended = gmp_gcdext($this->value, $n->value); + $g = $extended['g']; + $s = $extended['s']; + $t = $extended['t']; return [ 'gcd' => $this->normalize(new self($g)), diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php index 2d89595..9f2ba94 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php @@ -304,7 +304,7 @@ abstract class PHP extends Engine * @param bool $y_negative * @return array */ - public static function subtractHelper(array $x_value, $x_negative, array $y_value, $y_negative) + protected static function subtractHelper(array $x_value, $x_negative, array $y_value, $y_negative) { $x_size = count($x_value); $y_size = count($y_value); @@ -533,6 +533,13 @@ abstract class PHP extends Engine $quotient = new static(); $remainder = new static(); $quotient->value = $q; + // The common residue is the first positive modulo, so it is only the + // negative remainders that need the divisor added. A remainder of 0 is + // already the residue; adding the divisor would return the modulus + // itself, which is never a valid residue. + if ($this->is_negative && $r) { + $r = $y->value[0] - $r; + } $remainder->value = [$r]; $quotient->is_negative = $this->is_negative != $y->is_negative; return [$this->normalize($quotient), $this->normalize($remainder)]; @@ -664,8 +671,9 @@ abstract class PHP extends Engine $quotient->is_negative = $x_sign != $y_sign; - // calculate the "common residue", if appropriate - if ($x_sign) { + // calculate the "common residue", if appropriate. A remainder of 0 is + // already the residue -- see divideHelper's single-digit branch. + if ($x_sign && count($x->value)) { $y->rshift($shift); $x = $y->subtract($x); } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php index 8868966..e624f3c 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php @@ -98,7 +98,9 @@ abstract class Barrett extends Base 'm1' => $m1 // m.length ]; } else { - extract($cache[self::DATA][$key]); + $cacheValues = $cache[self::DATA][$key]; + $u = $cacheValues['u']; + $m1 = $cacheValues['m1']; } $cutoff = $m_length + ($m_length >> 1); diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php index 15eb99c..e2aa3e7 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php @@ -54,10 +54,31 @@ class Integer extends Base /** * Zero * - * @var BigInteger + * @var BigInteger[] */ protected static $zero; + /** + * One + * + * @var BigInteger[] + */ + protected static $one; + + /** + * Two + * + * @var BigInteger[] + */ + protected static $two; + + /** + * Constant Time Mask + * + * @var BigInteger[] + */ + protected static $mask; + /** * Default constructor * @@ -68,7 +89,7 @@ class Integer extends Base { $this->instanceID = $instanceID; if (!isset($num)) { - $this->value = clone static::$zero[static::class]; + $this->value = clone static::$zero[$instanceID]; } else { $reduce = static::$reduce[$instanceID]; $this->value = $reduce($num); @@ -84,6 +105,11 @@ class Integer extends Base public static function setModulo($instanceID, BigInteger $modulo) { static::$modulo[$instanceID] = $modulo; + $one = new BigInteger(1); + static::$mask[$instanceID] = [ + new BigInteger(0), + $one->bitwise_leftShift($modulo->getLength())->subtract($one) + ]; } /** @@ -95,8 +121,8 @@ class Integer extends Base public static function setRecurringModuloFunction($instanceID, callable $function) { static::$reduce[$instanceID] = $function; - if (!isset(static::$zero[static::class])) { - static::$zero[static::class] = new BigInteger(); + if (!isset(static::$zero[$instanceID])) { + static::$zero[$instanceID] = new BigInteger(); } } @@ -107,6 +133,10 @@ class Integer extends Base { unset(static::$modulo[$instanceID]); unset(static::$reduce[$instanceID]); + unset(static::$zero[$instanceID]); + unset(static::$one[$instanceID]); + unset(static::$two[$instanceID]); + unset(static::$mask[$instanceID]); } /** @@ -158,6 +188,25 @@ class Integer extends Base return $this->value->compare($x->value); } + /** + * Conditionally add the modulus, without branching on the value. + * + * $diff must be in (-modulo, modulo). Returns $diff + modulo when $diff is + * negative, $diff otherwise. + * + * @return static + */ + private function conditionalAddModulo(BigInteger $diff) + { + $mask = static::$mask[$this->instanceID][(int) $diff->isNegative()]; + + $temp = new static($this->instanceID); + $temp->value = $diff->add( + static::$modulo[$this->instanceID]->bitwise_and($mask) + ); + return $temp; + } + /** * Adds two PrimeFieldIntegers. * @@ -167,13 +216,10 @@ class Integer extends Base { static::checkInstance($this, $x); - $temp = new static($this->instanceID); - $temp->value = $this->value->add($x->value); - if ($temp->value->compare(static::$modulo[$this->instanceID]) >= 0) { - $temp->value = $temp->value->subtract(static::$modulo[$this->instanceID]); - } - - return $temp; + // $this->value + $x->value is in [0, 2m), so subtracting once lands in [-m, m) + return $this->conditionalAddModulo( + $this->value->add($x->value)->subtract(static::$modulo[$this->instanceID]) + ); } /** @@ -185,13 +231,8 @@ class Integer extends Base { static::checkInstance($this, $x); - $temp = new static($this->instanceID); - $temp->value = $this->value->subtract($x->value); - if ($temp->value->isNegative()) { - $temp->value = $temp->value->add(static::$modulo[$this->instanceID]); - } - - return $temp; + // already in (-m, m) + return $this->conditionalAddModulo($this->value->subtract($x->value)); } /** @@ -240,32 +281,35 @@ class Integer extends Base */ public function squareRoot() { - static $one, $two; - if (!isset($one)) { - $one = new BigInteger(1); - $two = new BigInteger(2); + if (!isset(static::$one[$this->instanceID])) { + static::$one[$this->instanceID] = new BigInteger(1); + static::$two[$this->instanceID] = new BigInteger(2); } - $reduce = static::$reduce[$this->instanceID]; - $p_1 = static::$modulo[$this->instanceID]->subtract($one); + $one = &static::$one[$this->instanceID]; + $two = &static::$two[$this->instanceID]; + $modulo = &static::$modulo[$this->instanceID]; + $reduce = &static::$reduce[$this->instanceID]; + + $p_1 = $modulo->subtract($one); $q = clone $p_1; $s = BigInteger::scan1divide($q); list($pow) = $p_1->divide($two); - for ($z = $one; !$z->equals(static::$modulo[$this->instanceID]); $z = $z->add($one)) { - $temp = $z->powMod($pow, static::$modulo[$this->instanceID]); + for ($z = $one; !$z->equals($modulo); $z = $z->add($one)) { + $temp = $z->powMod($pow, $modulo); if ($temp->equals($p_1)) { break; } } $m = new BigInteger($s); - $c = $z->powMod($q, static::$modulo[$this->instanceID]); - $t = $this->value->powMod($q, static::$modulo[$this->instanceID]); + $c = $z->powMod($q, $modulo); + $t = $this->value->powMod($q, $modulo); list($temp) = $q->add($one)->divide($two); - $r = $this->value->powMod($temp, static::$modulo[$this->instanceID]); + $r = $this->value->powMod($temp, $modulo); while (!$t->equals($one)) { for ($i = clone $one; $i->compare($m) < 0; $i = $i->add($one)) { - if ($t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) { + if ($t->powMod($two->pow($i), $modulo)->equals($one)) { break; } } @@ -273,7 +317,7 @@ class Integer extends Base if ($i->compare($m) == 0) { return false; } - $b = $c->powMod($two->pow($m->subtract($i)->subtract($one)), static::$modulo[$this->instanceID]); + $b = $c->powMod($two->pow($m->subtract($i)->subtract($one)), $modulo); $m = $i; $c = $reduce($b->multiply($b)); $t = $reduce($t->multiply($c)); @@ -356,6 +400,8 @@ class Integer extends Base { $w++; + $zero = &static::$zero[$this->instanceID]; + $mask = new BigInteger((1 << $w) - 1); $sub = new BigInteger(1 << $w); //$sub = new BigInteger(1 << ($w - 1)); @@ -363,7 +409,7 @@ class Integer extends Base $d_i = []; $i = 0; - while ($d->compare(static::$zero[static::class]) > 0) { + while ($d->compare($zero) > 0) { if ($d->isOdd()) { // start mods @@ -377,7 +423,7 @@ class Integer extends Base } else { $d_i[$i] = 0; } - $shift = !$d->equals(static::$zero[static::class]) && $d->bitwise_and($mask)->equals(static::$zero[static::class]) ? $w : 1; // $w or $w + 1? + $shift = !$d->equals($zero) && $d->bitwise_and($mask)->equals($zero) ? $w : 1; // $w or $w + 1? $d = $d->bitwise_rightShift($shift); while (--$shift > 0) { $d_i[++$i] = 0; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php new file mode 100644 index 0000000..6d603de --- /dev/null +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php @@ -0,0 +1,302 @@ + + * login('username', 'password')) { + * exit('Login Failed'); + * } + * + * echo $scp->exec('pwd') . "\r\n"; + * $scp->put('filename.ext', 'hello, world!'); + * echo $scp->exec('ls -latr'); + * ?> + * + * + * @author Jim Wigginton + * @copyright 2009 Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + */ + +namespace phpseclib3\Net; + +use phpseclib3\Exception\FileNotFoundException; + +/** + * Pure-PHP implementations of SCP. + * + * @author Jim Wigginton + */ +class SCP extends SSH2 +{ + /** + * Reads data from a local file. + * + * @see SCP::put() + */ + const SOURCE_LOCAL_FILE = 1; + /** + * Reads data from a string. + * + * @see SCP::put() + */ + // this value isn't really used anymore but i'm keeping it reserved for historical reasons + const SOURCE_STRING = 2; + /** + * SCP.php doesn't support SOURCE_CALLBACK because, with that one, we don't know the size, in advance + */ + //const SOURCE_CALLBACK = 16; + + /** + * Error information + * + * @see self::getSCPErrors() + * @see self::getLastSCPError() + * @var array + */ + private $scp_errors = []; + + /** + * Uploads a file to the SCP server. + * + * By default, \phpseclib\Net\SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file. + * So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SCP::get(), you will get a file, twelve bytes + * long, containing 'filename.ext' as its contents. + * + * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will + * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how + * large $remote_file will be, as well. + * + * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take + * care of that, yourself. + * + * @param string $remote_file + * @param string $data + * @param int $mode + * @param callable $callback + * @return bool + * @access public + */ + public function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null) + { + if (!($this->bitmap & self::MASK_LOGIN)) { + return false; + } + + if (empty($remote_file)) { + // remote file cannot be blank + return false; + } + + if (!$this->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to + return false; + } + + $temp = $this->get_channel_packet(self::CHANNEL_EXEC, true); + if ($temp !== chr(0)) { + $this->close_channel(self::CHANNEL_EXEC, true); + return false; + } + + $packet_size = $this->packet_size_client_to_server[self::CHANNEL_EXEC] - 4; + + $remote_file = basename($remote_file); + + $dataCallback = false; + switch (true) { + case is_resource($data): + $mode = $mode & ~self::SOURCE_LOCAL_FILE; + $info = stream_get_meta_data($data); + if (isset($info['wrapper_type']) && $info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') { + $fp = fopen('php://memory', 'w+'); + stream_copy_to_stream($data, $fp); + rewind($fp); + } else { + $fp = $data; + } + break; + case $mode & self::SOURCE_LOCAL_FILE: + if (!is_file($data)) { + throw new FileNotFoundException("$data is not a valid file"); + } + $fp = @fopen($data, 'rb'); + if (!$fp) { + $this->close_channel(self::CHANNEL_EXEC, true); + return false; + } + } + + if (isset($fp)) { + $stat = fstat($fp); + $size = !empty($stat) ? $stat['size'] : 0; + } else { + $size = strlen($data); + } + + $sent = 0; + $size = $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size; + + $temp = 'C0644 ' . $size . ' ' . $remote_file . "\n"; + $this->send_channel_packet(self::CHANNEL_EXEC, $temp); + + $temp = $this->get_channel_packet(self::CHANNEL_EXEC, true); + if ($temp !== chr(0)) { + $this->close_channel(self::CHANNEL_EXEC, true); + return false; + } + + $sent = 0; + while ($sent < $size) { + $temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $packet_size) : fread($fp, $packet_size); + $this->send_channel_packet(self::CHANNEL_EXEC, $temp); + $sent += strlen($temp); + + if (is_callable($callback)) { + call_user_func($callback, $sent); + } + } + $this->close_channel(self::CHANNEL_EXEC, true); + + if ($mode != self::SOURCE_STRING) { + fclose($fp); + } + + return true; + } + + /** + * Downloads a file from the SCP server. + * + * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if + * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the + * operation + * + * @param string $remote_file + * @param string $local_file + * @return mixed + * @access public + */ + public function get($remote_file, $local_file = null, $progressCallback = null) + { + if (!($this->bitmap & self::MASK_LOGIN)) { + return false; + } + + if (!$this->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from + return false; + } + + $this->send_channel_packet(self::CHANNEL_EXEC, chr(0)); + + $info = $this->get_channel_packet(self::CHANNEL_EXEC, true); + // per https://goteleport.com/blog/scp-familiar-simple-insecure-slow/ non-zero responses mean there are errors + if ($info[0] === chr(1) || $info[0] == chr(2)) { + $type = $info[0] === chr(1) ? 'warning' : 'error'; + $this->scp_errors[] = "$type: " . substr($info, 1); + $this->close_channel(self::CHANNEL_EXEC, true); + return false; + } + + $this->send_channel_packet(self::CHANNEL_EXEC, chr(0)); + + if (!preg_match('#(?[^ ]+) (?\d+) (?.+)#', rtrim($info), $info)) { + $this->close_channel(self::CHANNEL_EXEC, true); + return false; + } + + $fclose_check = false; + if (is_resource($local_file)) { + $fp = $local_file; + } elseif (!is_null($local_file)) { + $fp = @fopen($local_file, 'wb'); + if (!$fp) { + $this->close_channel(self::CHANNEL_EXEC, true); + return false; + } + $fclose_check = true; + } else { + $content = ''; + } + + $size = 0; + while (true) { + $data = $this->get_channel_packet(self::CHANNEL_EXEC, true); + // Terminate the loop in case the server repeatedly sends an empty response + if ($data === false) { + $this->close_channel(self::CHANNEL_EXEC, true); + // no data received from server + return false; + } + // SCP usually seems to split stuff out into 16k chunks + $length = strlen($data); + $size += $length; + $end = $size > $info['size']; + if ($end) { + $diff = $size - $info['size']; + $offset = $length - $diff; + if ($data[$offset] === chr(0)) { + $data = substr($data, 0, -$diff); + } else { + $type = $data[$offset] === chr(1) ? 'warning' : 'error'; + $this->scp_errors[] = "$type: " . substr($data, 1); + $this->close_channel(self::CHANNEL_EXEC, true); + return false; + } + } + + if (is_null($local_file)) { + $content .= $data; + } else { + fputs($fp, $data); + } + + if (is_callable($progressCallback)) { + call_user_func($progressCallback, $size); + } + + if ($end) { + break; + } + } + + $this->close_channel(self::CHANNEL_EXEC, true); + + if ($fclose_check) { + fclose($fp); + } + + // if $content isn't set that means a file was written to + return isset($content) ? $content : true; + } + + /** + * Returns all errors on the SCP layer + * + * @return array + */ + public function getSCPErrors() + { + return $this->scp_errors; + } + + /** + * Returns the last error on the SCP layer + * + * @return string + */ + public function getLastSCPError() + { + return count($this->scp_errors) ? $this->scp_errors[count($this->scp_errors) - 1] : ''; + } +} diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php index 47dac48..038b191 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php @@ -35,6 +35,7 @@ namespace phpseclib3\Net; use phpseclib3\Common\Functions\Strings; use phpseclib3\Exception\FileNotFoundException; +use phpseclib3\Exception\TimeoutException; /** * Pure-PHP implementations of SFTP. @@ -48,21 +49,21 @@ class SFTP extends SSH2 * * \phpseclib3\Net\SSH2::exec() uses 0 and \phpseclib3\Net\SSH2::read() / \phpseclib3\Net\SSH2::write() use 1. * - * @see \phpseclib3\Net\SSH2::send_channel_packet() - * @see \phpseclib3\Net\SSH2::get_channel_packet() + * @see SSH2::send_channel_packet() + * @see SSH2::get_channel_packet() */ const CHANNEL = 0x100; /** * Reads data from a local file. * - * @see \phpseclib3\Net\SFTP::put() + * @see SFTP::put() */ const SOURCE_LOCAL_FILE = 1; /** * Reads data from a string. * - * @see \phpseclib3\Net\SFTP::put() + * @see SFTP::put() */ // this value isn't really used anymore but i'm keeping it reserved for historical reasons const SOURCE_STRING = 2; @@ -70,19 +71,19 @@ class SFTP extends SSH2 * Reads data from callback: * function callback($length) returns string to proceed, null for EOF * - * @see \phpseclib3\Net\SFTP::put() + * @see SFTP::put() */ const SOURCE_CALLBACK = 16; /** * Resumes an upload * - * @see \phpseclib3\Net\SFTP::put() + * @see SFTP::put() */ const RESUME = 4; /** * Append a local file to an already existing remote file * - * @see \phpseclib3\Net\SFTP::put() + * @see SFTP::put() */ const RESUME_START = 8; @@ -598,6 +599,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_VERSION) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_VERSION. ' . 'Got packet type: ' . $this->packet_type); } @@ -667,6 +671,9 @@ class SFTP extends SSH2 $this->send_sftp_packet(NET_SFTP_EXTENDED, $packet); $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -836,6 +843,8 @@ class SFTP extends SSH2 return false; } + $path = (string) $path; + if (!$this->canonicalize_paths) { if ($this->pwd === true) { return '.'; @@ -881,6 +890,9 @@ class SFTP extends SSH2 $this->logError($response); return false; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -923,6 +935,8 @@ class SFTP extends SSH2 return false; } + $dir = (string) $dir; + // assume current dir if $dir is empty if ($dir === '') { $dir = './'; @@ -932,6 +946,9 @@ class SFTP extends SSH2 } $dir = $this->realpath($dir); + if ($dir === false) { + return false; + } // confirm that $dir is, in fact, a valid directory if ($this->use_stat_cache && is_array($this->query_stat_cache($dir))) { @@ -956,6 +973,9 @@ class SFTP extends SSH2 $this->logError($response); return false; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS' . 'Got packet type: ' . $this->packet_type); } @@ -1108,6 +1128,9 @@ class SFTP extends SSH2 $this->logError($response, $status); return $status; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -1518,6 +1541,9 @@ class SFTP extends SSH2 return false; } + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -1585,6 +1611,9 @@ class SFTP extends SSH2 $this->logError($response); break; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -1674,6 +1703,7 @@ class SFTP extends SSH2 * @param bool $recursive * @throws \UnexpectedValueException on receipt of unexpected packets * @return mixed + * @changed in phpseclib 4.0.0 */ public function chmod($mode, $filename, $recursive = false) { @@ -1708,6 +1738,9 @@ class SFTP extends SSH2 return false; } + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -1756,6 +1789,9 @@ class SFTP extends SSH2 */ $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -1869,6 +1905,9 @@ class SFTP extends SSH2 $this->logError($response); return false; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -1937,6 +1976,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -1997,6 +2039,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2036,6 +2081,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2159,6 +2207,9 @@ class SFTP extends SSH2 $this->logError($response); return false; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2301,6 +2352,9 @@ class SFTP extends SSH2 while ($i--) { $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2330,6 +2384,9 @@ class SFTP extends SSH2 // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2386,6 +2443,9 @@ class SFTP extends SSH2 $this->logError($response); return false; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2478,6 +2538,8 @@ class SFTP extends SSH2 $this->partial_init = false; $this->init_sftp_connection(); return false; + } elseif ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); } else { throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); @@ -2541,6 +2603,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2726,6 +2791,9 @@ class SFTP extends SSH2 case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED return false; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2753,6 +2821,9 @@ class SFTP extends SSH2 case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED return false; default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -2993,6 +3064,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -3355,8 +3429,7 @@ class SFTP extends SSH2 if (strlen($this->packet_buffer) < 4) { throw new \RuntimeException('Packet is too small'); } - extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4))); - /** @var integer $length */ + $length = unpack('Nlength', Strings::shift($this->packet_buffer, 4))['length']; $tempLength = $length; $tempLength -= strlen($this->packet_buffer); @@ -3386,7 +3459,7 @@ class SFTP extends SSH2 $this->packet_type = ord(Strings::shift($this->packet_buffer)); if ($this->use_request_id) { - extract(unpack('Npacket_id', Strings::shift($this->packet_buffer, 4))); // remove the request id + $packet_id = unpack('Npacket_id', Strings::shift($this->packet_buffer, 4))['packet_id']; // remove the request id $length -= 5; // account for the request id and the packet type } else { $length -= 1; // account for the packet type @@ -3456,11 +3529,11 @@ class SFTP extends SSH2 return $this->packet_type_log; } } - /** * Returns all errors on the SFTP layer * * @return array + * @removed in phpseclib 4.0.0 */ public function getSFTPErrors() { @@ -3471,6 +3544,7 @@ class SFTP extends SSH2 * Returns the last error on the SFTP layer * * @return string + * @removed in phpseclib 4.0.0 */ public function getLastSFTPError() { @@ -3559,7 +3633,6 @@ class SFTP extends SSH2 /** * Enable Date Preservation - * */ public function enableDatePreservation() { @@ -3568,13 +3641,110 @@ class SFTP extends SSH2 /** * Disable Date Preservation - * */ public function disableDatePreservation() { $this->preserveTime = false; } + /** + * Copy + * + * This method (currently) only works if the copy-data extension is available + * + * @param string $oldname + * @param string $newname + * @return bool + */ + public function copy($oldname, $newname) + { + if (!$this->precheck()) { + return false; + } + + $oldname = $this->realpath($oldname); + $newname = $this->realpath($newname); + if ($oldname === false || $newname === false) { + return false; + } + + if (!isset($this->extensions['copy-data']) || $this->extensions['copy-data'] !== '1') { + throw new \RuntimeException( + "Extension 'copy-data' is not supported by the server. " . + "Call getSupportedVersions() to see a list of supported extension" + ); + } + + $size = $this->filesize($oldname); + + $packet = Strings::packSSH2('s', $oldname); + $packet .= $this->version >= 5 ? + pack('N3', 0, NET_SFTP_OPEN_OPEN_EXISTING, 0) : + pack('N2', NET_SFTP_OPEN_READ, 0); + $this->send_sftp_packet(NET_SFTP_OPEN, $packet); + + $response = $this->get_sftp_packet(); + switch ($this->packet_type) { + case NET_SFTP_HANDLE: + $oldhandle = substr($response, 4); + break; + case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED + $this->logError($response); + return false; + default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } + throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' + . 'Got packet type: ' . $this->packet_type); + } + + if ($this->version >= 5) { + $flags = NET_SFTP_OPEN_OPEN_OR_CREATE; + } else { + $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE; + } + + $packet = Strings::packSSH2('s', $newname); + $packet .= $this->version >= 5 ? + pack('N3', 0, $flags, 0) : + pack('N2', $flags, 0); + $this->send_sftp_packet(NET_SFTP_OPEN, $packet); + + $response = $this->get_sftp_packet(); + switch ($this->packet_type) { + case NET_SFTP_HANDLE: + $newhandle = substr($response, 4); + break; + case NET_SFTP_STATUS: + $this->logError($response); + return false; + default: + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } + throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. ' + . 'Got packet type: ' . $this->packet_type); + } + + $packet = Strings::packSSH2('ssQQsQ', 'copy-data', $oldhandle, 0, $size, $newhandle, 0); + $this->send_sftp_packet(NET_SFTP_EXTENDED, $packet); + + $response = $this->get_sftp_packet(); + if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } + throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' + . 'Got packet type: ' . $this->packet_type); + } + + $this->close_handle($oldhandle); + $this->close_handle($newhandle); + + return true; + } + /** * POSIX Rename * @@ -3606,6 +3776,9 @@ class SFTP extends SSH2 $packet = Strings::packSSH2('sss', 'posix-rename@openssh.com', $oldname, $newname); $this->send_sftp_packet(NET_SFTP_EXTENDED, $packet); } else { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \RuntimeException( "Extension 'posix-rename@openssh.com' is not supported by the server. " . "Call getSupportedVersions() to see a list of supported extension" @@ -3614,6 +3787,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' . 'Got packet type: ' . $this->packet_type); } @@ -3666,6 +3842,9 @@ class SFTP extends SSH2 $response = $this->get_sftp_packet(); if ($this->packet_type !== NET_SFTP_EXTENDED_REPLY) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } throw new \UnexpectedValueException( 'Expected SSH_FXP_EXTENDED_REPLY. ' . 'Got packet type: ' . $this->packet_type @@ -3694,4 +3873,53 @@ class SFTP extends SSH2 Strings::unpackSSH2('QQQQQQQQQQQ', $response) ); } + + public function hardlink($oldpath, $newpath) + { + if (!$this->precheck()) { + return false; + } + + if (!isset($this->extensions['hardlink@openssh.com']) || $this->extensions['hardlink@openssh.com'] !== '1') { + throw new \RuntimeException( + "Extension 'hardlink@openssh.com' is not supported by the server. " . + "Call getSupportedVersions() to see a list of supported extension" + ); + } + + $oldpath = $this->realpath($oldpath); + $newpath = $this->realpath($newpath); + if ($oldpath === false || $newpath === false) { + return false; + } + + $packet = Strings::packSSH2('sss', 'hardlink@openssh.com', $oldpath, $newpath); + $this->send_sftp_packet(NET_SFTP_EXTENDED, $packet); + + $response = $this->get_sftp_packet(); + if ($this->packet_type !== NET_SFTP_STATUS) { + if ($this->is_timeout) { + throw new TimeoutException('Timed out waiting for SFTP packet response'); + } + throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. ' + . 'Got packet type: ' . $this->packet_type); + } + + // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED + list($status) = Strings::unpackSSH2('N', $response); + if ($status !== NET_SFTP_STATUS_OK) { + $this->logError($response, $status); + return false; + } + + // this operation will change the ctime and link-count attributes + // which could be cached depending on sftp version + $this->remove_from_stat_cache($oldpath); + + // hardlink creation should fail if $newpath exists; + // removing it from the cache anyway, just to be sure + $this->remove_from_stat_cache($newpath); + + return true; + } } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php index 24047b4..eedd1a0 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php @@ -139,7 +139,15 @@ class Stream protected function parse_path($path) { $orig = $path; - extract(parse_url($path) + ['port' => 22]); + $url = parse_url($path) + ['port' => 22]; + + $keys = ['scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment']; + foreach ($keys as $key) { + if (isset($url[$key])) { + $$key = $url[$key]; + } + } + if (isset($query)) { $path .= '?' . $query; } elseif (preg_match('/(\?|\?#)$/', $orig)) { @@ -169,9 +177,9 @@ class Stream } $this->sftp = $host; } else { - if (isset($this->context)) { - $context = stream_context_get_options($this->context); - } + $context = isset($this->context) ? + stream_context_get_options($this->context) : + stream_context_get_options(stream_context_get_default()); if (isset($context[$scheme]['session'])) { $sftp = $context[$scheme]['session']; } diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php index ac44eaa..e8e4894 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php @@ -118,10 +118,10 @@ class SSH2 * open request, and 'sender channel' is the channel number allocated by * the other side. * - * @see \phpseclib3\Net\SSH2::send_channel_packet() - * @see \phpseclib3\Net\SSH2::get_channel_packet() + * @see SSH2::send_channel_packet() + * @see SSH2::get_channel_packet() */ - const CHANNEL_EXEC = 1; // PuTTy uses 0x100 + const CHANNEL_EXEC = 1; // PuTTY uses 0x100 const CHANNEL_SHELL = 2; const CHANNEL_SUBSYSTEM = 3; const CHANNEL_AGENT_FORWARD = 4; @@ -130,13 +130,13 @@ class SSH2 /** * Returns the message numbers * - * @see \phpseclib3\Net\SSH2::getLog() + * @see SSH2::getLog() */ const LOG_SIMPLE = 1; /** * Returns the message content * - * @see \phpseclib3\Net\SSH2::getLog() + * @see SSH2::getLog() */ const LOG_COMPLEX = 2; /** @@ -158,20 +158,20 @@ class SSH2 /** * Make sure that the log never gets larger than this * - * @see \phpseclib3\Net\SSH2::getLog() + * @see SSH2::getLog() */ const LOG_MAX_SIZE = 1048576; // 1024 * 1024 /** * Returns when a string matching $expect exactly is found * - * @see \phpseclib3\Net\SSH2::read() + * @see SSH2::read() */ const READ_SIMPLE = 1; /** * Returns when a string matching the regular expression $expect is found * - * @see \phpseclib3\Net\SSH2::read() + * @see SSH2::read() */ const READ_REGEX = 2; /** @@ -180,7 +180,7 @@ class SSH2 * Some data packets may only contain a single character so it may be necessary * to call read() multiple times when using this option * - * @see \phpseclib3\Net\SSH2::read() + * @see SSH2::read() */ const READ_NEXT = 3; @@ -679,7 +679,7 @@ class SSH2 * @see self::send_channel_packet() * @var array */ - private $packet_size_client_to_server = []; + protected $packet_size_client_to_server = []; /** * Message Number Log @@ -1477,7 +1477,7 @@ class SSH2 } if (defined('NET_SSH2_LOGGING')) { - $this->append_log('<- (network: ' . round($totalElapsed, 4) . ')', $line); + $this->append_log('<- (network: ' . round($totalElapsed, 4) . ')', $data); } if (feof($this->fsock)) { @@ -1487,7 +1487,13 @@ class SSH2 $extra = $matches[1]; - $this->server_identifier = trim($data, "\r\n"); + // earlier the SSH specs were quoted. + // "The server MAY send other lines of data before sending the version string." they said. + // the implication of this is that the lines of data before the server string are *not* a part of it + // getting this right is important because the correct server identifier needs to be fed into the + // exchange hash for the shared keys to be calculated correctly + $data = explode("\r\n", trim($data, "\r\n")); + $this->server_identifier = $data[count($data) - 1]; if (strlen($extra)) { $this->errors[] = $data; } @@ -1677,7 +1683,6 @@ class SSH2 case NET_SSH2_MSG_DISCONNECT: return $this->handleDisconnect($kexinit_payload_server); } - $this->kex_buffer[] = $kexinit_payload_server; } @@ -2936,6 +2941,9 @@ class SSH2 $this->channel_id_last_interactive = self::CHANNEL_EXEC; return true; } + if ($callback === false) { + return true; + } $output = ''; while (true) { @@ -2977,7 +2985,7 @@ class SSH2 */ protected function open_channel($channel, $skip_extended = false) { - if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_CLOSE) { + if (isset($this->channel_status[$channel])) { throw new \RuntimeException('Please close the channel (' . $channel . ') before trying to open it again'); } @@ -3346,6 +3354,27 @@ class SSH2 } } + /** + * Send EOF on a channel + * + * Sends an EOF to the stream; this is typically used to close standard + * input, while keeping output and error alive. + * + * @param int|null $channel Channel id returned by self::getInteractiveChannelId() + * @return void + */ + public function sendEOF($channel = null) + { + if ($channel === null) { + $channel = $this->get_interactive_channel(); + } + + $excludeStatuses = [NET_SSH2_MSG_CHANNEL_EOF, NET_SSH2_MSG_CHANNEL_CLOSE]; + if (isset($this->channel_status[$channel]) && !in_array($this->channel_status[$channel], $excludeStatuses)) { + $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$channel])); + } + } + /** * Is timeout? * @@ -3709,12 +3738,12 @@ class SSH2 substr($packet->raw, 0, -$this->hmac_size); if (($this->hmac_check->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') { $this->hmac_check->setNonce("\0\0\0\0" . pack('N', $this->get_seq_no)); - if ($hmac != $this->hmac_check->hash($reconstructed)) { + if (!hash_equals($hmac, $this->hmac_check->hash($reconstructed))) { $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR); throw new ConnectionClosedException('Invalid UMAC'); } } else { - if ($hmac != $this->hmac_check->hash(pack('Na*', $this->get_seq_no, $reconstructed))) { + if (!hash_equals($hmac, $this->hmac_check->hash(pack('Na*', $this->get_seq_no, $reconstructed)))) { $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR); throw new ConnectionClosedException('Invalid HMAC'); } @@ -3722,7 +3751,7 @@ class SSH2 } $padding_length = 0; $payload = $packet->plain; - extract(unpack('Cpadding_length', Strings::shift($payload, 1))); + $padding_length = unpack('Cpadding_length', Strings::shift($payload, 1))['padding_length']; if ($padding_length > 0) { Strings::pop($payload, $padding_length); } @@ -3788,8 +3817,7 @@ class SSH2 $this->key_exchange(); } - // don't filter if we're in the middle of a key exchange (since _filter might send out packets) - return $this->keyExchangeInProgress ? $payload : $this->filter($payload); + return $this->filter($payload); } /** @@ -3809,13 +3837,13 @@ class SSH2 switch ($this->decryptName) { case 'aes128-gcm@openssh.com': case 'aes256-gcm@openssh.com': - extract(unpack('Npacket_length', substr($packet->raw, 0, $packet_length_header_size))); + $packet_length = unpack('Npacket_length', substr($packet->raw, 0, $packet_length_header_size))['packet_length']; $packet->size = $packet_length_header_size + $packet_length + $this->decrypt_block_size; // expect tag break; case 'chacha20-poly1305@openssh.com': $this->lengthDecrypt->setNonce(pack('N2', 0, $this->get_seq_no)); $packet_length_header = $this->lengthDecrypt->decrypt(substr($packet->raw, 0, $packet_length_header_size)); - extract(unpack('Npacket_length', $packet_length_header)); + $packet_length = unpack('Npacket_length', $packet_length_header)['packet_length']; $packet->size = $packet_length_header_size + $packet_length + 16; // expect tag break; default: @@ -3824,17 +3852,17 @@ class SSH2 return; } $packet->plain = $this->decrypt->decrypt(substr($packet->raw, 0, $this->decrypt_block_size)); - extract(unpack('Npacket_length', Strings::shift($packet->plain, $packet_length_header_size))); + $packet_length = unpack('Npacket_length', Strings::shift($packet->plain, $packet_length_header_size))['packet_length']; $packet->size = $packet_length_header_size + $packet_length; $added_validation_length = $packet_length_header_size; } else { - extract(unpack('Npacket_length', substr($packet->raw, 0, $packet_length_header_size))); + $packet_length = unpack('Npacket_length', substr($packet->raw, 0, $packet_length_header_size))['packet_length']; $packet->size = $packet_length_header_size + $packet_length; } break; } } else { - extract(unpack('Npacket_length', substr($packet->raw, 0, $packet_length_header_size))); + $packet_length = unpack('Npacket_length', substr($packet->raw, 0, $packet_length_header_size))['packet_length']; $packet->size = $packet_length_header_size + $packet_length; $added_validation_length = $packet_length_header_size; } @@ -3884,9 +3912,15 @@ class SSH2 */ private function filter($payload) { + if (ord($payload[0]) == NET_SSH2_MSG_DISCONNECT) { + return $this->handleDisconnect($payload); + } + + if ($this->session_id === false && $this->keyExchangeInProgress) { + return $payload; + } + switch (ord($payload[0])) { - case NET_SSH2_MSG_DISCONNECT: - return $this->handleDisconnect($payload); case NET_SSH2_MSG_IGNORE: $payload = $this->get_binary_packet(); break; @@ -3900,7 +3934,7 @@ class SSH2 break; // return payload case NET_SSH2_MSG_KEXINIT: // this is here for server initiated key re-exchanges after the initial key exchange - if ($this->session_id !== false) { + if (!$this->keyExchangeInProgress && $this->session_id !== false) { if (!$this->key_exchange($payload)) { $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); throw new ConnectionClosedException('Key exchange failed'); @@ -3920,6 +3954,26 @@ class SSH2 $payload = $this->get_binary_packet(); } + /* + Once a party has sent a SSH_MSG_KEXINIT message for key exchange or + re-exchange, until it has sent a SSH_MSG_NEWKEYS message (Section + 7.3), it MUST NOT send any messages other than: + + o Transport layer generic messages (1 to 19) (but + SSH_MSG_SERVICE_REQUEST and SSH_MSG_SERVICE_ACCEPT MUST NOT be + sent); + + o Algorithm negotiation messages (20 to 29) (but further + SSH_MSG_KEXINIT messages MUST NOT be sent); + + o Specific key exchange method messages (30 to 49). + + -- https://www.rfc-editor.org/rfc/rfc4253#section-7.1 + */ + if ($this->keyExchangeInProgress) { + return $payload; + } + // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) { Strings::shift($payload, 1); @@ -3932,7 +3986,10 @@ class SSH2 switch (ord($payload[0])) { case NET_SSH2_MSG_CHANNEL_REQUEST: if (strlen($payload) == 31) { - extract(unpack('cpacket_type/Nchannel/Nlength', $payload)); + $unpacked = unpack('cpacket_type/Nchannel/Nlength', $payload); + $packet_type = $unpacked['packet_type']; + $channel = $unpacked['channel']; + $length = $unpacked['length']; if (substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) { if (ord(substr($payload, 9 + $length))) { // want reply $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel])); @@ -3943,9 +4000,11 @@ class SSH2 break; case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4 Strings::shift($payload, 1); - list($request_name) = Strings::unpackSSH2('s', $payload); + list($request_name, $want_reply) = Strings::unpackSSH2('sb', $payload); $this->errors[] = "SSH_MSG_GLOBAL_REQUEST: $request_name"; - $this->send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE)); + if ($want_reply) { + $this->send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE)); + } $payload = $this->get_binary_packet(); break; case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1 @@ -4096,7 +4155,8 @@ class SSH2 protected function get_channel_packet($client_channel, $skip_extended = false) { if (!empty($this->channel_buffers[$client_channel])) { - switch ($this->channel_status[$client_channel]) { + // in phpseclib 4.0 this should be changed to $this->channel_status[$client_channel] ?? null + switch (isset($this->channel_status[$client_channel]) ? $this->channel_status[$client_channel] : null) { case NET_SSH2_MSG_CHANNEL_REQUEST: foreach ($this->channel_buffers[$client_channel] as $i => $packet) { switch (ord($packet[0])) { @@ -4164,7 +4224,7 @@ class SSH2 continue 2; case NET_SSH2_MSG_CHANNEL_REQUEST: - if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) { + if (!isset($this->channel_status[$channel])) { continue 2; } list($value) = Strings::unpackSSH2('s', $response); @@ -4181,12 +4241,14 @@ class SSH2 if (strlen($error_message)) { $this->errors[count($this->errors) - 1] .= "\r\n$error_message"; } + if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_CLOSE) { + if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) { + $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$channel])); + } + $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); - - $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF; - + $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE; + } continue 3; case 'exit-status': list(, $this->exit_status) = Strings::unpackSSH2('CN', $response); @@ -4196,8 +4258,13 @@ class SSH2 continue 3; default: - // "Some systems may not implement signals, in which case they SHOULD ignore this message." - // -- http://tools.ietf.org/html/rfc4254#section-6.9 + list($want_reply) = Strings::unpackSSH2('b', $response); + if ($want_reply) { + // "If the request is not recognized or is not supported for the channel, + // SSH_MSG_CHANNEL_FAILURE is returned." + // -- https://datatracker.ietf.org/doc/html/rfc4254#page-10 + $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_FAILURE, $this->server_channels[$channel])); + } continue 3; } } @@ -4286,11 +4353,11 @@ class SSH2 $this->close_channel_bitmap($channel); - if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) { + if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_CLOSE) { $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); } - $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE; + unset($this->channel_status[$channel]); $this->channelCount--; if ($client_channel == $channel) { @@ -4515,7 +4582,7 @@ class SSH2 protected function append_log_helper($constant, $message_number, $message, array &$message_number_log, array &$message_log, &$log_size, &$realtime_log_file, &$realtime_log_wrap, &$realtime_log_size) { // remove the byte identifying the message type from all but the first two messages (ie. the identification strings) - if (strlen($message_number) > 2) { + if (!in_array(substr($message_number, 0, 4), ['<- (', '-> (']) && strlen($message_number) > 2) { Strings::shift($message); } @@ -4655,27 +4722,24 @@ class SSH2 * @param bool $want_reply * @return void */ - private function close_channel($client_channel, $want_reply = false) + protected function close_channel($client_channel) { // see http://tools.ietf.org/html/rfc4254#section-5.3 - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - - if (!$want_reply) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); + if ($this->channel_status[$client_channel] != NET_SSH2_MSG_CHANNEL_EOF) { + $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); } + $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; + $this->channelCount--; $this->curTimeout = 5; - while (!is_bool($this->get_channel_packet($client_channel))) { } - if ($want_reply) { - $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); - } + unset($this->channel_status[$client_channel]); $this->close_channel_bitmap($client_channel); } @@ -4849,6 +4913,7 @@ class SSH2 * If you are looking for messages from the SFTP layer, please see SFTP::getSFTPErrors() * * @return string[] + * @removed in phpseclib 4.0.0 */ public function getErrors() { @@ -4861,6 +4926,7 @@ class SSH2 * If you are looking for messages from the SFTP layer, please see SFTP::getLastSFTPError() * * @return string + * @removed in phpseclib 4.0.0 */ public function getLastError() { diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php b/Web/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php index 376d77b..7defe8e 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php @@ -35,7 +35,6 @@ namespace phpseclib3\System\SSH; use phpseclib3\Common\Functions\Strings; use phpseclib3\Crypt\Common\PublicKey; use phpseclib3\Crypt\PublicKeyLoader; -use phpseclib3\Crypt\RSA; use phpseclib3\Exception\BadConfigurationException; use phpseclib3\Net\SSH2; use phpseclib3\System\SSH\Agent\Identity; diff --git a/Web/vendor/phpseclib/phpseclib/phpseclib/openssl.cnf b/Web/vendor/phpseclib/phpseclib/phpseclib/openssl.cnf index 2b8b52f..6a5c0f5 100644 --- a/Web/vendor/phpseclib/phpseclib/phpseclib/openssl.cnf +++ b/Web/vendor/phpseclib/phpseclib/phpseclib/openssl.cnf @@ -2,5 +2,8 @@ HOME = . RANDFILE = $ENV::HOME/.rnd +# without this line you'll get this error with openssl_pkey_new(): +# Warning: openssl_pkey_new(): Private key length must be at least 384 bits, configured to 0 +default_bits = 384 [ v3_ca ]