From ad7a7d5c8f0288d7d30af2120987d7574bf202d6 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Fri, 10 Feb 2023 12:20:12 -0600 Subject: [PATCH 1/7] fix PHP <5.4 compatability --- phpseclib/Net/SFTP.php | 2 +- phpseclib/Net/SSH2.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index cdccd60e..ea5fb083 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -923,7 +923,7 @@ class SFTP extends SSH2 } $parts = explode('/', $path); - $afterPWD = $beforePWD = []; + $afterPWD = $beforePWD = array(); foreach ($parts as $part) { switch ($part) { //case '': // some SFTP servers /require/ double /'s. see https://github.com/phpseclib/phpseclib/pull/1137 diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 03b50f62..4ae74fc4 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -2745,7 +2745,7 @@ class SSH2 $publickey['n'] ); - $algos = ['rsa-sha2-256', 'rsa-sha2-512', 'ssh-rsa']; + $algos = array('rsa-sha2-256', 'rsa-sha2-512', 'ssh-rsa'); if (isset($this->preferred['hostkey'])) { $algos = array_intersect($this->preferred['hostkey'], $algos); } From 8e8b214820a98d6cb86705057a7093629583ec35 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Fri, 10 Feb 2023 13:26:59 -0600 Subject: [PATCH 2/7] use github actions instead of travis ci --- .github/workflows/ci.yml | 76 +++++++++++++++++++++++++ .travis.yml | 39 ------------- tests/make_compatible_with_phpunit9.php | 35 ++++++++++++ 3 files changed, 111 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml create mode 100644 tests/make_compatible_with_phpunit9.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..b55a1595 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,76 @@ +name: CI +on: [push, pull_request] + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + lint: + name: Lint + timeout-minutes: 5 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + tools: php-parallel-lint/php-parallel-lint:1 + - name: Lint + run: parallel-lint --show-deprecated build phpseclib tests + strategy: + fail-fast: false + matrix: + php-version: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + tests: + name: Tests + timeout-minutes: 10 + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + - name: Composer Install + run: composer install --no-interaction --no-cache + - name: Make Tests Compatiable With PHPUnit 9+ + if: contains(fromJSON('["7.3", "7.4", "8.0", "8.1", "8.2"]'), matrix.php-version) + run: php tests/make_compatible_with_phpunit9.php + - name: Setup Secure Shell Functional Tests + if: matrix.os == 'ubuntu-latest' + run: | + PHPSECLIB_SSH_USERNAME='phpseclib' + PHPSECLIB_SSH_PASSWORD='EePoov8po1aethu2kied1ne0' + + sudo useradd --create-home --base-dir /home "$PHPSECLIB_SSH_USERNAME" + echo "$PHPSECLIB_SSH_USERNAME:$PHPSECLIB_SSH_PASSWORD" | sudo chpasswd + ssh-keygen -t rsa -b 1024 -f "$HOME/.ssh/id_rsa" -q -N "" + eval `ssh-agent -s` + ssh-add "$HOME/.ssh/id_rsa" + sudo mkdir -p "/home/$PHPSECLIB_SSH_USERNAME/.ssh/" + sudo cp "$HOME/.ssh/id_rsa.pub" "/home/$PHPSECLIB_SSH_USERNAME/.ssh/authorized_keys" + sudo ssh-keyscan -t rsa localhost > "/tmp/known_hosts" + sudo cp "/tmp/known_hosts" "/home/$PHPSECLIB_SSH_USERNAME/.ssh/known_hosts" + sudo chown "$PHPSECLIB_SSH_USERNAME:$PHPSECLIB_SSH_USERNAME" "/home/$PHPSECLIB_SSH_USERNAME/.ssh/" -R + + echo "PHPSECLIB_SSH_HOSTNAME=localhost" >> $GITHUB_ENV + echo "PHPSECLIB_SSH_USERNAME=$PHPSECLIB_SSH_USERNAME" >> $GITHUB_ENV + echo "PHPSECLIB_SSH_PASSWORD=$PHPSECLIB_SSH_PASSWORD" >> $GITHUB_ENV + echo "PHPSECLIB_SSH_HOME=/home/phpseclib" >> $GITHUB_ENV + echo "SSH_AUTH_SOCK=$SSH_AUTH_SOCK" >> $GITHUB_ENV + - name: PHPUnit + run: vendor/bin/phpunit + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + php-version: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + exclude: + # PHP 5.3 / 5.4 on windows don't have openssl or curl installed, which prevents composer from running + - os: windows-latest + php-version: '5.3' + - os: windows-latest + php-version: '5.4' \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b32fc3d8..00000000 --- a/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -language: php - -matrix: - include: - - php: 5.4 - dist: trusty - - php: 5.5.9 - dist: trusty - - php: 5.5 - dist: trusty - - php: 5.6 - dist: xenial - - php: 7.0 - dist: xenial - - php: 7.1 - dist: xenial - - php: 7.2 - dist: xenial - - php: 7.3 - dist: xenial - - php: 7.4 - dist: xenial - - php: 8.0 - dist: bionic - - php: 8.1 - dist: bionic - -before_install: true - -install: - - phpenv config-rm xdebug.ini - - eval `ssh-agent -s` - - travis/setup-secure-shell.sh - - sh -c "if [ '$TRAVIS_PHP_VERSION' != 'hhvm' -a `php -r "echo (int) version_compare(PHP_VERSION, '7.0', '<');"` = "1" ]; then travis/install-php-extensions.sh; fi" - - travis/setup-composer.sh - -script: - - sh -c "if [ '$TRAVIS_PHP_VERSION' = '5.5' ]; then vendor/bin/phing -f build/build.xml sniff; fi" - - travis/run-phpunit.sh diff --git a/tests/make_compatible_with_phpunit9.php b/tests/make_compatible_with_phpunit9.php new file mode 100644 index 00000000..651e5086 --- /dev/null +++ b/tests/make_compatible_with_phpunit9.php @@ -0,0 +1,35 @@ + $files */ +$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__)); +foreach ($files as $file) { + if ($file->getExtension() === 'php' && $file->getPathname() !== __FILE__) { + $fileContents = file_get_contents($file->getPathname()); + if ($fileContents === false) { + throw new \RuntimeException('file_get_contents() failed: ' . $file->getPathname()); + } + $patternToReplacementMap = array( + '~n setUpBeforeClass\(\)~' => 'n setUpBeforeClass(): void', + '~n setUp\(\)~' => 'n setUp(): void', + '~n tearDown\(\)~' => 'n tearDown(): void', + '~(n assertIsArray\([^\)]*\))~' => '$1: void', + '~(n assertIsString\([^\)]*\))~' => '$1: void', + '~(n assertStringContainsString\([^\)]*\))~' => '$1: void', + '~(n assertStringNotContainsString\([^\)]*\))~' => '$1: void', + '~^class Unit_Crypt_(AES|Hash|RSA)_~m' => 'class ', + '~^class Unit_File_X509_~m' => 'class ', + '~^class Unit_Math_BigInteger_~m' => 'class ', + '~^class Unit_(Crypt|File|Math|Net)_~m' => 'class ', + '~^class Functional_Net__~m' => 'class ', + '~extends Unit_Crypt_Hash_(SHA512Test|SHA256Test)~' => 'extends $1' + ); + $updatedFileContents = preg_replace( + array_keys($patternToReplacementMap), + array_values($patternToReplacementMap), + $fileContents + ); + if (file_put_contents($file->getPathname(), $updatedFileContents) === false) { + throw new \RuntimeException('file_put_contents() failed: ' . $file->getPathname()); + } + } +} From 50ab21b7cb20786a1eee5726f8a87840cb0004c7 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sat, 11 Feb 2023 14:55:25 -0600 Subject: [PATCH 3/7] Crypt: don't do OpenSSL version check unless OpenSSL is installed --- phpseclib/Crypt/Blowfish.php | 2 +- phpseclib/Crypt/DES.php | 2 +- phpseclib/Crypt/RC2.php | 2 +- phpseclib/Crypt/RC4.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpseclib/Crypt/Blowfish.php b/phpseclib/Crypt/Blowfish.php index 94552f94..567e37c0 100644 --- a/phpseclib/Crypt/Blowfish.php +++ b/phpseclib/Crypt/Blowfish.php @@ -445,7 +445,7 @@ class Blowfish extends Base // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { + if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { return false; } if (version_compare(PHP_VERSION, '5.3.7') < 0 && $this->key_length != 16) { diff --git a/phpseclib/Crypt/DES.php b/phpseclib/Crypt/DES.php index d9244b51..26bd385f 100644 --- a/phpseclib/Crypt/DES.php +++ b/phpseclib/Crypt/DES.php @@ -595,7 +595,7 @@ class DES extends Base // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { + if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { return false; } $this->cipher_name_openssl_ecb = 'des-ecb'; diff --git a/phpseclib/Crypt/RC2.php b/phpseclib/Crypt/RC2.php index 72a15d35..e0511b32 100644 --- a/phpseclib/Crypt/RC2.php +++ b/phpseclib/Crypt/RC2.php @@ -276,7 +276,7 @@ class RC2 extends Base // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { + if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { return false; } if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) { diff --git a/phpseclib/Crypt/RC4.php b/phpseclib/Crypt/RC4.php index 195d97ee..2e5c0556 100644 --- a/phpseclib/Crypt/RC4.php +++ b/phpseclib/Crypt/RC4.php @@ -148,7 +148,7 @@ class RC4 extends Base // quoting https://www.openssl.org/news/openssl-3.0-notes.html, OpenSSL 3.0.1 // "Moved all variations of the EVP ciphers CAST5, BF, IDEA, SEED, RC2, RC4, RC5, and DES to the legacy provider" // in theory openssl_get_cipher_methods() should catch this but, on GitHub Actions, at least, it does not - if (version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { + if (defined('OPENSSL_VERSION_TEXT') && version_compare(preg_replace('#OpenSSL (\d+\.\d+\.\d+) .*#', '$1', OPENSSL_VERSION_TEXT), '3.0.1', '>=')) { return false; } if (version_compare(PHP_VERSION, '5.3.7') >= 0) { From e3b9a97200c2312ad8ce113197583f0c50183121 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sat, 11 Feb 2023 17:47:40 -0600 Subject: [PATCH 4/7] Blowfish: fix issues on 32-bit PHP installs --- phpseclib/Crypt/Blowfish.php | 78 +++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/phpseclib/Crypt/Blowfish.php b/phpseclib/Crypt/Blowfish.php index 567e37c0..f44871ee 100644 --- a/phpseclib/Crypt/Blowfish.php +++ b/phpseclib/Crypt/Blowfish.php @@ -762,9 +762,13 @@ class Blowfish extends Base $l = $in[1]; $r = $in[2]; - list($r, $l) = CRYPT_BASE_USE_REG_INTVAL ? - $this->_encryptBlockHelperFast($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p) : - $this->_encryptBlockHelperSlow($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p); + if (CRYPT_BASE_USE_REG_INTVAL) { + list($r, $l) = PHP_INT_SIZE === 8 ? + $this->_encryptBlockHelperFast($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p) : + $this->_encryptBlockHelperFast32($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p); + } else { + list($r, $l) = $this->_encryptBlockHelperSlow($l, $r, $sb_0, $sb_1, $sb_2, $sb_3, $p); + } return pack("N*", $r, $l); } @@ -805,6 +809,42 @@ class Blowfish extends Base return array($x1 & 0xFFFFFFFF ^ $p[17], $x0 & 0xFFFFFFFF); } + /** + * Fast helper function for block encryption (32-bit) + * + * @access private + * @param int $x0 + * @param int $x1 + * @param int[] $sbox0 + * @param int[] $sbox1 + * @param int[] $sbox2 + * @param int[] $sbox3 + * @param int[] $p + * @return int[] + */ + function _encryptBlockHelperFast32($x0, $x1, $sbox0, $sbox1, $sbox2, $sbox3, $p) + { + $x0 ^= $p[0]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14]; + $x1 ^= ((($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15]; + $x0 ^= ((($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16]; + + return array($x1 & 0xFFFFFFFF ^ $p[17], $x0 & 0xFFFFFFFF); + } + /** * Slow helper function for block encryption * @@ -821,22 +861,22 @@ class Blowfish extends Base function _encryptBlockHelperSlow($x0, $x1, $sbox0, $sbox1, $sbox2, $sbox3, $p) { $x0^= $p[0]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14]; - $x1^= $this->safe_intval(($this->safe_intval($sbox0[($x0 & 0xFF000000) >> 24] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15]; - $x0^= $this->safe_intval(($this->safe_intval($sbox0[($x1 & 0xFF000000) >> 24] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[1]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[2]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[3]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[4]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[5]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[6]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[7]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[8]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[9]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[10]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[11]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[12]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[13]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[14]; + $x1^= $this->safe_intval(($this->safe_intval($sbox0[(($x0 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x0 & 0xFF0000) >> 16]) ^ $sbox2[($x0 & 0xFF00) >> 8]) + $sbox3[$x0 & 0xFF]) ^ $p[15]; + $x0^= $this->safe_intval(($this->safe_intval($sbox0[(($x1 & 0xFF000000) >> 24) & 0xFF] + $sbox1[($x1 & 0xFF0000) >> 16]) ^ $sbox2[($x1 & 0xFF00) >> 8]) + $sbox3[$x1 & 0xFF]) ^ $p[16]; return array($x1 & 0xFFFFFFFF ^ $p[17], $x0 & 0xFFFFFFFF); } From 233f617e084a507e762bd0be88628aa455017685 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sat, 11 Feb 2023 17:56:02 -0600 Subject: [PATCH 5/7] Tests: don't test encrypted OpenSSH private keys on 32-bit installs --- tests/Unit/Crypt/RSA/LoadKeyTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Unit/Crypt/RSA/LoadKeyTest.php b/tests/Unit/Crypt/RSA/LoadKeyTest.php index 8ef39ad2..24b5af29 100644 --- a/tests/Unit/Crypt/RSA/LoadKeyTest.php +++ b/tests/Unit/Crypt/RSA/LoadKeyTest.php @@ -633,6 +633,10 @@ Private-MAC: d26baf87446604974287b682ed9e0c00ce54e460e1cb719953a81291147b3c59 public function testOpenSSHEncrypted() { + if (PHP_INT_SIZE === 4) { + self::markTestSkipped('bcrypt is far too slow to be practical on 32-bit versions of PHP'); + } + $key = '-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBN2Ff3Kw SIOWyzRiboPRIhAAAAEAAAAAEAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQCpxMxDEG0S From de80c6a955eb8a419a6843417f316d3a81b7a0e4 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sat, 11 Feb 2023 18:28:57 -0600 Subject: [PATCH 6/7] Tests: hex numbers with new lines in them should have own test --- tests/Unit/Crypt/RSA/ModeTest.php | 14 +++++++------- tests/Unit/Math/BigInteger/TestCase.php | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/tests/Unit/Crypt/RSA/ModeTest.php b/tests/Unit/Crypt/RSA/ModeTest.php index 43ad398d..28d00733 100644 --- a/tests/Unit/Crypt/RSA/ModeTest.php +++ b/tests/Unit/Crypt/RSA/ModeTest.php @@ -121,13 +121,13 @@ k12yS6pCS3c+1wZ9cYFVtgfpSL4XpylLe9EnRT2GRVYCqUkR4AUeTuvnAgMBAAE= { $rsa = new RSA(); $rsa->loadKey(array( - 'n' => new BigInteger('0xE932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD -4C2BE0F9FA6E49C605ADF77B5174230AF7BD50E5D6D6D6D28CCF0A886A514CC72E51D209CC7 -72A52EF419F6A953F3135929588EBE9B351FCA61CED78F346FE00DBB6306E5C2A4C6DFC3779 -AF85AB417371CF34D8387B9B30AE46D7A5FF5A655B8D8455F1B94AE736989D60A6F2FD5CADB -FFBD504C5A756A2E6BB5CECC13BCA7503F6DF8B52ACE5C410997E98809DB4DC30D943DE4E81 -2A47553DCE54844A78E36401D13F77DC650619FED88D8B3926E3D8E319C80C744779AC5D6AB -E252896950917476ECE5E8FC27D5F053D6018D91B502C4787558A002B9283DA7', 16), + 'n' => new BigInteger('0xE932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD' . + '4C2BE0F9FA6E49C605ADF77B5174230AF7BD50E5D6D6D6D28CCF0A886A514CC72E51D209CC7' . + '72A52EF419F6A953F3135929588EBE9B351FCA61CED78F346FE00DBB6306E5C2A4C6DFC3779' . + 'AF85AB417371CF34D8387B9B30AE46D7A5FF5A655B8D8455F1B94AE736989D60A6F2FD5CADB' . + 'FFBD504C5A756A2E6BB5CECC13BCA7503F6DF8B52ACE5C410997E98809DB4DC30D943DE4E81' . + '2A47553DCE54844A78E36401D13F77DC650619FED88D8B3926E3D8E319C80C744779AC5D6AB' . + 'E252896950917476ECE5E8FC27D5F053D6018D91B502C4787558A002B9283DA7', 16), 'e' => new BigInteger('3') )); diff --git a/tests/Unit/Math/BigInteger/TestCase.php b/tests/Unit/Math/BigInteger/TestCase.php index 5c17c15e..fb7fbbeb 100644 --- a/tests/Unit/Math/BigInteger/TestCase.php +++ b/tests/Unit/Math/BigInteger/TestCase.php @@ -448,4 +448,18 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase $this->assertSame(0, $x->compare($x2)); } } + + public function testHexWithNewLines() + { + $x = $this->getInstance('0xE932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD +4C2BE0F9FA6E49C605ADF77B5174230AF7BD50E5D6D6D6D28CCF0A886A514CC72E51D209CC7 +72A52EF419F6A953F3135929588EBE9B351FCA61CED78F346FE00DBB6306E5C2A4C6DFC3779 +AF85AB417371CF34D8387B9B30AE46D7A5FF5A655B8D8455F1B94AE736989D60A6F2FD5CADB +FFBD504C5A756A2E6BB5CECC13BCA7503F6DF8B52ACE5C410997E98809DB4DC30D943DE4E81 +2A47553DCE54844A78E36401D13F77DC650619FED88D8B3926E3D8E319C80C744779AC5D6AB +E252896950917476ECE5E8FC27D5F053D6018D91B502C4787558A002B9283DA7', 16); + + $y = $this->getInstance('0xE932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD'); + $this->assertSame($x, $y); + } } From e42185c6727f35c816d356fd1d107f73b88a3b84 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sat, 11 Feb 2023 18:31:58 -0600 Subject: [PATCH 7/7] BigInteger: fix for hex numbers with new lines in them --- phpseclib/Math/BigInteger.php | 6 +++--- tests/Unit/Math/BigInteger/TestCase.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpseclib/Math/BigInteger.php b/phpseclib/Math/BigInteger.php index 8d1291db..81b69ace 100644 --- a/phpseclib/Math/BigInteger.php +++ b/phpseclib/Math/BigInteger.php @@ -408,7 +408,7 @@ class BigInteger $x = substr($x, 1); } - $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x); + $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#s', '$1', $x); $is_negative = false; if ($base < 0 && hexdec($x[0]) >= 8) { @@ -444,7 +444,7 @@ class BigInteger // (?getInstance('0xE932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD'); - $this->assertSame($x, $y); + $y = $this->getInstance('0xE932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD', 16); + $this->assertSame("$x", "$y"); } }