mirror of
https://github.com/michalcz10/USB-RAID-Array.git
synced 2026-11-11 07:59:04 +00:00
Bump phpseclib
This commit is contained in:
Generated
+10
-10
@@ -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"
|
||||
}
|
||||
|
||||
Vendored
+1
-4
@@ -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';
|
||||
|
||||
+41
-4
@@ -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<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|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<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $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;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
@@ -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.
|
||||
|
||||
|
||||
Vendored
+7
-7
@@ -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": [
|
||||
{
|
||||
|
||||
Vendored
+9
-9
@@ -1,9 +1,9 @@
|
||||
<?php return array(
|
||||
'root' => 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(),
|
||||
|
||||
+2
-3
@@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
+3
@@ -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
|
||||
@@ -17,3 +18,5 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
|
||||
- [Anna Filina](https://github.com/afilina)
|
||||
- [blakemckeeby](https://github.com/blakemckeeby)
|
||||
- [ssddanbrown](https://github.com/ssddanbrown)
|
||||
- Stefan Beck
|
||||
- [Greg Mayes](https://github.com/GregMayes)
|
||||
+23
-3
@@ -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!:
|
||||
<p align="left">
|
||||
<a target="_blank" href="https://www.sovereign.tech/tech/phpseclib">
|
||||
<img src="https://phpseclib.com/img/sponsors/sovereign-tech-agency.webp" alt="Sovereign Tech Agency" style="width: 200px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Additional Thanks
|
||||
|
||||
- [HeroDevs](https://www.herodevs.com/sustainability-fund)
|
||||
- Allan Simon
|
||||
- [Anna Filina](https://afilina.com/)
|
||||
- delovelady
|
||||
- [ChargeOver](https://chargeover.com/)
|
||||
- <a href="https://jb.gg/OpenSource"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" height="20px"></a>
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
+13
@@ -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.
|
||||
@@ -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;
|
||||
|
||||
+1
-1
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
+328
-328
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
+1
-1
@@ -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]);
|
||||
|
||||
+18
-8
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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})");
|
||||
}
|
||||
|
||||
|
||||
+35
-35
@@ -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]];
|
||||
|
||||
+53
-9
@@ -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";
|
||||
|
||||
+44
-28
@@ -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
|
||||
*
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+229
-81
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -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)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+1
-1
@@ -171,7 +171,7 @@ class TwistedEdwards extends Base
|
||||
/**
|
||||
* Returns the affine point
|
||||
*
|
||||
* @return PrimeField\Integer[]
|
||||
* @return PrimeInteger[]
|
||||
*/
|
||||
public function convertToAffine(array $p)
|
||||
{
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
+8
-6
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -71,6 +71,10 @@ abstract class XML
|
||||
|
||||
$use_errors = libxml_use_internal_errors(true);
|
||||
|
||||
if (substr($key, 0, 5) != '<?xml') {
|
||||
$key = '<xml>' . $key . '</xml>';
|
||||
}
|
||||
|
||||
$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) != '<?xml') {
|
||||
$key = '<xml>' . $key . '</xml>';
|
||||
}
|
||||
|
||||
if (!$dom->loadXML($key)) {
|
||||
libxml_use_internal_errors($use_errors);
|
||||
|
||||
+103
-21
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+107
-7
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+14
-14
@@ -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()
|
||||
{
|
||||
|
||||
+8
-8
@@ -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()
|
||||
{
|
||||
|
||||
+319
-76
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-13
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'])) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
+31
-21
@@ -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 <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (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 ) ^
|
||||
|
||||
@@ -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);
|
||||
|
||||
+20
-20
@@ -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)
|
||||
|
||||
+10
-10
@@ -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()
|
||||
{
|
||||
|
||||
+113
-15
@@ -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)
|
||||
{
|
||||
|
||||
+138
-27
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+46
-11
@@ -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)
|
||||
|
||||
+18
-13
@@ -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;
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
Vendored
+20
-18
@@ -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;
|
||||
|
||||
Vendored
+9
-9
@@ -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;';
|
||||
|
||||
+50
-18
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Vendored
+3
-1
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Pure-PHP implementation of SCP.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
|
||||
*
|
||||
* Here's a short example of how to use this library:
|
||||
* <code>
|
||||
* <?php
|
||||
* include 'vendor/autoload.php';
|
||||
*
|
||||
* $scp = new \phpseclib3\Net\SCP('www.domain.tld');
|
||||
* if (!$scp->login('username', 'password')) {
|
||||
* exit('Login Failed');
|
||||
* }
|
||||
*
|
||||
* echo $scp->exec('pwd') . "\r\n";
|
||||
* $scp->put('filename.ext', 'hello, world!');
|
||||
* echo $scp->exec('ls -latr');
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @author Jim Wigginton <terrafrost@php.net>
|
||||
* @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 <terrafrost@php.net>
|
||||
*/
|
||||
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('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', 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] : '';
|
||||
}
|
||||
}
|
||||
+241
-13
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'];
|
||||
}
|
||||
|
||||
+117
-51
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ]
|
||||
|
||||
Reference in New Issue
Block a user