mirror of
https://github.com/michalcz10/USB-RAID-Array.git
synced 2026-11-12 08:29:03 +00:00
Bump phpseclib
This commit is contained in:
Generated
+10
-10
@@ -125,16 +125,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpseclib/phpseclib",
|
"name": "phpseclib/phpseclib",
|
||||||
"version": "3.0.43",
|
"version": "3.0.57",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||||
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02"
|
"reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02",
|
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
|
||||||
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02",
|
"reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -215,7 +215,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
"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": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -231,16 +231,16 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-12-14T21:12:59+00:00"
|
"time": "2026-08-26T12:13:21+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": [],
|
"stability-flags": {},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": {},
|
||||||
"platform-dev": [],
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.9.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-4
@@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) {
|
|||||||
echo $err;
|
echo $err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trigger_error(
|
throw new RuntimeException($err);
|
||||||
$err,
|
|
||||||
E_USER_ERROR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once __DIR__ . '/composer/autoload_real.php';
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|||||||
+41
-4
@@ -26,12 +26,23 @@ use Composer\Semver\VersionParser;
|
|||||||
*/
|
*/
|
||||||
class InstalledVersions
|
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
|
* @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
|
* @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;
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private static $installedIsLocalDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool|null
|
* @var bool|null
|
||||||
*/
|
*/
|
||||||
@@ -309,6 +320,24 @@ class InstalledVersions
|
|||||||
{
|
{
|
||||||
self::$installed = $data;
|
self::$installed = $data;
|
||||||
self::$installedByVendor = array();
|
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();
|
$installed = array();
|
||||||
|
$copiedLocalDir = false;
|
||||||
|
|
||||||
if (self::$canGetVendors) {
|
if (self::$canGetVendors) {
|
||||||
|
$selfDir = self::getSelfDir();
|
||||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
$installed[] = self::$installedByVendor[$vendorDir];
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
} 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 */
|
/** @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';
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
self::$installedByVendor[$vendorDir] = $required;
|
||||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
$installed[] = $required;
|
||||||
self::$installed = $installed[count($installed) - 1];
|
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;
|
$installed[] = self::$installed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
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,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -11,22 +11,22 @@ class ComposerStaticInita702940bbf24a822224611db5c22942b
|
|||||||
);
|
);
|
||||||
|
|
||||||
public static $prefixLengthsPsr4 = array (
|
public static $prefixLengthsPsr4 = array (
|
||||||
'p' =>
|
'p' =>
|
||||||
array (
|
array (
|
||||||
'phpseclib3\\' => 11,
|
'phpseclib3\\' => 11,
|
||||||
),
|
),
|
||||||
'P' =>
|
'P' =>
|
||||||
array (
|
array (
|
||||||
'ParagonIE\\ConstantTime\\' => 23,
|
'ParagonIE\\ConstantTime\\' => 23,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $prefixDirsPsr4 = array (
|
public static $prefixDirsPsr4 = array (
|
||||||
'phpseclib3\\' =>
|
'phpseclib3\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
|
0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
|
||||||
),
|
),
|
||||||
'ParagonIE\\ConstantTime\\' =>
|
'ParagonIE\\ConstantTime\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
|
0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
|
||||||
),
|
),
|
||||||
|
|||||||
Vendored
+7
-7
@@ -125,17 +125,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpseclib/phpseclib",
|
"name": "phpseclib/phpseclib",
|
||||||
"version": "3.0.43",
|
"version": "3.0.57",
|
||||||
"version_normalized": "3.0.43.0",
|
"version_normalized": "3.0.57.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||||
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02"
|
"reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02",
|
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
|
||||||
"reference": "709ec107af3cb2f385b9617be72af8cf62441d02",
|
"reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
"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."
|
"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",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/phpseclib/phpseclib/issues",
|
"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": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|||||||
Vendored
+9
-9
@@ -1,9 +1,9 @@
|
|||||||
<?php return array(
|
<?php return array(
|
||||||
'root' => array(
|
'root' => array(
|
||||||
'name' => '__root__',
|
'name' => '__root__',
|
||||||
'pretty_version' => '1.0.0+no-version-set',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '1.0.0.0',
|
'version' => 'dev-main',
|
||||||
'reference' => null,
|
'reference' => '6f6e2e6c92dba1cabd61ab6e3dd0c13ae52f161a',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
),
|
),
|
||||||
'versions' => array(
|
'versions' => array(
|
||||||
'__root__' => array(
|
'__root__' => array(
|
||||||
'pretty_version' => '1.0.0+no-version-set',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => '1.0.0.0',
|
'version' => 'dev-main',
|
||||||
'reference' => null,
|
'reference' => '6f6e2e6c92dba1cabd61ab6e3dd0c13ae52f161a',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@@ -38,9 +38,9 @@
|
|||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'phpseclib/phpseclib' => array(
|
'phpseclib/phpseclib' => array(
|
||||||
'pretty_version' => '3.0.43',
|
'pretty_version' => '3.0.57',
|
||||||
'version' => '3.0.43.0',
|
'version' => '3.0.57.0',
|
||||||
'reference' => '709ec107af3cb2f385b9617be72af8cf62441d02',
|
'reference' => 'd17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
|
'install_path' => __DIR__ . '/../phpseclib/phpseclib',
|
||||||
'aliases' => array(),
|
'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;
|
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(
|
throw new \RuntimeException(
|
||||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
'Composer detected issues in your platform: ' . implode(' ', $issues)
|
||||||
E_USER_ERROR
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -4,6 +4,7 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
|
|||||||
|
|
||||||
## Backers
|
## Backers
|
||||||
|
|
||||||
|
- [HeroDevs](https://www.herodevs.com/sustainability-fund)
|
||||||
- Allan Simon
|
- Allan Simon
|
||||||
- [ChargeOver](https://chargeover.com/)
|
- [ChargeOver](https://chargeover.com/)
|
||||||
- Raghu Veer Dendukuri
|
- Raghu Veer Dendukuri
|
||||||
@@ -16,4 +17,6 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
|
|||||||
- [istiak-tridip](https://github.com/istiak-tridip)
|
- [istiak-tridip](https://github.com/istiak-tridip)
|
||||||
- [Anna Filina](https://github.com/afilina)
|
- [Anna Filina](https://github.com/afilina)
|
||||||
- [blakemckeeby](https://github.com/blakemckeeby)
|
- [blakemckeeby](https://github.com/blakemckeeby)
|
||||||
- [ssddanbrown](https://github.com/ssddanbrown)
|
- [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
|
* Unstable API
|
||||||
* Do not use in production
|
* 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
|
### 3.0
|
||||||
|
|
||||||
* Long term support (LTS) release
|
* Long term support (LTS) release
|
||||||
@@ -51,7 +62,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
|
|||||||
* PHP4 compatible
|
* PHP4 compatible
|
||||||
* Composer compatible (PSR-0 autoloading)
|
* Composer compatible (PSR-0 autoloading)
|
||||||
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
|
* 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
|
## Security contact information
|
||||||
|
|
||||||
@@ -63,14 +74,23 @@ Need Support?
|
|||||||
|
|
||||||
* [Checkout Questions and Answers on Stack Overflow](http://stackoverflow.com/questions/tagged/phpseclib)
|
* [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)
|
* [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
|
||||||
|
|
||||||
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
|
- Allan Simon
|
||||||
|
- [Anna Filina](https://afilina.com/)
|
||||||
|
- delovelady
|
||||||
- [ChargeOver](https://chargeover.com/)
|
- [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
|
## 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
|
// 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
|
// 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
|
// 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 = $upper ? 4294967296 * $upper : 0;
|
||||||
$temp += $lower < 0 ? ($lower & 0x7FFFFFFFF) + 0x80000000 : $lower;
|
$temp += $lower < 0 ? ($lower & 0x7FFFFFFFF) + 0x80000000 : $lower;
|
||||||
// $temp = hexdec(bin2hex(self::shift($data, 8)));
|
// $temp = hexdec(bin2hex(self::shift($data, 8)));
|
||||||
@@ -354,9 +356,11 @@ abstract class Strings
|
|||||||
// from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
|
// from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
|
||||||
$p1 = ($b * 0x0802) & 0x22110;
|
$p1 = ($b * 0x0802) & 0x22110;
|
||||||
$p2 = ($b * 0x8020) & 0x88440;
|
$p2 = ($b * 0x8020) & 0x88440;
|
||||||
$r .= chr(
|
$temp = ($p1 | $p2) * 0x10101;
|
||||||
(($p1 | $p2) * 0x10101) >> 16
|
if (is_float($temp)) {
|
||||||
);
|
$temp = (int) fmod($temp, 0x7FFFFFFF);
|
||||||
|
}
|
||||||
|
$r .= chr(($temp >> 16) & 0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $r;
|
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.
|
* 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
|
* @param int $length
|
||||||
* @throws \BadMethodCallException anytime it's called
|
* @throws \BadMethodCallException anytime it's called
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class Blowfish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Block Length of the cipher
|
* Block Length of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
|
* @see Common\SymmetricKey::block_size
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $block_size = 8;
|
protected $block_size = 8;
|
||||||
@@ -137,7 +137,7 @@ class Blowfish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
|
* @see Common\SymmetricKey::cipher_name_mcrypt
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $cipher_name_mcrypt = 'blowfish';
|
protected $cipher_name_mcrypt = 'blowfish';
|
||||||
@@ -145,7 +145,7 @@ class Blowfish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Optimizing value while CFB-encrypting
|
* Optimizing value while CFB-encrypting
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
|
* @see Common\SymmetricKey::cfb_init_len
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $cfb_init_len = 500;
|
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
|
* 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.}
|
* of that, we'll just precompute it once.}
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength()
|
* @see Common\SymmetricKey::setKeyLength()
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $key_length = 16;
|
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()
|
* 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
|
* @param int $engine
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -394,7 +394,7 @@ class Blowfish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the key (expansion)
|
* Setup the key (expansion)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
|
* @see Common\SymmetricKey::_setupKey()
|
||||||
*/
|
*/
|
||||||
protected function setupKey()
|
protected function setupKey()
|
||||||
{
|
{
|
||||||
@@ -448,8 +448,8 @@ class Blowfish extends BlockCipher
|
|||||||
protected static function initialize_static_variables()
|
protected static function initialize_static_variables()
|
||||||
{
|
{
|
||||||
if (is_float(self::$sbox[0x200])) {
|
if (is_float(self::$sbox[0x200])) {
|
||||||
self::$sbox = array_map('intval', self::$sbox);
|
self::$sbox = array_map([self::class, 'safe_intval'], self::$sbox);
|
||||||
self::$parray = array_map('intval', self::$parray);
|
self::$parray = array_map([self::class, 'safe_intval'], self::$parray);
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::initialize_static_variables();
|
parent::initialize_static_variables();
|
||||||
@@ -755,7 +755,7 @@ class Blowfish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the performance-optimized function for de/encrypt()
|
* Setup the performance-optimized function for de/encrypt()
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
|
* @see Common\SymmetricKey::_setupInlineCrypt()
|
||||||
*/
|
*/
|
||||||
protected function 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()
|
* 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
|
* @param int $engine
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -73,7 +73,7 @@ class ChaCha20 extends Salsa20
|
|||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* @see SymmetricKey::decrypt()
|
||||||
* @see self::crypt()
|
* @see self::crypt()
|
||||||
* @param string $plaintext
|
* @param string $plaintext
|
||||||
* @return string $ciphertext
|
* @return string $ciphertext
|
||||||
@@ -95,7 +95,7 @@ class ChaCha20 extends Salsa20
|
|||||||
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
||||||
* At least if the continuous buffer is disabled.
|
* At least if the continuous buffer is disabled.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* @see SymmetricKey::encrypt()
|
||||||
* @see self::crypt()
|
* @see self::crypt()
|
||||||
* @param string $ciphertext
|
* @param string $ciphertext
|
||||||
* @return string $plaintext
|
* @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
|
// xor'ing and rotation are all on the same line so i'm keeping it on the same
|
||||||
// line here as well
|
// line here as well
|
||||||
// @codingStandardsIgnoreStart
|
// @codingStandardsIgnoreStart
|
||||||
$a+= $b; $d = self::leftRotate(intval($d) ^ intval($a), 16);
|
$a+= $b; $d = self::leftRotate(self::safe_intval($d) ^ self::safe_intval($a), 16);
|
||||||
$c+= $d; $b = self::leftRotate(intval($b) ^ intval($c), 12);
|
$c+= $d; $b = self::leftRotate(self::safe_intval($b) ^ self::safe_intval($c), 12);
|
||||||
$a+= $b; $d = self::leftRotate(intval($d) ^ intval($a), 8);
|
$a+= $b; $d = self::leftRotate(self::safe_intval($d) ^ self::safe_intval($a), 8);
|
||||||
$c+= $d; $b = self::leftRotate(intval($b) ^ intval($c), 7);
|
$c+= $d; $b = self::leftRotate(self::safe_intval($b) ^ self::safe_intval($c), 7);
|
||||||
// @codingStandardsIgnoreEnd
|
// @codingStandardsIgnoreEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,424 +357,424 @@ class ChaCha20 extends Salsa20
|
|||||||
|
|
||||||
// @codingStandardsIgnoreStart
|
// @codingStandardsIgnoreStart
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
// columnRound
|
// columnRound
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 16);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 16);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 12);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 12);
|
||||||
$x0+= $x4; $x12 = self::leftRotate(intval($x12) ^ intval($x0), 8);
|
$x0+= $x4; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x0), 8);
|
||||||
$x8+= $x12; $x4 = self::leftRotate(intval($x4) ^ intval($x8), 7);
|
$x8+= $x12; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 16);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 16);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 12);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 12);
|
||||||
$x1+= $x5; $x13 = self::leftRotate(intval($x13) ^ intval($x1), 8);
|
$x1+= $x5; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x1), 8);
|
||||||
$x9+= $x13; $x5 = self::leftRotate(intval($x5) ^ intval($x9), 7);
|
$x9+= $x13; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x9), 7);
|
||||||
|
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 16);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 16);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 12);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 12);
|
||||||
$x2+= $x6; $x14 = self::leftRotate(intval($x14) ^ intval($x2), 8);
|
$x2+= $x6; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x2), 8);
|
||||||
$x10+= $x14; $x6 = self::leftRotate(intval($x6) ^ intval($x10), 7);
|
$x10+= $x14; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 16);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 16);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 12);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 12);
|
||||||
$x3+= $x7; $x15 = self::leftRotate(intval($x15) ^ intval($x3), 8);
|
$x3+= $x7; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x3), 8);
|
||||||
$x11+= $x15; $x7 = self::leftRotate(intval($x7) ^ intval($x11), 7);
|
$x11+= $x15; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
// rowRound
|
// rowRound
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 16);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 16);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 12);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 12);
|
||||||
$x0+= $x5; $x15 = self::leftRotate(intval($x15) ^ intval($x0), 8);
|
$x0+= $x5; $x15 = self::leftRotate(self::safe_intval($x15) ^ self::safe_intval($x0), 8);
|
||||||
$x10+= $x15; $x5 = self::leftRotate(intval($x5) ^ intval($x10), 7);
|
$x10+= $x15; $x5 = self::leftRotate(self::safe_intval($x5) ^ self::safe_intval($x10), 7);
|
||||||
|
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 16);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 16);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 12);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 12);
|
||||||
$x1+= $x6; $x12 = self::leftRotate(intval($x12) ^ intval($x1), 8);
|
$x1+= $x6; $x12 = self::leftRotate(self::safe_intval($x12) ^ self::safe_intval($x1), 8);
|
||||||
$x11+= $x12; $x6 = self::leftRotate(intval($x6) ^ intval($x11), 7);
|
$x11+= $x12; $x6 = self::leftRotate(self::safe_intval($x6) ^ self::safe_intval($x11), 7);
|
||||||
|
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 16);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 16);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 12);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 12);
|
||||||
$x2+= $x7; $x13 = self::leftRotate(intval($x13) ^ intval($x2), 8);
|
$x2+= $x7; $x13 = self::leftRotate(self::safe_intval($x13) ^ self::safe_intval($x2), 8);
|
||||||
$x8+= $x13; $x7 = self::leftRotate(intval($x7) ^ intval($x8), 7);
|
$x8+= $x13; $x7 = self::leftRotate(self::safe_intval($x7) ^ self::safe_intval($x8), 7);
|
||||||
|
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 16);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 16);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 12);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 12);
|
||||||
$x3+= $x4; $x14 = self::leftRotate(intval($x14) ^ intval($x3), 8);
|
$x3+= $x4; $x14 = self::leftRotate(self::safe_intval($x14) ^ self::safe_intval($x3), 8);
|
||||||
$x9+= $x14; $x4 = self::leftRotate(intval($x4) ^ intval($x9), 7);
|
$x9+= $x14; $x4 = self::leftRotate(self::safe_intval($x4) ^ self::safe_intval($x9), 7);
|
||||||
// @codingStandardsIgnoreEnd
|
// @codingStandardsIgnoreEnd
|
||||||
|
|
||||||
$x0 += $z0;
|
$x0 += $z0;
|
||||||
@@ -794,6 +794,6 @@ class ChaCha20 extends Salsa20
|
|||||||
$x14 += $z14;
|
$x14 += $z14;
|
||||||
$x15 += $z15;
|
$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 = [];
|
private static $invisiblePlugins = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Available Engines
|
|
||||||
*
|
|
||||||
* @var boolean[]
|
|
||||||
*/
|
|
||||||
protected static $engines = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key Comment
|
* Key Comment
|
||||||
*
|
*
|
||||||
@@ -92,6 +85,14 @@ abstract class AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
private $comment;
|
private $comment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenSSL configuration file name.
|
||||||
|
*
|
||||||
|
* @see self::createKey()
|
||||||
|
* @var ?string
|
||||||
|
*/
|
||||||
|
protected static $configFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @return array|string
|
* @return array|string
|
||||||
@@ -119,6 +120,10 @@ abstract class AsymmetricKey
|
|||||||
self::$one = new BigInteger(1);
|
self::$one = new BigInteger(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isset(self::$configFile)) {
|
||||||
|
self::$configFile = dirname(__FILE__) . '/../../openssl.cnf';
|
||||||
|
}
|
||||||
|
|
||||||
self::loadPlugins('Keys');
|
self::loadPlugins('Keys');
|
||||||
if (static::ALGORITHM != 'RSA' && static::ALGORITHM != 'DH') {
|
if (static::ALGORITHM != 'RSA' && static::ALGORITHM != 'DH') {
|
||||||
self::loadPlugins('Signature');
|
self::loadPlugins('Signature');
|
||||||
@@ -363,6 +368,18 @@ abstract class AsymmetricKey
|
|||||||
return self::$plugins[static::ALGORITHM]['Keys'];
|
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
|
* 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 = [
|
if (!isset($engine)) {
|
||||||
'PHP' => true,
|
static::$forcedEngine = null;
|
||||||
'OpenSSL' => extension_loaded('openssl'),
|
return;
|
||||||
// this test can be satisfied by either of the following:
|
}
|
||||||
// http://php.net/manual/en/book.sodium.php
|
switch ($engine) {
|
||||||
// https://github.com/paragonie/sodium_compat
|
case 'PHP':
|
||||||
'libsodium' => function_exists('sodium_crypto_sign_keypair')
|
case 'OpenSSL':
|
||||||
];
|
case 'libsodium':
|
||||||
|
static::$forcedEngine = $engine;
|
||||||
return static::$engines;
|
break;
|
||||||
|
default:
|
||||||
|
throw new \InvalidArgumentException('Valid engines are null, PHP, OpenSSL or libsodium');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function getForcedEngine()
|
||||||
* Flag to use internal engine only (useful for unit testing)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static function useInternalEngine()
|
|
||||||
{
|
{
|
||||||
static::$engines = [
|
return static::$forcedEngine;
|
||||||
'PHP' => true,
|
|
||||||
'OpenSSL' => false,
|
|
||||||
'libsodium' => false
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ abstract class JWK
|
|||||||
return $key;
|
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) {
|
if (count($key->keys) != 1) {
|
||||||
throw new \RuntimeException('Although the JWK key format supports multiple keys phpseclib does not');
|
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');
|
return compact('type', 'publicKey', 'paddedKey');
|
||||||
}
|
}
|
||||||
|
|
||||||
$parts = explode(' ', $key, 3);
|
$parts = preg_split("#[\t ]+#", $key, 3);
|
||||||
|
|
||||||
if (!isset($parts[1])) {
|
if (!isset($parts[1])) {
|
||||||
$key = base64_decode($parts[0]);
|
$key = base64_decode($parts[0]);
|
||||||
|
|||||||
+18
-8
@@ -361,7 +361,9 @@ abstract class PKCS8 extends PKCS
|
|||||||
if (!$temp) {
|
if (!$temp) {
|
||||||
throw new \RuntimeException('Unable to decode BER');
|
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();
|
$iterationCount = (int) $iterationCount->toString();
|
||||||
$cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount);
|
$cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount);
|
||||||
$key = $cipher->decrypt($decrypted['encryptedData']);
|
$key = $cipher->decrypt($decrypted['encryptedData']);
|
||||||
@@ -379,7 +381,8 @@ abstract class PKCS8 extends PKCS
|
|||||||
throw new \RuntimeException('Unable to decode BER');
|
throw new \RuntimeException('Unable to decode BER');
|
||||||
}
|
}
|
||||||
$temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
|
$temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
|
||||||
extract($temp);
|
$keyDerivationFunc = $temp['keyDerivationFunc'];
|
||||||
|
$encryptionScheme = $temp['encryptionScheme'];
|
||||||
|
|
||||||
$cipher = self::getPBES2EncryptionObject($encryptionScheme['algorithm']);
|
$cipher = self::getPBES2EncryptionObject($encryptionScheme['algorithm']);
|
||||||
$meta['meta']['cipher'] = $encryptionScheme['algorithm'];
|
$meta['meta']['cipher'] = $encryptionScheme['algorithm'];
|
||||||
@@ -389,7 +392,8 @@ abstract class PKCS8 extends PKCS
|
|||||||
throw new \RuntimeException('Unable to decode BER');
|
throw new \RuntimeException('Unable to decode BER');
|
||||||
}
|
}
|
||||||
$temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
|
$temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
|
||||||
extract($temp);
|
$keyDerivationFunc = $temp['keyDerivationFunc'];
|
||||||
|
$encryptionScheme = $temp['encryptionScheme'];
|
||||||
|
|
||||||
if (!$cipher instanceof RC2) {
|
if (!$cipher instanceof RC2) {
|
||||||
$cipher->setIV($encryptionScheme['parameters']['octetString']);
|
$cipher->setIV($encryptionScheme['parameters']['octetString']);
|
||||||
@@ -398,7 +402,9 @@ abstract class PKCS8 extends PKCS
|
|||||||
if (!$temp) {
|
if (!$temp) {
|
||||||
throw new \RuntimeException('Unable to decode BER');
|
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();
|
$effectiveKeyLength = (int) $rc2ParametersVersion->toString();
|
||||||
switch ($effectiveKeyLength) {
|
switch ($effectiveKeyLength) {
|
||||||
case 160:
|
case 160:
|
||||||
@@ -423,9 +429,13 @@ abstract class PKCS8 extends PKCS
|
|||||||
if (!$temp) {
|
if (!$temp) {
|
||||||
throw new \RuntimeException('Unable to decode BER');
|
throw new \RuntimeException('Unable to decode BER');
|
||||||
}
|
}
|
||||||
$prf = ['algorithm' => 'id-hmacWithSHA1'];
|
|
||||||
$params = ASN1::asn1map($temp[0], Maps\PBKDF2params::MAP);
|
$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'];
|
$meta['meta']['prf'] = $prf['algorithm'];
|
||||||
$hash = str_replace('-', '/', substr($prf['algorithm'], 11));
|
$hash = str_replace('-', '/', substr($prf['algorithm'], 11));
|
||||||
$params = [
|
$params = [
|
||||||
@@ -555,7 +565,7 @@ abstract class PKCS8 extends PKCS
|
|||||||
],
|
],
|
||||||
'privateKey' => $key
|
'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;
|
$key['privateKeyAlgorithm']['parameters'] = $params;
|
||||||
}
|
}
|
||||||
if (!empty($attr)) {
|
if (!empty($attr)) {
|
||||||
@@ -672,7 +682,7 @@ abstract class PKCS8 extends PKCS
|
|||||||
'publicKey' => "\0" . $key
|
'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;
|
$key['publicKeyAlgorithm']['parameters'] = $params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-3
@@ -199,7 +199,7 @@ abstract class PuTTY
|
|||||||
|
|
||||||
$source = Strings::packSSH2('ssss', $type, $encryption, $components['comment'], $public);
|
$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);
|
$newtype = Strings::shift($public, $length);
|
||||||
if ($newtype != $type) {
|
if ($newtype != $type) {
|
||||||
throw new \RuntimeException('The binary type does not match the human readable type field');
|
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++]));
|
$parallelism = trim(preg_replace('#Argon2-Parallelism: (\d+)#', '$1', $key[$offset++]));
|
||||||
$salt = Strings::hex2bin(trim(preg_replace('#Argon2-Salt: ([0-9a-f]+)#', '$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;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@@ -323,7 +326,10 @@ abstract class PuTTY
|
|||||||
$key .= "Argon2-Passes: 13\r\n";
|
$key .= "Argon2-Passes: 13\r\n";
|
||||||
$key .= "Argon2-Parallelism: 1\r\n";
|
$key .= "Argon2-Parallelism: 1\r\n";
|
||||||
$key .= "Argon2-Salt: " . Strings::bin2hex($salt) . "\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 = new Hash('sha256');
|
||||||
$hash->setKey($hashkey);
|
$hash->setKey($hashkey);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ abstract class StreamCipher extends SymmetricKey
|
|||||||
*
|
*
|
||||||
* Stream ciphers do not have a block size
|
* Stream ciphers do not have a block size
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
|
* @see SymmetricKey::block_size
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $block_size = 0;
|
protected $block_size = 0;
|
||||||
@@ -34,7 +34,7 @@ abstract class StreamCipher extends SymmetricKey
|
|||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* @see SymmetricKey::__construct()
|
||||||
* @return StreamCipher
|
* @return StreamCipher
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
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.
|
* 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
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_CTR = -1;
|
const MODE_CTR = -1;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Electronic Code Book mode.
|
* Encrypt / decrypt using the Electronic Code Book mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_ECB = 1;
|
const MODE_ECB = 1;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Code Book Chaining mode.
|
* Encrypt / decrypt using the Code Book Chaining mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_CBC = 2;
|
const MODE_CBC = 2;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Cipher Feedback mode.
|
* Encrypt / decrypt using the Cipher Feedback mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_CFB = 3;
|
const MODE_CFB = 3;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Cipher Feedback mode (8bit)
|
* Encrypt / decrypt using the Cipher Feedback mode (8bit)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_CFB8 = 7;
|
const MODE_CFB8 = 7;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Output Feedback mode (8bit)
|
* Encrypt / decrypt using the Output Feedback mode (8bit)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_OFB8 = 8;
|
const MODE_OFB8 = 8;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using the Output Feedback mode.
|
* Encrypt / decrypt using the Output Feedback mode.
|
||||||
*
|
*
|
||||||
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
|
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_OFB = 4;
|
const MODE_OFB = 4;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using Galois/Counter mode.
|
* Encrypt / decrypt using Galois/Counter mode.
|
||||||
*
|
*
|
||||||
* @link https://en.wikipedia.org/wiki/Galois/Counter_Mode
|
* @link https://en.wikipedia.org/wiki/Galois/Counter_Mode
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_GCM = 5;
|
const MODE_GCM = 5;
|
||||||
/**
|
/**
|
||||||
* Encrypt / decrypt using streaming mode.
|
* Encrypt / decrypt using streaming mode.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* SymmetricKey::encrypt()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* SymmetricKey::decrypt()
|
||||||
*/
|
*/
|
||||||
const MODE_STREAM = 6;
|
const MODE_STREAM = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mode Map
|
* Mode Map
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* SymmetricKey::__construct()
|
||||||
*/
|
*/
|
||||||
const MODE_MAP = [
|
const MODE_MAP = [
|
||||||
'ctr' => self::MODE_CTR,
|
'ctr' => self::MODE_CTR,
|
||||||
@@ -146,44 +146,44 @@ abstract class SymmetricKey
|
|||||||
/**
|
/**
|
||||||
* Base value for the internal implementation $engine switch
|
* Base value for the internal implementation $engine switch
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* SymmetricKey::__construct()
|
||||||
*/
|
*/
|
||||||
const ENGINE_INTERNAL = 1;
|
const ENGINE_INTERNAL = 1;
|
||||||
/**
|
/**
|
||||||
* Base value for the eval() implementation $engine switch
|
* Base value for the eval() implementation $engine switch
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* SymmetricKey::__construct()
|
||||||
*/
|
*/
|
||||||
const ENGINE_EVAL = 2;
|
const ENGINE_EVAL = 2;
|
||||||
/**
|
/**
|
||||||
* Base value for the mcrypt implementation $engine switch
|
* Base value for the mcrypt implementation $engine switch
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* SymmetricKey::__construct()
|
||||||
*/
|
*/
|
||||||
const ENGINE_MCRYPT = 3;
|
const ENGINE_MCRYPT = 3;
|
||||||
/**
|
/**
|
||||||
* Base value for the openssl implementation $engine switch
|
* Base value for the openssl implementation $engine switch
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* SymmetricKey::__construct()
|
||||||
*/
|
*/
|
||||||
const ENGINE_OPENSSL = 4;
|
const ENGINE_OPENSSL = 4;
|
||||||
/**
|
/**
|
||||||
* Base value for the libsodium implementation $engine switch
|
* Base value for the libsodium implementation $engine switch
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* SymmetricKey::__construct()
|
||||||
*/
|
*/
|
||||||
const ENGINE_LIBSODIUM = 5;
|
const ENGINE_LIBSODIUM = 5;
|
||||||
/**
|
/**
|
||||||
* Base value for the openssl / gcm implementation $engine switch
|
* Base value for the openssl / gcm implementation $engine switch
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* SymmetricKey::__construct()
|
||||||
*/
|
*/
|
||||||
const ENGINE_OPENSSL_GCM = 6;
|
const ENGINE_OPENSSL_GCM = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Engine Reverse Map
|
* Engine Reverse Map
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine()
|
* SymmetricKey::getEngine()
|
||||||
*/
|
*/
|
||||||
const ENGINE_MAP = [
|
const ENGINE_MAP = [
|
||||||
self::ENGINE_INTERNAL => 'PHP',
|
self::ENGINE_INTERNAL => 'PHP',
|
||||||
@@ -666,6 +666,11 @@ abstract class SymmetricKey
|
|||||||
{
|
{
|
||||||
if (!isset(self::$use_reg_intval)) {
|
if (!isset(self::$use_reg_intval)) {
|
||||||
switch (true) {
|
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
|
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
|
||||||
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
|
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
|
||||||
case !function_exists('php_uname'):
|
case !function_exists('php_uname'):
|
||||||
@@ -1265,7 +1270,7 @@ abstract class SymmetricKey
|
|||||||
if ($this->continuousBuffer) {
|
if ($this->continuousBuffer) {
|
||||||
$this->encryptIV = $iv;
|
$this->encryptIV = $iv;
|
||||||
}
|
}
|
||||||
break;
|
return $ciphertext;
|
||||||
case self::MODE_OFB:
|
case self::MODE_OFB:
|
||||||
return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
|
return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
|
||||||
}
|
}
|
||||||
@@ -2591,7 +2596,7 @@ abstract class SymmetricKey
|
|||||||
|
|
||||||
$length = ord($text[strlen($text) - 1]);
|
$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})");
|
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]
|
* Contains $keys[self::ENCRYPT]
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\DES::setupKey()
|
* @see DES::setupKey()
|
||||||
* @see \phpseclib3\Crypt\DES::processBlock()
|
* @see DES::processBlock()
|
||||||
*/
|
*/
|
||||||
const ENCRYPT = 0;
|
const ENCRYPT = 0;
|
||||||
/**
|
/**
|
||||||
* Contains $keys[self::DECRYPT]
|
* Contains $keys[self::DECRYPT]
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\DES::setupKey()
|
* @see DES::setupKey()
|
||||||
* @see \phpseclib3\Crypt\DES::processBlock()
|
* @see DES::processBlock()
|
||||||
*/
|
*/
|
||||||
const DECRYPT = 1;
|
const DECRYPT = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block Length of the cipher
|
* Block Length of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
|
* @see Common\SymmetricKey::block_size
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $block_size = 8;
|
protected $block_size = 8;
|
||||||
@@ -76,7 +76,7 @@ class DES extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Key Length (in bytes)
|
* Key Length (in bytes)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength()
|
* @see Common\SymmetricKey::setKeyLength()
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $key_length = 8;
|
protected $key_length = 8;
|
||||||
@@ -84,7 +84,7 @@ class DES extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
|
* @see Common\SymmetricKey::cipher_name_mcrypt
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $cipher_name_mcrypt = 'des';
|
protected $cipher_name_mcrypt = 'des';
|
||||||
@@ -92,7 +92,7 @@ class DES extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* The OpenSSL names of the cipher / modes
|
* The OpenSSL names of the cipher / modes
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::openssl_mode_names
|
* @see Common\SymmetricKey::openssl_mode_names
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $openssl_mode_names = [
|
protected $openssl_mode_names = [
|
||||||
@@ -106,7 +106,7 @@ class DES extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Optimizing value while CFB-encrypting
|
* Optimizing value while CFB-encrypting
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
|
* @see Common\SymmetricKey::cfb_init_len
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $cfb_init_len = 500;
|
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()
|
* 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
|
* @param int $engine
|
||||||
* @return bool
|
* @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.
|
* 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
|
* @param string $key
|
||||||
*/
|
*/
|
||||||
public function setKey($key)
|
public function setKey($key)
|
||||||
@@ -631,8 +631,8 @@ class DES extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Encrypts a block
|
* Encrypts a block
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock()
|
* @see Common\SymmetricKey::encryptBlock()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* @see Common\SymmetricKey::encrypt()
|
||||||
* @see self::encrypt()
|
* @see self::encrypt()
|
||||||
* @param string $in
|
* @param string $in
|
||||||
* @return string
|
* @return string
|
||||||
@@ -645,8 +645,8 @@ class DES extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Decrypts a block
|
* Decrypts a block
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock()
|
* @see Common\SymmetricKey::decryptBlock()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* @see Common\SymmetricKey::decrypt()
|
||||||
* @see self::decrypt()
|
* @see self::decrypt()
|
||||||
* @param string $in
|
* @param string $in
|
||||||
* @return string
|
* @return string
|
||||||
@@ -673,14 +673,14 @@ class DES extends BlockCipher
|
|||||||
{
|
{
|
||||||
static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
|
static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
|
||||||
if (!$sbox1) {
|
if (!$sbox1) {
|
||||||
$sbox1 = array_map('intval', self::$sbox1);
|
$sbox1 = array_map([self::class, 'safe_intval'], self::$sbox1);
|
||||||
$sbox2 = array_map('intval', self::$sbox2);
|
$sbox2 = array_map([self::class, 'safe_intval'], self::$sbox2);
|
||||||
$sbox3 = array_map('intval', self::$sbox3);
|
$sbox3 = array_map([self::class, 'safe_intval'], self::$sbox3);
|
||||||
$sbox4 = array_map('intval', self::$sbox4);
|
$sbox4 = array_map([self::class, 'safe_intval'], self::$sbox4);
|
||||||
$sbox5 = array_map('intval', self::$sbox5);
|
$sbox5 = array_map([self::class, 'safe_intval'], self::$sbox5);
|
||||||
$sbox6 = array_map('intval', self::$sbox6);
|
$sbox6 = array_map([self::class, 'safe_intval'], self::$sbox6);
|
||||||
$sbox7 = array_map('intval', self::$sbox7);
|
$sbox7 = array_map([self::class, 'safe_intval'], self::$sbox7);
|
||||||
$sbox8 = array_map('intval', self::$sbox8);
|
$sbox8 = array_map([self::class, 'safe_intval'], self::$sbox8);
|
||||||
/* Merge $shuffle with $[inv]ipmap */
|
/* Merge $shuffle with $[inv]ipmap */
|
||||||
for ($i = 0; $i < 256; ++$i) {
|
for ($i = 0; $i < 256; ++$i) {
|
||||||
$shuffleip[] = self::$shuffle[self::$ipmap[$i]];
|
$shuffleip[] = self::$shuffle[self::$ipmap[$i]];
|
||||||
@@ -747,7 +747,7 @@ class DES extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Creates the key schedule
|
* Creates the key schedule
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
|
* @see Common\SymmetricKey::setupKey()
|
||||||
*/
|
*/
|
||||||
protected function setupKey()
|
protected function setupKey()
|
||||||
{
|
{
|
||||||
@@ -1243,9 +1243,9 @@ class DES extends BlockCipher
|
|||||||
$pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF];
|
$pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF];
|
||||||
|
|
||||||
// Reorder: odd bytes/even bytes. Push the result in key schedule.
|
// 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);
|
(($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);
|
(($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF);
|
||||||
$keys[$des_round][self::ENCRYPT][ ] = $val1;
|
$keys[$des_round][self::ENCRYPT][ ] = $val1;
|
||||||
$keys[$des_round][self::DECRYPT][$ki - 1] = $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()
|
* Setup the performance-optimized function for de/encrypt()
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
|
* @see Common\SymmetricKey::setupInlineCrypt()
|
||||||
*/
|
*/
|
||||||
protected function 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;
|
$init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
|
||||||
if (!$sbox1) {
|
if (!$sbox1) {
|
||||||
$sbox1 = array_map("intval", self::$sbox1);
|
$sbox1 = array_map(["' . self::class . '", "safe_intval"], self::$sbox1);
|
||||||
$sbox2 = array_map("intval", self::$sbox2);
|
$sbox2 = array_map(["' . self::class . '", "safe_intval"], self::$sbox2);
|
||||||
$sbox3 = array_map("intval", self::$sbox3);
|
$sbox3 = array_map(["' . self::class . '", "safe_intval"], self::$sbox3);
|
||||||
$sbox4 = array_map("intval", self::$sbox4);
|
$sbox4 = array_map(["' . self::class . '", "safe_intval"], self::$sbox4);
|
||||||
$sbox5 = array_map("intval", self::$sbox5);
|
$sbox5 = array_map(["' . self::class . '", "safe_intval"], self::$sbox5);
|
||||||
$sbox6 = array_map("intval", self::$sbox6);
|
$sbox6 = array_map(["' . self::class . '", "safe_intval"], self::$sbox6);
|
||||||
$sbox7 = array_map("intval", self::$sbox7);
|
$sbox7 = array_map(["' . self::class . '", "safe_intval"], self::$sbox7);
|
||||||
$sbox8 = array_map("intval", self::$sbox8);'
|
$sbox8 = array_map(["' . self::class . '", "safe_intval"], self::$sbox8);'
|
||||||
/* Merge $shuffle with $[inv]ipmap */ . '
|
/* Merge $shuffle with $[inv]ipmap */ . '
|
||||||
for ($i = 0; $i < 256; ++$i) {
|
for ($i = 0; $i < 256; ++$i) {
|
||||||
$shuffleip[] = self::$shuffle[self::$ipmap[$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\Parameters;
|
||||||
use phpseclib3\Crypt\DH\PrivateKey;
|
use phpseclib3\Crypt\DH\PrivateKey;
|
||||||
use phpseclib3\Crypt\DH\PublicKey;
|
use phpseclib3\Crypt\DH\PublicKey;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Exception\NoKeyLoadedException;
|
use phpseclib3\Exception\NoKeyLoadedException;
|
||||||
use phpseclib3\Exception\UnsupportedOperationException;
|
use phpseclib3\Exception\UnsupportedOperationException;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
@@ -295,21 +296,64 @@ abstract class DH extends AsymmetricKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($private instanceof EC\PrivateKey) {
|
if ($private instanceof EC\PrivateKey) {
|
||||||
|
$privateCurve = $private->getCurve();
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case $public instanceof EC\PublicKey:
|
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();
|
$public = $public->getEncodedCoordinates();
|
||||||
// fall-through
|
// fall-through
|
||||||
case is_string($public):
|
case is_string($public):
|
||||||
$point = $private->multiply($public);
|
$forcedEngine = EC::getForcedEngine();
|
||||||
switch ($private->getCurve()) {
|
if ($forcedEngine === 'libsodium' && $privateCurve !== 'Curve25519') {
|
||||||
case 'Curve25519':
|
throw new BadConfigurationException('Engine libsodium is forced but can only used with Curve25519 for ECDH');
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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") {
|
if (($secret[0] & "\x80") === "\x80") {
|
||||||
$secret = "\0$secret";
|
$secret = "\0$secret";
|
||||||
|
|||||||
+44
-28
@@ -33,6 +33,7 @@ use phpseclib3\Crypt\Common\AsymmetricKey;
|
|||||||
use phpseclib3\Crypt\DSA\Parameters;
|
use phpseclib3\Crypt\DSA\Parameters;
|
||||||
use phpseclib3\Crypt\DSA\PrivateKey;
|
use phpseclib3\Crypt\DSA\PrivateKey;
|
||||||
use phpseclib3\Crypt\DSA\PublicKey;
|
use phpseclib3\Crypt\DSA\PublicKey;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Exception\InsufficientSetupException;
|
use phpseclib3\Exception\InsufficientSetupException;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
|
|
||||||
@@ -87,6 +88,14 @@ abstract class DSA extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected $sigFormat;
|
protected $sigFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forced Engine
|
||||||
|
*
|
||||||
|
* @var ?string
|
||||||
|
* @see parent::forceEngine()
|
||||||
|
*/
|
||||||
|
protected static $forcedEngine = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature Format (Short)
|
* 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 . ')');
|
throw new \RuntimeException('createParameters() should not be called from final classes (' . static::class . ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(self::$engines['PHP'])) {
|
|
||||||
self::useBestEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case $N == 160:
|
case $N == 160:
|
||||||
/*
|
/*
|
||||||
@@ -185,15 +190,19 @@ abstract class DSA extends AsymmetricKey
|
|||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
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);
|
$class = new \ReflectionClass(static::class);
|
||||||
if ($class->isFinal()) {
|
if ($class->isFinal()) {
|
||||||
throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
|
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])) {
|
if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) {
|
||||||
$params = self::createParameters($args[0], $args[1]);
|
$params = self::createParameters($args[0], $args[1]);
|
||||||
} elseif (count($args) == 1 && $args[0] instanceof Parameters) {
|
} 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.');
|
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 = new PrivateKey();
|
||||||
$private->p = $params->p;
|
$private->p = $params->p;
|
||||||
$private->q = $params->q;
|
$private->q = $params->q;
|
||||||
@@ -227,10 +263,6 @@ abstract class DSA extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected static function onLoad(array $components)
|
protected static function onLoad(array $components)
|
||||||
{
|
{
|
||||||
if (!isset(self::$engines['PHP'])) {
|
|
||||||
self::useBestEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($components['x']) && !isset($components['y'])) {
|
if (!isset($components['x']) && !isset($components['y'])) {
|
||||||
$new = new Parameters();
|
$new = new Parameters();
|
||||||
} elseif (isset($components['x'])) {
|
} elseif (isset($components['x'])) {
|
||||||
@@ -276,22 +308,6 @@ abstract class DSA extends AsymmetricKey
|
|||||||
return ['L' => $this->p->getLength(), 'N' => $this->q->getLength()];
|
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
|
* Returns the parameters
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -63,13 +63,28 @@ abstract class PKCS1 extends Progenitor
|
|||||||
|
|
||||||
$key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP);
|
$key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP);
|
||||||
if (is_array($key)) {
|
if (is_array($key)) {
|
||||||
|
if ($key['version']->toString() !== '0') {
|
||||||
|
throw new \UnexpectedValueException('Version number is not valid');
|
||||||
|
}
|
||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
$key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
|
// PKCS1 DSA public keys are not supported by phpseclib since they can't be used to do
|
||||||
if (is_array($key)) {
|
// anything on their own. in order to verify a signature with DSA you need p, q, g and y.
|
||||||
return $key;
|
// 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');
|
throw new \RuntimeException('Unable to perform ASN1 mapping');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ abstract class PuTTY extends Progenitor
|
|||||||
if (!isset($components['private'])) {
|
if (!isset($components['private'])) {
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
||||||
extract($components);
|
$type = $components['type'];
|
||||||
|
$comment = $components['comment'];
|
||||||
|
$public = $components['public'];
|
||||||
|
$private = $components['private'];
|
||||||
unset($components['public'], $components['private']);
|
unset($components['public'], $components['private']);
|
||||||
|
|
||||||
list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $public);
|
list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $public);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace phpseclib3\Crypt\DSA;
|
|||||||
use phpseclib3\Crypt\Common;
|
use phpseclib3\Crypt\Common;
|
||||||
use phpseclib3\Crypt\DSA;
|
use phpseclib3\Crypt\DSA;
|
||||||
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
|
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,18 +80,34 @@ final class PrivateKey extends DSA implements Common\PrivateKey
|
|||||||
{
|
{
|
||||||
$format = $this->sigFormat;
|
$format = $this->sigFormat;
|
||||||
|
|
||||||
if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
|
if (self::$forcedEngine === 'libsodium') {
|
||||||
$signature = '';
|
throw new BadConfigurationException('Engine libsodium is forced but unsupported for DSA');
|
||||||
$result = openssl_sign($message, $signature, $this->toString('PKCS8'), $this->hash->getHash());
|
}
|
||||||
|
|
||||||
if ($result) {
|
if (self::$forcedEngine === 'OpenSSL' && !function_exists('openssl_get_md_methods')) {
|
||||||
if ($this->shortFormat == 'ASN1') {
|
throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for DSA');
|
||||||
return $signature;
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
} elseif (self::$forcedEngine === 'OpenSSL') {
|
||||||
extract(ASN1Signature::load($signature));
|
throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for DSA / ' . $this->hash->getHash());
|
||||||
|
|
||||||
return $format::save($r, $s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace phpseclib3\Crypt\DSA;
|
|||||||
use phpseclib3\Crypt\Common;
|
use phpseclib3\Crypt\Common;
|
||||||
use phpseclib3\Crypt\DSA;
|
use phpseclib3\Crypt\DSA;
|
||||||
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
|
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DSA Public Key
|
* DSA Public Key
|
||||||
@@ -34,21 +35,34 @@ final class PublicKey extends DSA implements Common\PublicKey
|
|||||||
*/
|
*/
|
||||||
public function verify($message, $signature)
|
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;
|
$format = $this->sigFormat;
|
||||||
|
|
||||||
$params = $format::load($signature);
|
$params = $format::load($signature);
|
||||||
if ($params === false || count($params) != 2) {
|
if ($params === false || count($params) != 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
extract($params);
|
$r = $params['r'];
|
||||||
|
$s = $params['s'];
|
||||||
|
|
||||||
if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
|
if (function_exists('openssl_get_md_methods') && self::$forcedEngine !== 'PHP') {
|
||||||
$sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
|
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) {
|
if ($result != -1) {
|
||||||
return (bool) $result;
|
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\Montgomery as MontgomeryCurve;
|
||||||
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
use phpseclib3\Crypt\EC\Curves\Curve25519;
|
use phpseclib3\Crypt\EC\Curves\Curve25519;
|
||||||
|
use phpseclib3\Crypt\EC\Curves\Curve448;
|
||||||
use phpseclib3\Crypt\EC\Curves\Ed25519;
|
use phpseclib3\Crypt\EC\Curves\Ed25519;
|
||||||
use phpseclib3\Crypt\EC\Curves\Ed448;
|
use phpseclib3\Crypt\EC\Curves\Ed448;
|
||||||
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
|
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
|
||||||
|
use phpseclib3\Crypt\EC\Formats\Keys\PKCS8;
|
||||||
use phpseclib3\Crypt\EC\Parameters;
|
use phpseclib3\Crypt\EC\Parameters;
|
||||||
use phpseclib3\Crypt\EC\PrivateKey;
|
use phpseclib3\Crypt\EC\PrivateKey;
|
||||||
use phpseclib3\Crypt\EC\PublicKey;
|
use phpseclib3\Crypt\EC\PublicKey;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Exception\UnsupportedAlgorithmException;
|
use phpseclib3\Exception\UnsupportedAlgorithmException;
|
||||||
use phpseclib3\Exception\UnsupportedCurveException;
|
use phpseclib3\Exception\UnsupportedCurveException;
|
||||||
use phpseclib3\Exception\UnsupportedOperationException;
|
use phpseclib3\Exception\UnsupportedOperationException;
|
||||||
@@ -74,13 +77,6 @@ abstract class EC extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected $curve;
|
protected $curve;
|
||||||
|
|
||||||
/**
|
|
||||||
* Signature Format
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $format;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature Format (Short)
|
* Signature Format (Short)
|
||||||
*
|
*
|
||||||
@@ -130,6 +126,14 @@ abstract class EC extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected $sigFormat;
|
protected $sigFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forced Engine
|
||||||
|
*
|
||||||
|
* @var ?string
|
||||||
|
* @see parent::forceEngine()
|
||||||
|
*/
|
||||||
|
protected static $forcedEngine = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create public / private key pair.
|
* 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 . ')');
|
throw new \RuntimeException('createKey() should not be called from final classes (' . static::class . ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(self::$engines['PHP'])) {
|
$curveName = self::getCurveCase($curve);
|
||||||
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);
|
|
||||||
}
|
|
||||||
$curve = '\phpseclib3\Crypt\EC\Curves\\' . $curveName;
|
$curve = '\phpseclib3\Crypt\EC\Curves\\' . $curveName;
|
||||||
|
|
||||||
if (!class_exists($curve)) {
|
if (!class_exists($curve)) {
|
||||||
@@ -180,6 +160,54 @@ abstract class EC extends AsymmetricKey
|
|||||||
$curveName = $reflect->isFinal() ?
|
$curveName = $reflect->isFinal() ?
|
||||||
$reflect->getParentClass()->getShortName() :
|
$reflect->getParentClass()->getShortName() :
|
||||||
$reflect->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();
|
$curve = new $curve();
|
||||||
if ($curve instanceof TwistedEdwardsCurve) {
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
@@ -189,21 +217,14 @@ abstract class EC extends AsymmetricKey
|
|||||||
} else {
|
} else {
|
||||||
$privatekey->dA = $dA = $curve->createRandomMultiplier();
|
$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->curve = $curve;
|
||||||
|
$privatekey->curveName = $curveName;
|
||||||
|
$privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA);
|
||||||
|
|
||||||
//$publickey = clone $privatekey;
|
//$publickey = clone $privatekey;
|
||||||
//unset($publickey->dA);
|
//unset($publickey->dA);
|
||||||
//unset($publickey->x);
|
//unset($publickey->x);
|
||||||
|
|
||||||
$privatekey->curveName = $curveName;
|
|
||||||
//$publickey->curveName = $curveName;
|
//$publickey->curveName = $curveName;
|
||||||
|
|
||||||
if ($privatekey->curve instanceof TwistedEdwardsCurve) {
|
if ($privatekey->curve instanceof TwistedEdwardsCurve) {
|
||||||
@@ -213,6 +234,130 @@ abstract class EC extends AsymmetricKey
|
|||||||
return $privatekey;
|
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
|
* OnLoad Handler
|
||||||
*
|
*
|
||||||
@@ -220,10 +365,6 @@ abstract class EC extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected static function onLoad(array $components)
|
protected static function onLoad(array $components)
|
||||||
{
|
{
|
||||||
if (!isset(self::$engines['PHP'])) {
|
|
||||||
self::useBestEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($components['dA']) && !isset($components['QA'])) {
|
if (!isset($components['dA']) && !isset($components['QA'])) {
|
||||||
$new = new Parameters();
|
$new = new Parameters();
|
||||||
$new->curve = $components['curve'];
|
$new->curve = $components['curve'];
|
||||||
@@ -320,27 +461,6 @@ abstract class EC extends AsymmetricKey
|
|||||||
return $this->curve->getLength();
|
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
|
* 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);
|
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
|
* Returns the parameters
|
||||||
*
|
*
|
||||||
@@ -380,7 +542,7 @@ abstract class EC extends AsymmetricKey
|
|||||||
/**
|
/**
|
||||||
* Determines the signature padding mode
|
* Determines the signature padding mode
|
||||||
*
|
*
|
||||||
* Valid values are: ASN1, SSH2, Raw
|
* Valid values are: ASN1, IEEE, SSH2, Raw
|
||||||
*
|
*
|
||||||
* @param string $format
|
* @param string $format
|
||||||
*/
|
*/
|
||||||
@@ -463,18 +625,4 @@ abstract class EC extends AsymmetricKey
|
|||||||
|
|
||||||
return parent::withHash($hash);
|
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);
|
$p2 = $this->convertToInternal($p);
|
||||||
$x = $p[0];
|
$x = $p[0];
|
||||||
|
|
||||||
|
$r = $this->randomInteger();
|
||||||
|
$p2 = [$p2[0]->multiply($r), $p2[1]->multiply($r)];
|
||||||
|
|
||||||
$b = $d->toBits();
|
$b = $d->toBits();
|
||||||
$b = str_pad($b, 256, '0', STR_PAD_LEFT);
|
$b = str_pad($b, 256, '0', STR_PAD_LEFT);
|
||||||
for ($i = 0; $i < strlen($b); $i++) {
|
for ($i = 0; $i < strlen($b); $i++) {
|
||||||
@@ -246,7 +249,7 @@ class Montgomery extends Base
|
|||||||
*
|
*
|
||||||
* x=X/Z
|
* x=X/Z
|
||||||
*
|
*
|
||||||
* @return \phpseclib3\Math\PrimeField\Integer[]
|
* @return PrimeInteger[]
|
||||||
*/
|
*/
|
||||||
public function convertToInternal(array $p)
|
public function convertToInternal(array $p)
|
||||||
{
|
{
|
||||||
@@ -266,7 +269,7 @@ class Montgomery extends Base
|
|||||||
/**
|
/**
|
||||||
* Returns the affine point
|
* Returns the affine point
|
||||||
*
|
*
|
||||||
* @return \phpseclib3\Math\PrimeField\Integer[]
|
* @return PrimeInteger[]
|
||||||
*/
|
*/
|
||||||
public function convertToAffine(array $p)
|
public function convertToAffine(array $p)
|
||||||
{
|
{
|
||||||
@@ -274,6 +277,9 @@ class Montgomery extends Base
|
|||||||
return $p;
|
return $p;
|
||||||
}
|
}
|
||||||
list($x, $z) = $p;
|
list($x, $z) = $p;
|
||||||
|
if ($z->equals($this->zero)) {
|
||||||
|
return [clone $this->zero];
|
||||||
|
}
|
||||||
return [$x->divide($z)];
|
return [$x->divide($z)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -751,7 +751,7 @@ class Prime extends Base
|
|||||||
* To convert a Jacobian Coordinate to an Affine Point
|
* To convert a Jacobian Coordinate to an Affine Point
|
||||||
* you do (x / z^2, y / z^3)
|
* you do (x / z^2, y / z^3)
|
||||||
*
|
*
|
||||||
* @return \phpseclib3\Math\PrimeField\Integer[]
|
* @return PrimeInteger[]
|
||||||
*/
|
*/
|
||||||
public function convertToAffine(array $p)
|
public function convertToAffine(array $p)
|
||||||
{
|
{
|
||||||
@@ -770,7 +770,7 @@ class Prime extends Base
|
|||||||
/**
|
/**
|
||||||
* Converts an affine point to a jacobian coordinate
|
* Converts an affine point to a jacobian coordinate
|
||||||
*
|
*
|
||||||
* @return \phpseclib3\Math\PrimeField\Integer[]
|
* @return PrimeInteger[]
|
||||||
*/
|
*/
|
||||||
public function convertToInternal(array $p)
|
public function convertToInternal(array $p)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -171,7 +171,7 @@ class TwistedEdwards extends Base
|
|||||||
/**
|
/**
|
||||||
* Returns the affine point
|
* Returns the affine point
|
||||||
*
|
*
|
||||||
* @return PrimeField\Integer[]
|
* @return PrimeInteger[]
|
||||||
*/
|
*/
|
||||||
public function convertToAffine(array $p)
|
public function convertToAffine(array $p)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ use phpseclib3\Math\BigInteger;
|
|||||||
|
|
||||||
class Curve25519 extends Montgomery
|
class Curve25519 extends Montgomery
|
||||||
{
|
{
|
||||||
|
const SIZE = 32;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
// 2^255 - 19
|
// 2^255 - 19
|
||||||
@@ -47,10 +49,12 @@ class Curve25519 extends Montgomery
|
|||||||
*/
|
*/
|
||||||
public function multiplyPoint(array $p, BigInteger $d)
|
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))];
|
//return [$this->factory->newInteger(new BigInteger($r, 256))];
|
||||||
|
|
||||||
$d = $d->toBytes();
|
|
||||||
$d &= "\xF8" . str_repeat("\xFF", 30) . "\x7F";
|
$d &= "\xF8" . str_repeat("\xFF", 30) . "\x7F";
|
||||||
$d = strrev($d);
|
$d = strrev($d);
|
||||||
$d |= "\x40";
|
$d |= "\x40";
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ use phpseclib3\Math\BigInteger;
|
|||||||
|
|
||||||
class Curve448 extends Montgomery
|
class Curve448 extends Montgomery
|
||||||
{
|
{
|
||||||
|
const SIZE = 56;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
// 2^448 - 2^224 - 1
|
// 2^448 - 2^224 - 1
|
||||||
@@ -58,10 +60,12 @@ class Curve448 extends Montgomery
|
|||||||
*/
|
*/
|
||||||
public function multiplyPoint(array $p, BigInteger $d)
|
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))];
|
//return [$this->factory->newInteger(new BigInteger($r, 256))];
|
||||||
|
|
||||||
$d = $d->toBytes();
|
|
||||||
$d[0] = $d[0] & "\xFC";
|
$d[0] = $d[0] & "\xFC";
|
||||||
$d = strrev($d);
|
$d = strrev($d);
|
||||||
$d |= "\x80";
|
$d |= "\x80";
|
||||||
|
|||||||
@@ -14,10 +14,14 @@
|
|||||||
namespace phpseclib3\Crypt\EC\Formats\Keys;
|
namespace phpseclib3\Crypt\EC\Formats\Keys;
|
||||||
|
|
||||||
use phpseclib3\Common\Functions\Strings;
|
use phpseclib3\Common\Functions\Strings;
|
||||||
|
use phpseclib3\Crypt\EC;
|
||||||
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
|
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
|
||||||
use phpseclib3\Crypt\EC\BaseCurves\Binary as BinaryCurve;
|
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\Prime as PrimeCurve;
|
||||||
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
||||||
|
use phpseclib3\Crypt\EC\Curves\Curve25519;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Exception\UnsupportedCurveException;
|
use phpseclib3\Exception\UnsupportedCurveException;
|
||||||
use phpseclib3\File\ASN1;
|
use phpseclib3\File\ASN1;
|
||||||
use phpseclib3\File\ASN1\Maps;
|
use phpseclib3\File\ASN1\Maps;
|
||||||
@@ -274,6 +278,9 @@ trait Common
|
|||||||
*/
|
*/
|
||||||
public static function extractPoint($str, BaseCurve $curve)
|
public static function extractPoint($str, BaseCurve $curve)
|
||||||
{
|
{
|
||||||
|
if ($curve instanceof Montgomery) {
|
||||||
|
return [new BigInteger($str, 256)];
|
||||||
|
}
|
||||||
if ($curve instanceof TwistedEdwardsCurve) {
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
// first step of point deciding as discussed at the following URL's:
|
// first step of point deciding as discussed at the following URL's:
|
||||||
// https://tools.ietf.org/html/rfc8032#section-5.1.3
|
// https://tools.ietf.org/html/rfc8032#section-5.1.3
|
||||||
@@ -524,6 +531,54 @@ trait Common
|
|||||||
throw new UnsupportedCurveException('Curve cannot be serialized');
|
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
|
* Use Specified Curve
|
||||||
*
|
*
|
||||||
|
|||||||
+8
-6
@@ -33,6 +33,8 @@ use phpseclib3\Math\BigInteger;
|
|||||||
*/
|
*/
|
||||||
abstract class MontgomeryPrivate
|
abstract class MontgomeryPrivate
|
||||||
{
|
{
|
||||||
|
use Common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is invisible flag
|
* Is invisible flag
|
||||||
*
|
*
|
||||||
@@ -59,11 +61,11 @@ abstract class MontgomeryPrivate
|
|||||||
throw new \LengthException('The only supported lengths are 32 and 56');
|
throw new \LengthException('The only supported lengths are 32 and 56');
|
||||||
}
|
}
|
||||||
|
|
||||||
$components = ['curve' => $curve];
|
$components = [
|
||||||
$components['dA'] = new BigInteger($key, 256);
|
'curve' => $curve,
|
||||||
$curve->rangeCheck($components['dA']);
|
'dA' => new BigInteger($key, 256)
|
||||||
// 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['QA'] = self::deriveMontgomeryPublicKey($components);
|
||||||
|
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
||||||
@@ -96,6 +98,6 @@ abstract class MontgomeryPrivate
|
|||||||
throw new UnsupportedFormatException('MontgomeryPrivate private keys do not support encryption');
|
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);
|
$reflect = new \ReflectionClass($curve);
|
||||||
$name = $reflect->getShortName();
|
$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];
|
$oid = self::$curveOIDs[$name];
|
||||||
$aliases = array_filter(self::$curveOIDs, function ($v) use ($oid) {
|
$aliases = array_filter(self::$curveOIDs, function ($v) use ($oid) {
|
||||||
return $v == $oid;
|
return $v == $oid;
|
||||||
|
|||||||
@@ -132,8 +132,8 @@ abstract class PKCS1 extends Progenitor
|
|||||||
$components = [];
|
$components = [];
|
||||||
$components['curve'] = self::loadCurveByParam($key['parameters']);
|
$components['curve'] = self::loadCurveByParam($key['parameters']);
|
||||||
$components['dA'] = new BigInteger($key['privateKey'], 256);
|
$components['dA'] = new BigInteger($key['privateKey'], 256);
|
||||||
$components['QA'] = isset($ecPrivate['publicKey']) ?
|
$components['QA'] = isset($key['publicKey']) ?
|
||||||
self::extractPoint($ecPrivate['publicKey'], $components['curve']) :
|
self::extractPoint($key['publicKey'], $components['curve']) :
|
||||||
$components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
|
$components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
|
||||||
|
|
||||||
return $components;
|
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\Base as BaseCurve;
|
||||||
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
|
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
|
||||||
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
|
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\Ed25519;
|
||||||
use phpseclib3\Crypt\EC\Curves\Ed448;
|
use phpseclib3\Crypt\EC\Curves\Ed448;
|
||||||
use phpseclib3\Exception\UnsupportedCurveException;
|
|
||||||
use phpseclib3\File\ASN1;
|
use phpseclib3\File\ASN1;
|
||||||
use phpseclib3\File\ASN1\Maps;
|
use phpseclib3\File\ASN1\Maps;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
|
use phpseclib3\Math\Common\FiniteField\Integer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PKCS#8 Formatted EC Key Handler
|
* PKCS#8 Formatted EC Key Handler
|
||||||
@@ -48,14 +50,14 @@ abstract class PKCS8 extends Progenitor
|
|||||||
*
|
*
|
||||||
* @var array
|
* @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
|
* OID Value
|
||||||
*
|
*
|
||||||
* @var string
|
* @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
|
* 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-Ed25519':
|
||||||
case 'id-Ed448':
|
case 'id-Ed448':
|
||||||
return self::loadEdDSA($key);
|
return self::loadEdDSA($key);
|
||||||
|
case 'id-X25519':
|
||||||
|
case 'id-X448':
|
||||||
|
return self::loadECDH($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
|
$decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
|
||||||
@@ -158,20 +163,57 @@ abstract class PKCS8 extends Progenitor
|
|||||||
return $components;
|
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
|
* Convert an EC public key to the appropriate format
|
||||||
*
|
*
|
||||||
* @param BaseCurve $curve
|
* @param BaseCurve $curve
|
||||||
* @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
|
* @param Integer[] $publicKey
|
||||||
* @param array $options optional
|
* @param array $options optional
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
|
public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
|
||||||
{
|
{
|
||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
if ($curve instanceof MontgomeryCurve) {
|
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) {
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
@@ -195,7 +237,7 @@ abstract class PKCS8 extends Progenitor
|
|||||||
*
|
*
|
||||||
* @param BigInteger $privateKey
|
* @param BigInteger $privateKey
|
||||||
* @param BaseCurve $curve
|
* @param BaseCurve $curve
|
||||||
* @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
|
* @param Integer[] $publicKey
|
||||||
* @param string $secret optional
|
* @param string $secret optional
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @param array $options optional
|
* @param array $options optional
|
||||||
@@ -206,7 +248,13 @@ abstract class PKCS8 extends Progenitor
|
|||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
if ($curve instanceof MontgomeryCurve) {
|
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) {
|
if ($curve instanceof TwistedEdwardsCurve) {
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ abstract class XML
|
|||||||
|
|
||||||
$use_errors = libxml_use_internal_errors(true);
|
$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#');
|
$temp = self::isolateNamespace($key, 'http://www.w3.org/2009/xmldsig11#');
|
||||||
if ($temp) {
|
if ($temp) {
|
||||||
$key = $temp;
|
$key = $temp;
|
||||||
@@ -82,9 +86,6 @@ abstract class XML
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
if (substr($key, 0, 5) != '<?xml') {
|
|
||||||
$key = '<xml>' . $key . '</xml>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$dom->loadXML($key)) {
|
if (!$dom->loadXML($key)) {
|
||||||
libxml_use_internal_errors($use_errors);
|
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\Keys\PKCS1;
|
||||||
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
|
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
|
||||||
use phpseclib3\Crypt\Hash;
|
use phpseclib3\Crypt\Hash;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Exception\UnsupportedOperationException;
|
use phpseclib3\Exception\UnsupportedOperationException;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
|
|
||||||
@@ -59,18 +60,40 @@ final class PrivateKey extends EC implements Common\PrivateKey
|
|||||||
*/
|
*/
|
||||||
public function multiply($coordinates)
|
public function multiply($coordinates)
|
||||||
{
|
{
|
||||||
if ($this->curve instanceof MontgomeryCurve) {
|
if (self::$forcedEngine === 'OpenSSL') {
|
||||||
if ($this->curve instanceof Curve25519 && self::$engines['libsodium']) {
|
throw new BadConfigurationException('Engine OpenSSL is not supported for the multiplication operation');
|
||||||
return sodium_crypto_scalarmult($this->dA->toBytes(), $coordinates);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
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->convertInteger(new BigInteger(strrev($coordinates), 256))];
|
||||||
$point = $this->curve->multiplyPoint($point, $this->dA);
|
$point = $this->curve->multiplyPoint($point, $this->dA);
|
||||||
return strrev($point[0]->toBytes(true));
|
return strrev($point[0]->toBytes(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->curve instanceof TwistedEdwardsCurve) {
|
if (!$this->curve instanceof TwistedEdwardsCurve) {
|
||||||
$coordinates = "\0$coordinates";
|
$coordinates = "\0$coordinates";
|
||||||
}
|
}
|
||||||
|
|
||||||
$point = PKCS1::extractPoint($coordinates, $this->curve);
|
$point = PKCS1::extractPoint($coordinates, $this->curve);
|
||||||
$point = $this->curve->multiplyPoint($point, $this->dA);
|
$point = $this->curve->multiplyPoint($point, $this->dA);
|
||||||
if ($this->curve instanceof TwistedEdwardsCurve) {
|
if ($this->curve instanceof TwistedEdwardsCurve) {
|
||||||
@@ -104,11 +127,56 @@ final class PrivateKey extends EC implements Common\PrivateKey
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->curve instanceof TwistedEdwardsCurve) {
|
if (self::$forcedEngine === 'libsodium' && !$this->curve instanceof Ed25519) {
|
||||||
if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
|
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'));
|
$result = sodium_crypto_sign_detached($message, $this->withPassword()->toString('libsodium'));
|
||||||
return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) : $result;
|
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.
|
// contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not.
|
||||||
// quoting https://tools.ietf.org/html/rfc8032#section-8.5 ,
|
// 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;
|
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())) {
|
if (self::$forcedEngine === 'OpenSSL' && !function_exists('openssl_get_md_methods')) {
|
||||||
$signature = '';
|
throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for ECDSA');
|
||||||
// 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) {
|
// at this point $forcedEngine is either PHP or null. either that OR openssl_get_md_methods() exists
|
||||||
if ($shortFormat == 'ASN1') {
|
|
||||||
return $signature;
|
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());
|
||||||
}
|
}
|
||||||
|
} elseif (self::$forcedEngine === 'OpenSSL') {
|
||||||
extract(ASN1Signature::load($signature));
|
throw new BadConfigurationException('Engine OpenSSL is forced but unsupported for ECDSA / ' . $this->hash->getHash());
|
||||||
|
|
||||||
return $this->formatSignature($r, $s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use phpseclib3\Crypt\EC\Curves\Ed25519;
|
|||||||
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
|
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
|
||||||
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
|
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
|
||||||
use phpseclib3\Crypt\Hash;
|
use phpseclib3\Crypt\Hash;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Exception\UnsupportedOperationException;
|
use phpseclib3\Exception\UnsupportedOperationException;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
|
|
||||||
@@ -52,17 +53,62 @@ final class PublicKey extends EC implements Common\PublicKey
|
|||||||
return false;
|
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 ($this->curve instanceof TwistedEdwardsCurve) {
|
||||||
if ($shortFormat == 'SSH2') {
|
if ($shortFormat == 'SSH2') {
|
||||||
list(, $signature) = Strings::unpackSSH2('ss', $signature);
|
list(, $signature) = Strings::unpackSSH2('ss', $signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
|
if (self::$forcedEngine !== 'PHP') {
|
||||||
return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium'));
|
$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;
|
$curve = $this->curve;
|
||||||
if (strlen($signature) != 2 * $curve::SIZE) {
|
if (strlen($signature) != 2 * $curve::SIZE) {
|
||||||
return false;
|
return false;
|
||||||
@@ -115,18 +161,34 @@ final class PublicKey extends EC implements Common\PublicKey
|
|||||||
if ($params === false || count($params) != 2) {
|
if ($params === false || count($params) != 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
extract($params);
|
$r = $params['r'];
|
||||||
|
$s = $params['s'];
|
||||||
|
|
||||||
if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
|
if (self::$forcedEngine === 'OpenSSL' && !function_exists('openssl_get_md_methods')) {
|
||||||
$sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
|
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) {
|
if (self::$forcedEngine !== 'PHP') {
|
||||||
return (bool) $result;
|
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);
|
$n_1 = $order->subtract(self::$one);
|
||||||
if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) {
|
if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+107
-7
@@ -194,6 +194,15 @@ class Hash
|
|||||||
private static $maxwordrange128;
|
private static $maxwordrange128;
|
||||||
/**#@-*/
|
/**#@-*/
|
||||||
|
|
||||||
|
/**#@+
|
||||||
|
* AES_CMAC variables
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $k1;
|
||||||
|
private $k2;
|
||||||
|
/**#@-*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
@@ -286,7 +295,7 @@ class Hash
|
|||||||
public function setHash($hash)
|
public function setHash($hash)
|
||||||
{
|
{
|
||||||
$oldHash = $this->hashParam;
|
$oldHash = $this->hashParam;
|
||||||
$this->hashParam = $hash = strtolower($hash);
|
$this->hashParam = $hash = strtolower(str_replace('/', '-', $hash));
|
||||||
switch ($hash) {
|
switch ($hash) {
|
||||||
case 'umac-32':
|
case 'umac-32':
|
||||||
case 'umac-64':
|
case 'umac-64':
|
||||||
@@ -299,6 +308,14 @@ class Hash
|
|||||||
$this->length = abs(substr($hash, -3)) >> 3;
|
$this->length = abs(substr($hash, -3)) >> 3;
|
||||||
$this->algo = 'umac';
|
$this->algo = 'umac';
|
||||||
return;
|
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 'md2-96':
|
||||||
case 'md5-96':
|
case 'md5-96':
|
||||||
case 'sha1-96':
|
case 'sha1-96':
|
||||||
@@ -306,8 +323,8 @@ class Hash
|
|||||||
case 'sha256-96':
|
case 'sha256-96':
|
||||||
case 'sha384-96':
|
case 'sha384-96':
|
||||||
case 'sha512-96':
|
case 'sha512-96':
|
||||||
case 'sha512/224-96':
|
case 'sha512-224-96':
|
||||||
case 'sha512/256-96':
|
case 'sha512-256-96':
|
||||||
$hash = substr($hash, 0, -3);
|
$hash = substr($hash, 0, -3);
|
||||||
$this->length = 12; // 96 / 8 = 12
|
$this->length = 12; // 96 / 8 = 12
|
||||||
break;
|
break;
|
||||||
@@ -319,7 +336,7 @@ class Hash
|
|||||||
$this->length = 20;
|
$this->length = 20;
|
||||||
break;
|
break;
|
||||||
case 'sha224':
|
case 'sha224':
|
||||||
case 'sha512/224':
|
case 'sha512-224':
|
||||||
case 'sha3-224':
|
case 'sha3-224':
|
||||||
$this->length = 28;
|
$this->length = 28;
|
||||||
break;
|
break;
|
||||||
@@ -327,7 +344,7 @@ class Hash
|
|||||||
$this->paddingType = self::PADDING_KECCAK;
|
$this->paddingType = self::PADDING_KECCAK;
|
||||||
// fall-through
|
// fall-through
|
||||||
case 'sha256':
|
case 'sha256':
|
||||||
case 'sha512/256':
|
case 'sha512-256':
|
||||||
case 'sha3-256':
|
case 'sha3-256':
|
||||||
$this->length = 32;
|
$this->length = 32;
|
||||||
break;
|
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:
|
// PHP 7.1.0 introduced sha512/224 and sha512/256 support:
|
||||||
// http://php.net/ChangeLog-7.php#7.1.0
|
// http://php.net/ChangeLog-7.php#7.1.0
|
||||||
if (version_compare(PHP_VERSION, '7.1.0') < 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
|
// 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',
|
'22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD',
|
||||||
'96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2'
|
'96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2'
|
||||||
@@ -442,6 +459,15 @@ class Hash
|
|||||||
$this->opad = str_repeat(chr(0x5C), $b);
|
$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->algo = $hash;
|
||||||
|
|
||||||
$this->computeKey();
|
$this->computeKey();
|
||||||
@@ -977,6 +1003,69 @@ class Hash
|
|||||||
public function hash($text)
|
public function hash($text)
|
||||||
{
|
{
|
||||||
$algo = $this->algo;
|
$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 ($algo == 'umac') {
|
||||||
if ($this->recomputeAESKey) {
|
if ($this->recomputeAESKey) {
|
||||||
if (!is_string($this->nonce)) {
|
if (!is_string($this->nonce)) {
|
||||||
@@ -1790,6 +1879,17 @@ class Hash
|
|||||||
return pack('J*', ...$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
|
* __toString() magic method
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ abstract class PublicKeyLoader
|
|||||||
* @return AsymmetricKey
|
* @return AsymmetricKey
|
||||||
* @param string|array $key
|
* @param string|array $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
|
* @throws NoKeyLoadedException if key is not valid
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = false)
|
public static function load($key, $password = false)
|
||||||
{
|
{
|
||||||
|
|||||||
+14
-14
@@ -45,7 +45,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Block Length of the cipher
|
* Block Length of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
|
* @see Common\SymmetricKey::block_size
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $block_size = 8;
|
protected $block_size = 8;
|
||||||
@@ -53,7 +53,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* The Key
|
* The Key
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::key
|
* @see Common\SymmetricKey::key
|
||||||
* @see self::setKey()
|
* @see self::setKey()
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
@@ -62,7 +62,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* The Original (unpadded) Key
|
* The Original (unpadded) Key
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::key
|
* @see Common\SymmetricKey::key
|
||||||
* @see self::setKey()
|
* @see self::setKey()
|
||||||
* @see self::encrypt()
|
* @see self::encrypt()
|
||||||
* @see self::decrypt()
|
* @see self::decrypt()
|
||||||
@@ -73,7 +73,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Key Length (in bytes)
|
* Key Length (in bytes)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\RC2::setKeyLength()
|
* @see RC2::setKeyLength()
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $key_length = 16; // = 128 bits
|
protected $key_length = 16; // = 128 bits
|
||||||
@@ -81,7 +81,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
|
* @see Common\SymmetricKey::cipher_name_mcrypt
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $cipher_name_mcrypt = 'rc2';
|
protected $cipher_name_mcrypt = 'rc2';
|
||||||
@@ -89,7 +89,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Optimizing value while CFB-encrypting
|
* Optimizing value while CFB-encrypting
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
|
* @see Common\SymmetricKey::cfb_init_len
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $cfb_init_len = 500;
|
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()
|
* 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
|
* @param int $engine
|
||||||
* @return bool
|
* @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
|
* has more then 128 bytes in it, and set $key to a single null byte if
|
||||||
* it is empty.
|
* it is empty.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
|
* @see Common\SymmetricKey::setKey()
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param int|boolean $t1 optional Effective key length in bits.
|
* @param int|boolean $t1 optional Effective key length in bits.
|
||||||
* @throws \LengthException if the key length isn't supported
|
* @throws \LengthException if the key length isn't supported
|
||||||
@@ -426,8 +426,8 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Encrypts a block
|
* Encrypts a block
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock()
|
* @see Common\SymmetricKey::encryptBlock()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* @see Common\SymmetricKey::encrypt()
|
||||||
* @param string $in
|
* @param string $in
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@@ -470,8 +470,8 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Decrypts a block
|
* Decrypts a block
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock()
|
* @see Common\SymmetricKey::decryptBlock()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* @see Common\SymmetricKey::decrypt()
|
||||||
* @param string $in
|
* @param string $in
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@@ -514,7 +514,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Creates the key schedule
|
* Creates the key schedule
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
|
* @see Common\SymmetricKey::setupKey()
|
||||||
*/
|
*/
|
||||||
protected function setupKey()
|
protected function setupKey()
|
||||||
{
|
{
|
||||||
@@ -534,7 +534,7 @@ class RC2 extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the performance-optimized function for de/encrypt()
|
* Setup the performance-optimized function for de/encrypt()
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
|
* @see Common\SymmetricKey::setupInlineCrypt()
|
||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
|
|||||||
+8
-8
@@ -52,19 +52,19 @@ use phpseclib3\Crypt\Common\StreamCipher;
|
|||||||
class RC4 extends StreamCipher
|
class RC4 extends StreamCipher
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @see \phpseclib3\Crypt\RC4::_crypt()
|
* @see RC4::_crypt()
|
||||||
*/
|
*/
|
||||||
const ENCRYPT = 0;
|
const ENCRYPT = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see \phpseclib3\Crypt\RC4::_crypt()
|
* @see RC4::_crypt()
|
||||||
*/
|
*/
|
||||||
const DECRYPT = 1;
|
const DECRYPT = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key Length (in bytes)
|
* Key Length (in bytes)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\RC4::setKeyLength()
|
* @see RC4::setKeyLength()
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $key_length = 128; // = 1024 bits
|
protected $key_length = 128; // = 1024 bits
|
||||||
@@ -72,7 +72,7 @@ class RC4 extends StreamCipher
|
|||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
|
* @see Common\SymmetricKey::cipher_name_mcrypt
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $cipher_name_mcrypt = 'arcfour';
|
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()
|
* 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
|
* @param int $engine
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -159,7 +159,7 @@ class RC4 extends StreamCipher
|
|||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* @see Common\SymmetricKey::decrypt()
|
||||||
* @see self::crypt()
|
* @see self::crypt()
|
||||||
* @param string $plaintext
|
* @param string $plaintext
|
||||||
* @return string $ciphertext
|
* @return string $ciphertext
|
||||||
@@ -178,7 +178,7 @@ class RC4 extends StreamCipher
|
|||||||
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
||||||
* At least if the continuous buffer is disabled.
|
* At least if the continuous buffer is disabled.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* @see Common\SymmetricKey::encrypt()
|
||||||
* @see self::crypt()
|
* @see self::crypt()
|
||||||
* @param string $ciphertext
|
* @param string $ciphertext
|
||||||
* @return string $plaintext
|
* @return string $plaintext
|
||||||
@@ -214,7 +214,7 @@ class RC4 extends StreamCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the key (expansion)
|
* Setup the key (expansion)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
|
* @see Common\SymmetricKey::_setupKey()
|
||||||
*/
|
*/
|
||||||
protected function 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\Formats\Keys\PSS;
|
||||||
use phpseclib3\Crypt\RSA\PrivateKey;
|
use phpseclib3\Crypt\RSA\PrivateKey;
|
||||||
use phpseclib3\Crypt\RSA\PublicKey;
|
use phpseclib3\Crypt\RSA\PublicKey;
|
||||||
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Exception\InconsistentSetupException;
|
use phpseclib3\Exception\InconsistentSetupException;
|
||||||
use phpseclib3\Exception\UnsupportedAlgorithmException;
|
use phpseclib3\Exception\UnsupportedAlgorithmException;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
@@ -228,12 +229,11 @@ abstract class RSA extends AsymmetricKey
|
|||||||
protected static $enableBlinding = true;
|
protected static $enableBlinding = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenSSL configuration file name.
|
* Enable automatic salt length determination
|
||||||
*
|
*
|
||||||
* @see self::createKey()
|
* @var bool
|
||||||
* @var ?string
|
|
||||||
*/
|
*/
|
||||||
protected static $configFile;
|
protected static $autoSaltLength = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Smallest Prime
|
* Smallest Prime
|
||||||
@@ -256,6 +256,14 @@ abstract class RSA extends AsymmetricKey
|
|||||||
*/
|
*/
|
||||||
protected $publicExponent;
|
protected $publicExponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forced Engine
|
||||||
|
*
|
||||||
|
* @var ?string
|
||||||
|
* @see parent::forceEngine()
|
||||||
|
*/
|
||||||
|
protected static $forcedEngine = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the public exponent for key generation
|
* Sets the public exponent for key generation
|
||||||
*
|
*
|
||||||
@@ -280,18 +288,6 @@ abstract class RSA extends AsymmetricKey
|
|||||||
self::$smallestPrime = $val;
|
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
|
* 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 . ')');
|
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
|
$regSize = $bits >> 1; // divide by two to see how many bits P and Q would be
|
||||||
if ($regSize > self::$smallestPrime) {
|
if ($regSize > self::$smallestPrime) {
|
||||||
$num_primes = floor($bits / 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 ($num_primes == 2 && $bits >= 384 && self::$defaultExponent == 65537) {
|
||||||
if (!isset(self::$engines['PHP'])) {
|
// at this point the only two supported values for self::$forcedEngine are OpenSSL, PHP and null
|
||||||
self::useBestEngine();
|
// if it's either OpenSSL or null we'll use OpenSSL (if it's available)
|
||||||
}
|
if (self::$forcedEngine !== 'PHP' && function_exists('openssl_pkey_new')) {
|
||||||
|
|
||||||
// OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
|
|
||||||
if (self::$engines['OpenSSL']) {
|
|
||||||
$config = [];
|
$config = [];
|
||||||
if (self::$configFile) {
|
if (self::$configFile) {
|
||||||
$config['config'] = 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);
|
$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
|
return RSA::load($privatekeystr);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,22 +347,21 @@ abstract class RSA extends AsymmetricKey
|
|||||||
$e = new BigInteger(self::$defaultExponent);
|
$e = new BigInteger(self::$defaultExponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
$n = clone self::$one;
|
|
||||||
$exponents = $coefficients = $primes = [];
|
|
||||||
$lcm = [
|
|
||||||
'top' => clone self::$one,
|
|
||||||
'bottom' => false
|
|
||||||
];
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
$n = clone self::$one;
|
||||||
|
$exponents = $coefficients = $primes = [];
|
||||||
|
$lcm = [
|
||||||
|
'top' => clone self::$one,
|
||||||
|
'bottom' => false
|
||||||
|
];
|
||||||
|
|
||||||
for ($i = 1; $i <= $num_primes; $i++) {
|
for ($i = 1; $i <= $num_primes; $i++) {
|
||||||
if ($i != $num_primes) {
|
if ($i != $num_primes) {
|
||||||
$primes[$i] = BigInteger::randomPrime($regSize);
|
$primes[$i] = BigInteger::randomPrime($regSize);
|
||||||
} else {
|
} else {
|
||||||
extract(BigInteger::minMaxBits($bits));
|
$minMax = BigInteger::minMaxBits($bits);
|
||||||
/** @var BigInteger $min
|
$min = $minMax['min'];
|
||||||
* @var BigInteger $max
|
$max = $minMax['max'];
|
||||||
*/
|
|
||||||
list($min) = $min->divide($n);
|
list($min) = $min->divide($n);
|
||||||
$min = $min->add(self::$one);
|
$min = $min->add(self::$one);
|
||||||
list($max) = $max->divide($n);
|
list($max) = $max->divide($n);
|
||||||
@@ -479,18 +480,6 @@ abstract class RSA extends AsymmetricKey
|
|||||||
return $key;
|
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
|
* Constructor
|
||||||
*
|
*
|
||||||
@@ -582,6 +571,22 @@ abstract class RSA extends AsymmetricKey
|
|||||||
break;
|
break;
|
||||||
case 'sha512/256':
|
case 'sha512/256':
|
||||||
$t = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x05\x00\x04\x20";
|
$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;
|
$t .= $h;
|
||||||
$tLen = strlen($t);
|
$tLen = strlen($t);
|
||||||
@@ -639,6 +644,22 @@ abstract class RSA extends AsymmetricKey
|
|||||||
case 'sha512/256':
|
case 'sha512/256':
|
||||||
$t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x04\x20";
|
$t = "\x30\x2f\x30\x0b\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06\x04\x20";
|
||||||
break;
|
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:
|
default:
|
||||||
throw new UnsupportedAlgorithmException('md2 and md5 require NULLs');
|
throw new UnsupportedAlgorithmException('md2 and md5 require NULLs');
|
||||||
}
|
}
|
||||||
@@ -714,11 +735,15 @@ abstract class RSA extends AsymmetricKey
|
|||||||
case 'sha224':
|
case 'sha224':
|
||||||
case 'sha512/224':
|
case 'sha512/224':
|
||||||
case 'sha512/256':
|
case 'sha512/256':
|
||||||
|
case 'sha3/224':
|
||||||
|
case 'sha3/256':
|
||||||
|
case 'sha3/384':
|
||||||
|
case 'sha3/512':
|
||||||
$new->hash = new Hash($hash);
|
$new->hash = new Hash($hash);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedAlgorithmException(
|
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();
|
$new->hLen = $new->hash->getLengthInBytes();
|
||||||
@@ -749,11 +774,15 @@ abstract class RSA extends AsymmetricKey
|
|||||||
case 'sha224':
|
case 'sha224':
|
||||||
case 'sha512/224':
|
case 'sha512/224':
|
||||||
case 'sha512/256':
|
case 'sha512/256':
|
||||||
|
case 'sha3/224':
|
||||||
|
case 'sha3/256':
|
||||||
|
case 'sha3/384':
|
||||||
|
case 'sha3/512':
|
||||||
$new->mgfHash = new Hash($hash);
|
$new->mgfHash = new Hash($hash);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedAlgorithmException(
|
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();
|
$new->mgfHLen = $new->mgfHash->getLengthInBytes();
|
||||||
@@ -763,7 +792,6 @@ abstract class RSA extends AsymmetricKey
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MGF hash algorithm currently being used
|
* Returns the MGF hash algorithm currently being used
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public function getMGFHash()
|
public function getMGFHash()
|
||||||
{
|
{
|
||||||
@@ -892,28 +920,6 @@ abstract class RSA extends AsymmetricKey
|
|||||||
return $this->signaturePadding | $this->encryptionPadding;
|
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
|
* Enable RSA Blinding
|
||||||
*
|
*
|
||||||
@@ -931,4 +937,241 @@ abstract class RSA extends AsymmetricKey
|
|||||||
{
|
{
|
||||||
static::$enableBlinding = false;
|
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
|
// PUBLICKEYSTRUC publickeystruc
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx
|
||||||
extract(unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8)));
|
$unpacked = unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8));
|
||||||
/**
|
$type = $unpacked['type'];
|
||||||
* @var string $type
|
$version = $unpacked['version'];
|
||||||
* @var string $version
|
$reserved = $unpacked['reserved'];
|
||||||
* @var integer $reserved
|
$algo = $unpacked['algo'];
|
||||||
* @var integer $algo
|
|
||||||
*/
|
|
||||||
switch (ord($type)) {
|
switch (ord($type)) {
|
||||||
case self::PUBLICKEYBLOB:
|
case self::PUBLICKEYBLOB:
|
||||||
case self::PUBLICKEYBLOBEX:
|
case self::PUBLICKEYBLOBEX:
|
||||||
@@ -121,12 +119,10 @@ abstract class MSBLOB
|
|||||||
// RSAPUBKEY rsapubkey
|
// RSAPUBKEY rsapubkey
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx
|
// 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
|
// 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)));
|
$unpacked = unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12));
|
||||||
/**
|
$magic = $unpacked['magic'];
|
||||||
* @var integer $magic
|
$bitlen = $unpacked['bitlen'];
|
||||||
* @var integer $bitlen
|
$pubexp = $unpacked['pubexp'];
|
||||||
* @var string $pubexp
|
|
||||||
*/
|
|
||||||
switch ($magic) {
|
switch ($magic) {
|
||||||
case self::RSA2:
|
case self::RSA2:
|
||||||
$components['isPublicKey'] = false;
|
$components['isPublicKey'] = false;
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ abstract class PKCS1 extends Progenitor
|
|||||||
|
|
||||||
$key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP);
|
$key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP);
|
||||||
if (is_array($key)) {
|
if (is_array($key)) {
|
||||||
|
if ($key['version'] === false) {
|
||||||
|
throw new \UnexpectedValueException('Version number is not valid');
|
||||||
|
}
|
||||||
$components += [
|
$components += [
|
||||||
'modulus' => $key['modulus'],
|
'modulus' => $key['modulus'],
|
||||||
'publicExponent' => $key['publicExponent'],
|
'publicExponent' => $key['publicExponent'],
|
||||||
@@ -96,6 +99,20 @@ abstract class PKCS1 extends Progenitor
|
|||||||
$components['isPublicKey'] = true;
|
$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;
|
return $components + $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,4 +174,17 @@ abstract class PKCS1 extends Progenitor
|
|||||||
|
|
||||||
return self::wrapPublicKey($key, 'RSA');
|
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['hash'] = str_replace('id-', '', $params['hashAlgorithm']['algorithm']);
|
||||||
$result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']);
|
$result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']);
|
||||||
if (isset($params['saltLength'])) {
|
if (isset($params['saltLength'])) {
|
||||||
$result['saltLength'] = (int) $params['saltLength']->toString();
|
$result['saltLength'] = (int) "$params[saltLength]";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($key['meta'])) {
|
if (isset($key['meta'])) {
|
||||||
|
|||||||
@@ -56,7 +56,10 @@ abstract class PuTTY extends Progenitor
|
|||||||
if (!isset($components['private'])) {
|
if (!isset($components['private'])) {
|
||||||
return $components;
|
return $components;
|
||||||
}
|
}
|
||||||
extract($components);
|
$type = $components['type'];
|
||||||
|
$comment = $components['comment'];
|
||||||
|
$public = $components['public'];
|
||||||
|
$private = $components['private'];
|
||||||
unset($components['public'], $components['private']);
|
unset($components['public'], $components['private']);
|
||||||
|
|
||||||
$isPublicKey = false;
|
$isPublicKey = false;
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ final class PrivateKey extends RSA implements Common\PrivateKey
|
|||||||
$db = $ps . chr(1) . $salt;
|
$db = $ps . chr(1) . $salt;
|
||||||
$dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); // ie. stlren($db)
|
$dbMask = $this->mgf1($h, $emLen - $this->hLen - 1); // ie. stlren($db)
|
||||||
$maskedDB = $db ^ $dbMask;
|
$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);
|
$em = $maskedDB . $h . chr(0xBC);
|
||||||
|
|
||||||
return $em;
|
return $em;
|
||||||
@@ -288,6 +288,11 @@ final class PrivateKey extends RSA implements Common\PrivateKey
|
|||||||
*/
|
*/
|
||||||
public function sign($message)
|
public function sign($message)
|
||||||
{
|
{
|
||||||
|
$result = $this->handleOpenSSL('openssl_sign', $message);
|
||||||
|
if ($result !== null) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($this->signaturePadding) {
|
switch ($this->signaturePadding) {
|
||||||
case self::SIGNATURE_PKCS1:
|
case self::SIGNATURE_PKCS1:
|
||||||
case self::SIGNATURE_RELAXED_PKCS1:
|
case self::SIGNATURE_RELAXED_PKCS1:
|
||||||
@@ -434,6 +439,11 @@ final class PrivateKey extends RSA implements Common\PrivateKey
|
|||||||
*/
|
*/
|
||||||
public function decrypt($ciphertext)
|
public function decrypt($ciphertext)
|
||||||
{
|
{
|
||||||
|
$result = $this->handleOpenSSL('openssl_private_decrypt', $ciphertext);
|
||||||
|
if ($result !== null) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($this->encryptionPadding) {
|
switch ($this->encryptionPadding) {
|
||||||
case self::ENCRYPTION_NONE:
|
case self::ENCRYPTION_NONE:
|
||||||
return $this->raw_encrypt($ciphertext);
|
return $this->raw_encrypt($ciphertext);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ final class PublicKey extends RSA implements Common\PublicKey
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compare
|
// Compare
|
||||||
return $r1 || $r2;
|
return boolval($r1 | $r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,7 +228,11 @@ final class PublicKey extends RSA implements Common\PublicKey
|
|||||||
// be output.
|
// be output.
|
||||||
|
|
||||||
$emLen = ($emBits + 7) >> 3; // ie. ceil($emBits / 8);
|
$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);
|
$mHash = $this->hash->hash($m);
|
||||||
if ($emLen < $this->hLen + $sLen + 2) {
|
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);
|
$maskedDB = substr($em, 0, -$this->hLen - 1);
|
||||||
$h = substr($em, -$this->hLen - 1, $this->hLen);
|
$h = substr($em, -$this->hLen - 1, $this->hLen);
|
||||||
$temp = chr(0xFF << ($emBits & 7));
|
$temp = chr(256 - (1 << ($emBits & 7)));
|
||||||
if ((~$maskedDB[0] & $temp) != $temp) {
|
if ((~$maskedDB[0] & $temp) != $temp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$dbMask = $this->mgf1($h, $emLen - $this->hLen - 1);
|
$dbMask = $this->mgf1($h, $emLen - $this->hLen - 1);
|
||||||
$db = $maskedDB ^ $dbMask;
|
$db = $maskedDB ^ $dbMask;
|
||||||
$db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0];
|
$db[0] = ~chr(256 - (1 << ($emBits & 7))) & $db[0];
|
||||||
$temp = $emLen - $this->hLen - $sLen - 2;
|
|
||||||
if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) {
|
// 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;
|
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;
|
$m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt;
|
||||||
$h2 = $this->hash->hash($m2);
|
$h2 = $this->hash->hash($m2);
|
||||||
return hash_equals($h, $h2);
|
return hash_equals($h, $h2);
|
||||||
@@ -301,6 +311,11 @@ final class PublicKey extends RSA implements Common\PublicKey
|
|||||||
*/
|
*/
|
||||||
public function verify($message, $signature)
|
public function verify($message, $signature)
|
||||||
{
|
{
|
||||||
|
$result = $this->handleOpenSSL('openssl_verify', $message, $signature);
|
||||||
|
if ($result !== null) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($this->signaturePadding) {
|
switch ($this->signaturePadding) {
|
||||||
case self::SIGNATURE_RELAXED_PKCS1:
|
case self::SIGNATURE_RELAXED_PKCS1:
|
||||||
return $this->rsassa_pkcs1_v1_5_relaxed_verify($message, $signature);
|
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)
|
public function encrypt($plaintext)
|
||||||
{
|
{
|
||||||
|
$result = $this->handleOpenSSL('openssl_public_encrypt', $plaintext);
|
||||||
|
if ($result !== null) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($this->encryptionPadding) {
|
switch ($this->encryptionPadding) {
|
||||||
case self::ENCRYPTION_NONE:
|
case self::ENCRYPTION_NONE:
|
||||||
return $this->raw_encrypt($plaintext);
|
return $this->raw_encrypt($plaintext);
|
||||||
|
|||||||
+31
-21
@@ -74,8 +74,8 @@ class Rijndael extends BlockCipher
|
|||||||
* or not for the current $block_size/$key_length.
|
* or not for the current $block_size/$key_length.
|
||||||
* In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
|
* In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
|
* @see Common\SymmetricKey::cipher_name_mcrypt
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::engine
|
* @see Common\SymmetricKey::engine
|
||||||
* @see self::isValidEngine()
|
* @see self::isValidEngine()
|
||||||
* @var string
|
* @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()
|
* 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
|
* @param int $engine
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -378,7 +378,7 @@ class Rijndael extends BlockCipher
|
|||||||
$k = $c[2];
|
$k = $c[2];
|
||||||
$l = $c[3];
|
$l = $c[3];
|
||||||
while ($i < $Nb) {
|
while ($i < $Nb) {
|
||||||
$temp[$i] = ($state[$i] & intval(0xFF000000)) ^
|
$temp[$i] = ($state[$i] & (PHP_INT_SIZE == 8 ? 0xFF000000 : -16777216)) ^
|
||||||
($state[$j] & 0x00FF0000) ^
|
($state[$j] & 0x00FF0000) ^
|
||||||
($state[$k] & 0x0000FF00) ^
|
($state[$k] & 0x0000FF00) ^
|
||||||
($state[$l] & 0x000000FF) ^
|
($state[$l] & 0x000000FF) ^
|
||||||
@@ -452,7 +452,7 @@ class Rijndael extends BlockCipher
|
|||||||
$l = $Nb - $c[3];
|
$l = $Nb - $c[3];
|
||||||
|
|
||||||
while ($i < $Nb) {
|
while ($i < $Nb) {
|
||||||
$word = ($state[$i] & intval(0xFF000000)) |
|
$word = ($state[$i] & (PHP_INT_SIZE == 8 ? 0xFF000000 : -16777216)) |
|
||||||
($state[$j] & 0x00FF0000) |
|
($state[$j] & 0x00FF0000) |
|
||||||
($state[$k] & 0x0000FF00) |
|
($state[$k] & 0x0000FF00) |
|
||||||
($state[$l] & 0x000000FF);
|
($state[$l] & 0x000000FF);
|
||||||
@@ -511,7 +511,7 @@ class Rijndael extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the key (expansion)
|
* Setup the key (expansion)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
|
* Common\SymmetricKey::setupKey()
|
||||||
*/
|
*/
|
||||||
protected function setupKey()
|
protected function setupKey()
|
||||||
{
|
{
|
||||||
@@ -528,7 +528,7 @@ class Rijndael extends BlockCipher
|
|||||||
0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
|
0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
|
||||||
0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
|
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']) {
|
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,
|
// 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'
|
// 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.
|
// 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];
|
$temp = $this->subWord($temp) ^ $rcon[$i / $this->Nk];
|
||||||
} elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
|
} elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
|
||||||
$temp = $this->subWord($temp);
|
$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),
|
// 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
|
// 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.
|
// 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
|
// with array_map('intval', ...) we ensure we have only int's and not
|
||||||
// some slower floats converted by php automatically on high values
|
// some slower floats converted by php automatically on high values
|
||||||
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
|
0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
|
||||||
@@ -697,9 +699,9 @@ class Rijndael extends BlockCipher
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($t3 as $t3i) {
|
foreach ($t3 as $t3i) {
|
||||||
$t0[] = (($t3i << 24) & intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF);
|
$t0[] = (($t3i << 24) & self::safe_intval(0xFF000000)) | (($t3i >> 8) & 0x00FFFFFF);
|
||||||
$t1[] = (($t3i << 16) & intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF);
|
$t1[] = (($t3i << 16) & self::safe_intval(0xFFFF0000)) | (($t3i >> 16) & 0x0000FFFF);
|
||||||
$t2[] = (($t3i << 8) & intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF);
|
$t2[] = (($t3i << 8) & self::safe_intval(0xFFFFFF00)) | (($t3i >> 24) & 0x000000FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tables = [
|
$tables = [
|
||||||
@@ -744,7 +746,7 @@ class Rijndael extends BlockCipher
|
|||||||
{
|
{
|
||||||
static $tables;
|
static $tables;
|
||||||
if (empty($tables)) {
|
if (empty($tables)) {
|
||||||
$dt3 = array_map('intval', [
|
$dt3 = array_map([self::class, 'safe_intval'], [
|
||||||
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
|
0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
|
||||||
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
|
0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
|
||||||
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
|
0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
|
||||||
@@ -779,11 +781,19 @@ class Rijndael extends BlockCipher
|
|||||||
0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
|
0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
foreach ($dt3 as $dt3i) {
|
if (PHP_INT_SIZE === 8) {
|
||||||
$dt0[] = (($dt3i << 24) & intval(0xFF000000)) | (($dt3i >> 8) & 0x00FFFFFF);
|
foreach ($dt3 as $dt3i) {
|
||||||
$dt1[] = (($dt3i << 16) & intval(0xFFFF0000)) | (($dt3i >> 16) & 0x0000FFFF);
|
$dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF);
|
||||||
$dt2[] = (($dt3i << 8) & intval(0xFFFFFF00)) | (($dt3i >> 24) & 0x000000FF);
|
$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 = [
|
$tables = [
|
||||||
// The Precomputed inverse mixColumns tables dt0 - dt3
|
// The Precomputed inverse mixColumns tables dt0 - dt3
|
||||||
@@ -818,7 +828,7 @@ class Rijndael extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the performance-optimized function for de/encrypt()
|
* Setup the performance-optimized function for de/encrypt()
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
|
* Common\SymmetricKey::setupInlineCrypt()
|
||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
@@ -879,7 +889,7 @@ class Rijndael extends BlockCipher
|
|||||||
$encrypt_block .= '$in = pack("N*"' . "\n";
|
$encrypt_block .= '$in = pack("N*"' . "\n";
|
||||||
for ($i = 0; $i < $Nb; ++$i) {
|
for ($i = 0; $i < $Nb; ++$i) {
|
||||||
$encrypt_block .= ',
|
$encrypt_block .= ',
|
||||||
($' . $e . $i . ' & ' . ((int)0xFF000000) . ') ^
|
($' . $e . $i . ' & ' . (PHP_INT_SIZE == 8 ? 0xFF000000 : -16777216) . ') ^
|
||||||
($' . $e . (($i + $c[1]) % $Nb) . ' & 0x00FF0000 ) ^
|
($' . $e . (($i + $c[1]) % $Nb) . ' & 0x00FF0000 ) ^
|
||||||
($' . $e . (($i + $c[2]) % $Nb) . ' & 0x0000FF00 ) ^
|
($' . $e . (($i + $c[2]) % $Nb) . ' & 0x0000FF00 ) ^
|
||||||
($' . $e . (($i + $c[3]) % $Nb) . ' & 0x000000FF ) ^
|
($' . $e . (($i + $c[3]) % $Nb) . ' & 0x000000FF ) ^
|
||||||
@@ -935,7 +945,7 @@ class Rijndael extends BlockCipher
|
|||||||
$decrypt_block .= '$in = pack("N*"' . "\n";
|
$decrypt_block .= '$in = pack("N*"' . "\n";
|
||||||
for ($i = 0; $i < $Nb; ++$i) {
|
for ($i = 0; $i < $Nb; ++$i) {
|
||||||
$decrypt_block .= ',
|
$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[1]) % $Nb) . ' & 0x00FF0000 ) ^
|
||||||
($' . $e . (($Nb + $i - $c[2]) % $Nb) . ' & 0x0000FF00 ) ^
|
($' . $e . (($Nb + $i - $c[2]) % $Nb) . ' & 0x0000FF00 ) ^
|
||||||
($' . $e . (($Nb + $i - $c[3]) % $Nb) . ' & 0x000000FF ) ^
|
($' . $e . (($Nb + $i - $c[3]) % $Nb) . ' & 0x000000FF ) ^
|
||||||
|
|||||||
@@ -47,12 +47,12 @@ class Salsa20 extends StreamCipher
|
|||||||
protected $key_length = 32; // = 256 bits
|
protected $key_length = 32; // = 256 bits
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see \phpseclib3\Crypt\Salsa20::crypt()
|
* @see Salsa20::crypt()
|
||||||
*/
|
*/
|
||||||
const ENCRYPT = 0;
|
const ENCRYPT = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see \phpseclib3\Crypt\Salsa20::crypt()
|
* @see Salsa20::crypt()
|
||||||
*/
|
*/
|
||||||
const DECRYPT = 1;
|
const DECRYPT = 1;
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ class Salsa20 extends StreamCipher
|
|||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* @see SymmetricKey::decrypt()
|
||||||
* @see self::crypt()
|
* @see self::crypt()
|
||||||
* @param string $plaintext
|
* @param string $plaintext
|
||||||
* @return string $ciphertext
|
* @return string $ciphertext
|
||||||
@@ -256,7 +256,7 @@ class Salsa20 extends StreamCipher
|
|||||||
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
||||||
* At least if the continuous buffer is disabled.
|
* At least if the continuous buffer is disabled.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* @see SymmetricKey::encrypt()
|
||||||
* @see self::crypt()
|
* @see self::crypt()
|
||||||
* @param string $ciphertext
|
* @param string $ciphertext
|
||||||
* @return string $plaintext
|
* @return string $plaintext
|
||||||
@@ -411,7 +411,7 @@ class Salsa20 extends StreamCipher
|
|||||||
$r1 &= 0xFFFFFFFF;
|
$r1 &= 0xFFFFFFFF;
|
||||||
$r2 = ($x & 0xFFFFFFFF) >> (32 - $n);
|
$r2 = ($x & 0xFFFFFFFF) >> (32 - $n);
|
||||||
} else {
|
} else {
|
||||||
$x = (int) $x;
|
$x = self::safe_intval($x);
|
||||||
$r1 = $x << $n;
|
$r1 = $x << $n;
|
||||||
$r2 = $x >> (32 - $n);
|
$r2 = $x >> (32 - $n);
|
||||||
$r2 &= (1 << $n) - 1;
|
$r2 &= (1 << $n) - 1;
|
||||||
@@ -482,7 +482,7 @@ class Salsa20 extends StreamCipher
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ($i = 1; $i <= 16; $i++) {
|
for ($i = 1; $i <= 16; $i++) {
|
||||||
$x[$i] += $z[$i];
|
$x[$i] = self::safe_intval($x[$i] + $z[$i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pack('V*', ...$x);
|
return pack('V*', ...$x);
|
||||||
|
|||||||
+20
-20
@@ -58,7 +58,7 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Key Length (in bytes)
|
* Key Length (in bytes)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\TripleDES::setKeyLength()
|
* @see TripleDES::setKeyLength()
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $key_length = 24;
|
protected $key_length = 24;
|
||||||
@@ -66,8 +66,8 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\DES::cipher_name_mcrypt
|
* @see DES::cipher_name_mcrypt
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
|
* @see Common\SymmetricKey::cipher_name_mcrypt
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $cipher_name_mcrypt = 'tripledes';
|
protected $cipher_name_mcrypt = 'tripledes';
|
||||||
@@ -75,7 +75,7 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Optimizing value while CFB-encrypting
|
* Optimizing value while CFB-encrypting
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
|
* @see Common\SymmetricKey::cfb_init_len
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $cfb_init_len = 750;
|
protected $cfb_init_len = 750;
|
||||||
@@ -84,7 +84,7 @@ class TripleDES extends DES
|
|||||||
* max possible size of $key
|
* max possible size of $key
|
||||||
*
|
*
|
||||||
* @see self::setKey()
|
* @see self::setKey()
|
||||||
* @see \phpseclib3\Crypt\DES::setKey()
|
* @see DES::setKey()
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $key_length_max = 24;
|
protected $key_length_max = 24;
|
||||||
@@ -126,8 +126,8 @@ class TripleDES extends DES
|
|||||||
*
|
*
|
||||||
* - cbc3 (same as cbc)
|
* - cbc3 (same as cbc)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\DES::__construct()
|
* @see Crypt\DES::__construct()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* @see Common\SymmetricKey::__construct()
|
||||||
* @param string $mode
|
* @param string $mode
|
||||||
*/
|
*/
|
||||||
public function __construct($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()
|
* 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
|
* @param int $engine
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@@ -189,7 +189,7 @@ class TripleDES extends DES
|
|||||||
*
|
*
|
||||||
* SetIV is not required when \phpseclib3\Crypt\Common\SymmetricKey::MODE_ECB is being used.
|
* 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
|
* @param string $iv
|
||||||
*/
|
*/
|
||||||
public function setIV($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
|
* 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
|
* @throws \LengthException if the key length is invalid
|
||||||
* @param int $length
|
* @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.
|
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\DES::setKey()
|
* @see DES::setKey()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
|
* @see Common\SymmetricKey::setKey()
|
||||||
* @throws \LengthException if the key length is invalid
|
* @throws \LengthException if the key length is invalid
|
||||||
* @param string $key
|
* @param string $key
|
||||||
*/
|
*/
|
||||||
@@ -270,7 +270,7 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Encrypts a message.
|
* Encrypts a message.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
|
* @see Common\SymmetricKey::encrypt()
|
||||||
* @param string $plaintext
|
* @param string $plaintext
|
||||||
* @return string $cipertext
|
* @return string $cipertext
|
||||||
*/
|
*/
|
||||||
@@ -296,7 +296,7 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Decrypts a message.
|
* Decrypts a message.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
|
* @see Common\SymmetricKey::decrypt()
|
||||||
* @param string $ciphertext
|
* @param string $ciphertext
|
||||||
* @return string $plaintext
|
* @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),
|
* 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.
|
* 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()
|
* @see self::disableContinuousBuffer()
|
||||||
*/
|
*/
|
||||||
public function enableContinuousBuffer()
|
public function enableContinuousBuffer()
|
||||||
@@ -369,7 +369,7 @@ class TripleDES extends DES
|
|||||||
*
|
*
|
||||||
* The default behavior.
|
* The default behavior.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer()
|
* @see Common\SymmetricKey::disableContinuousBuffer()
|
||||||
* @see self::enableContinuousBuffer()
|
* @see self::enableContinuousBuffer()
|
||||||
*/
|
*/
|
||||||
public function disableContinuousBuffer()
|
public function disableContinuousBuffer()
|
||||||
@@ -385,8 +385,8 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Creates the key schedule
|
* Creates the key schedule
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\DES::setupKey()
|
* @see DES::setupKey()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
|
* @see Common\SymmetricKey::setupKey()
|
||||||
*/
|
*/
|
||||||
protected function setupKey()
|
protected function setupKey()
|
||||||
{
|
{
|
||||||
@@ -419,8 +419,8 @@ class TripleDES extends DES
|
|||||||
/**
|
/**
|
||||||
* Sets the internal crypt engine
|
* Sets the internal crypt engine
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
|
* @see Common\SymmetricKey::__construct()
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::setPreferredEngine()
|
* @see Common\SymmetricKey::setPreferredEngine()
|
||||||
* @param int $engine
|
* @param int $engine
|
||||||
*/
|
*/
|
||||||
public function setPreferredEngine($engine)
|
public function setPreferredEngine($engine)
|
||||||
|
|||||||
+10
-10
@@ -49,7 +49,7 @@ class Twofish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* The mcrypt specific name of the cipher
|
* The mcrypt specific name of the cipher
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
|
* @see Common\SymmetricKey::cipher_name_mcrypt
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $cipher_name_mcrypt = 'twofish';
|
protected $cipher_name_mcrypt = 'twofish';
|
||||||
@@ -57,7 +57,7 @@ class Twofish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Optimizing value while CFB-encrypting
|
* Optimizing value while CFB-encrypting
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
|
* @see Common\SymmetricKey::cfb_init_len
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $cfb_init_len = 800;
|
protected $cfb_init_len = 800;
|
||||||
@@ -373,12 +373,12 @@ class Twofish extends BlockCipher
|
|||||||
protected static function initialize_static_variables()
|
protected static function initialize_static_variables()
|
||||||
{
|
{
|
||||||
if (is_float(self::$m3[0])) {
|
if (is_float(self::$m3[0])) {
|
||||||
self::$m0 = array_map('intval', self::$m0);
|
self::$m0 = array_map([self::class, 'safe_intval'], self::$m0);
|
||||||
self::$m1 = array_map('intval', self::$m1);
|
self::$m1 = array_map([self::class, 'safe_intval'], self::$m1);
|
||||||
self::$m2 = array_map('intval', self::$m2);
|
self::$m2 = array_map([self::class, 'safe_intval'], self::$m2);
|
||||||
self::$m3 = array_map('intval', self::$m3);
|
self::$m3 = array_map([self::class, 'safe_intval'], self::$m3);
|
||||||
self::$q0 = array_map('intval', self::$q0);
|
self::$q0 = array_map([self::class, 'safe_intval'], self::$q0);
|
||||||
self::$q1 = array_map('intval', self::$q1);
|
self::$q1 = array_map([self::class, 'safe_intval'], self::$q1);
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::initialize_static_variables();
|
parent::initialize_static_variables();
|
||||||
@@ -431,7 +431,7 @@ class Twofish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the key (expansion)
|
* Setup the key (expansion)
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
|
* @see Common\SymmetricKey::_setupKey()
|
||||||
*/
|
*/
|
||||||
protected function setupKey()
|
protected function setupKey()
|
||||||
{
|
{
|
||||||
@@ -700,7 +700,7 @@ class Twofish extends BlockCipher
|
|||||||
/**
|
/**
|
||||||
* Setup the performance-optimized function for de/encrypt()
|
* Setup the performance-optimized function for de/encrypt()
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
|
* @see Common\SymmetricKey::_setupInlineCrypt()
|
||||||
*/
|
*/
|
||||||
protected function setupInlineCrypt()
|
protected function setupInlineCrypt()
|
||||||
{
|
{
|
||||||
|
|||||||
+113
-15
@@ -131,6 +131,8 @@ abstract class ASN1
|
|||||||
*/
|
*/
|
||||||
private static $encoded;
|
private static $encoded;
|
||||||
|
|
||||||
|
private static $use64BitOIDHandling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type mapping table for the ANY type.
|
* Type mapping table for the ANY type.
|
||||||
*
|
*
|
||||||
@@ -190,6 +192,7 @@ abstract class ASN1
|
|||||||
*
|
*
|
||||||
* @param Element|string $encoded
|
* @param Element|string $encoded
|
||||||
* @return ?array
|
* @return ?array
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function decodeBER($encoded)
|
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
|
// tags of indefinte length don't really have a header length; this length includes the tag
|
||||||
$current += ['headerlength' => $length + 2];
|
$current += ['headerlength' => $length + 2];
|
||||||
$start += $length;
|
$start += $length;
|
||||||
extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
|
$length = unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4))['length'];
|
||||||
/** @var integer $length */
|
|
||||||
} else {
|
} else {
|
||||||
$current += ['headerlength' => 2];
|
$current += ['headerlength' => 2];
|
||||||
}
|
}
|
||||||
@@ -515,6 +517,7 @@ abstract class ASN1
|
|||||||
* @param array $mapping
|
* @param array $mapping
|
||||||
* @param array $special
|
* @param array $special
|
||||||
* @return array|bool|Element|string|null
|
* @return array|bool|Element|string|null
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function asn1map(array $decoded, $mapping, $special = [])
|
public static function asn1map(array $decoded, $mapping, $special = [])
|
||||||
{
|
{
|
||||||
@@ -537,7 +540,7 @@ abstract class ASN1
|
|||||||
case $mapping['type'] == self::TYPE_CHOICE:
|
case $mapping['type'] == self::TYPE_CHOICE:
|
||||||
foreach ($mapping['children'] as $key => $option) {
|
foreach ($mapping['children'] as $key => $option) {
|
||||||
switch (true) {
|
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']:
|
case !isset($option['constant']) && $option['type'] == $decoded['type']:
|
||||||
$value = self::asn1map($decoded, $option, $special);
|
$value = self::asn1map($decoded, $option, $special);
|
||||||
break;
|
break;
|
||||||
@@ -621,6 +624,13 @@ abstract class ASN1
|
|||||||
// Can only match if no constant expected and type matches or is generic.
|
// 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;
|
$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.
|
// 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;
|
$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) {
|
if ($maymatch) {
|
||||||
@@ -790,10 +805,17 @@ abstract class ASN1
|
|||||||
case self::TYPE_ENUMERATED:
|
case self::TYPE_ENUMERATED:
|
||||||
$temp = $decoded['content'];
|
$temp = $decoded['content'];
|
||||||
if (isset($mapping['implicit'])) {
|
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'])) {
|
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]) ?
|
return isset($mapping['mapping'][$temp]) ?
|
||||||
$mapping['mapping'][$temp] :
|
$mapping['mapping'][$temp] :
|
||||||
false;
|
false;
|
||||||
@@ -834,6 +856,7 @@ abstract class ASN1
|
|||||||
* @param array $mapping
|
* @param array $mapping
|
||||||
* @param array $special
|
* @param array $special
|
||||||
* @return string
|
* @return string
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function encodeDER($source, $mapping, $special = [])
|
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)."
|
an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
|
||||||
*/
|
*/
|
||||||
if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
|
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;
|
$temp = $subtag . self::encodeLength(strlen($temp)) . $temp;
|
||||||
} else {
|
} else {
|
||||||
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
|
$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;
|
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
|
* BER-decode the OID
|
||||||
*
|
*
|
||||||
@@ -1137,20 +1185,27 @@ abstract class ASN1
|
|||||||
*
|
*
|
||||||
* @param string $content
|
* @param string $content
|
||||||
* @return string
|
* @return string
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function decodeOID($content)
|
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;
|
static $eighty;
|
||||||
if (!$eighty) {
|
if (!$eighty) {
|
||||||
$eighty = new BigInteger(80);
|
$eighty = new BigInteger(80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isset(self::$use64BitOIDHandling)) {
|
||||||
|
self::$use64BitOIDHandling = PHP_INT_SIZE === 8;
|
||||||
|
}
|
||||||
|
|
||||||
$oid = [];
|
$oid = [];
|
||||||
$pos = 0;
|
$pos = 0;
|
||||||
$len = strlen($content);
|
$len = strlen($content);
|
||||||
// see https://github.com/openjdk/jdk/blob/2deb318c9f047ec5a4b160d66a4b52f93688ec42/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java#L55
|
// see https://github.com/openjdk/jdk/blob/2deb318c9f047ec5a4b160d66a4b52f93688ec42/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java#L55
|
||||||
if ($len > 4096) {
|
if ($len > 128) {
|
||||||
//throw new \RuntimeException("Object identifier size is limited to 4096 bytes ($len bytes present)");
|
//throw new \RuntimeException("Object identifier size is limited to 128 bytes ($len bytes present)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1159,13 +1214,50 @@ abstract class ASN1
|
|||||||
}
|
}
|
||||||
|
|
||||||
$n = new BigInteger();
|
$n = new BigInteger();
|
||||||
while ($pos < $len) {
|
$subn = $numBytes = 0;
|
||||||
$temp = ord($content[$pos++]);
|
if (self::$use64BitOIDHandling) {
|
||||||
$n = $n->bitwise_leftShift(7);
|
$prefix = '';
|
||||||
$n = $n->bitwise_or(new BigInteger($temp & 0x7F));
|
while ($pos < $len) {
|
||||||
if (~$temp & 0x80) {
|
$temp = ord($content[$pos++]);
|
||||||
$oid[] = $n;
|
$subn <<= 7;
|
||||||
$n = new BigInteger();
|
$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);
|
$part1 = array_shift($oid);
|
||||||
@@ -1252,6 +1344,7 @@ abstract class ASN1
|
|||||||
* @param string $content
|
* @param string $content
|
||||||
* @param int $tag
|
* @param int $tag
|
||||||
* @return \DateTime|false
|
* @return \DateTime|false
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
private static function decodeTime($content, $tag)
|
private static function decodeTime($content, $tag)
|
||||||
{
|
{
|
||||||
@@ -1297,6 +1390,7 @@ abstract class ASN1
|
|||||||
* Sets the time / date format for asn1map().
|
* Sets the time / date format for asn1map().
|
||||||
*
|
*
|
||||||
* @param string $format
|
* @param string $format
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function setTimeFormat($format)
|
public static function setTimeFormat($format)
|
||||||
{
|
{
|
||||||
@@ -1310,6 +1404,7 @@ abstract class ASN1
|
|||||||
* Previously loaded OIDs are retained.
|
* Previously loaded OIDs are retained.
|
||||||
*
|
*
|
||||||
* @param array $oids
|
* @param array $oids
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function loadOIDs(array $oids)
|
public static function loadOIDs(array $oids)
|
||||||
{
|
{
|
||||||
@@ -1324,6 +1419,7 @@ abstract class ASN1
|
|||||||
* Previously loaded filters are not retained.
|
* Previously loaded filters are not retained.
|
||||||
*
|
*
|
||||||
* @param array $filters
|
* @param array $filters
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function setFilters(array $filters)
|
public static function setFilters(array $filters)
|
||||||
{
|
{
|
||||||
@@ -1340,6 +1436,7 @@ abstract class ASN1
|
|||||||
* @param int $from
|
* @param int $from
|
||||||
* @param int $to
|
* @param int $to
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING)
|
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
|
* @param string $name
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function getOID($name)
|
public static function getOID($name)
|
||||||
{
|
{
|
||||||
|
|||||||
+138
-27
@@ -57,37 +57,37 @@ class X509
|
|||||||
/**
|
/**
|
||||||
* Return internal array representation
|
* Return internal array representation
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::getDN()
|
* @see X509::getDN()
|
||||||
*/
|
*/
|
||||||
const DN_ARRAY = 0;
|
const DN_ARRAY = 0;
|
||||||
/**
|
/**
|
||||||
* Return string
|
* Return string
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::getDN()
|
* @see X509::getDN()
|
||||||
*/
|
*/
|
||||||
const DN_STRING = 1;
|
const DN_STRING = 1;
|
||||||
/**
|
/**
|
||||||
* Return ASN.1 name string
|
* Return ASN.1 name string
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::getDN()
|
* @see X509::getDN()
|
||||||
*/
|
*/
|
||||||
const DN_ASN1 = 2;
|
const DN_ASN1 = 2;
|
||||||
/**
|
/**
|
||||||
* Return OpenSSL compatible array
|
* Return OpenSSL compatible array
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::getDN()
|
* @see X509::getDN()
|
||||||
*/
|
*/
|
||||||
const DN_OPENSSL = 3;
|
const DN_OPENSSL = 3;
|
||||||
/**
|
/**
|
||||||
* Return canonical ASN.1 RDNs string
|
* Return canonical ASN.1 RDNs string
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::getDN()
|
* @see X509::getDN()
|
||||||
*/
|
*/
|
||||||
const DN_CANON = 4;
|
const DN_CANON = 4;
|
||||||
/**
|
/**
|
||||||
* Return name hash for file indexing
|
* Return name hash for file indexing
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::getDN()
|
* @see X509::getDN()
|
||||||
*/
|
*/
|
||||||
const DN_HASH = 5;
|
const DN_HASH = 5;
|
||||||
|
|
||||||
@@ -96,25 +96,25 @@ class X509
|
|||||||
*
|
*
|
||||||
* ie. a base64-encoded PEM with a header and a footer
|
* ie. a base64-encoded PEM with a header and a footer
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::saveX509()
|
* @see X509::saveX509()
|
||||||
* @see \phpseclib3\File\X509::saveCSR()
|
* @see X509::saveCSR()
|
||||||
* @see \phpseclib3\File\X509::saveCRL()
|
* @see X509::saveCRL()
|
||||||
*/
|
*/
|
||||||
const FORMAT_PEM = 0;
|
const FORMAT_PEM = 0;
|
||||||
/**
|
/**
|
||||||
* Save as DER
|
* Save as DER
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::saveX509()
|
* @see X509::saveX509()
|
||||||
* @see \phpseclib3\File\X509::saveCSR()
|
* @see X509::saveCSR()
|
||||||
* @see \phpseclib3\File\X509::saveCRL()
|
* @see X509::saveCRL()
|
||||||
*/
|
*/
|
||||||
const FORMAT_DER = 1;
|
const FORMAT_DER = 1;
|
||||||
/**
|
/**
|
||||||
* Save as a SPKAC
|
* Save as a SPKAC
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::saveX509()
|
* @see X509::saveX509()
|
||||||
* @see \phpseclib3\File\X509::saveCSR()
|
* @see X509::saveCSR()
|
||||||
* @see \phpseclib3\File\X509::saveCRL()
|
* @see X509::saveCRL()
|
||||||
*
|
*
|
||||||
* Only works on CSRs. Not currently supported.
|
* Only works on CSRs. Not currently supported.
|
||||||
*/
|
*/
|
||||||
@@ -124,9 +124,9 @@ class X509
|
|||||||
*
|
*
|
||||||
* Used only by the load*() functions
|
* Used only by the load*() functions
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\File\X509::saveX509()
|
* @see X509::saveX509()
|
||||||
* @see \phpseclib3\File\X509::saveCSR()
|
* @see X509::saveCSR()
|
||||||
* @see \phpseclib3\File\X509::saveCRL()
|
* @see X509::saveCRL()
|
||||||
*/
|
*/
|
||||||
const FORMAT_AUTO_DETECT = 3;
|
const FORMAT_AUTO_DETECT = 3;
|
||||||
|
|
||||||
@@ -269,10 +269,18 @@ class X509
|
|||||||
*/
|
*/
|
||||||
private $domains = null;
|
private $domains = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL fetch callback
|
||||||
|
*
|
||||||
|
* @var string|array|null
|
||||||
|
*/
|
||||||
|
private static $urlFetchCallback = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor.
|
* Default Constructor.
|
||||||
*
|
*
|
||||||
* @return X509
|
* @return X509
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -315,6 +323,7 @@ class X509
|
|||||||
'id-at-uniqueIdentifier' => '2.5.4.45',
|
'id-at-uniqueIdentifier' => '2.5.4.45',
|
||||||
'id-at-role' => '2.5.4.72',
|
'id-at-role' => '2.5.4.72',
|
||||||
'id-at-postalAddress' => '2.5.4.16',
|
'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',
|
'jurisdictionOfIncorporationCountryName' => '1.3.6.1.4.1.311.60.2.1.3',
|
||||||
'jurisdictionOfIncorporationStateOrProvinceName' => '1.3.6.1.4.1.311.60.2.1.2',
|
'jurisdictionOfIncorporationStateOrProvinceName' => '1.3.6.1.4.1.311.60.2.1.2',
|
||||||
'jurisdictionLocalityName' => '1.3.6.1.4.1.311.60.2.1.1',
|
'jurisdictionLocalityName' => '1.3.6.1.4.1.311.60.2.1.1',
|
||||||
@@ -428,6 +437,7 @@ class X509
|
|||||||
* @param array|string $cert
|
* @param array|string $cert
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT)
|
public function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT)
|
||||||
{
|
{
|
||||||
@@ -501,6 +511,7 @@ class X509
|
|||||||
* @param array $cert
|
* @param array $cert
|
||||||
* @param int $format optional
|
* @param int $format optional
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function saveX509(array $cert, $format = self::FORMAT_PEM)
|
public function saveX509(array $cert, $format = self::FORMAT_PEM)
|
||||||
{
|
{
|
||||||
@@ -626,7 +637,9 @@ class X509
|
|||||||
$extensions = &$this->subArray($root, $path, !empty($this->extensionValues));
|
$extensions = &$this->subArray($root, $path, !empty($this->extensionValues));
|
||||||
|
|
||||||
foreach ($this->extensionValues as $id => $data) {
|
foreach ($this->extensionValues as $id => $data) {
|
||||||
extract($data);
|
$critical = $data['critical'];
|
||||||
|
$replace = $data['replace'];
|
||||||
|
$value = $data['value'];
|
||||||
$newext = [
|
$newext = [
|
||||||
'extnId' => $id,
|
'extnId' => $id,
|
||||||
'extnValue' => $value,
|
'extnValue' => $value,
|
||||||
@@ -956,6 +969,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param string $cert
|
* @param string $cert
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function loadCA($cert)
|
public function loadCA($cert)
|
||||||
{
|
{
|
||||||
@@ -1082,6 +1096,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param \DateTimeInterface|string $date optional
|
* @param \DateTimeInterface|string $date optional
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function validateDate($date = null)
|
public function validateDate($date = null)
|
||||||
{
|
{
|
||||||
@@ -1112,6 +1127,10 @@ class X509
|
|||||||
/**
|
/**
|
||||||
* Fetches a URL
|
* 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
|
* @param string $url
|
||||||
* @return bool|string
|
* @return bool|string
|
||||||
*/
|
*/
|
||||||
@@ -1122,25 +1141,58 @@ class X509
|
|||||||
}
|
}
|
||||||
|
|
||||||
$parts = parse_url($url);
|
$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 = '';
|
$data = '';
|
||||||
switch ($parts['scheme']) {
|
switch ($parts['scheme']) {
|
||||||
case 'http':
|
case 'http':
|
||||||
$fsock = @fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80);
|
$fsock = @fsockopen($target, $port);
|
||||||
if (!$fsock) {
|
if (!$fsock) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$path = $parts['path'];
|
$path = isset($parts['path']) ? $parts['path'] : '/';
|
||||||
if (isset($parts['query'])) {
|
if (isset($parts['query'])) {
|
||||||
$path .= '?' . $parts['query'];
|
$path .= '?' . $parts['query'];
|
||||||
}
|
}
|
||||||
fputs($fsock, "GET $path HTTP/1.0\r\n");
|
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);
|
$line = fgets($fsock, 1024);
|
||||||
if (strlen($line) < 3) {
|
if ($line === false || strlen($line) < 3) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
preg_match('#HTTP/1.\d (\d{3})#', $line, $temp);
|
if (!preg_match('#HTTP/1.\d (\d{3})#', $line, $temp) || $temp[1] != '200') {
|
||||||
if ($temp[1] != '200') {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1159,7 +1211,8 @@ class X509
|
|||||||
break;
|
break;
|
||||||
//case 'ftp':
|
//case 'ftp':
|
||||||
//case 'ldap':
|
//case 'ldap':
|
||||||
//default:
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
@@ -1239,6 +1292,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param bool $caonly optional
|
* @param bool $caonly optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function validateSignature($caonly = true)
|
public function validateSignature($caonly = true)
|
||||||
{
|
{
|
||||||
@@ -1470,6 +1524,7 @@ class X509
|
|||||||
/**
|
/**
|
||||||
* Prevents URIs from being automatically retrieved
|
* Prevents URIs from being automatically retrieved
|
||||||
*
|
*
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function disableURLFetch()
|
public static function disableURLFetch()
|
||||||
{
|
{
|
||||||
@@ -1479,6 +1534,7 @@ class X509
|
|||||||
/**
|
/**
|
||||||
* Allows URIs to be automatically retrieved
|
* Allows URIs to be automatically retrieved
|
||||||
*
|
*
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function enableURLFetch()
|
public static function enableURLFetch()
|
||||||
{
|
{
|
||||||
@@ -1492,6 +1548,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param string $ip
|
* @param string $ip
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function decodeIP($ip)
|
public static function decodeIP($ip)
|
||||||
{
|
{
|
||||||
@@ -1505,6 +1562,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param string $ip
|
* @param string $ip
|
||||||
* @return array
|
* @return array
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function decodeNameConstraintIP($ip)
|
public static function decodeNameConstraintIP($ip)
|
||||||
{
|
{
|
||||||
@@ -1521,6 +1579,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param string|array $ip
|
* @param string|array $ip
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public static function encodeIP($ip)
|
public static function encodeIP($ip)
|
||||||
{
|
{
|
||||||
@@ -1610,6 +1669,9 @@ class X509
|
|||||||
case 'organizationalunitname':
|
case 'organizationalunitname':
|
||||||
case 'ou':
|
case 'ou':
|
||||||
return 'id-at-organizationalUnitName';
|
return 'id-at-organizationalUnitName';
|
||||||
|
case 'id-at-organizationidentifier':
|
||||||
|
case 'organizationIdentifier':
|
||||||
|
return 'id-at-organizationIdentifier';
|
||||||
case 'id-at-pseudonym':
|
case 'id-at-pseudonym':
|
||||||
case 'pseudonym':
|
case 'pseudonym':
|
||||||
return 'id-at-pseudonym';
|
return 'id-at-pseudonym';
|
||||||
@@ -1641,6 +1703,7 @@ class X509
|
|||||||
* @param mixed $propValue
|
* @param mixed $propValue
|
||||||
* @param string $type optional
|
* @param string $type optional
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setDNProp($propName, $propValue, $type = 'utf8String')
|
public function setDNProp($propName, $propValue, $type = 'utf8String')
|
||||||
{
|
{
|
||||||
@@ -1671,6 +1734,7 @@ class X509
|
|||||||
* Remove Distinguished Name properties
|
* Remove Distinguished Name properties
|
||||||
*
|
*
|
||||||
* @param string $propName
|
* @param string $propName
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function removeDNProp($propName)
|
public function removeDNProp($propName)
|
||||||
{
|
{
|
||||||
@@ -1704,6 +1768,7 @@ class X509
|
|||||||
* @param array $dn optional
|
* @param array $dn optional
|
||||||
* @param bool $withType optional
|
* @param bool $withType optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getDNProp($propName, $dn = null, $withType = false)
|
public function getDNProp($propName, $dn = null, $withType = false)
|
||||||
{
|
{
|
||||||
@@ -1768,6 +1833,7 @@ class X509
|
|||||||
* @param bool $merge optional
|
* @param bool $merge optional
|
||||||
* @param string $type optional
|
* @param string $type optional
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setDN($dn, $merge = false, $type = 'utf8String')
|
public function setDN($dn, $merge = false, $type = 'utf8String')
|
||||||
{
|
{
|
||||||
@@ -1809,6 +1875,7 @@ class X509
|
|||||||
* @param mixed $format optional
|
* @param mixed $format optional
|
||||||
* @param array $dn optional
|
* @param array $dn optional
|
||||||
* @return array|bool|string
|
* @return array|bool|string
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getDN($format = self::DN_ARRAY, $dn = null)
|
public function getDN($format = self::DN_ARRAY, $dn = null)
|
||||||
{
|
{
|
||||||
@@ -1858,7 +1925,7 @@ class X509
|
|||||||
$dn = $this->getDN(self::DN_CANON, $dn);
|
$dn = $this->getDN(self::DN_CANON, $dn);
|
||||||
$hash = new Hash('sha1');
|
$hash = new Hash('sha1');
|
||||||
$hash = $hash->hash($dn);
|
$hash = $hash->hash($dn);
|
||||||
extract(unpack('Vhash', $hash));
|
$hash = unpack('Vhash', $hash)['hash'];
|
||||||
return strtolower(Strings::bin2hex(pack('N', $hash)));
|
return strtolower(Strings::bin2hex(pack('N', $hash)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1950,6 +2017,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param int $format optional
|
* @param int $format optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getIssuerDN($format = self::DN_ARRAY)
|
public function getIssuerDN($format = self::DN_ARRAY)
|
||||||
{
|
{
|
||||||
@@ -1971,6 +2039,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param int $format optional
|
* @param int $format optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getSubjectDN($format = self::DN_ARRAY)
|
public function getSubjectDN($format = self::DN_ARRAY)
|
||||||
{
|
{
|
||||||
@@ -1994,6 +2063,7 @@ class X509
|
|||||||
* @param string $propName
|
* @param string $propName
|
||||||
* @param bool $withType optional
|
* @param bool $withType optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getIssuerDNProp($propName, $withType = false)
|
public function getIssuerDNProp($propName, $withType = false)
|
||||||
{
|
{
|
||||||
@@ -2015,6 +2085,7 @@ class X509
|
|||||||
* @param string $propName
|
* @param string $propName
|
||||||
* @param bool $withType optional
|
* @param bool $withType optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getSubjectDNProp($propName, $withType = false)
|
public function getSubjectDNProp($propName, $withType = false)
|
||||||
{
|
{
|
||||||
@@ -2036,6 +2107,7 @@ class X509
|
|||||||
* Get the certificate chain for the current cert
|
* Get the certificate chain for the current cert
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getChain()
|
public function getChain()
|
||||||
{
|
{
|
||||||
@@ -2077,6 +2149,7 @@ class X509
|
|||||||
* Returns the current cert
|
* Returns the current cert
|
||||||
*
|
*
|
||||||
* @return array|bool
|
* @return array|bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function &getCurrentCert()
|
public function &getCurrentCert()
|
||||||
{
|
{
|
||||||
@@ -2102,6 +2175,7 @@ class X509
|
|||||||
* Key needs to be a \phpseclib3\Crypt\RSA object
|
* Key needs to be a \phpseclib3\Crypt\RSA object
|
||||||
*
|
*
|
||||||
* @param PrivateKey $key
|
* @param PrivateKey $key
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setPrivateKey(PrivateKey $key)
|
public function setPrivateKey(PrivateKey $key)
|
||||||
{
|
{
|
||||||
@@ -2114,6 +2188,7 @@ class X509
|
|||||||
* Used for SPKAC CSR's
|
* Used for SPKAC CSR's
|
||||||
*
|
*
|
||||||
* @param string $challenge
|
* @param string $challenge
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setChallenge($challenge)
|
public function setChallenge($challenge)
|
||||||
{
|
{
|
||||||
@@ -2174,6 +2249,7 @@ class X509
|
|||||||
* @param string $csr
|
* @param string $csr
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT)
|
public function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT)
|
||||||
{
|
{
|
||||||
@@ -2248,6 +2324,7 @@ class X509
|
|||||||
* @param array $csr
|
* @param array $csr
|
||||||
* @param int $format optional
|
* @param int $format optional
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function saveCSR(array $csr, $format = self::FORMAT_PEM)
|
public function saveCSR(array $csr, $format = self::FORMAT_PEM)
|
||||||
{
|
{
|
||||||
@@ -2293,6 +2370,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param string $spkac
|
* @param string $spkac
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function loadSPKAC($spkac)
|
public function loadSPKAC($spkac)
|
||||||
{
|
{
|
||||||
@@ -2357,6 +2435,7 @@ class X509
|
|||||||
* @param array $spkac
|
* @param array $spkac
|
||||||
* @param int $format optional
|
* @param int $format optional
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function saveSPKAC(array $spkac, $format = self::FORMAT_PEM)
|
public function saveSPKAC(array $spkac, $format = self::FORMAT_PEM)
|
||||||
{
|
{
|
||||||
@@ -2394,6 +2473,7 @@ class X509
|
|||||||
* @param string $crl
|
* @param string $crl
|
||||||
* @param int $mode
|
* @param int $mode
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT)
|
public function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT)
|
||||||
{
|
{
|
||||||
@@ -2460,6 +2540,7 @@ class X509
|
|||||||
* @param array $crl
|
* @param array $crl
|
||||||
* @param int $format optional
|
* @param int $format optional
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function saveCRL(array $crl, $format = self::FORMAT_PEM)
|
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.
|
* a CSR or something with the DN and public key explicitly set.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function sign(X509 $issuer, X509 $subject)
|
public function sign(X509 $issuer, X509 $subject)
|
||||||
{
|
{
|
||||||
@@ -2722,6 +2804,7 @@ class X509
|
|||||||
* Sign a CSR
|
* Sign a CSR
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function signCSR()
|
public function signCSR()
|
||||||
{
|
{
|
||||||
@@ -2777,6 +2860,7 @@ class X509
|
|||||||
* Sign a SPKAC
|
* Sign a SPKAC
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function signSPKAC()
|
public function signSPKAC()
|
||||||
{
|
{
|
||||||
@@ -2839,6 +2923,7 @@ class X509
|
|||||||
* $issuer's private key needs to be loaded.
|
* $issuer's private key needs to be loaded.
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function signCRL(X509 $issuer, X509 $crl)
|
public function signCRL(X509 $issuer, X509 $crl)
|
||||||
{
|
{
|
||||||
@@ -3389,6 +3474,7 @@ class X509
|
|||||||
* @param array $cert optional
|
* @param array $cert optional
|
||||||
* @param string $path optional
|
* @param string $path optional
|
||||||
* @return array
|
* @return array
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getExtensions($cert = null, $path = null)
|
public function getExtensions($cert = null, $path = null)
|
||||||
{
|
{
|
||||||
@@ -3415,6 +3501,7 @@ class X509
|
|||||||
* @param string $id
|
* @param string $id
|
||||||
* @param int $disposition optional
|
* @param int $disposition optional
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function removeAttribute($id, $disposition = self::ATTR_ALL)
|
public function removeAttribute($id, $disposition = self::ATTR_ALL)
|
||||||
{
|
{
|
||||||
@@ -3465,6 +3552,7 @@ class X509
|
|||||||
* @param int $disposition optional
|
* @param int $disposition optional
|
||||||
* @param array $csr optional
|
* @param array $csr optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null)
|
public function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null)
|
||||||
{
|
{
|
||||||
@@ -3506,6 +3594,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param array $csr optional
|
* @param array $csr optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getRequestedCertificateExtensions($csr = null)
|
public function getRequestedCertificateExtensions($csr = null)
|
||||||
{
|
{
|
||||||
@@ -3526,6 +3615,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param array $csr optional
|
* @param array $csr optional
|
||||||
* @return array
|
* @return array
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getAttributes($csr = null)
|
public function getAttributes($csr = null)
|
||||||
{
|
{
|
||||||
@@ -3552,6 +3642,7 @@ class X509
|
|||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @param int $disposition optional
|
* @param int $disposition optional
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setAttribute($id, $value, $disposition = self::ATTR_ALL)
|
public function setAttribute($id, $value, $disposition = self::ATTR_ALL)
|
||||||
{
|
{
|
||||||
@@ -3633,6 +3724,7 @@ class X509
|
|||||||
* @param mixed $key optional
|
* @param mixed $key optional
|
||||||
* @param int $method optional
|
* @param int $method optional
|
||||||
* @return string binary key identifier
|
* @return string binary key identifier
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function computeKeyIdentifier($key = null, $method = 1)
|
public function computeKeyIdentifier($key = null, $method = 1)
|
||||||
{
|
{
|
||||||
@@ -3729,6 +3821,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param mixed ...$domains
|
* @param mixed ...$domains
|
||||||
* @return void
|
* @return void
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setDomain(...$domains)
|
public function setDomain(...$domains)
|
||||||
{
|
{
|
||||||
@@ -3741,6 +3834,7 @@ class X509
|
|||||||
* Set the IP Addresses's which the cert is to be valid for
|
* Set the IP Addresses's which the cert is to be valid for
|
||||||
*
|
*
|
||||||
* @param mixed[] ...$ipAddresses
|
* @param mixed[] ...$ipAddresses
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setIPAddress(...$ipAddresses)
|
public function setIPAddress(...$ipAddresses)
|
||||||
{
|
{
|
||||||
@@ -3837,6 +3931,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param string $serial
|
* @param string $serial
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function unrevoke($serial)
|
public function unrevoke($serial)
|
||||||
{
|
{
|
||||||
@@ -3856,6 +3951,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param string $serial
|
* @param string $serial
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getRevoked($serial)
|
public function getRevoked($serial)
|
||||||
{
|
{
|
||||||
@@ -3873,6 +3969,7 @@ class X509
|
|||||||
*
|
*
|
||||||
* @param array $crl optional
|
* @param array $crl optional
|
||||||
* @return array|bool
|
* @return array|bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function listRevoked($crl = null)
|
public function listRevoked($crl = null)
|
||||||
{
|
{
|
||||||
@@ -3901,6 +3998,7 @@ class X509
|
|||||||
* @param string $serial
|
* @param string $serial
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function removeRevokedCertificateExtension($serial, $id)
|
public function removeRevokedCertificateExtension($serial, $id)
|
||||||
{
|
{
|
||||||
@@ -3922,6 +4020,7 @@ class X509
|
|||||||
* @param string $id
|
* @param string $id
|
||||||
* @param array $crl optional
|
* @param array $crl optional
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getRevokedCertificateExtension($serial, $id, $crl = null)
|
public function getRevokedCertificateExtension($serial, $id, $crl = null)
|
||||||
{
|
{
|
||||||
@@ -3969,6 +4068,7 @@ class X509
|
|||||||
* @param bool $critical optional
|
* @param bool $critical optional
|
||||||
* @param bool $replace optional
|
* @param bool $replace optional
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true)
|
public function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true)
|
||||||
{
|
{
|
||||||
@@ -4019,9 +4119,20 @@ class X509
|
|||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @param bool $critical
|
* @param bool $critical
|
||||||
* @param bool $replace
|
* @param bool $replace
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function setExtensionValue($id, $value, $critical = false, $replace = false)
|
public function setExtensionValue($id, $value, $critical = false, $replace = false)
|
||||||
{
|
{
|
||||||
$this->extensionValues[$id] = compact('critical', 'replace', 'value');
|
$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']],
|
['PHP64', ['DefaultEngine']],
|
||||||
['PHP32', ['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) {
|
foreach ($engines as $engine) {
|
||||||
try {
|
try {
|
||||||
@@ -317,6 +322,7 @@ class BigInteger implements \JsonSerializable
|
|||||||
*
|
*
|
||||||
* @param BigInteger $n
|
* @param BigInteger $n
|
||||||
* @return BigInteger
|
* @return BigInteger
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function modInverse(BigInteger $n)
|
public function modInverse(BigInteger $n)
|
||||||
{
|
{
|
||||||
@@ -333,12 +339,10 @@ class BigInteger implements \JsonSerializable
|
|||||||
*/
|
*/
|
||||||
public function extendedGCD(BigInteger $n)
|
public function extendedGCD(BigInteger $n)
|
||||||
{
|
{
|
||||||
extract($this->value->extendedGCD($n->value));
|
$extended = $this->value->extendedGCD($n->value);
|
||||||
/**
|
$gcd = $extended['gcd'];
|
||||||
* @var BigInteger $gcd
|
$x = $extended['x'];
|
||||||
* @var BigInteger $x
|
$y = $extended['y'];
|
||||||
* @var BigInteger $y
|
|
||||||
*/
|
|
||||||
return [
|
return [
|
||||||
'gcd' => new static($gcd),
|
'gcd' => new static($gcd),
|
||||||
'x' => new static($x),
|
'x' => new static($x),
|
||||||
@@ -399,7 +403,7 @@ class BigInteger implements \JsonSerializable
|
|||||||
*
|
*
|
||||||
* Will be called, automatically, when serialize() is called on a BigInteger object.
|
* 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:
|
* \Serializable was introduced in PHP 5.1 and deprecated in PHP 8.1:
|
||||||
* https://wiki.php.net/rfc/phase_out_serializable
|
* 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
|
* JSON Serialize
|
||||||
*
|
*
|
||||||
@@ -617,10 +653,9 @@ class BigInteger implements \JsonSerializable
|
|||||||
self::initialize_static_variables();
|
self::initialize_static_variables();
|
||||||
|
|
||||||
$class = self::$mainEngine;
|
$class = self::$mainEngine;
|
||||||
extract($class::minMaxBits($bits));
|
$minMax = $class::minMaxBits($bits);
|
||||||
/** @var BigInteger $min
|
$min = $minMax['min'];
|
||||||
* @var BigInteger $max
|
$max = $minMax['max'];
|
||||||
*/
|
|
||||||
return [
|
return [
|
||||||
'min' => new static($min),
|
'min' => new static($min),
|
||||||
'max' => new static($max)
|
'max' => new static($max)
|
||||||
|
|||||||
+18
-13
@@ -38,6 +38,11 @@ class BCMath extends Engine
|
|||||||
*/
|
*/
|
||||||
const ENGINE_DIR = 'BCMath';
|
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
|
* Test for engine validity
|
||||||
*
|
*
|
||||||
@@ -148,8 +153,8 @@ class BCMath extends Engine
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (bccomp($current, '0', 0) > 0) {
|
while (bccomp($current, '0', 0) > 0) {
|
||||||
$temp = bcmod($current, '16777216');
|
$temp = self::BCMOD_THREE_PARAMS ? bcmod($current, '16777216', 0) : bcmod($current, '16777216');
|
||||||
$value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
|
$value = chr($temp >> 16) . chr(($temp >> 8) & 0xFF) . chr($temp & 0xFF) . $value;
|
||||||
$current = bcdiv($current, '16777216', 0);
|
$current = bcdiv($current, '16777216', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +172,7 @@ class BCMath extends Engine
|
|||||||
public function add(BCMath $y)
|
public function add(BCMath $y)
|
||||||
{
|
{
|
||||||
$temp = new self();
|
$temp = new self();
|
||||||
$temp->value = bcadd($this->value, $y->value);
|
$temp->value = bcadd($this->value, $y->value, 0);
|
||||||
|
|
||||||
return $this->normalize($temp);
|
return $this->normalize($temp);
|
||||||
}
|
}
|
||||||
@@ -181,7 +186,7 @@ class BCMath extends Engine
|
|||||||
public function subtract(BCMath $y)
|
public function subtract(BCMath $y)
|
||||||
{
|
{
|
||||||
$temp = new self();
|
$temp = new self();
|
||||||
$temp->value = bcsub($this->value, $y->value);
|
$temp->value = bcsub($this->value, $y->value, 0);
|
||||||
|
|
||||||
return $this->normalize($temp);
|
return $this->normalize($temp);
|
||||||
}
|
}
|
||||||
@@ -195,7 +200,7 @@ class BCMath extends Engine
|
|||||||
public function multiply(BCMath $x)
|
public function multiply(BCMath $x)
|
||||||
{
|
{
|
||||||
$temp = new self();
|
$temp = new self();
|
||||||
$temp->value = bcmul($this->value, $x->value);
|
$temp->value = bcmul($this->value, $x->value, 0);
|
||||||
|
|
||||||
return $this->normalize($temp);
|
return $this->normalize($temp);
|
||||||
}
|
}
|
||||||
@@ -217,7 +222,7 @@ class BCMath extends Engine
|
|||||||
$remainder = new self();
|
$remainder = new self();
|
||||||
|
|
||||||
$quotient->value = bcdiv($this->value, $y->value, 0);
|
$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] == '-') {
|
if ($remainder->value[0] == '-') {
|
||||||
$remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->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)
|
public function gcd(BCMath $n)
|
||||||
{
|
{
|
||||||
extract($this->extendedGCD($n));
|
$gcd = $this->extendedGCD($n)['gcd'];
|
||||||
/** @var BCMath $gcd */
|
|
||||||
return $gcd;
|
return $gcd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,7 +479,7 @@ class BCMath extends Engine
|
|||||||
$result->bitmask = $this->bitmask;
|
$result->bitmask = $this->bitmask;
|
||||||
|
|
||||||
if ($result->bitmask !== false) {
|
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;
|
return $result;
|
||||||
@@ -523,7 +527,7 @@ class BCMath extends Engine
|
|||||||
protected function make_odd()
|
protected function make_odd()
|
||||||
{
|
{
|
||||||
if (!$this->isOdd()) {
|
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;
|
$value = $this->value;
|
||||||
|
|
||||||
foreach (self::PRIMES as $prime) {
|
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') {
|
if ($r == '0') {
|
||||||
return $this->value == $prime;
|
return $this->value == $prime;
|
||||||
}
|
}
|
||||||
@@ -587,7 +591,7 @@ class BCMath extends Engine
|
|||||||
public function pow(BCMath $n)
|
public function pow(BCMath $n)
|
||||||
{
|
{
|
||||||
$temp = new self();
|
$temp = new self();
|
||||||
$temp->value = bcpow($this->value, $n->value);
|
$temp->value = bcpow($this->value, $n->value, 0);
|
||||||
|
|
||||||
return $this->normalize($temp);
|
return $this->normalize($temp);
|
||||||
}
|
}
|
||||||
@@ -656,8 +660,9 @@ class BCMath extends Engine
|
|||||||
*/
|
*/
|
||||||
public function testBit($x)
|
public function testBit($x)
|
||||||
{
|
{
|
||||||
|
$divisor = bcpow('2', $x + 1, 0);
|
||||||
return bccomp(
|
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),
|
bcpow('2', $x, 0),
|
||||||
0
|
0
|
||||||
) >= 0;
|
) >= 0;
|
||||||
|
|||||||
+2
-2
@@ -91,7 +91,7 @@ abstract class Base extends BCMath
|
|||||||
*/
|
*/
|
||||||
protected static function multiplyReduce($x, $y, $n, $class)
|
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)
|
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)
|
protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n)
|
||||||
{
|
{
|
||||||
$temp = new BCMath();
|
$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);
|
return $x->normalize($temp);
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+20
-18
@@ -67,7 +67,7 @@ abstract class Barrett extends Base
|
|||||||
$m_length = strlen($m);
|
$m_length = strlen($m);
|
||||||
|
|
||||||
if (strlen($n) > 2 * $m_length) {
|
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
|
// 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));
|
$lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1));
|
||||||
$u = bcdiv($lhs, $m, 0);
|
$u = bcdiv($lhs, $m, 0);
|
||||||
$m1 = bcsub($lhs, bcmul($u, $m));
|
$m1 = bcsub($lhs, bcmul($u, $m, 0), 0);
|
||||||
|
|
||||||
$cache[self::DATA][] = [
|
$cache[self::DATA][] = [
|
||||||
'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
|
'u' => $u, // m.length >> 1 (technically (m.length >> 1) + 1)
|
||||||
'm1' => $m1 // m.length
|
'm1' => $m1 // m.length
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
extract($cache[self::DATA][$key]);
|
$cacheValues = $cache[self::DATA][$key];
|
||||||
|
$u = $cacheValues['u'];
|
||||||
|
$m1 = $cacheValues['m1'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$cutoff = $m_length + ($m_length >> 1);
|
$cutoff = $m_length + ($m_length >> 1);
|
||||||
@@ -104,8 +106,8 @@ abstract class Barrett extends Base
|
|||||||
$lsd = substr($n, -$cutoff);
|
$lsd = substr($n, -$cutoff);
|
||||||
$msd = substr($n, 0, -$cutoff);
|
$msd = substr($n, 0, -$cutoff);
|
||||||
|
|
||||||
$temp = bcmul($msd, $m1); // m.length + (m.length >> 1)
|
$temp = bcmul($msd, $m1, 0); // m.length + (m.length >> 1)
|
||||||
$n = bcadd($lsd, $temp); // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers)
|
$n = bcadd($lsd, $temp, 0); // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers)
|
||||||
//if ($m_length & 1) {
|
//if ($m_length & 1) {
|
||||||
// return self::regularBarrett($n, $m);
|
// return self::regularBarrett($n, $m);
|
||||||
//}
|
//}
|
||||||
@@ -114,31 +116,31 @@ abstract class Barrett extends Base
|
|||||||
$temp = substr($n, 0, -$m_length + 1);
|
$temp = substr($n, 0, -$m_length + 1);
|
||||||
// if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
|
// 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
|
// 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 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)
|
// if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
|
||||||
$temp = substr($temp, 0, -($m_length >> 1) - 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 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)
|
// 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
|
// 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
|
// 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).
|
// 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 (bccomp($result, '0') < 0) {
|
||||||
if ($result[0] == '-') {
|
if ($result[0] == '-') {
|
||||||
$temp = '1' . str_repeat('0', $m_length + 1);
|
$temp = '1' . str_repeat('0', $m_length + 1);
|
||||||
$result = bcadd($result, $temp);
|
$result = bcadd($result, $temp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bccomp($result, $m) >= 0) {
|
while (bccomp($result, $m, 0) >= 0) {
|
||||||
$result = bcsub($result, $m);
|
$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);
|
$n_length = strlen($n);
|
||||||
|
|
||||||
if (strlen($x) > 2 * $n_length) {
|
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) {
|
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 = 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);
|
$temp = substr($temp, 0, -$n_length - 1);
|
||||||
|
|
||||||
$r1 = substr($x, -$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);
|
$result = bcsub($r1, $r2);
|
||||||
|
|
||||||
//if (bccomp($result, '0') < 0) {
|
//if (bccomp($result, '0') < 0) {
|
||||||
if ($result[0] == '-') {
|
if ($result[0] == '-') {
|
||||||
$q = '1' . str_repeat('0', $n_length + 1);
|
$q = '1' . str_repeat('0', $n_length + 1);
|
||||||
$result = bcadd($result, $q);
|
$result = bcadd($result, $q, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bccomp($result, $n) >= 0) {
|
while (bccomp($result, $n, 0) >= 0) {
|
||||||
$result = bcsub($result, $n);
|
$result = bcsub($result, $n, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
|||||||
Vendored
+9
-9
@@ -58,7 +58,7 @@ abstract class EvalBarrett extends Base
|
|||||||
$m_length = strlen($m);
|
$m_length = strlen($m);
|
||||||
|
|
||||||
if ($m_length < 5) {
|
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 . '};');
|
eval('$func = function ($n) { ' . $code . '};');
|
||||||
self::$custom_reduction = $func;
|
self::$custom_reduction = $func;
|
||||||
return;
|
return;
|
||||||
@@ -66,7 +66,7 @@ abstract class EvalBarrett extends Base
|
|||||||
|
|
||||||
$lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1));
|
$lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1));
|
||||||
$u = bcdiv($lhs, $m, 0);
|
$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);
|
$cutoff = $m_length + ($m_length >> 1);
|
||||||
|
|
||||||
@@ -78,23 +78,23 @@ abstract class EvalBarrett extends Base
|
|||||||
$lsd = substr($n, -' . $cutoff . ');
|
$lsd = substr($n, -' . $cutoff . ');
|
||||||
$msd = substr($n, 0, -' . $cutoff . ');
|
$msd = substr($n, 0, -' . $cutoff . ');
|
||||||
|
|
||||||
$temp = bcmul($msd, ' . $m1 . ');
|
$temp = bcmul($msd, ' . $m1 . ', 0);
|
||||||
$n = bcadd($lsd, $temp);
|
$n = bcadd($lsd, $temp, 0);
|
||||||
|
|
||||||
$temp = substr($n, 0, ' . (-$m_length + 1) . ');
|
$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 = 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] == \'-\') {
|
if ($result[0] == \'-\') {
|
||||||
$temp = \'1' . str_repeat('0', $m_length + 1) . '\';
|
$temp = \'1' . str_repeat('0', $m_length + 1) . '\';
|
||||||
$result = bcadd($result, $temp);
|
$result = bcadd($result, $temp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (bccomp($result, ' . $m . ') >= 0) {
|
while (bccomp($result, ' . $m . ') >= 0) {
|
||||||
$result = bcsub($result, ' . $m . ');
|
$result = bcsub($result, ' . $m . ', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;';
|
return $result;';
|
||||||
|
|||||||
+50
-18
@@ -316,11 +316,9 @@ abstract class Engine implements \JsonSerializable
|
|||||||
return $this->normalize($n->subtract($temp));
|
return $this->normalize($n->subtract($temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
extract($this->extendedGCD($n));
|
$extended = $this->extendedGCD($n);
|
||||||
/**
|
$gcd = $extended['gcd'];
|
||||||
* @var Engine $gcd
|
$x = $extended['x'];
|
||||||
* @var Engine $x
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!$gcd->equals(static::$one[static::class])) {
|
if (!$gcd->equals(static::$one[static::class])) {
|
||||||
return false;
|
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
|
* JSON Serialize
|
||||||
*
|
*
|
||||||
@@ -513,8 +549,8 @@ abstract class Engine implements \JsonSerializable
|
|||||||
|
|
||||||
$carry = 0;
|
$carry = 0;
|
||||||
for ($i = strlen($x) - 1; $i >= 0; --$i) {
|
for ($i = strlen($x) - 1; $i >= 0; --$i) {
|
||||||
$temp = ord($x[$i]) << $shift | $carry;
|
$temp = (ord($x[$i]) << $shift) | $carry;
|
||||||
$x[$i] = chr($temp);
|
$x[$i] = chr($temp & 0xFF);
|
||||||
$carry = $temp >> 8;
|
$carry = $temp >> 8;
|
||||||
}
|
}
|
||||||
$carry = ($carry != 0) ? chr($carry) : '';
|
$carry = ($carry != 0) ? chr($carry) : '';
|
||||||
@@ -644,7 +680,7 @@ abstract class Engine implements \JsonSerializable
|
|||||||
return $this->normalize($temp->powModInner($e, $n));
|
return $this->normalize($temp->powModInner($e, $n));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->compare($n) > 0) {
|
if ($this->compare($n) > 0 || $this->isNegative()) {
|
||||||
list(, $temp) = $this->divide($n);
|
list(, $temp) = $this->divide($n);
|
||||||
return $temp->powModInner($e, $n);
|
return $temp->powModInner($e, $n);
|
||||||
}
|
}
|
||||||
@@ -740,11 +776,9 @@ abstract class Engine implements \JsonSerializable
|
|||||||
*/
|
*/
|
||||||
public static function random($size)
|
public static function random($size)
|
||||||
{
|
{
|
||||||
extract(static::minMaxBits($size));
|
$minMax = static::minMaxBits($size);
|
||||||
/**
|
$min = $minMax['min'];
|
||||||
* @var BigInteger $min
|
$max = $minMax['max'];
|
||||||
* @var BigInteger $max
|
|
||||||
*/
|
|
||||||
return static::randomRange($min, $max);
|
return static::randomRange($min, $max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,11 +792,9 @@ abstract class Engine implements \JsonSerializable
|
|||||||
*/
|
*/
|
||||||
public static function randomPrime($size)
|
public static function randomPrime($size)
|
||||||
{
|
{
|
||||||
extract(static::minMaxBits($size));
|
$minMax = static::minMaxBits($size);
|
||||||
/**
|
$min = $minMax['min'];
|
||||||
* @var static $min
|
$max = $minMax['max'];
|
||||||
* @var static $max
|
|
||||||
*/
|
|
||||||
return static::randomRangePrime($min, $max);
|
return static::randomRangePrime($min, $max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,7 @@ class GMP extends Engine
|
|||||||
public function toBits($twos_compliment = false)
|
public function toBits($twos_compliment = false)
|
||||||
{
|
{
|
||||||
$hex = $this->toHex($twos_compliment);
|
$hex = $this->toHex($twos_compliment);
|
||||||
|
$bits = strlen($hex) ? gmp_strval(gmp_init($hex, 16), 2) : '';
|
||||||
$bits = gmp_strval(gmp_init($hex, 16), 2);
|
|
||||||
|
|
||||||
if ($this->precision > 0) {
|
if ($this->precision > 0) {
|
||||||
$bits = substr($bits, -$this->precision);
|
$bits = substr($bits, -$this->precision);
|
||||||
@@ -296,7 +295,10 @@ class GMP extends Engine
|
|||||||
*/
|
*/
|
||||||
public function extendedGCD(GMP $n)
|
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 [
|
return [
|
||||||
'gcd' => $this->normalize(new self($g)),
|
'gcd' => $this->normalize(new self($g)),
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ abstract class PHP extends Engine
|
|||||||
* @param bool $y_negative
|
* @param bool $y_negative
|
||||||
* @return array
|
* @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);
|
$x_size = count($x_value);
|
||||||
$y_size = count($y_value);
|
$y_size = count($y_value);
|
||||||
@@ -533,6 +533,13 @@ abstract class PHP extends Engine
|
|||||||
$quotient = new static();
|
$quotient = new static();
|
||||||
$remainder = new static();
|
$remainder = new static();
|
||||||
$quotient->value = $q;
|
$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];
|
$remainder->value = [$r];
|
||||||
$quotient->is_negative = $this->is_negative != $y->is_negative;
|
$quotient->is_negative = $this->is_negative != $y->is_negative;
|
||||||
return [$this->normalize($quotient), $this->normalize($remainder)];
|
return [$this->normalize($quotient), $this->normalize($remainder)];
|
||||||
@@ -664,8 +671,9 @@ abstract class PHP extends Engine
|
|||||||
|
|
||||||
$quotient->is_negative = $x_sign != $y_sign;
|
$quotient->is_negative = $x_sign != $y_sign;
|
||||||
|
|
||||||
// calculate the "common residue", if appropriate
|
// calculate the "common residue", if appropriate. A remainder of 0 is
|
||||||
if ($x_sign) {
|
// already the residue -- see divideHelper's single-digit branch.
|
||||||
|
if ($x_sign && count($x->value)) {
|
||||||
$y->rshift($shift);
|
$y->rshift($shift);
|
||||||
$x = $y->subtract($x);
|
$x = $y->subtract($x);
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+3
-1
@@ -98,7 +98,9 @@ abstract class Barrett extends Base
|
|||||||
'm1' => $m1 // m.length
|
'm1' => $m1 // m.length
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
extract($cache[self::DATA][$key]);
|
$cacheValues = $cache[self::DATA][$key];
|
||||||
|
$u = $cacheValues['u'];
|
||||||
|
$m1 = $cacheValues['m1'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$cutoff = $m_length + ($m_length >> 1);
|
$cutoff = $m_length + ($m_length >> 1);
|
||||||
|
|||||||
@@ -54,10 +54,31 @@ class Integer extends Base
|
|||||||
/**
|
/**
|
||||||
* Zero
|
* Zero
|
||||||
*
|
*
|
||||||
* @var BigInteger
|
* @var BigInteger[]
|
||||||
*/
|
*/
|
||||||
protected static $zero;
|
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
|
* Default constructor
|
||||||
*
|
*
|
||||||
@@ -68,7 +89,7 @@ class Integer extends Base
|
|||||||
{
|
{
|
||||||
$this->instanceID = $instanceID;
|
$this->instanceID = $instanceID;
|
||||||
if (!isset($num)) {
|
if (!isset($num)) {
|
||||||
$this->value = clone static::$zero[static::class];
|
$this->value = clone static::$zero[$instanceID];
|
||||||
} else {
|
} else {
|
||||||
$reduce = static::$reduce[$instanceID];
|
$reduce = static::$reduce[$instanceID];
|
||||||
$this->value = $reduce($num);
|
$this->value = $reduce($num);
|
||||||
@@ -84,6 +105,11 @@ class Integer extends Base
|
|||||||
public static function setModulo($instanceID, BigInteger $modulo)
|
public static function setModulo($instanceID, BigInteger $modulo)
|
||||||
{
|
{
|
||||||
static::$modulo[$instanceID] = $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)
|
public static function setRecurringModuloFunction($instanceID, callable $function)
|
||||||
{
|
{
|
||||||
static::$reduce[$instanceID] = $function;
|
static::$reduce[$instanceID] = $function;
|
||||||
if (!isset(static::$zero[static::class])) {
|
if (!isset(static::$zero[$instanceID])) {
|
||||||
static::$zero[static::class] = new BigInteger();
|
static::$zero[$instanceID] = new BigInteger();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +133,10 @@ class Integer extends Base
|
|||||||
{
|
{
|
||||||
unset(static::$modulo[$instanceID]);
|
unset(static::$modulo[$instanceID]);
|
||||||
unset(static::$reduce[$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);
|
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.
|
* Adds two PrimeFieldIntegers.
|
||||||
*
|
*
|
||||||
@@ -167,13 +216,10 @@ class Integer extends Base
|
|||||||
{
|
{
|
||||||
static::checkInstance($this, $x);
|
static::checkInstance($this, $x);
|
||||||
|
|
||||||
$temp = new static($this->instanceID);
|
// $this->value + $x->value is in [0, 2m), so subtracting once lands in [-m, m)
|
||||||
$temp->value = $this->value->add($x->value);
|
return $this->conditionalAddModulo(
|
||||||
if ($temp->value->compare(static::$modulo[$this->instanceID]) >= 0) {
|
$this->value->add($x->value)->subtract(static::$modulo[$this->instanceID])
|
||||||
$temp->value = $temp->value->subtract(static::$modulo[$this->instanceID]);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return $temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,13 +231,8 @@ class Integer extends Base
|
|||||||
{
|
{
|
||||||
static::checkInstance($this, $x);
|
static::checkInstance($this, $x);
|
||||||
|
|
||||||
$temp = new static($this->instanceID);
|
// already in (-m, m)
|
||||||
$temp->value = $this->value->subtract($x->value);
|
return $this->conditionalAddModulo($this->value->subtract($x->value));
|
||||||
if ($temp->value->isNegative()) {
|
|
||||||
$temp->value = $temp->value->add(static::$modulo[$this->instanceID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,32 +281,35 @@ class Integer extends Base
|
|||||||
*/
|
*/
|
||||||
public function squareRoot()
|
public function squareRoot()
|
||||||
{
|
{
|
||||||
static $one, $two;
|
if (!isset(static::$one[$this->instanceID])) {
|
||||||
if (!isset($one)) {
|
static::$one[$this->instanceID] = new BigInteger(1);
|
||||||
$one = new BigInteger(1);
|
static::$two[$this->instanceID] = new BigInteger(2);
|
||||||
$two = new BigInteger(2);
|
|
||||||
}
|
}
|
||||||
$reduce = static::$reduce[$this->instanceID];
|
$one = &static::$one[$this->instanceID];
|
||||||
$p_1 = static::$modulo[$this->instanceID]->subtract($one);
|
$two = &static::$two[$this->instanceID];
|
||||||
|
$modulo = &static::$modulo[$this->instanceID];
|
||||||
|
$reduce = &static::$reduce[$this->instanceID];
|
||||||
|
|
||||||
|
$p_1 = $modulo->subtract($one);
|
||||||
$q = clone $p_1;
|
$q = clone $p_1;
|
||||||
$s = BigInteger::scan1divide($q);
|
$s = BigInteger::scan1divide($q);
|
||||||
list($pow) = $p_1->divide($two);
|
list($pow) = $p_1->divide($two);
|
||||||
for ($z = $one; !$z->equals(static::$modulo[$this->instanceID]); $z = $z->add($one)) {
|
for ($z = $one; !$z->equals($modulo); $z = $z->add($one)) {
|
||||||
$temp = $z->powMod($pow, static::$modulo[$this->instanceID]);
|
$temp = $z->powMod($pow, $modulo);
|
||||||
if ($temp->equals($p_1)) {
|
if ($temp->equals($p_1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$m = new BigInteger($s);
|
$m = new BigInteger($s);
|
||||||
$c = $z->powMod($q, static::$modulo[$this->instanceID]);
|
$c = $z->powMod($q, $modulo);
|
||||||
$t = $this->value->powMod($q, static::$modulo[$this->instanceID]);
|
$t = $this->value->powMod($q, $modulo);
|
||||||
list($temp) = $q->add($one)->divide($two);
|
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)) {
|
while (!$t->equals($one)) {
|
||||||
for ($i = clone $one; $i->compare($m) < 0; $i = $i->add($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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +317,7 @@ class Integer extends Base
|
|||||||
if ($i->compare($m) == 0) {
|
if ($i->compare($m) == 0) {
|
||||||
return false;
|
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;
|
$m = $i;
|
||||||
$c = $reduce($b->multiply($b));
|
$c = $reduce($b->multiply($b));
|
||||||
$t = $reduce($t->multiply($c));
|
$t = $reduce($t->multiply($c));
|
||||||
@@ -356,6 +400,8 @@ class Integer extends Base
|
|||||||
{
|
{
|
||||||
$w++;
|
$w++;
|
||||||
|
|
||||||
|
$zero = &static::$zero[$this->instanceID];
|
||||||
|
|
||||||
$mask = new BigInteger((1 << $w) - 1);
|
$mask = new BigInteger((1 << $w) - 1);
|
||||||
$sub = new BigInteger(1 << $w);
|
$sub = new BigInteger(1 << $w);
|
||||||
//$sub = new BigInteger(1 << ($w - 1));
|
//$sub = new BigInteger(1 << ($w - 1));
|
||||||
@@ -363,7 +409,7 @@ class Integer extends Base
|
|||||||
$d_i = [];
|
$d_i = [];
|
||||||
|
|
||||||
$i = 0;
|
$i = 0;
|
||||||
while ($d->compare(static::$zero[static::class]) > 0) {
|
while ($d->compare($zero) > 0) {
|
||||||
if ($d->isOdd()) {
|
if ($d->isOdd()) {
|
||||||
// start mods
|
// start mods
|
||||||
|
|
||||||
@@ -377,7 +423,7 @@ class Integer extends Base
|
|||||||
} else {
|
} else {
|
||||||
$d_i[$i] = 0;
|
$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);
|
$d = $d->bitwise_rightShift($shift);
|
||||||
while (--$shift > 0) {
|
while (--$shift > 0) {
|
||||||
$d_i[++$i] = 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\Common\Functions\Strings;
|
||||||
use phpseclib3\Exception\FileNotFoundException;
|
use phpseclib3\Exception\FileNotFoundException;
|
||||||
|
use phpseclib3\Exception\TimeoutException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pure-PHP implementations of SFTP.
|
* 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.
|
* \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 SSH2::send_channel_packet()
|
||||||
* @see \phpseclib3\Net\SSH2::get_channel_packet()
|
* @see SSH2::get_channel_packet()
|
||||||
*/
|
*/
|
||||||
const CHANNEL = 0x100;
|
const CHANNEL = 0x100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from a local file.
|
* Reads data from a local file.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SFTP::put()
|
* @see SFTP::put()
|
||||||
*/
|
*/
|
||||||
const SOURCE_LOCAL_FILE = 1;
|
const SOURCE_LOCAL_FILE = 1;
|
||||||
/**
|
/**
|
||||||
* Reads data from a string.
|
* 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
|
// this value isn't really used anymore but i'm keeping it reserved for historical reasons
|
||||||
const SOURCE_STRING = 2;
|
const SOURCE_STRING = 2;
|
||||||
@@ -70,19 +71,19 @@ class SFTP extends SSH2
|
|||||||
* Reads data from callback:
|
* Reads data from callback:
|
||||||
* function callback($length) returns string to proceed, null for EOF
|
* function callback($length) returns string to proceed, null for EOF
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SFTP::put()
|
* @see SFTP::put()
|
||||||
*/
|
*/
|
||||||
const SOURCE_CALLBACK = 16;
|
const SOURCE_CALLBACK = 16;
|
||||||
/**
|
/**
|
||||||
* Resumes an upload
|
* Resumes an upload
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SFTP::put()
|
* @see SFTP::put()
|
||||||
*/
|
*/
|
||||||
const RESUME = 4;
|
const RESUME = 4;
|
||||||
/**
|
/**
|
||||||
* Append a local file to an already existing remote file
|
* Append a local file to an already existing remote file
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SFTP::put()
|
* @see SFTP::put()
|
||||||
*/
|
*/
|
||||||
const RESUME_START = 8;
|
const RESUME_START = 8;
|
||||||
|
|
||||||
@@ -598,6 +599,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_VERSION) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_VERSION. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -667,6 +671,9 @@ class SFTP extends SSH2
|
|||||||
$this->send_sftp_packet(NET_SFTP_EXTENDED, $packet);
|
$this->send_sftp_packet(NET_SFTP_EXTENDED, $packet);
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -836,6 +843,8 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$path = (string) $path;
|
||||||
|
|
||||||
if (!$this->canonicalize_paths) {
|
if (!$this->canonicalize_paths) {
|
||||||
if ($this->pwd === true) {
|
if ($this->pwd === true) {
|
||||||
return '.';
|
return '.';
|
||||||
@@ -881,6 +890,9 @@ class SFTP extends SSH2
|
|||||||
$this->logError($response);
|
$this->logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -923,6 +935,8 @@ class SFTP extends SSH2
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$dir = (string) $dir;
|
||||||
|
|
||||||
// assume current dir if $dir is empty
|
// assume current dir if $dir is empty
|
||||||
if ($dir === '') {
|
if ($dir === '') {
|
||||||
$dir = './';
|
$dir = './';
|
||||||
@@ -932,6 +946,9 @@ class SFTP extends SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dir = $this->realpath($dir);
|
$dir = $this->realpath($dir);
|
||||||
|
if ($dir === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// confirm that $dir is, in fact, a valid directory
|
// confirm that $dir is, in fact, a valid directory
|
||||||
if ($this->use_stat_cache && is_array($this->query_stat_cache($dir))) {
|
if ($this->use_stat_cache && is_array($this->query_stat_cache($dir))) {
|
||||||
@@ -956,6 +973,9 @@ class SFTP extends SSH2
|
|||||||
$this->logError($response);
|
$this->logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
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' .
|
throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS' .
|
||||||
'Got packet type: ' . $this->packet_type);
|
'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1128,9 @@ class SFTP extends SSH2
|
|||||||
$this->logError($response, $status);
|
$this->logError($response, $status);
|
||||||
return $status;
|
return $status;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1518,6 +1541,9 @@ class SFTP extends SSH2
|
|||||||
return false;
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1585,6 +1611,9 @@ class SFTP extends SSH2
|
|||||||
$this->logError($response);
|
$this->logError($response);
|
||||||
break;
|
break;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1674,6 +1703,7 @@ class SFTP extends SSH2
|
|||||||
* @param bool $recursive
|
* @param bool $recursive
|
||||||
* @throws \UnexpectedValueException on receipt of unexpected packets
|
* @throws \UnexpectedValueException on receipt of unexpected packets
|
||||||
* @return mixed
|
* @return mixed
|
||||||
|
* @changed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function chmod($mode, $filename, $recursive = false)
|
public function chmod($mode, $filename, $recursive = false)
|
||||||
{
|
{
|
||||||
@@ -1708,6 +1738,9 @@ class SFTP extends SSH2
|
|||||||
return false;
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1756,6 +1789,9 @@ class SFTP extends SSH2
|
|||||||
*/
|
*/
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1869,6 +1905,9 @@ class SFTP extends SSH2
|
|||||||
$this->logError($response);
|
$this->logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1937,6 +1976,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -1997,6 +2039,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -2036,6 +2081,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -2159,6 +2207,9 @@ class SFTP extends SSH2
|
|||||||
$this->logError($response);
|
$this->logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -2301,6 +2352,9 @@ class SFTP extends SSH2
|
|||||||
while ($i--) {
|
while ($i--) {
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. '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
|
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -2386,6 +2443,9 @@ class SFTP extends SSH2
|
|||||||
$this->logError($response);
|
$this->logError($response);
|
||||||
return false;
|
return false;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -2478,6 +2538,8 @@ class SFTP extends SSH2
|
|||||||
$this->partial_init = false;
|
$this->partial_init = false;
|
||||||
$this->init_sftp_connection();
|
$this->init_sftp_connection();
|
||||||
return false;
|
return false;
|
||||||
|
} elseif ($this->is_timeout) {
|
||||||
|
throw new TimeoutException('Timed out waiting for SFTP packet response');
|
||||||
} else {
|
} else {
|
||||||
throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
@@ -2541,6 +2603,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. '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
|
case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||||
return false;
|
return false;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. '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
|
case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
||||||
return false;
|
return false;
|
||||||
default:
|
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. '
|
throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -2993,6 +3064,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -3355,8 +3429,7 @@ class SFTP extends SSH2
|
|||||||
if (strlen($this->packet_buffer) < 4) {
|
if (strlen($this->packet_buffer) < 4) {
|
||||||
throw new \RuntimeException('Packet is too small');
|
throw new \RuntimeException('Packet is too small');
|
||||||
}
|
}
|
||||||
extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4)));
|
$length = unpack('Nlength', Strings::shift($this->packet_buffer, 4))['length'];
|
||||||
/** @var integer $length */
|
|
||||||
|
|
||||||
$tempLength = $length;
|
$tempLength = $length;
|
||||||
$tempLength -= strlen($this->packet_buffer);
|
$tempLength -= strlen($this->packet_buffer);
|
||||||
@@ -3386,7 +3459,7 @@ class SFTP extends SSH2
|
|||||||
$this->packet_type = ord(Strings::shift($this->packet_buffer));
|
$this->packet_type = ord(Strings::shift($this->packet_buffer));
|
||||||
|
|
||||||
if ($this->use_request_id) {
|
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
|
$length -= 5; // account for the request id and the packet type
|
||||||
} else {
|
} else {
|
||||||
$length -= 1; // account for the packet type
|
$length -= 1; // account for the packet type
|
||||||
@@ -3456,11 +3529,11 @@ class SFTP extends SSH2
|
|||||||
return $this->packet_type_log;
|
return $this->packet_type_log;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all errors on the SFTP layer
|
* Returns all errors on the SFTP layer
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getSFTPErrors()
|
public function getSFTPErrors()
|
||||||
{
|
{
|
||||||
@@ -3471,6 +3544,7 @@ class SFTP extends SSH2
|
|||||||
* Returns the last error on the SFTP layer
|
* Returns the last error on the SFTP layer
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getLastSFTPError()
|
public function getLastSFTPError()
|
||||||
{
|
{
|
||||||
@@ -3559,7 +3633,6 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable Date Preservation
|
* Enable Date Preservation
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public function enableDatePreservation()
|
public function enableDatePreservation()
|
||||||
{
|
{
|
||||||
@@ -3568,13 +3641,110 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable Date Preservation
|
* Disable Date Preservation
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public function disableDatePreservation()
|
public function disableDatePreservation()
|
||||||
{
|
{
|
||||||
$this->preserveTime = false;
|
$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
|
* POSIX Rename
|
||||||
*
|
*
|
||||||
@@ -3606,6 +3776,9 @@ class SFTP extends SSH2
|
|||||||
$packet = Strings::packSSH2('sss', 'posix-rename@openssh.com', $oldname, $newname);
|
$packet = Strings::packSSH2('sss', 'posix-rename@openssh.com', $oldname, $newname);
|
||||||
$this->send_sftp_packet(NET_SFTP_EXTENDED, $packet);
|
$this->send_sftp_packet(NET_SFTP_EXTENDED, $packet);
|
||||||
} else {
|
} else {
|
||||||
|
if ($this->is_timeout) {
|
||||||
|
throw new TimeoutException('Timed out waiting for SFTP packet response');
|
||||||
|
}
|
||||||
throw new \RuntimeException(
|
throw new \RuntimeException(
|
||||||
"Extension 'posix-rename@openssh.com' is not supported by the server. " .
|
"Extension 'posix-rename@openssh.com' is not supported by the server. " .
|
||||||
"Call getSupportedVersions() to see a list of supported extension"
|
"Call getSupportedVersions() to see a list of supported extension"
|
||||||
@@ -3614,6 +3787,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type != NET_SFTP_STATUS) {
|
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. '
|
throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. '
|
||||||
. 'Got packet type: ' . $this->packet_type);
|
. 'Got packet type: ' . $this->packet_type);
|
||||||
}
|
}
|
||||||
@@ -3666,6 +3842,9 @@ class SFTP extends SSH2
|
|||||||
|
|
||||||
$response = $this->get_sftp_packet();
|
$response = $this->get_sftp_packet();
|
||||||
if ($this->packet_type !== NET_SFTP_EXTENDED_REPLY) {
|
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(
|
throw new \UnexpectedValueException(
|
||||||
'Expected SSH_FXP_EXTENDED_REPLY. '
|
'Expected SSH_FXP_EXTENDED_REPLY. '
|
||||||
. 'Got packet type: ' . $this->packet_type
|
. 'Got packet type: ' . $this->packet_type
|
||||||
@@ -3694,4 +3873,53 @@ class SFTP extends SSH2
|
|||||||
Strings::unpackSSH2('QQQQQQQQQQQ', $response)
|
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)
|
protected function parse_path($path)
|
||||||
{
|
{
|
||||||
$orig = $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)) {
|
if (isset($query)) {
|
||||||
$path .= '?' . $query;
|
$path .= '?' . $query;
|
||||||
} elseif (preg_match('/(\?|\?#)$/', $orig)) {
|
} elseif (preg_match('/(\?|\?#)$/', $orig)) {
|
||||||
@@ -169,9 +177,9 @@ class Stream
|
|||||||
}
|
}
|
||||||
$this->sftp = $host;
|
$this->sftp = $host;
|
||||||
} else {
|
} else {
|
||||||
if (isset($this->context)) {
|
$context = isset($this->context) ?
|
||||||
$context = stream_context_get_options($this->context);
|
stream_context_get_options($this->context) :
|
||||||
}
|
stream_context_get_options(stream_context_get_default());
|
||||||
if (isset($context[$scheme]['session'])) {
|
if (isset($context[$scheme]['session'])) {
|
||||||
$sftp = $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
|
* open request, and 'sender channel' is the channel number allocated by
|
||||||
* the other side.
|
* the other side.
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SSH2::send_channel_packet()
|
* @see SSH2::send_channel_packet()
|
||||||
* @see \phpseclib3\Net\SSH2::get_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_SHELL = 2;
|
||||||
const CHANNEL_SUBSYSTEM = 3;
|
const CHANNEL_SUBSYSTEM = 3;
|
||||||
const CHANNEL_AGENT_FORWARD = 4;
|
const CHANNEL_AGENT_FORWARD = 4;
|
||||||
@@ -130,13 +130,13 @@ class SSH2
|
|||||||
/**
|
/**
|
||||||
* Returns the message numbers
|
* Returns the message numbers
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SSH2::getLog()
|
* @see SSH2::getLog()
|
||||||
*/
|
*/
|
||||||
const LOG_SIMPLE = 1;
|
const LOG_SIMPLE = 1;
|
||||||
/**
|
/**
|
||||||
* Returns the message content
|
* Returns the message content
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SSH2::getLog()
|
* @see SSH2::getLog()
|
||||||
*/
|
*/
|
||||||
const LOG_COMPLEX = 2;
|
const LOG_COMPLEX = 2;
|
||||||
/**
|
/**
|
||||||
@@ -158,20 +158,20 @@ class SSH2
|
|||||||
/**
|
/**
|
||||||
* Make sure that the log never gets larger than this
|
* 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
|
const LOG_MAX_SIZE = 1048576; // 1024 * 1024
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns when a string matching $expect exactly is found
|
* Returns when a string matching $expect exactly is found
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SSH2::read()
|
* @see SSH2::read()
|
||||||
*/
|
*/
|
||||||
const READ_SIMPLE = 1;
|
const READ_SIMPLE = 1;
|
||||||
/**
|
/**
|
||||||
* Returns when a string matching the regular expression $expect is found
|
* Returns when a string matching the regular expression $expect is found
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SSH2::read()
|
* @see SSH2::read()
|
||||||
*/
|
*/
|
||||||
const READ_REGEX = 2;
|
const READ_REGEX = 2;
|
||||||
/**
|
/**
|
||||||
@@ -180,7 +180,7 @@ class SSH2
|
|||||||
* Some data packets may only contain a single character so it may be necessary
|
* Some data packets may only contain a single character so it may be necessary
|
||||||
* to call read() multiple times when using this option
|
* to call read() multiple times when using this option
|
||||||
*
|
*
|
||||||
* @see \phpseclib3\Net\SSH2::read()
|
* @see SSH2::read()
|
||||||
*/
|
*/
|
||||||
const READ_NEXT = 3;
|
const READ_NEXT = 3;
|
||||||
|
|
||||||
@@ -679,7 +679,7 @@ class SSH2
|
|||||||
* @see self::send_channel_packet()
|
* @see self::send_channel_packet()
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $packet_size_client_to_server = [];
|
protected $packet_size_client_to_server = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message Number Log
|
* Message Number Log
|
||||||
@@ -1477,7 +1477,7 @@ class SSH2
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (defined('NET_SSH2_LOGGING')) {
|
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)) {
|
if (feof($this->fsock)) {
|
||||||
@@ -1487,7 +1487,13 @@ class SSH2
|
|||||||
|
|
||||||
$extra = $matches[1];
|
$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)) {
|
if (strlen($extra)) {
|
||||||
$this->errors[] = $data;
|
$this->errors[] = $data;
|
||||||
}
|
}
|
||||||
@@ -1677,7 +1683,6 @@ class SSH2
|
|||||||
case NET_SSH2_MSG_DISCONNECT:
|
case NET_SSH2_MSG_DISCONNECT:
|
||||||
return $this->handleDisconnect($kexinit_payload_server);
|
return $this->handleDisconnect($kexinit_payload_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->kex_buffer[] = $kexinit_payload_server;
|
$this->kex_buffer[] = $kexinit_payload_server;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2936,6 +2941,9 @@ class SSH2
|
|||||||
$this->channel_id_last_interactive = self::CHANNEL_EXEC;
|
$this->channel_id_last_interactive = self::CHANNEL_EXEC;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if ($callback === false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$output = '';
|
$output = '';
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -2977,7 +2985,7 @@ class SSH2
|
|||||||
*/
|
*/
|
||||||
protected function open_channel($channel, $skip_extended = false)
|
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');
|
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?
|
* Is timeout?
|
||||||
*
|
*
|
||||||
@@ -3709,12 +3738,12 @@ class SSH2
|
|||||||
substr($packet->raw, 0, -$this->hmac_size);
|
substr($packet->raw, 0, -$this->hmac_size);
|
||||||
if (($this->hmac_check->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') {
|
if (($this->hmac_check->getHash() & "\xFF\xFF\xFF\xFF") == 'umac') {
|
||||||
$this->hmac_check->setNonce("\0\0\0\0" . pack('N', $this->get_seq_no));
|
$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);
|
$this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
|
||||||
throw new ConnectionClosedException('Invalid UMAC');
|
throw new ConnectionClosedException('Invalid UMAC');
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
$this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
|
||||||
throw new ConnectionClosedException('Invalid HMAC');
|
throw new ConnectionClosedException('Invalid HMAC');
|
||||||
}
|
}
|
||||||
@@ -3722,7 +3751,7 @@ class SSH2
|
|||||||
}
|
}
|
||||||
$padding_length = 0;
|
$padding_length = 0;
|
||||||
$payload = $packet->plain;
|
$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) {
|
if ($padding_length > 0) {
|
||||||
Strings::pop($payload, $padding_length);
|
Strings::pop($payload, $padding_length);
|
||||||
}
|
}
|
||||||
@@ -3788,8 +3817,7 @@ class SSH2
|
|||||||
$this->key_exchange();
|
$this->key_exchange();
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't filter if we're in the middle of a key exchange (since _filter might send out packets)
|
return $this->filter($payload);
|
||||||
return $this->keyExchangeInProgress ? $payload : $this->filter($payload);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3809,13 +3837,13 @@ class SSH2
|
|||||||
switch ($this->decryptName) {
|
switch ($this->decryptName) {
|
||||||
case 'aes128-gcm@openssh.com':
|
case 'aes128-gcm@openssh.com':
|
||||||
case 'aes256-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
|
$packet->size = $packet_length_header_size + $packet_length + $this->decrypt_block_size; // expect tag
|
||||||
break;
|
break;
|
||||||
case 'chacha20-poly1305@openssh.com':
|
case 'chacha20-poly1305@openssh.com':
|
||||||
$this->lengthDecrypt->setNonce(pack('N2', 0, $this->get_seq_no));
|
$this->lengthDecrypt->setNonce(pack('N2', 0, $this->get_seq_no));
|
||||||
$packet_length_header = $this->lengthDecrypt->decrypt(substr($packet->raw, 0, $packet_length_header_size));
|
$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
|
$packet->size = $packet_length_header_size + $packet_length + 16; // expect tag
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -3824,17 +3852,17 @@ class SSH2
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$packet->plain = $this->decrypt->decrypt(substr($packet->raw, 0, $this->decrypt_block_size));
|
$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;
|
$packet->size = $packet_length_header_size + $packet_length;
|
||||||
$added_validation_length = $packet_length_header_size;
|
$added_validation_length = $packet_length_header_size;
|
||||||
} else {
|
} 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;
|
$packet->size = $packet_length_header_size + $packet_length;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
$packet->size = $packet_length_header_size + $packet_length;
|
||||||
$added_validation_length = $packet_length_header_size;
|
$added_validation_length = $packet_length_header_size;
|
||||||
}
|
}
|
||||||
@@ -3884,9 +3912,15 @@ class SSH2
|
|||||||
*/
|
*/
|
||||||
private function filter($payload)
|
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])) {
|
switch (ord($payload[0])) {
|
||||||
case NET_SSH2_MSG_DISCONNECT:
|
|
||||||
return $this->handleDisconnect($payload);
|
|
||||||
case NET_SSH2_MSG_IGNORE:
|
case NET_SSH2_MSG_IGNORE:
|
||||||
$payload = $this->get_binary_packet();
|
$payload = $this->get_binary_packet();
|
||||||
break;
|
break;
|
||||||
@@ -3900,7 +3934,7 @@ class SSH2
|
|||||||
break; // return payload
|
break; // return payload
|
||||||
case NET_SSH2_MSG_KEXINIT:
|
case NET_SSH2_MSG_KEXINIT:
|
||||||
// this is here for server initiated key re-exchanges after the initial key exchange
|
// 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)) {
|
if (!$this->key_exchange($payload)) {
|
||||||
$this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
$this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
|
||||||
throw new ConnectionClosedException('Key exchange failed');
|
throw new ConnectionClosedException('Key exchange failed');
|
||||||
@@ -3920,6 +3954,26 @@ class SSH2
|
|||||||
$payload = $this->get_binary_packet();
|
$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
|
// 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) {
|
if (($this->bitmap & self::MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
|
||||||
Strings::shift($payload, 1);
|
Strings::shift($payload, 1);
|
||||||
@@ -3932,7 +3986,10 @@ class SSH2
|
|||||||
switch (ord($payload[0])) {
|
switch (ord($payload[0])) {
|
||||||
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
||||||
if (strlen($payload) == 31) {
|
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 (substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) {
|
||||||
if (ord(substr($payload, 9 + $length))) { // want reply
|
if (ord(substr($payload, 9 + $length))) { // want reply
|
||||||
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel]));
|
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel]));
|
||||||
@@ -3943,9 +4000,11 @@ class SSH2
|
|||||||
break;
|
break;
|
||||||
case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
|
case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
|
||||||
Strings::shift($payload, 1);
|
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->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();
|
$payload = $this->get_binary_packet();
|
||||||
break;
|
break;
|
||||||
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
|
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)
|
protected function get_channel_packet($client_channel, $skip_extended = false)
|
||||||
{
|
{
|
||||||
if (!empty($this->channel_buffers[$client_channel])) {
|
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:
|
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
||||||
foreach ($this->channel_buffers[$client_channel] as $i => $packet) {
|
foreach ($this->channel_buffers[$client_channel] as $i => $packet) {
|
||||||
switch (ord($packet[0])) {
|
switch (ord($packet[0])) {
|
||||||
@@ -4164,7 +4224,7 @@ class SSH2
|
|||||||
|
|
||||||
continue 2;
|
continue 2;
|
||||||
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
case NET_SSH2_MSG_CHANNEL_REQUEST:
|
||||||
if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) {
|
if (!isset($this->channel_status[$channel])) {
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
list($value) = Strings::unpackSSH2('s', $response);
|
list($value) = Strings::unpackSSH2('s', $response);
|
||||||
@@ -4181,12 +4241,14 @@ class SSH2
|
|||||||
if (strlen($error_message)) {
|
if (strlen($error_message)) {
|
||||||
$this->errors[count($this->errors) - 1] .= "\r\n$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->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_EOF;
|
|
||||||
|
|
||||||
continue 3;
|
continue 3;
|
||||||
case 'exit-status':
|
case 'exit-status':
|
||||||
list(, $this->exit_status) = Strings::unpackSSH2('CN', $response);
|
list(, $this->exit_status) = Strings::unpackSSH2('CN', $response);
|
||||||
@@ -4196,8 +4258,13 @@ class SSH2
|
|||||||
|
|
||||||
continue 3;
|
continue 3;
|
||||||
default:
|
default:
|
||||||
// "Some systems may not implement signals, in which case they SHOULD ignore this message."
|
list($want_reply) = Strings::unpackSSH2('b', $response);
|
||||||
// -- http://tools.ietf.org/html/rfc4254#section-6.9
|
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;
|
continue 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4286,11 +4353,11 @@ class SSH2
|
|||||||
|
|
||||||
$this->close_channel_bitmap($channel);
|
$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->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--;
|
$this->channelCount--;
|
||||||
|
|
||||||
if ($client_channel == $channel) {
|
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)
|
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)
|
// 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);
|
Strings::shift($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4655,27 +4722,24 @@ class SSH2
|
|||||||
* @param bool $want_reply
|
* @param bool $want_reply
|
||||||
* @return void
|
* @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
|
// 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 ($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]));
|
||||||
if (!$want_reply) {
|
|
||||||
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $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->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
|
||||||
|
|
||||||
$this->channelCount--;
|
$this->channelCount--;
|
||||||
|
|
||||||
$this->curTimeout = 5;
|
$this->curTimeout = 5;
|
||||||
|
|
||||||
while (!is_bool($this->get_channel_packet($client_channel))) {
|
while (!is_bool($this->get_channel_packet($client_channel))) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($want_reply) {
|
unset($this->channel_status[$client_channel]);
|
||||||
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->close_channel_bitmap($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()
|
* If you are looking for messages from the SFTP layer, please see SFTP::getSFTPErrors()
|
||||||
*
|
*
|
||||||
* @return string[]
|
* @return string[]
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getErrors()
|
public function getErrors()
|
||||||
{
|
{
|
||||||
@@ -4861,6 +4926,7 @@ class SSH2
|
|||||||
* If you are looking for messages from the SFTP layer, please see SFTP::getLastSFTPError()
|
* If you are looking for messages from the SFTP layer, please see SFTP::getLastSFTPError()
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @removed in phpseclib 4.0.0
|
||||||
*/
|
*/
|
||||||
public function getLastError()
|
public function getLastError()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ namespace phpseclib3\System\SSH;
|
|||||||
use phpseclib3\Common\Functions\Strings;
|
use phpseclib3\Common\Functions\Strings;
|
||||||
use phpseclib3\Crypt\Common\PublicKey;
|
use phpseclib3\Crypt\Common\PublicKey;
|
||||||
use phpseclib3\Crypt\PublicKeyLoader;
|
use phpseclib3\Crypt\PublicKeyLoader;
|
||||||
use phpseclib3\Crypt\RSA;
|
|
||||||
use phpseclib3\Exception\BadConfigurationException;
|
use phpseclib3\Exception\BadConfigurationException;
|
||||||
use phpseclib3\Net\SSH2;
|
use phpseclib3\Net\SSH2;
|
||||||
use phpseclib3\System\SSH\Agent\Identity;
|
use phpseclib3\System\SSH\Agent\Identity;
|
||||||
|
|||||||
@@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
HOME = .
|
HOME = .
|
||||||
RANDFILE = $ENV::HOME/.rnd
|
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 ]
|
[ v3_ca ]
|
||||||
|
|||||||
Reference in New Issue
Block a user