diff --git a/.gitignore b/.gitignore index 4bbc396943e59..7d607f224dbc1 100644 --- a/.gitignore +++ b/.gitignore @@ -148,12 +148,16 @@ Desktop.ini /libraries/vendor/paragonie/random_compat/psalm.xml /libraries/vendor/paragonie/random_compat/tests /libraries/vendor/paragonie/sodium_compat/.gitignore +/libraries/vendor/paragonie/sodium_compat/.github /libraries/vendor/paragonie/sodium_compat/appveyor.yml /libraries/vendor/paragonie/sodium_compat/build-phar.sh /libraries/vendor/paragonie/sodium_compat/composer.json +/libraries/vendor/paragonie/sodium_compat/composer-php52.json /libraries/vendor/paragonie/sodium_compat/composer.lock /libraries/vendor/paragonie/sodium_compat/dist /libraries/vendor/paragonie/sodium_compat/phpunit.xml.dist +/libraries/vendor/paragonie/sodium_compat/psalm-above-3.xml +/libraries/vendor/paragonie/sodium_compat/psalm-below-3.xml /libraries/vendor/paragonie/sodium_compat/README.md /libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/README.md /libraries/vendor/phpmailer/phpmailer/docs diff --git a/composer.json b/composer.json index 702e137d0ddf9..c7eff35dfd2fd 100644 --- a/composer.json +++ b/composer.json @@ -50,7 +50,7 @@ "ircmaxell/password-compat": "1.*", "leafo/lessphp": "dev-joomla3-php8", "paragonie/random_compat": "~1.4", - "paragonie/sodium_compat": "1.9.1", + "paragonie/sodium_compat": "1.17.0", "phpmailer/phpmailer": "dev-joomla-backports", "symfony/polyfill-php55": "~1.9", "symfony/polyfill-php56": "~1.9", diff --git a/composer.lock b/composer.lock index c429aed3ef2c6..7e34db9848e3c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bbed972753d37f5dfa3e43d4a7e6d356", + "content-hash": "576ba4484df6a684545e5b84464c8c95", "packages": [ { "name": "brumann/polyfill-unserialize", @@ -1189,16 +1189,16 @@ }, { "name": "paragonie/sodium_compat", - "version": "v1.9.1", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/paragonie/sodium_compat.git", - "reference": "87125d5b265f98c4d1b8d83a1f0726607c229421" + "reference": "c59cac21abbcc0df06a3dd18076450ea4797b321" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/87125d5b265f98c4d1b8d83a1f0726607c229421", - "reference": "87125d5b265f98c4d1b8d83a1f0726607c229421", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/c59cac21abbcc0df06a3dd18076450ea4797b321", + "reference": "c59cac21abbcc0df06a3dd18076450ea4797b321", "shasum": "" }, "require": { @@ -1206,7 +1206,7 @@ "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" }, "require-dev": { - "phpunit/phpunit": "^3|^4|^5" + "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9" }, "suggest": { "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", @@ -1269,9 +1269,9 @@ ], "support": { "issues": "https://github.com/paragonie/sodium_compat/issues", - "source": "https://github.com/paragonie/sodium_compat/tree/master" + "source": "https://github.com/paragonie/sodium_compat/tree/v1.17.0" }, - "time": "2019-03-20T17:19:05+00:00" + "time": "2021-08-10T02:43:50+00:00" }, { "name": "phpmailer/phpmailer", @@ -3816,5 +3816,5 @@ "platform-overrides": { "php": "5.3.10" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.2.0" } diff --git a/libraries/vendor/composer/ClassLoader.php b/libraries/vendor/composer/ClassLoader.php index 6d0c3f2d001d8..afef3fa2ad83f 100644 --- a/libraries/vendor/composer/ClassLoader.php +++ b/libraries/vendor/composer/ClassLoader.php @@ -42,30 +42,75 @@ */ class ClassLoader { + /** @var ?string */ private $vendorDir; // PSR-4 + /** + * @var array[] + * @psalm-var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array[] + * @psalm-var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * @var array[] + * @psalm-var array> + */ private $prefixesPsr0 = array(); + /** + * @var array[] + * @psalm-var array + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var string[] + * @psalm-var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var bool[] + * @psalm-var array + */ private $missingClasses = array(); + + /** @var ?string */ private $apcuPrefix; + /** + * @var self[] + */ private static $registeredLoaders = array(); + /** + * @param ?string $vendorDir + */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; } + /** + * @return string[] + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { @@ -75,28 +120,47 @@ public function getPrefixes() return array(); } + /** + * @return array[] + * @psalm-return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return array[] + * @psalm-return array + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return string[] Array of classname => path + * @psalm-return array + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param string[] $classMap Class to filename map + * @psalm-param array $classMap + * + * @return void */ public function addClassMap(array $classMap) { @@ -111,9 +175,11 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { @@ -156,11 +222,13 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { @@ -204,8 +272,10 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param string[]|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -220,10 +290,12 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param string[]|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -243,6 +315,8 @@ public function setPsr4($prefix, $paths) * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -265,6 +339,8 @@ public function getUseIncludePath() * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -285,6 +361,8 @@ public function isClassMapAuthoritative() * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -305,6 +383,8 @@ public function getApcuPrefix() * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { @@ -324,6 +404,8 @@ public function register($prepend = false) /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { @@ -403,6 +485,11 @@ public static function getRegisteredLoaders() return self::$registeredLoaders; } + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -474,6 +561,10 @@ private function findFileWithExtension($class, $ext) * Scope isolated include. * * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + * @private */ function includeFile($file) { diff --git a/libraries/vendor/composer/InstalledVersions.php b/libraries/vendor/composer/InstalledVersions.php index b3a4e1611e6e5..d50e0c9fcc47d 100644 --- a/libraries/vendor/composer/InstalledVersions.php +++ b/libraries/vendor/composer/InstalledVersions.php @@ -20,12 +20,25 @@ * * See also https://getcomposer.org/doc/07-runtime.md#installed-versions * - * To require it's presence, you can require `composer-runtime-api ^2.0` + * To require its presence, you can require `composer-runtime-api ^2.0` */ class InstalledVersions { + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null + */ private static $installed; + + /** + * @var bool|null + */ private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ private static $installedByVendor = array(); /** @@ -228,7 +241,7 @@ public static function getInstallPath($packageName) /** * @return array - * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string} + * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} */ public static function getRootPackage() { @@ -242,7 +255,7 @@ public static function getRootPackage() * * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. * @return array[] - * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array} + * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} */ public static function getRawData() { @@ -265,7 +278,7 @@ public static function getRawData() * Returns the raw data of all installed.php which are currently loaded for custom implementations * * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ public static function getAllRawData() { @@ -288,7 +301,7 @@ public static function getAllRawData() * @param array[] $data A vendor/composer/installed.php data set * @return void * - * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array} $data + * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array} $data */ public static function reload($data) { @@ -298,7 +311,7 @@ public static function reload($data) /** * @return array[] - * @psalm-return list}> + * @psalm-return list}> */ private static function getInstalled() { diff --git a/libraries/vendor/composer/autoload_classmap.php b/libraries/vendor/composer/autoload_classmap.php index ab44497339f91..0a1689bf0e6ef 100644 --- a/libraries/vendor/composer/autoload_classmap.php +++ b/libraries/vendor/composer/autoload_classmap.php @@ -42,6 +42,8 @@ 'Joomla\\Data\\DataObject' => $vendorDir . '/joomla/data/src/DataObject.php', 'Joomla\\Data\\DataSet' => $vendorDir . '/joomla/data/src/DataSet.php', 'Joomla\\Data\\DumpableInterface' => $vendorDir . '/joomla/data/src/DumpableInterface.php', + 'Joomla\\Data\\Tests\\DataObjectTest' => $vendorDir . '/joomla/data/Tests/DataObjectTest.php', + 'Joomla\\Data\\Tests\\DataSetTest' => $vendorDir . '/joomla/data/Tests/DataSetTest.php', 'Joomla\\Event\\AbstractEvent' => $vendorDir . '/joomla/event/src/AbstractEvent.php', 'Joomla\\Event\\DelegatingDispatcher' => $vendorDir . '/joomla/event/src/DelegatingDispatcher.php', 'Joomla\\Event\\Dispatcher' => $vendorDir . '/joomla/event/src/Dispatcher.php', @@ -103,6 +105,15 @@ 'Joomla\\Session\\Storage\\None' => $vendorDir . '/joomla/session/Joomla/Session/Storage/None.php', 'Joomla\\Session\\Storage\\Wincache' => $vendorDir . '/joomla/session/Joomla/Session/Storage/Wincache.php', 'Joomla\\Session\\Storage\\Xcache' => $vendorDir . '/joomla/session/Joomla/Session/Storage/Xcache.php', + 'Joomla\\Session\\Tests\\StorageCase' => $vendorDir . '/joomla/session/Joomla/Session/Tests/StorageCase.php', + 'Joomla\\Session\\Tests\\StorageTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/StorageTest.php', + 'Joomla\\Session\\Tests\\Storage\\ApcTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/Storage/ApcTest.php', + 'Joomla\\Session\\Tests\\Storage\\DatabaseTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/Storage/DatabaseTest.php', + 'Joomla\\Session\\Tests\\Storage\\MemcacheTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/Storage/MemcacheTest.php', + 'Joomla\\Session\\Tests\\Storage\\MemcachedTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/Storage/MemcachedTest.php', + 'Joomla\\Session\\Tests\\Storage\\NoneTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/Storage/NoneTest.php', + 'Joomla\\Session\\Tests\\Storage\\WincacheTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/Storage/WincacheTest.php', + 'Joomla\\Session\\Tests\\Storage\\XcacheTest' => $vendorDir . '/joomla/session/Joomla/Session/Tests/Storage/XcacheTest.php', 'Joomla\\String\\Inflector' => $vendorDir . '/joomla/string/src/Inflector.php', 'Joomla\\String\\Normalise' => $vendorDir . '/joomla/string/src/Normalise.php', 'Joomla\\String\\String' => $vendorDir . '/joomla/string/src/String.php', @@ -131,6 +142,9 @@ 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/DummyTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', 'ReCaptcha\\ReCaptcha' => $vendorDir . '/google/recaptcha/src/ReCaptcha/ReCaptcha.php', 'ReCaptcha\\RequestMethod' => $vendorDir . '/google/recaptcha/src/ReCaptcha/RequestMethod.php', 'ReCaptcha\\RequestMethod\\Curl' => $vendorDir . '/google/recaptcha/src/ReCaptcha/RequestMethod/Curl.php', @@ -193,6 +207,11 @@ 'Symfony\\Polyfill\\Util\\Binary' => $vendorDir . '/symfony/polyfill-util/Binary.php', 'Symfony\\Polyfill\\Util\\BinaryNoFuncOverload' => $vendorDir . '/symfony/polyfill-util/BinaryNoFuncOverload.php', 'Symfony\\Polyfill\\Util\\BinaryOnFuncOverload' => $vendorDir . '/symfony/polyfill-util/BinaryOnFuncOverload.php', + 'Symfony\\Polyfill\\Util\\TestListener' => $vendorDir . '/symfony/polyfill-util/TestListener.php', + 'Symfony\\Polyfill\\Util\\TestListenerForV5' => $vendorDir . '/symfony/polyfill-util/TestListenerForV5.php', + 'Symfony\\Polyfill\\Util\\TestListenerForV6' => $vendorDir . '/symfony/polyfill-util/TestListenerForV6.php', + 'Symfony\\Polyfill\\Util\\TestListenerForV7' => $vendorDir . '/symfony/polyfill-util/TestListenerForV7.php', + 'Symfony\\Polyfill\\Util\\TestListenerTrait' => $vendorDir . '/symfony/polyfill-util/TestListenerTrait.php', 'TYPO3\\PharStreamWrapper\\Assertable' => $vendorDir . '/typo3/phar-stream-wrapper/src/Assertable.php', 'TYPO3\\PharStreamWrapper\\Behavior' => $vendorDir . '/typo3/phar-stream-wrapper/src/Behavior.php', 'TYPO3\\PharStreamWrapper\\Collectable' => $vendorDir . '/typo3/phar-stream-wrapper/src/Collectable.php', diff --git a/libraries/vendor/composer/autoload_real.php b/libraries/vendor/composer/autoload_real.php index 0f5b19606b505..559a005cb7898 100644 --- a/libraries/vendor/composer/autoload_real.php +++ b/libraries/vendor/composer/autoload_real.php @@ -65,11 +65,16 @@ public static function getLoader() } } +/** + * @param string $fileIdentifier + * @param string $file + * @return void + */ function composerRequirec14bde14f8c86840049f5c1809c453dd($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; } } diff --git a/libraries/vendor/composer/autoload_static.php b/libraries/vendor/composer/autoload_static.php index c3d477b1df289..5fd8e9fa1954e 100644 --- a/libraries/vendor/composer/autoload_static.php +++ b/libraries/vendor/composer/autoload_static.php @@ -245,6 +245,8 @@ class ComposerStaticInitc14bde14f8c86840049f5c1809c453dd 'Joomla\\Data\\DataObject' => __DIR__ . '/..' . '/joomla/data/src/DataObject.php', 'Joomla\\Data\\DataSet' => __DIR__ . '/..' . '/joomla/data/src/DataSet.php', 'Joomla\\Data\\DumpableInterface' => __DIR__ . '/..' . '/joomla/data/src/DumpableInterface.php', + 'Joomla\\Data\\Tests\\DataObjectTest' => __DIR__ . '/..' . '/joomla/data/Tests/DataObjectTest.php', + 'Joomla\\Data\\Tests\\DataSetTest' => __DIR__ . '/..' . '/joomla/data/Tests/DataSetTest.php', 'Joomla\\Event\\AbstractEvent' => __DIR__ . '/..' . '/joomla/event/src/AbstractEvent.php', 'Joomla\\Event\\DelegatingDispatcher' => __DIR__ . '/..' . '/joomla/event/src/DelegatingDispatcher.php', 'Joomla\\Event\\Dispatcher' => __DIR__ . '/..' . '/joomla/event/src/Dispatcher.php', @@ -306,6 +308,15 @@ class ComposerStaticInitc14bde14f8c86840049f5c1809c453dd 'Joomla\\Session\\Storage\\None' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Storage/None.php', 'Joomla\\Session\\Storage\\Wincache' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Storage/Wincache.php', 'Joomla\\Session\\Storage\\Xcache' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Storage/Xcache.php', + 'Joomla\\Session\\Tests\\StorageCase' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/StorageCase.php', + 'Joomla\\Session\\Tests\\StorageTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/StorageTest.php', + 'Joomla\\Session\\Tests\\Storage\\ApcTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/Storage/ApcTest.php', + 'Joomla\\Session\\Tests\\Storage\\DatabaseTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/Storage/DatabaseTest.php', + 'Joomla\\Session\\Tests\\Storage\\MemcacheTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/Storage/MemcacheTest.php', + 'Joomla\\Session\\Tests\\Storage\\MemcachedTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/Storage/MemcachedTest.php', + 'Joomla\\Session\\Tests\\Storage\\NoneTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/Storage/NoneTest.php', + 'Joomla\\Session\\Tests\\Storage\\WincacheTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/Storage/WincacheTest.php', + 'Joomla\\Session\\Tests\\Storage\\XcacheTest' => __DIR__ . '/..' . '/joomla/session/Joomla/Session/Tests/Storage/XcacheTest.php', 'Joomla\\String\\Inflector' => __DIR__ . '/..' . '/joomla/string/src/Inflector.php', 'Joomla\\String\\Normalise' => __DIR__ . '/..' . '/joomla/string/src/Normalise.php', 'Joomla\\String\\String' => __DIR__ . '/..' . '/joomla/string/src/String.php', @@ -334,6 +345,9 @@ class ComposerStaticInitc14bde14f8c86840049f5c1809c453dd 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/DummyTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', 'ReCaptcha\\ReCaptcha' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/ReCaptcha.php', 'ReCaptcha\\RequestMethod' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/RequestMethod.php', 'ReCaptcha\\RequestMethod\\Curl' => __DIR__ . '/..' . '/google/recaptcha/src/ReCaptcha/RequestMethod/Curl.php', @@ -396,6 +410,11 @@ class ComposerStaticInitc14bde14f8c86840049f5c1809c453dd 'Symfony\\Polyfill\\Util\\Binary' => __DIR__ . '/..' . '/symfony/polyfill-util/Binary.php', 'Symfony\\Polyfill\\Util\\BinaryNoFuncOverload' => __DIR__ . '/..' . '/symfony/polyfill-util/BinaryNoFuncOverload.php', 'Symfony\\Polyfill\\Util\\BinaryOnFuncOverload' => __DIR__ . '/..' . '/symfony/polyfill-util/BinaryOnFuncOverload.php', + 'Symfony\\Polyfill\\Util\\TestListener' => __DIR__ . '/..' . '/symfony/polyfill-util/TestListener.php', + 'Symfony\\Polyfill\\Util\\TestListenerForV5' => __DIR__ . '/..' . '/symfony/polyfill-util/TestListenerForV5.php', + 'Symfony\\Polyfill\\Util\\TestListenerForV6' => __DIR__ . '/..' . '/symfony/polyfill-util/TestListenerForV6.php', + 'Symfony\\Polyfill\\Util\\TestListenerForV7' => __DIR__ . '/..' . '/symfony/polyfill-util/TestListenerForV7.php', + 'Symfony\\Polyfill\\Util\\TestListenerTrait' => __DIR__ . '/..' . '/symfony/polyfill-util/TestListenerTrait.php', 'TYPO3\\PharStreamWrapper\\Assertable' => __DIR__ . '/..' . '/typo3/phar-stream-wrapper/src/Assertable.php', 'TYPO3\\PharStreamWrapper\\Behavior' => __DIR__ . '/..' . '/typo3/phar-stream-wrapper/src/Behavior.php', 'TYPO3\\PharStreamWrapper\\Collectable' => __DIR__ . '/..' . '/typo3/phar-stream-wrapper/src/Collectable.php', diff --git a/libraries/vendor/composer/installed.json b/libraries/vendor/composer/installed.json index c3b25cba9015b..b27ac0a582391 100644 --- a/libraries/vendor/composer/installed.json +++ b/libraries/vendor/composer/installed.json @@ -1246,17 +1246,17 @@ }, { "name": "paragonie/sodium_compat", - "version": "v1.9.1", - "version_normalized": "1.9.1.0", + "version": "v1.17.0", + "version_normalized": "1.17.0.0", "source": { "type": "git", "url": "https://github.com/paragonie/sodium_compat.git", - "reference": "87125d5b265f98c4d1b8d83a1f0726607c229421" + "reference": "c59cac21abbcc0df06a3dd18076450ea4797b321" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/87125d5b265f98c4d1b8d83a1f0726607c229421", - "reference": "87125d5b265f98c4d1b8d83a1f0726607c229421", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/c59cac21abbcc0df06a3dd18076450ea4797b321", + "reference": "c59cac21abbcc0df06a3dd18076450ea4797b321", "shasum": "" }, "require": { @@ -1264,13 +1264,13 @@ "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" }, "require-dev": { - "phpunit/phpunit": "^3|^4|^5" + "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9" }, "suggest": { "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", "ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." }, - "time": "2019-03-20T17:19:05+00:00", + "time": "2021-08-10T02:43:50+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1329,7 +1329,7 @@ ], "support": { "issues": "https://github.com/paragonie/sodium_compat/issues", - "source": "https://github.com/paragonie/sodium_compat/tree/master" + "source": "https://github.com/paragonie/sodium_compat/tree/v1.17.0" }, "install-path": "../paragonie/sodium_compat" }, diff --git a/libraries/vendor/composer/installed.php b/libraries/vendor/composer/installed.php index 1a296effead07..8a5048f33836d 100644 --- a/libraries/vendor/composer/installed.php +++ b/libraries/vendor/composer/installed.php @@ -1,11 +1,11 @@ array( - 'pretty_version' => 'dev-3.10-dev', - 'version' => 'dev-3.10-dev', + 'pretty_version' => 'dev-3.10-drone', + 'version' => 'dev-3.10-drone', 'type' => 'project', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), - 'reference' => 'e9ef82568c974fdc9f610d73b24bd3f7e789713c', + 'reference' => 'd55ab7f9ddd92b19e519745c92f698ad5505cd9a', 'name' => 'joomla/joomla-cms', 'dev' => false, ), @@ -128,12 +128,12 @@ 'dev_requirement' => false, ), 'joomla/joomla-cms' => array( - 'pretty_version' => 'dev-3.10-dev', - 'version' => 'dev-3.10-dev', + 'pretty_version' => 'dev-3.10-drone', + 'version' => 'dev-3.10-drone', 'type' => 'project', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), - 'reference' => 'e9ef82568c974fdc9f610d73b24bd3f7e789713c', + 'reference' => 'd55ab7f9ddd92b19e519745c92f698ad5505cd9a', 'dev_requirement' => false, ), 'joomla/ldap' => array( @@ -211,12 +211,12 @@ 'dev_requirement' => false, ), 'paragonie/sodium_compat' => array( - 'pretty_version' => 'v1.9.1', - 'version' => '1.9.1.0', + 'pretty_version' => 'v1.17.0', + 'version' => '1.17.0.0', 'type' => 'library', 'install_path' => __DIR__ . '/../paragonie/sodium_compat', 'aliases' => array(), - 'reference' => '87125d5b265f98c4d1b8d83a1f0726607c229421', + 'reference' => 'c59cac21abbcc0df06a3dd18076450ea4797b321', 'dev_requirement' => false, ), 'phpmailer/phpmailer' => array( diff --git a/libraries/vendor/paragonie/sodium_compat/LICENSE b/libraries/vendor/paragonie/sodium_compat/LICENSE index 532a3cf52707f..f5c62818e94b8 100644 --- a/libraries/vendor/paragonie/sodium_compat/LICENSE +++ b/libraries/vendor/paragonie/sodium_compat/LICENSE @@ -1,21 +1,16 @@ -/* - * ISC License - * - * Copyright (c) 2016-2018 - * Paragon Initiative Enterprises - * - * Copyright (c) 2013-2018 - * Frank Denis - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ \ No newline at end of file +ISC License + +Copyright (c) 2016-2021, Paragon Initiative Enterprises +Copyright (c) 2013-2019, Frank Denis + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/libraries/vendor/paragonie/sodium_compat/autoload-php7.php b/libraries/vendor/paragonie/sodium_compat/autoload-php7.php new file mode 100644 index 0000000000000..482486043bec3 --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/autoload-php7.php @@ -0,0 +1,31 @@ += 50300) { + require_once (dirname(__FILE__) . '/tests/phpunit-shim.php'); +} +require_once (dirname(__FILE__) . '/autoload.php'); diff --git a/libraries/vendor/paragonie/sodium_compat/autoload.php b/libraries/vendor/paragonie/sodium_compat/autoload.php index de2683daee522..3f723bae7e820 100644 --- a/libraries/vendor/paragonie/sodium_compat/autoload.php +++ b/libraries/vendor/paragonie/sodium_compat/autoload.php @@ -1,49 +1,72 @@ = 50300) { // Namespaces didn't exist before 5.3.0, so don't even try to use this // unless PHP >= 5.3.0 require_once dirname(__FILE__) . '/lib/namespaced.php'; require_once dirname(__FILE__) . '/lib/sodium_compat.php'; +} else { + require_once dirname(__FILE__) . '/src/PHP52/SplFixedArray.php'; } if (PHP_VERSION_ID < 70200 || !extension_loaded('sodium')) { - require_once dirname(__FILE__) . '/lib/php72compat.php'; + if (PHP_VERSION_ID >= 50300 && !defined('SODIUM_CRYPTO_SCALARMULT_BYTES')) { + require_once dirname(__FILE__) . '/lib/php72compat_const.php'; + } + if (PHP_VERSION_ID >= 70000) { + assert(class_exists('ParagonIE_Sodium_Compat'), 'Possible filesystem/autoloader bug?'); + } else { + assert(class_exists('ParagonIE_Sodium_Compat')); + } + require_once(dirname(__FILE__) . '/lib/php72compat.php'); +} elseif (!function_exists('sodium_crypto_stream_xchacha20_xor')) { + // Older versions of {PHP, ext/sodium} will not define these + require_once(dirname(__FILE__) . '/lib/php72compat.php'); } +require_once(dirname(__FILE__) . '/lib/ristretto255.php'); diff --git a/libraries/vendor/paragonie/sodium_compat/lib/constants.php b/libraries/vendor/paragonie/sodium_compat/lib/constants.php index 8ddb6a4879c36..b6a120e4a4bd4 100644 --- a/libraries/vendor/paragonie/sodium_compat/lib/constants.php +++ b/libraries/vendor/paragonie/sodium_compat/lib/constants.php @@ -1,6 +1,8 @@ + * @throws SodiumException + */ + function sodium_crypto_secretstream_xchacha20poly1305_init_push($key) + { + return ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_init_push($key); + } +} +if (!is_callable('sodium_crypto_secretstream_xchacha20poly1305_push')) { + /** + * @param string $state + * @param string $msg + * @param string $aad + * @param int $tag + * @return string + * @throws SodiumException + */ + function sodium_crypto_secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0) + { + return ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_push($state, $msg, $aad, $tag); + } +} +if (!is_callable('sodium_crypto_secretstream_xchacha20poly1305_init_pull')) { + /** + * @param string $header + * @param string $key + * @return string + * @throws Exception + */ + function sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $key) + { + return ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_init_pull($header, $key); + } +} +if (!is_callable('sodium_crypto_secretstream_xchacha20poly1305_pull')) { + /** + * @param string $state + * @param string $cipher + * @param string $aad + * @return bool|array{0: string, 1: int} + * @throws SodiumException + */ + function sodium_crypto_secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '') + { + return ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_pull($state, $cipher, $aad); + } +} +if (!is_callable('sodium_crypto_secretstream_xchacha20poly1305_rekey')) { + /** + * @param string $state + * @return void + * @throws SodiumException + */ + function sodium_crypto_secretstream_xchacha20poly1305_rekey(&$state) + { + ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_rekey($state); + } +} +if (!is_callable('sodium_crypto_secretstream_xchacha20poly1305_keygen')) { + /** + * @return string + * @throws Exception + */ + function sodium_crypto_secretstream_xchacha20poly1305_keygen() + { + return ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_keygen(); + } +} if (!is_callable('sodium_crypto_shorthash')) { /** * @see ParagonIE_Sodium_Compat::crypto_shorthash() @@ -739,6 +1005,7 @@ function sodium_crypto_shorthash($message, $key = '') /** * @see ParagonIE_Sodium_Compat::crypto_shorthash_keygen() * @return string + * @throws Exception */ function sodium_crypto_shorthash_keygen() { @@ -773,6 +1040,20 @@ function sodium_crypto_sign_detached($message, $sk) return ParagonIE_Sodium_Compat::crypto_sign_detached($message, $sk); } } +if (!is_callable('sodium_crypto_sign_keypair_from_secretkey_and_publickey')) { + /** + * @see ParagonIE_Sodium_Compat::crypto_sign_keypair_from_secretkey_and_publickey() + * @param string $sk + * @param string $pk + * @return string + * @throws SodiumException + * @throws TypeError + */ + function sodium_crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk) + { + return ParagonIE_Sodium_Compat::crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk); + } +} if (!is_callable('sodium_crypto_sign_keypair')) { /** * @see ParagonIE_Sodium_Compat::crypto_sign_keypair() @@ -915,6 +1196,7 @@ function sodium_crypto_stream($len, $nonce, $key) /** * @see ParagonIE_Sodium_Compat::crypto_stream_keygen() * @return string + * @throws Exception */ function sodium_crypto_stream_keygen() { @@ -936,6 +1218,7 @@ function sodium_crypto_stream_xor($message, $nonce, $key) return ParagonIE_Sodium_Compat::crypto_stream_xor($message, $nonce, $key); } } +require_once dirname(__FILE__) . '/stream-xchacha20.php'; if (!is_callable('sodium_hex2bin')) { /** * @see ParagonIE_Sodium_Compat::hex2bin() @@ -952,7 +1235,7 @@ function sodium_hex2bin($string) if (!is_callable('sodium_increment')) { /** * @see ParagonIE_Sodium_Compat::increment() - * @param &string $string + * @param string $string * @return void * @throws SodiumException * @throws TypeError @@ -1009,7 +1292,7 @@ function sodium_memcmp($a, $b) if (!is_callable('sodium_memzero')) { /** * @see ParagonIE_Sodium_Compat::memzero() - * @param string &$str + * @param string $str * @return void * @throws SodiumException * @throws TypeError @@ -1019,6 +1302,34 @@ function sodium_memzero(&$str) ParagonIE_Sodium_Compat::memzero($str); } } +if (!is_callable('sodium_pad')) { + /** + * @see ParagonIE_Sodium_Compat::pad() + * @param string $unpadded + * @param int $blockSize + * @return int + * @throws SodiumException + * @throws TypeError + */ + function sodium_pad($unpadded, $blockSize) + { + return ParagonIE_Sodium_Compat::pad($unpadded, $blockSize, true); + } +} +if (!is_callable('sodium_unpad')) { + /** + * @see ParagonIE_Sodium_Compat::pad() + * @param string $padded + * @param int $blockSize + * @return int + * @throws SodiumException + * @throws TypeError + */ + function sodium_unpad($padded, $blockSize) + { + return ParagonIE_Sodium_Compat::unpad($padded, $blockSize, true); + } +} if (!is_callable('sodium_randombytes_buf')) { /** * @see ParagonIE_Sodium_Compat::randombytes_buf() @@ -1049,6 +1360,7 @@ function sodium_randombytes_uniform($upperLimit) /** * @see ParagonIE_Sodium_Compat::randombytes_random16() * @return int + * @throws Exception */ function sodium_randombytes_random16() { diff --git a/libraries/vendor/paragonie/sodium_compat/lib/php72compat_const.php b/libraries/vendor/paragonie/sodium_compat/lib/php72compat_const.php new file mode 100644 index 0000000000000..baa0f1e1cc46d --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/lib/php72compat_const.php @@ -0,0 +1,92 @@ +>= 8; + } + $val = ParagonIE_Sodium_Core_Util::intArrayToString($A); + } + + /** + * @param string $encoded + * @param int $variant + * @param string $ignore + * @return string + * @throws SodiumException + */ + public static function base642bin($encoded, $variant, $ignore = '') + { + /* Type checks: */ + ParagonIE_Sodium_Core_Util::declareScalarType($encoded, 'string', 1); + + /** @var string $encoded */ + $encoded = (string) $encoded; + if (ParagonIE_Sodium_Core_Util::strlen($encoded) === 0) { + return ''; + } + + // Just strip before decoding + if (!empty($ignore)) { + $encoded = str_replace($ignore, '', $encoded); + } + + try { + switch ($variant) { + case self::BASE64_VARIANT_ORIGINAL: + return ParagonIE_Sodium_Core_Base64_Original::decode($encoded, true); + case self::BASE64_VARIANT_ORIGINAL_NO_PADDING: + return ParagonIE_Sodium_Core_Base64_Original::decode($encoded, false); + case self::BASE64_VARIANT_URLSAFE: + return ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, true); + case self::BASE64_VARIANT_URLSAFE_NO_PADDING: + return ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, false); + default: + throw new SodiumException('invalid base64 variant identifier'); + } + } catch (Exception $ex) { + if ($ex instanceof SodiumException) { + throw $ex; + } + throw new SodiumException('invalid base64 string'); + } + } + + /** + * @param string $decoded + * @param int $variant + * @return string + * @throws SodiumException + */ + public static function bin2base64($decoded, $variant) + { + /* Type checks: */ + ParagonIE_Sodium_Core_Util::declareScalarType($decoded, 'string', 1); + /** @var string $decoded */ + $decoded = (string) $decoded; + if (ParagonIE_Sodium_Core_Util::strlen($decoded) === 0) { + return ''; + } + + switch ($variant) { + case self::BASE64_VARIANT_ORIGINAL: + return ParagonIE_Sodium_Core_Base64_Original::encode($decoded); + case self::BASE64_VARIANT_ORIGINAL_NO_PADDING: + return ParagonIE_Sodium_Core_Base64_Original::encodeUnpadded($decoded); + case self::BASE64_VARIANT_URLSAFE: + return ParagonIE_Sodium_Core_Base64_UrlSafe::encode($decoded); + case self::BASE64_VARIANT_URLSAFE_NO_PADDING: + return ParagonIE_Sodium_Core_Base64_UrlSafe::encodeUnpadded($decoded); + default: + throw new SodiumException('invalid base64 variant identifier'); + } + } /** * Cache-timing-safe implementation of bin2hex(). @@ -144,9 +277,9 @@ public static function bin2hex($string) * * @param string $left The left operand; must be a string * @param string $right The right operand; must be a string - * @return int < 0 if the left operand is less than the right - * = 0 if both strings are equal - * > 0 if the right operand is less than the left + * @return int If < 0 if the left operand is less than the right + * If = 0 if both strings are equal + * If > 0 if the right operand is less than the left * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument @@ -602,7 +735,9 @@ public static function crypto_aead_chacha20poly1305_ietf_encrypt( ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); - ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); + if (!is_null($assocData)) { + ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); + } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); @@ -675,7 +810,7 @@ public static function crypto_aead_chacha20poly1305_ietf_keygen() * @param string $key Encryption key * @param bool $dontFallback Don't fallback to ext/sodium * - * @return string The original plaintext message + * @return string|bool The original plaintext message * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument @@ -689,7 +824,11 @@ public static function crypto_aead_xchacha20poly1305_ietf_decrypt( ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext, 'string', 1); - ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); + if (!is_null($assocData)) { + ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); + } else { + $assocData = ''; + } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); @@ -760,7 +899,11 @@ public static function crypto_aead_xchacha20poly1305_ietf_encrypt( ) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($plaintext, 'string', 1); - ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); + if (!is_null($assocData)) { + ParagonIE_Sodium_Core_Util::declareScalarType($assocData, 'string', 2); + } else { + $assocData = ''; + } ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 3); ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); @@ -1303,12 +1446,14 @@ public static function crypto_generichash($message, $key = '', $length = self::C /** * Get the final BLAKE2b hash output for a given context. * - * @param string &$ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). - * @param int $length Hash output size. - * @return string Final BLAKE2b hash. + * @param string $ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). + * @param int $length Hash output size. + * @return string Final BLAKE2b hash. * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument + * @psalm-suppress ReferenceConstraintViolation + * @psalm-suppress ConflictingReferenceConstraint */ public static function crypto_generichash_final(&$ctx, $length = self::CRYPTO_GENERICHASH_BYTES) { @@ -1323,6 +1468,14 @@ public static function crypto_generichash_final(&$ctx, $length = self::CRYPTO_GE $func = '\\Sodium\\crypto_generichash_final'; return (string) $func($ctx, $length); } + if ($length < 1) { + try { + self::memzero($ctx); + } catch (SodiumException $ex) { + unset($ctx); + } + return ''; + } if (PHP_INT_SIZE === 4) { $result = ParagonIE_Sodium_Crypto32::generichash_final($ctx, $length); } else { @@ -1378,16 +1531,65 @@ public static function crypto_generichash_init($key = '', $length = self::CRYPTO return ParagonIE_Sodium_Crypto::generichash_init($key, $length); } + /** + * Initialize a BLAKE2b hashing context, for use in a streaming interface. + * + * @param string|null $key If specified must be a string between 16 and 64 bytes + * @param int $length The size of the desired hash output + * @param string $salt Salt (up to 16 bytes) + * @param string $personal Personalization string (up to 16 bytes) + * @return string A BLAKE2 hashing context, encoded as a string + * (To be 100% compatible with ext/libsodium) + * @throws SodiumException + * @throws TypeError + * @psalm-suppress MixedArgument + */ + public static function crypto_generichash_init_salt_personal( + $key = '', + $length = self::CRYPTO_GENERICHASH_BYTES, + $salt = '', + $personal = '' + ) { + /* Type checks: */ + if (is_null($key)) { + $key = ''; + } + ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($length, 'int', 2); + ParagonIE_Sodium_Core_Util::declareScalarType($salt, 'string', 3); + ParagonIE_Sodium_Core_Util::declareScalarType($personal, 'string', 4); + $salt = str_pad($salt, 16, "\0", STR_PAD_RIGHT); + $personal = str_pad($personal, 16, "\0", STR_PAD_RIGHT); + + /* Input validation: */ + if (!empty($key)) { + /* + if (ParagonIE_Sodium_Core_Util::strlen($key) < self::CRYPTO_GENERICHASH_KEYBYTES_MIN) { + throw new SodiumException('Unsupported key size. Must be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.'); + } + */ + if (ParagonIE_Sodium_Core_Util::strlen($key) > self::CRYPTO_GENERICHASH_KEYBYTES_MAX) { + throw new SodiumException('Unsupported key size. Must be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.'); + } + } + if (PHP_INT_SIZE === 4) { + return ParagonIE_Sodium_Crypto32::generichash_init_salt_personal($key, $length, $salt, $personal); + } + return ParagonIE_Sodium_Crypto::generichash_init_salt_personal($key, $length, $salt, $personal); + } + /** * Update a BLAKE2b hashing context with additional data. * - * @param string &$ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). - * $ctx is passed by reference and gets updated in-place. + * @param string $ctx BLAKE2 hashing context. Generated by crypto_generichash_init(). + * $ctx is passed by reference and gets updated in-place. + * @param-out string $ctx * @param string $message The message to append to the existing hash state. * @return void * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument + * @psalm-suppress ReferenceConstraintViolation */ public static function crypto_generichash_update(&$ctx, $message) { @@ -1421,6 +1623,65 @@ public static function crypto_generichash_keygen() return random_bytes(self::CRYPTO_GENERICHASH_KEYBYTES); } + /** + * @param int $subkey_len + * @param int $subkey_id + * @param string $context + * @param string $key + * @return string + * @throws SodiumException + */ + public static function crypto_kdf_derive_from_key( + $subkey_len, + $subkey_id, + $context, + $key + ) { + ParagonIE_Sodium_Core_Util::declareScalarType($subkey_len, 'int', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($subkey_id, 'int', 2); + ParagonIE_Sodium_Core_Util::declareScalarType($context, 'string', 3); + ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 4); + $subkey_id = (int) $subkey_id; + $subkey_len = (int) $subkey_len; + $context = (string) $context; + $key = (string) $key; + + if ($subkey_len < self::CRYPTO_KDF_BYTES_MIN) { + throw new SodiumException('subkey cannot be smaller than SODIUM_CRYPTO_KDF_BYTES_MIN'); + } + if ($subkey_len > self::CRYPTO_KDF_BYTES_MAX) { + throw new SodiumException('subkey cannot be larger than SODIUM_CRYPTO_KDF_BYTES_MAX'); + } + if ($subkey_id < 0) { + throw new SodiumException('subkey_id cannot be negative'); + } + if (ParagonIE_Sodium_Core_Util::strlen($context) !== self::CRYPTO_KDF_CONTEXTBYTES) { + throw new SodiumException('context should be SODIUM_CRYPTO_KDF_CONTEXTBYTES bytes'); + } + if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_KDF_KEYBYTES) { + throw new SodiumException('key should be SODIUM_CRYPTO_KDF_KEYBYTES bytes'); + } + + $salt = ParagonIE_Sodium_Core_Util::store64_le($subkey_id); + $state = self::crypto_generichash_init_salt_personal( + $key, + $subkey_len, + $salt, + $context + ); + return self::crypto_generichash_final($state, $subkey_len); + } + + /** + * @return string + * @throws Exception + * @throws Error + */ + public static function crypto_kdf_keygen() + { + return random_bytes(self::CRYPTO_KDF_KEYBYTES); + } + /** * Perform a key exchange, between a designated client and a server. * @@ -1445,12 +1706,13 @@ public static function crypto_generichash_keygen() * @param string $their_public * @param string $client_public * @param string $server_public + * @param bool $dontFallback * @return string * @throws SodiumException * @throws TypeError * @psalm-suppress MixedArgument */ - public static function crypto_kx($my_secret, $their_public, $client_public, $server_public) + public static function crypto_kx($my_secret, $their_public, $client_public, $server_public, $dontFallback = false) { /* Type checks: */ ParagonIE_Sodium_Core_Util::declareScalarType($my_secret, 'string', 1); @@ -1472,7 +1734,7 @@ public static function crypto_kx($my_secret, $their_public, $client_public, $ser throw new SodiumException('Argument 4 must be CRYPTO_BOX_PUBLICKEYBYTES long.'); } - if (self::useNewSodiumAPI()) { + if (self::useNewSodiumAPI() && !$dontFallback) { if (is_callable('sodium_crypto_kx')) { return (string) sodium_crypto_kx( $my_secret, @@ -1507,6 +1769,149 @@ public static function crypto_kx($my_secret, $their_public, $client_public, $ser ); } + /** + * @param string $seed + * @return string + * @throws SodiumException + */ + public static function crypto_kx_seed_keypair($seed) + { + ParagonIE_Sodium_Core_Util::declareScalarType($seed, 'string', 1); + + $seed = (string) $seed; + + if (ParagonIE_Sodium_Core_Util::strlen($seed) !== self::CRYPTO_KX_SEEDBYTES) { + throw new SodiumException('seed must be SODIUM_CRYPTO_KX_SEEDBYTES bytes'); + } + + $sk = self::crypto_generichash($seed, '', self::CRYPTO_KX_SECRETKEYBYTES); + $pk = self::crypto_scalarmult_base($sk); + return $sk . $pk; + } + + /** + * @return string + * @throws Exception + */ + public static function crypto_kx_keypair() + { + $sk = self::randombytes_buf(self::CRYPTO_KX_SECRETKEYBYTES); + $pk = self::crypto_scalarmult_base($sk); + return $sk . $pk; + } + + /** + * @param string $keypair + * @param string $serverPublicKey + * @return array{0: string, 1: string} + * @throws SodiumException + */ + public static function crypto_kx_client_session_keys($keypair, $serverPublicKey) + { + ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($serverPublicKey, 'string', 2); + + $keypair = (string) $keypair; + $serverPublicKey = (string) $serverPublicKey; + + if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_KX_KEYPAIRBYTES) { + throw new SodiumException('keypair should be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes'); + } + if (ParagonIE_Sodium_Core_Util::strlen($serverPublicKey) !== self::CRYPTO_KX_PUBLICKEYBYTES) { + throw new SodiumException('public keys must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes'); + } + + $sk = self::crypto_kx_secretkey($keypair); + $pk = self::crypto_kx_publickey($keypair); + $h = self::crypto_generichash_init(null, self::CRYPTO_KX_SESSIONKEYBYTES * 2); + self::crypto_generichash_update($h, self::crypto_scalarmult($sk, $serverPublicKey)); + self::crypto_generichash_update($h, $pk); + self::crypto_generichash_update($h, $serverPublicKey); + $sessionKeys = self::crypto_generichash_final($h, self::CRYPTO_KX_SESSIONKEYBYTES * 2); + return array( + ParagonIE_Sodium_Core_Util::substr( + $sessionKeys, + 0, + self::CRYPTO_KX_SESSIONKEYBYTES + ), + ParagonIE_Sodium_Core_Util::substr( + $sessionKeys, + self::CRYPTO_KX_SESSIONKEYBYTES, + self::CRYPTO_KX_SESSIONKEYBYTES + ) + ); + } + + /** + * @param string $keypair + * @param string $clientPublicKey + * @return array{0: string, 1: string} + * @throws SodiumException + */ + public static function crypto_kx_server_session_keys($keypair, $clientPublicKey) + { + ParagonIE_Sodium_Core_Util::declareScalarType($keypair, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($clientPublicKey, 'string', 2); + + $keypair = (string) $keypair; + $clientPublicKey = (string) $clientPublicKey; + + if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== self::CRYPTO_KX_KEYPAIRBYTES) { + throw new SodiumException('keypair should be SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes'); + } + if (ParagonIE_Sodium_Core_Util::strlen($clientPublicKey) !== self::CRYPTO_KX_PUBLICKEYBYTES) { + throw new SodiumException('public keys must be SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes'); + } + + $sk = self::crypto_kx_secretkey($keypair); + $pk = self::crypto_kx_publickey($keypair); + $h = self::crypto_generichash_init(null, self::CRYPTO_KX_SESSIONKEYBYTES * 2); + self::crypto_generichash_update($h, self::crypto_scalarmult($sk, $clientPublicKey)); + self::crypto_generichash_update($h, $clientPublicKey); + self::crypto_generichash_update($h, $pk); + $sessionKeys = self::crypto_generichash_final($h, self::CRYPTO_KX_SESSIONKEYBYTES * 2); + return array( + ParagonIE_Sodium_Core_Util::substr( + $sessionKeys, + self::CRYPTO_KX_SESSIONKEYBYTES, + self::CRYPTO_KX_SESSIONKEYBYTES + ), + ParagonIE_Sodium_Core_Util::substr( + $sessionKeys, + 0, + self::CRYPTO_KX_SESSIONKEYBYTES + ) + ); + } + + /** + * @param string $kp + * @return string + * @throws SodiumException + */ + public static function crypto_kx_secretkey($kp) + { + return ParagonIE_Sodium_Core_Util::substr( + $kp, + 0, + self::CRYPTO_KX_SECRETKEYBYTES + ); + } + + /** + * @param string $kp + * @return string + * @throws SodiumException + */ + public static function crypto_kx_publickey($kp) + { + return ParagonIE_Sodium_Core_Util::substr( + $kp, + self::CRYPTO_KX_SECRETKEYBYTES, + self::CRYPTO_KX_PUBLICKEYBYTES + ); + } + /** * @param int $outlen * @param string $passwd @@ -1589,6 +1994,36 @@ public static function crypto_pwhash_str($passwd, $opslimit, $memlimit) ); } + /** + * Do we need to rehash this password? + * + * @param string $hash + * @param int $opslimit + * @param int $memlimit + * @return bool + * @throws SodiumException + */ + public static function crypto_pwhash_str_needs_rehash($hash, $opslimit, $memlimit) + { + ParagonIE_Sodium_Core_Util::declareScalarType($hash, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($opslimit, 'int', 2); + ParagonIE_Sodium_Core_Util::declareScalarType($memlimit, 'int', 3); + + // Just grab the first 4 pieces. + $pieces = explode('$', (string) $hash); + $prefix = implode('$', array_slice($pieces, 0, 4)); + + // Rebuild the expected header. + /** @var int $ops */ + $ops = (int) $opslimit; + /** @var int $mem */ + $mem = (int) $memlimit >> 10; + $encoded = self::CRYPTO_PWHASH_STRPREFIX . 'v=19$m=' . $mem . ',t=' . $ops . ',p=1'; + + // Do they match? If so, we don't need to rehash, so return false. + return !ParagonIE_Sodium_Core_Util::hashEquals($encoded, $prefix); + } + /** * @param string $passwd * @param string $hash @@ -1984,6 +2419,111 @@ public static function crypto_secretbox_xchacha20poly1305_open($ciphertext, $non return ParagonIE_Sodium_Crypto::secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key); } + /** + * @param string $key + * @return array Returns a state and a header. + * @throws Exception + * @throws SodiumException + */ + public static function crypto_secretstream_xchacha20poly1305_init_push($key) + { + if (PHP_INT_SIZE === 4) { + return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_push($key); + } + return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_push($key); + } + + /** + * @param string $header + * @param string $key + * @return string Returns a state. + * @throws Exception + */ + public static function crypto_secretstream_xchacha20poly1305_init_pull($header, $key) + { + if (ParagonIE_Sodium_Core_Util::strlen($header) < self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES) { + throw new SodiumException( + 'header size should be SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES bytes' + ); + } + if (PHP_INT_SIZE === 4) { + return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_pull($key, $header); + } + return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_pull($key, $header); + } + + /** + * @param string $state + * @param string $msg + * @param string $aad + * @param int $tag + * @return string + * @throws SodiumException + */ + public static function crypto_secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0) + { + if (PHP_INT_SIZE === 4) { + return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_push( + $state, + $msg, + $aad, + $tag + ); + } + return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_push( + $state, + $msg, + $aad, + $tag + ); + } + + /** + * @param string $state + * @param string $msg + * @param string $aad + * @return bool|array{0: string, 1: int} + * @throws SodiumException + */ + public static function crypto_secretstream_xchacha20poly1305_pull(&$state, $msg, $aad = '') + { + if (PHP_INT_SIZE === 4) { + return ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_pull( + $state, + $msg, + $aad + ); + } + return ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_pull( + $state, + $msg, + $aad + ); + } + + /** + * @return string + * @throws Exception + */ + public static function crypto_secretstream_xchacha20poly1305_keygen() + { + return random_bytes(self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES); + } + + /** + * @param string $state + * @return void + * @throws SodiumException + */ + public static function crypto_secretstream_xchacha20poly1305_rekey(&$state) + { + if (PHP_INT_SIZE === 4) { + ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_rekey($state); + } else { + ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_rekey($state); + } + } + /** * Calculates a SipHash-2-4 hash of a message for a given key. * @@ -2133,6 +2673,32 @@ public static function crypto_sign_keypair() return ParagonIE_Sodium_Core_Ed25519::keypair(); } + /** + * @param string $sk + * @param string $pk + * @return string + * @throws SodiumException + */ + public static function crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk) + { + ParagonIE_Sodium_Core_Util::declareScalarType($sk, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($pk, 'string', 1); + $sk = (string) $sk; + $pk = (string) $pk; + + if (ParagonIE_Sodium_Core_Util::strlen($sk) !== self::CRYPTO_SIGN_SECRETKEYBYTES) { + throw new SodiumException('secretkey should be SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes'); + } + if (ParagonIE_Sodium_Core_Util::strlen($pk) !== self::CRYPTO_SIGN_PUBLICKEYBYTES) { + throw new SodiumException('publickey should be SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes'); + } + + if (self::useNewSodiumAPI()) { + return sodium_crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk); + } + return $sk . $pk; + } + /** * Generate an Ed25519 keypair from a seed. * @@ -2447,7 +3013,7 @@ public static function crypto_stream($len, $nonce, $key) /** * DANGER! UNAUTHENTICATED ENCRYPTION! * - * Unless you are following expert advice, do not used this feature. + * Unless you are following expert advice, do not use this feature. * * Algorithm: XSalsa20 * @@ -2503,6 +3069,103 @@ public static function crypto_stream_keygen() return random_bytes(self::CRYPTO_STREAM_KEYBYTES); } + + /** + * Expand a key and nonce into a keystream of pseudorandom bytes. + * + * @param int $len Number of bytes desired + * @param string $nonce Number to be used Once; must be 24 bytes + * @param string $key XChaCha20 key + * @param bool $dontFallback + * @return string Pseudorandom stream that can be XORed with messages + * to provide encryption (but not authentication; see + * Poly1305 or crypto_auth() for that, which is not + * optional for security) + * @throws SodiumException + * @throws TypeError + * @psalm-suppress MixedArgument + */ + public static function crypto_stream_xchacha20($len, $nonce, $key, $dontFallback = false) + { + /* Type checks: */ + ParagonIE_Sodium_Core_Util::declareScalarType($len, 'int', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); + ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); + + /* Input validation: */ + if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { + throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); + } + if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { + throw new SodiumException('Argument 3 must be CRYPTO_STREAM_XCHACHA20_KEYBYTES long.'); + } + + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_stream_xchacha20($len, $nonce, $key); + } + if (PHP_INT_SIZE === 4) { + return ParagonIE_Sodium_Core32_XChaCha20::stream($len, $nonce, $key); + } + return ParagonIE_Sodium_Core_XChaCha20::stream($len, $nonce, $key); + } + + /** + * DANGER! UNAUTHENTICATED ENCRYPTION! + * + * Unless you are following expert advice, do not use this feature. + * + * Algorithm: XChaCha20 + * + * This DOES NOT provide ciphertext integrity. + * + * @param string $message Plaintext message + * @param string $nonce Number to be used Once; must be 24 bytes + * @param string $key Encryption key + * @return string Encrypted text which is vulnerable to chosen- + * ciphertext attacks unless you implement some + * other mitigation to the ciphertext (i.e. + * Encrypt then MAC) + * @param bool $dontFallback + * @throws SodiumException + * @throws TypeError + * @psalm-suppress MixedArgument + */ + public static function crypto_stream_xchacha20_xor($message, $nonce, $key, $dontFallback = false) + { + /* Type checks: */ + ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); + ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); + + /* Input validation: */ + if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { + throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); + } + if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { + throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.'); + } + + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_stream_xchacha20_xor($message, $nonce, $key); + } + if (PHP_INT_SIZE === 4) { + return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key); + } + return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key); + } + + /** + * Return a secure random key for use with crypto_stream_xchacha20 + * + * @return string + * @throws Exception + * @throws Error + */ + public static function crypto_stream_xchacha20_keygen() + { + return random_bytes(self::CRYPTO_STREAM_XCHACHA20_KEYBYTES); + } + /** * Cache-timing-safe implementation of hex2bin(). * @@ -2567,20 +3230,34 @@ public static function increment(&$var) $var = $copy; } + /** + * @param string $str + * @return bool + * + * @throws SodiumException + */ + public static function is_zero($str) + { + $d = 0; + for ($i = 0; $i < 32; ++$i) { + $d |= ParagonIE_Sodium_Core_Util::chrToInt($str[$i]); + } + return ((($d - 1) >> 31) & 1) === 1; + } + /** * The equivalent to the libsodium minor version we aim to be compatible * with (sans pwhash and memzero). * * @return int - * @psalm-suppress MixedInferredReturnType - * @psalm-suppress UndefinedFunction */ public static function library_version_major() { - if (self::useNewSodiumAPI()) { - return sodium_library_version_major(); + if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MAJOR_VERSION')) { + return SODIUM_LIBRARY_MAJOR_VERSION; } if (self::use_fallback('library_version_major')) { + /** @psalm-suppress UndefinedFunction */ return (int) call_user_func('\\Sodium\\library_version_major'); } return self::LIBRARY_VERSION_MAJOR; @@ -2591,15 +3268,14 @@ public static function library_version_major() * with (sans pwhash and memzero). * * @return int - * @psalm-suppress MixedInferredReturnType - * @psalm-suppress UndefinedFunction */ public static function library_version_minor() { - if (self::useNewSodiumAPI()) { - return sodium_library_version_minor(); + if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MINOR_VERSION')) { + return SODIUM_LIBRARY_MINOR_VERSION; } if (self::use_fallback('library_version_minor')) { + /** @psalm-suppress UndefinedFunction */ return (int) call_user_func('\\Sodium\\library_version_minor'); } return self::LIBRARY_VERSION_MINOR; @@ -2621,6 +3297,9 @@ public static function memcmp($left, $right) ParagonIE_Sodium_Core_Util::declareScalarType($left, 'string', 1); ParagonIE_Sodium_Core_Util::declareScalarType($right, 'string', 2); + if (self::useNewSodiumAPI()) { + return sodium_memcmp($left, $right); + } if (self::use_fallback('memcmp')) { return (int) call_user_func('\\Sodium\\memcmp', $left, $right); } @@ -2634,6 +3313,7 @@ public static function memcmp($left, $right) * native library for that. * * @param string|null $var + * @param-out string|null $var * * @return void * @throws SodiumException (Unless libsodium is installed) @@ -2646,6 +3326,7 @@ public static function memzero(&$var) ParagonIE_Sodium_Core_Util::declareScalarType($var, 'string', 1); if (self::useNewSodiumAPI()) { + /** @psalm-suppress MixedArgument */ sodium_memzero($var); return; } @@ -2663,6 +3344,158 @@ public static function memzero(&$var) ); } + /** + * @param string $unpadded + * @param int $blockSize + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function pad($unpadded, $blockSize, $dontFallback = false) + { + /* Type checks: */ + ParagonIE_Sodium_Core_Util::declareScalarType($unpadded, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2); + + $unpadded = (string) $unpadded; + $blockSize = (int) $blockSize; + + if (self::useNewSodiumAPI() && !$dontFallback) { + return (string) sodium_pad($unpadded, $blockSize); + } + + if ($blockSize <= 0) { + throw new SodiumException( + 'block size cannot be less than 1' + ); + } + $unpadded_len = ParagonIE_Sodium_Core_Util::strlen($unpadded); + $xpadlen = ($blockSize - 1); + if (($blockSize & ($blockSize - 1)) === 0) { + $xpadlen -= $unpadded_len & ($blockSize - 1); + } else { + $xpadlen -= $unpadded_len % $blockSize; + } + + $xpadded_len = $unpadded_len + $xpadlen; + $padded = str_repeat("\0", $xpadded_len - 1); + if ($unpadded_len > 0) { + $st = 1; + $i = 0; + $k = $unpadded_len; + for ($j = 0; $j <= $xpadded_len; ++$j) { + $i = (int) $i; + $k = (int) $k; + $st = (int) $st; + if ($j >= $unpadded_len) { + $padded[$j] = "\0"; + } else { + $padded[$j] = $unpadded[$j]; + } + /** @var int $k */ + $k -= $st; + $st = (int) (~( + ( + ( + ($k >> 48) + | + ($k >> 32) + | + ($k >> 16) + | + $k + ) - 1 + ) >> 16 + ) + ) & 1; + $i += $st; + } + } + + $mask = 0; + $tail = $xpadded_len; + for ($i = 0; $i < $blockSize; ++$i) { + # barrier_mask = (unsigned char) + # (((i ^ xpadlen) - 1U) >> ((sizeof(size_t) - 1U) * CHAR_BIT)); + $barrier_mask = (($i ^ $xpadlen) -1) >> ((PHP_INT_SIZE << 3) - 1); + # tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask); + $padded[$tail - $i] = ParagonIE_Sodium_Core_Util::intToChr( + (ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]) & $mask) + | + (0x80 & $barrier_mask) + ); + # mask |= barrier_mask; + $mask |= $barrier_mask; + } + return $padded; + } + + /** + * @param string $padded + * @param int $blockSize + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function unpad($padded, $blockSize, $dontFallback = false) + { + /* Type checks: */ + ParagonIE_Sodium_Core_Util::declareScalarType($padded, 'string', 1); + ParagonIE_Sodium_Core_Util::declareScalarType($blockSize, 'int', 2); + + $padded = (string) $padded; + $blockSize = (int) $blockSize; + + if (self::useNewSodiumAPI() && !$dontFallback) { + return (string) sodium_unpad($padded, $blockSize); + } + if ($blockSize <= 0) { + throw new SodiumException('block size cannot be less than 1'); + } + $padded_len = ParagonIE_Sodium_Core_Util::strlen($padded); + if ($padded_len < $blockSize) { + throw new SodiumException('invalid padding'); + } + + # tail = &padded[padded_len - 1U]; + $tail = $padded_len - 1; + + $acc = 0; + $valid = 0; + $pad_len = 0; + + $found = 0; + for ($i = 0; $i < $blockSize; ++$i) { + # c = tail[-i]; + $c = ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]); + + # is_barrier = + # (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) - 1U) ) >> 8) & 1U; + $is_barrier = ( + ( + ($acc - 1) & ($pad_len - 1) & (($c ^ 80) - 1) + ) >> 7 + ) & 1; + $is_barrier &= ~$found; + $found |= $is_barrier; + + # acc |= c; + $acc |= $c; + + # pad_len |= i & (1U + ~is_barrier); + $pad_len |= $i & (1 + ~$is_barrier); + + # valid |= (unsigned char) is_barrier; + $valid |= ($is_barrier & 0xff); + } + # unpadded_len = padded_len - 1U - pad_len; + $unpadded_len = $padded_len - 1 - $pad_len; + if ($valid !== 1) { + throw new SodiumException('invalid padding'); + } + return ParagonIE_Sodium_Core_Util::substr($padded, 0, $unpadded_len); + } + /** * Will sodium_compat run fast on the current hardware and PHP configuration? * @@ -2749,6 +3582,298 @@ public static function randombytes_random16() return random_int(0, 65535); } + /** + * @param string $p + * @param bool $dontFallback + * @return bool + * @throws SodiumException + */ + public static function ristretto255_is_valid_point($p, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_is_valid_point($p); + } + try { + $r = ParagonIE_Sodium_Core_Ristretto255::ristretto255_frombytes($p); + return $r['res'] === 0 && + ParagonIE_Sodium_Core_Ristretto255::ristretto255_point_is_canonical($p) === 1; + } catch (SodiumException $ex) { + if ($ex->getMessage() === 'S is not canonical') { + return false; + } + throw $ex; + } + } + + /** + * @param string $p + * @param string $q + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_add($p, $q, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_add($p, $q); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_add($p, $q); + } + + /** + * @param string $p + * @param string $q + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_sub($p, $q, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_sub($p, $q); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_sub($p, $q); + } + + /** + * @param string $r + * @param bool $dontFallback + * @return string + * + * @throws SodiumException + */ + public static function ristretto255_from_hash($r, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_from_hash($r); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_from_hash($r); + } + + /** + * @param bool $dontFallback + * @return string + * + * @throws SodiumException + */ + public static function ristretto255_random($dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_random(); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_random(); + } + + /** + * @param bool $dontFallback + * @return string + * + * @throws SodiumException + */ + public static function ristretto255_scalar_random($dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_random(); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_random(); + } + + /** + * @param string $s + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_invert($s, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_invert($s); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_invert($s); + } + /** + * @param string $s + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_negate($s, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_negate($s); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_negate($s); + } + + /** + * @param string $s + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_complement($s, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_complement($s); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_complement($s); + } + + /** + * @param string $x + * @param string $y + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_add($x, $y, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_add($x, $y); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_add($x, $y); + } + + /** + * @param string $x + * @param string $y + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_sub($x, $y, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_sub($x, $y); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_sub($x, $y); + } + + /** + * @param string $x + * @param string $y + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_mul($x, $y, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_mul($x, $y); + } + return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_mul($x, $y); + } + + /** + * @param string $n + * @param string $p + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function scalarmult_ristretto255($n, $p, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_scalarmult_ristretto255($n, $p); + } + return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255($n, $p); + } + + /** + * @param string $n + * @param string $p + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function scalarmult_ristretto255_base($n, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_scalarmult_ristretto255_base($n); + } + return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255_base($n); + } + + /** + * @param string $s + * @param bool $dontFallback + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_reduce($s, $dontFallback = false) + { + if (self::useNewSodiumAPI() && !$dontFallback) { + return sodium_crypto_core_ristretto255_scalar_reduce($s); + } + return ParagonIE_Sodium_Core_Ristretto255::sc_reduce($s); + } + + /** + * Runtime testing method for 32-bit platforms. + * + * Usage: If runtime_speed_test() returns FALSE, then our 32-bit + * implementation is to slow to use safely without risking timeouts. + * If this happens, install sodium from PECL to get acceptable + * performance. + * + * @param int $iterations Number of multiplications to attempt + * @param int $maxTimeout Milliseconds + * @return bool TRUE if we're fast enough, FALSE is not + * @throws SodiumException + */ + public static function runtime_speed_test($iterations, $maxTimeout) + { + if (self::polyfill_is_fast()) { + return true; + } + /** @var float $end */ + $end = 0.0; + /** @var float $start */ + $start = microtime(true); + /** @var ParagonIE_Sodium_Core32_Int64 $a */ + $a = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1 << 16)); + for ($i = 0; $i < $iterations; ++$i) { + /** @var ParagonIE_Sodium_Core32_Int64 $b */ + $b = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1 << 16)); + $a->mulInt64($b); + } + /** @var float $end */ + $end = microtime(true); + /** @var int $diff */ + $diff = (int) ceil(($end - $start) * 1000); + return $diff < $maxTimeout; + } + + /** + * Add two numbers (little-endian unsigned), storing the value in the first + * parameter. + * + * This mutates $val. + * + * @param string $val + * @param string $addv + * @return void + * @throws SodiumException + */ + public static function sub(&$val, $addv) + { + $val_len = ParagonIE_Sodium_Core_Util::strlen($val); + $addv_len = ParagonIE_Sodium_Core_Util::strlen($addv); + if ($val_len !== $addv_len) { + throw new SodiumException('values must have the same length'); + } + $A = ParagonIE_Sodium_Core_Util::stringToIntArray($val); + $B = ParagonIE_Sodium_Core_Util::stringToIntArray($addv); + + $c = 0; + for ($i = 0; $i < $val_len; $i++) { + $c = ($A[$i] - $B[$i] - $c); + $A[$i] = ($c & 0xff); + $c = ($c >> 8) & 1; + } + $val = ParagonIE_Sodium_Core_Util::intArrayToString($A); + } + /** * This emulates libsodium's version_string() function, except ours is * prefixed with 'polyfill-'. diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/BLAKE2b.php b/libraries/vendor/paragonie/sodium_compat/src/Core/BLAKE2b.php index f0369df0c8c52..5251bafe71b0b 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/BLAKE2b.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/BLAKE2b.php @@ -88,10 +88,10 @@ protected static function add64($x, $y) { $l = ($x[1] + $y[1]) & 0xffffffff; return self::new64( - $x[0] + $y[0] + ( + (int) ($x[0] + $y[0] + ( ($l < $x[1]) ? 1 : 0 - ), - $l + )), + (int) $l ); } @@ -132,8 +132,8 @@ protected static function xor64(SplFixedArray $x, SplFixedArray $y) throw new SodiumException('y[1] is not an integer'); } return self::new64( - (int) ($x[0] ^ $y[0]), - (int) ($x[1] ^ $y[1]) + (int) (($x[0] ^ $y[0]) & 0xffffffff), + (int) (($x[1] ^ $y[1]) & 0xffffffff) ); } @@ -256,6 +256,7 @@ protected static function store64(SplFixedArray $x, $i, SplFixedArray $u) if (++$i > $maxLength) { return; } + /** @psalm-suppress MixedOperand */ $u[$uIdx] >>= 8; } } @@ -298,12 +299,13 @@ public static function pseudoConstructor() */ protected static function context() { - $ctx = new SplFixedArray(5); + $ctx = new SplFixedArray(6); $ctx[0] = new SplFixedArray(8); // h $ctx[1] = new SplFixedArray(2); // t $ctx[2] = new SplFixedArray(2); // f $ctx[3] = new SplFixedArray(256); // buf $ctx[4] = 0; // buflen + $ctx[5] = 0; // last_node (uint8_t) for ($i = 8; $i--;) { $ctx[0][$i] = self::$iv[$i]; @@ -549,6 +551,8 @@ public static function finish(SplFixedArray $ctx, SplFixedArray $out) * * @param SplFixedArray|null $key * @param int $outlen + * @param SplFixedArray|null $salt + * @param SplFixedArray|null $personal * @return SplFixedArray * @throws SodiumException * @throws TypeError @@ -558,8 +562,12 @@ public static function finish(SplFixedArray $ctx, SplFixedArray $out) * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedArrayOffset */ - public static function init($key = null, $outlen = 64) - { + public static function init( + $key = null, + $outlen = 64, + $salt = null, + $personal = null + ) { self::pseudoConstructor(); $klen = 0; @@ -577,6 +585,7 @@ public static function init($key = null, $outlen = 64) $ctx = self::context(); $p = new SplFixedArray(64); + // Zero our param buffer... for ($i = 64; --$i;) { $p[$i] = 0; } @@ -586,10 +595,32 @@ public static function init($key = null, $outlen = 64) $p[2] = 1; // fanout $p[3] = 1; // depth + if ($salt instanceof SplFixedArray) { + // salt: [32] through [47] + for ($i = 0; $i < 16; ++$i) { + $p[32 + $i] = (int) $salt[$i]; + } + } + if ($personal instanceof SplFixedArray) { + // personal: [48] through [63] + for ($i = 0; $i < 16; ++$i) { + $p[48 + $i] = (int) $personal[$i]; + } + } + $ctx[0][0] = self::xor64( $ctx[0][0], self::load64($p, 0) ); + if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) { + // We need to do what blake2b_init_param() does: + for ($i = 1; $i < 8; ++$i) { + $ctx[0][$i] = self::xor64( + $ctx[0][$i], + self::load64($p, $i << 3) + ); + } + } if ($klen > 0 && $key instanceof SplFixedArray) { $block = new SplFixedArray(128); @@ -600,6 +631,7 @@ public static function init($key = null, $outlen = 64) $block[$i] = $key[$i]; } self::update($ctx, $block, 128); + $ctx[4] = 128; } return $ctx; @@ -612,6 +644,7 @@ public static function init($key = null, $outlen = 64) * * @param string $str * @return SplFixedArray + * @psalm-suppress MixedArgumentTypeCoercion */ public static function stringToSplFixedArray($str = '') { @@ -642,7 +675,7 @@ public static function SplFixedArrayToString(SplFixedArray $a) /** * @internal You should not use this directly from another application * - * @param SplFixedArray[SplFixedArray] $ctx + * @param SplFixedArray $ctx * @return string * @throws TypeError * @psalm-suppress MixedArgument @@ -692,7 +725,7 @@ public static function contextToString(SplFixedArray $ctx) self::intToChr(($ctx4 >> 56) & 0xff) )); # uint8_t last_node; - return $str . "\x00"; + return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23); } /** @@ -745,7 +778,6 @@ public static function stringToContext($string) # uint8_t buf[2 * 128]; $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256)); - # uint8_t buf[2 * 128]; $int = 0; for ($i = 0; $i < 8; ++$i) { diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/Common.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/Common.php new file mode 100644 index 0000000000000..94b2e8f33ab3f --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/Common.php @@ -0,0 +1,213 @@ + $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3)); + $b0 = $chunk[1]; + $b1 = $chunk[2]; + $b2 = $chunk[3]; + + $dest .= + self::encode6Bits( $b0 >> 2 ) . + self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . + self::encode6Bits( $b2 & 63); + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); + $b0 = $chunk[1]; + if ($i + 1 < $srcLen) { + $b1 = $chunk[2]; + $dest .= + self::encode6Bits($b0 >> 2) . + self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + self::encode6Bits(($b1 << 2) & 63); + if ($pad) { + $dest .= '='; + } + } else { + $dest .= + self::encode6Bits( $b0 >> 2) . + self::encode6Bits(($b0 << 4) & 63); + if ($pad) { + $dest .= '=='; + } + } + } + return $dest; + } + + /** + * decode from base64 into binary + * + * Base64 character set "./[A-Z][a-z][0-9]" + * + * @param string $src + * @param bool $strictPadding + * @return string + * @throws RangeException + * @throws TypeError + * @psalm-suppress RedundantCondition + */ + public static function decode($src, $strictPadding = false) + { + // Remove padding + $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); + if ($srcLen === 0) { + return ''; + } + + if ($strictPadding) { + if (($srcLen & 3) === 0) { + if ($src[$srcLen - 1] === '=') { + $srcLen--; + if ($src[$srcLen - 1] === '=') { + $srcLen--; + } + } + } + if (($srcLen & 3) === 1) { + throw new RangeException( + 'Incorrect padding' + ); + } + if ($src[$srcLen - 1] === '=') { + throw new RangeException( + 'Incorrect padding' + ); + } + } else { + $src = rtrim($src, '='); + $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); + } + + $err = 0; + $dest = ''; + // Main loop (no padding): + for ($i = 0; $i + 4 <= $srcLen; $i += 4) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4)); + $c0 = self::decode6Bits($chunk[1]); + $c1 = self::decode6Bits($chunk[2]); + $c2 = self::decode6Bits($chunk[3]); + $c3 = self::decode6Bits($chunk[4]); + + $dest .= pack( + 'CCC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff), + ((($c2 << 6) | $c3 ) & 0xff) + ); + $err |= ($c0 | $c1 | $c2 | $c3) >> 8; + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); + $c0 = self::decode6Bits($chunk[1]); + + if ($i + 2 < $srcLen) { + $c1 = self::decode6Bits($chunk[2]); + $c2 = self::decode6Bits($chunk[3]); + $dest .= pack( + 'CC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff) + ); + $err |= ($c0 | $c1 | $c2) >> 8; + } elseif ($i + 1 < $srcLen) { + $c1 = self::decode6Bits($chunk[2]); + $dest .= pack( + 'C', + ((($c0 << 2) | ($c1 >> 4)) & 0xff) + ); + $err |= ($c0 | $c1) >> 8; + } elseif ($i < $srcLen && $strictPadding) { + $err |= 1; + } + } + /** @var bool $check */ + $check = ($err === 0); + if (!$check) { + throw new RangeException( + 'Base64::decode() only expects characters in the correct base64 alphabet' + ); + } + return $dest; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 6-bit integers + * into 8-bit integers. + * + * Base64 character set: + * [A-Z] [a-z] [0-9] + / + * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f + * + * @param int $src + * @return int + */ + abstract protected static function decode6Bits($src); + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 6-bit integers. + * + * @param int $src + * @return string + */ + abstract protected static function encode6Bits($src); +} diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/Original.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/Original.php new file mode 100644 index 0000000000000..dc939eeafb693 --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/Original.php @@ -0,0 +1,248 @@ + $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3)); + $b0 = $chunk[1]; + $b1 = $chunk[2]; + $b2 = $chunk[3]; + + $dest .= + self::encode6Bits( $b0 >> 2 ) . + self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . + self::encode6Bits( $b2 & 63); + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); + $b0 = $chunk[1]; + if ($i + 1 < $srcLen) { + $b1 = $chunk[2]; + $dest .= + self::encode6Bits($b0 >> 2) . + self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + self::encode6Bits(($b1 << 2) & 63); + if ($pad) { + $dest .= '='; + } + } else { + $dest .= + self::encode6Bits( $b0 >> 2) . + self::encode6Bits(($b0 << 4) & 63); + if ($pad) { + $dest .= '=='; + } + } + } + return $dest; + } + + /** + * decode from base64 into binary + * + * Base64 character set "./[A-Z][a-z][0-9]" + * + * @param string $src + * @param bool $strictPadding + * @return string + * @throws RangeException + * @throws TypeError + * @psalm-suppress RedundantCondition + */ + public static function decode($src, $strictPadding = false) + { + // Remove padding + $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); + if ($srcLen === 0) { + return ''; + } + + if ($strictPadding) { + if (($srcLen & 3) === 0) { + if ($src[$srcLen - 1] === '=') { + $srcLen--; + if ($src[$srcLen - 1] === '=') { + $srcLen--; + } + } + } + if (($srcLen & 3) === 1) { + throw new RangeException( + 'Incorrect padding' + ); + } + if ($src[$srcLen - 1] === '=') { + throw new RangeException( + 'Incorrect padding' + ); + } + } else { + $src = rtrim($src, '='); + $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); + } + + $err = 0; + $dest = ''; + // Main loop (no padding): + for ($i = 0; $i + 4 <= $srcLen; $i += 4) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4)); + $c0 = self::decode6Bits($chunk[1]); + $c1 = self::decode6Bits($chunk[2]); + $c2 = self::decode6Bits($chunk[3]); + $c3 = self::decode6Bits($chunk[4]); + + $dest .= pack( + 'CCC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff), + ((($c2 << 6) | $c3) & 0xff) + ); + $err |= ($c0 | $c1 | $c2 | $c3) >> 8; + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); + $c0 = self::decode6Bits($chunk[1]); + + if ($i + 2 < $srcLen) { + $c1 = self::decode6Bits($chunk[2]); + $c2 = self::decode6Bits($chunk[3]); + $dest .= pack( + 'CC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff) + ); + $err |= ($c0 | $c1 | $c2) >> 8; + } elseif ($i + 1 < $srcLen) { + $c1 = self::decode6Bits($chunk[2]); + $dest .= pack( + 'C', + ((($c0 << 2) | ($c1 >> 4)) & 0xff) + ); + $err |= ($c0 | $c1) >> 8; + } elseif ($i < $srcLen && $strictPadding) { + $err |= 1; + } + } + /** @var bool $check */ + $check = ($err === 0); + if (!$check) { + throw new RangeException( + 'Base64::decode() only expects characters in the correct base64 alphabet' + ); + } + return $dest; + } + // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE + + /** + * Uses bitwise operators instead of table-lookups to turn 6-bit integers + * into 8-bit integers. + * + * Base64 character set: + * [A-Z] [a-z] [0-9] + / + * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f + * + * @param int $src + * @return int + */ + protected static function decode6Bits($src) + { + $ret = -1; + + // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); + + // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); + + // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); + + // if ($src == 0x2b) $ret += 62 + 1; + $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63; + + // if ($src == 0x2f) ret += 63 + 1; + $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64; + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 6-bit integers. + * + * @param int $src + * @return string + */ + protected static function encode6Bits($src) + { + $diff = 0x41; + + // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 + $diff += ((25 - $src) >> 8) & 6; + + // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 + $diff -= ((51 - $src) >> 8) & 75; + + // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15 + $diff -= ((61 - $src) >> 8) & 15; + + // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3 + $diff += ((62 - $src) >> 8) & 3; + + return pack('C', $src + $diff); + } +} diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/UrlSafe.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/UrlSafe.php new file mode 100644 index 0000000000000..64bf53b858329 --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Base64/UrlSafe.php @@ -0,0 +1,247 @@ + $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 3)); + $b0 = $chunk[1]; + $b1 = $chunk[2]; + $b2 = $chunk[3]; + + $dest .= + self::encode6Bits( $b0 >> 2 ) . + self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + self::encode6Bits((($b1 << 2) | ($b2 >> 6)) & 63) . + self::encode6Bits( $b2 & 63); + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); + $b0 = $chunk[1]; + if ($i + 1 < $srcLen) { + $b1 = $chunk[2]; + $dest .= + self::encode6Bits($b0 >> 2) . + self::encode6Bits((($b0 << 4) | ($b1 >> 4)) & 63) . + self::encode6Bits(($b1 << 2) & 63); + if ($pad) { + $dest .= '='; + } + } else { + $dest .= + self::encode6Bits( $b0 >> 2) . + self::encode6Bits(($b0 << 4) & 63); + if ($pad) { + $dest .= '=='; + } + } + } + return $dest; + } + + /** + * decode from base64 into binary + * + * Base64 character set "./[A-Z][a-z][0-9]" + * + * @param string $src + * @param bool $strictPadding + * @return string + * @throws RangeException + * @throws TypeError + * @psalm-suppress RedundantCondition + */ + public static function decode($src, $strictPadding = false) + { + // Remove padding + $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); + if ($srcLen === 0) { + return ''; + } + + if ($strictPadding) { + if (($srcLen & 3) === 0) { + if ($src[$srcLen - 1] === '=') { + $srcLen--; + if ($src[$srcLen - 1] === '=') { + $srcLen--; + } + } + } + if (($srcLen & 3) === 1) { + throw new RangeException( + 'Incorrect padding' + ); + } + if ($src[$srcLen - 1] === '=') { + throw new RangeException( + 'Incorrect padding' + ); + } + } else { + $src = rtrim($src, '='); + $srcLen = ParagonIE_Sodium_Core_Util::strlen($src); + } + + $err = 0; + $dest = ''; + // Main loop (no padding): + for ($i = 0; $i + 4 <= $srcLen; $i += 4) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, 4)); + $c0 = self::decode6Bits($chunk[1]); + $c1 = self::decode6Bits($chunk[2]); + $c2 = self::decode6Bits($chunk[3]); + $c3 = self::decode6Bits($chunk[4]); + + $dest .= pack( + 'CCC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff), + ((($c2 << 6) | $c3) & 0xff) + ); + $err |= ($c0 | $c1 | $c2 | $c3) >> 8; + } + // The last chunk, which may have padding: + if ($i < $srcLen) { + /** @var array $chunk */ + $chunk = unpack('C*', ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i)); + $c0 = self::decode6Bits($chunk[1]); + + if ($i + 2 < $srcLen) { + $c1 = self::decode6Bits($chunk[2]); + $c2 = self::decode6Bits($chunk[3]); + $dest .= pack( + 'CC', + ((($c0 << 2) | ($c1 >> 4)) & 0xff), + ((($c1 << 4) | ($c2 >> 2)) & 0xff) + ); + $err |= ($c0 | $c1 | $c2) >> 8; + } elseif ($i + 1 < $srcLen) { + $c1 = self::decode6Bits($chunk[2]); + $dest .= pack( + 'C', + ((($c0 << 2) | ($c1 >> 4)) & 0xff) + ); + $err |= ($c0 | $c1) >> 8; + } elseif ($i < $srcLen && $strictPadding) { + $err |= 1; + } + } + /** @var bool $check */ + $check = ($err === 0); + if (!$check) { + throw new RangeException( + 'Base64::decode() only expects characters in the correct base64 alphabet' + ); + } + return $dest; + } + // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE + /** + * Uses bitwise operators instead of table-lookups to turn 6-bit integers + * into 8-bit integers. + * + * Base64 character set: + * [A-Z] [a-z] [0-9] + / + * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f + * + * @param int $src + * @return int + */ + protected static function decode6Bits($src) + { + $ret = -1; + + // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64 + $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) & ($src - 64); + + // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70 + $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) & ($src - 70); + + // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5 + $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) & ($src + 5); + + // if ($src == 0x2c) $ret += 62 + 1; + $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63; + + // if ($src == 0x5f) ret += 63 + 1; + $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64; + + return $ret; + } + + /** + * Uses bitwise operators instead of table-lookups to turn 8-bit integers + * into 6-bit integers. + * + * @param int $src + * @return string + */ + protected static function encode6Bits($src) + { + $diff = 0x41; + + // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6 + $diff += ((25 - $src) >> 8) & 6; + + // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75 + $diff -= ((51 - $src) >> 8) & 75; + + // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13 + $diff -= ((61 - $src) >> 8) & 13; + + // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3 + $diff += ((62 - $src) >> 8) & 49; + + return pack('C', $src + $diff); + } +} diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/ChaCha20/Ctx.php b/libraries/vendor/paragonie/sodium_compat/src/Core/ChaCha20/Ctx.php index b29ab90054df7..01e4c46c3e05c 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/ChaCha20/Ctx.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/ChaCha20/Ctx.php @@ -69,6 +69,7 @@ public function __construct($key = '', $iv = '', $counter = '') * @return void * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($offset)) { @@ -83,10 +84,10 @@ public function offsetSet($offset, $value) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return bool - * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); @@ -95,10 +96,11 @@ public function offsetExists($offset) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return void * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); @@ -107,10 +109,11 @@ public function offsetUnset($offset) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return mixed|null * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetGet($offset) { return isset($this->container[$offset]) diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519.php index 4402f91703d65..7c31cfc925d4a 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519.php @@ -86,9 +86,8 @@ public static function fe_cmov( $h = array(); $b *= -1; for ($i = 0; $i < 10; ++$i) { - /** @var int $x */ $x = (($f[$i] ^ $g[$i]) & $b); - $h[$i] = (int) ((int) ($f[$i]) ^ $x); + $h[$i] = ($f[$i]) ^ $x; } return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h); } @@ -123,65 +122,45 @@ public static function fe_frombytes($s) if (self::strlen($s) !== 32) { throw new RangeException('Expected a 32-byte string.'); } - /** @var int $h0 */ $h0 = self::load_4($s); - /** @var int $h1 */ $h1 = self::load_3(self::substr($s, 4, 3)) << 6; - /** @var int $h2 */ $h2 = self::load_3(self::substr($s, 7, 3)) << 5; - /** @var int $h3 */ $h3 = self::load_3(self::substr($s, 10, 3)) << 3; - /** @var int $h4 */ $h4 = self::load_3(self::substr($s, 13, 3)) << 2; - /** @var int $h5 */ $h5 = self::load_4(self::substr($s, 16, 4)); - /** @var int $h6 */ $h6 = self::load_3(self::substr($s, 20, 3)) << 7; - /** @var int $h7 */ $h7 = self::load_3(self::substr($s, 23, 3)) << 5; - /** @var int $h8 */ $h8 = self::load_3(self::substr($s, 26, 3)) << 4; - /** @var int $h9 */ $h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607) << 2; - /** @var int $carry9 */ $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; - /** @var int $carry1 */ $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; - /** @var int $carry3 */ $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; - /** @var int $carry5 */ $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; - /** @var int $carry7 */ $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; - /** @var int $carry0 */ $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; - /** @var int $carry2 */ $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; - /** @var int $carry4 */ $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry6 */ $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; - /** @var int $carry8 */ $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; @@ -212,89 +191,58 @@ public static function fe_frombytes($s) */ public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe $h) { - /** @var int $h0 */ $h0 = (int) $h[0]; - /** @var int $h1 */ $h1 = (int) $h[1]; - /** @var int $h2 */ $h2 = (int) $h[2]; - /** @var int $h3 */ $h3 = (int) $h[3]; - /** @var int $h4 */ $h4 = (int) $h[4]; - /** @var int $h5 */ $h5 = (int) $h[5]; - /** @var int $h6 */ $h6 = (int) $h[6]; - /** @var int $h7 */ $h7 = (int) $h[7]; - /** @var int $h8 */ $h8 = (int) $h[8]; - /** @var int $h9 */ $h9 = (int) $h[9]; - /** @var int $q */ $q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25; - /** @var int $q */ $q = ($h0 + $q) >> 26; - /** @var int $q */ $q = ($h1 + $q) >> 25; - /** @var int $q */ $q = ($h2 + $q) >> 26; - /** @var int $q */ $q = ($h3 + $q) >> 25; - /** @var int $q */ $q = ($h4 + $q) >> 26; - /** @var int $q */ $q = ($h5 + $q) >> 25; - /** @var int $q */ $q = ($h6 + $q) >> 26; - /** @var int $q */ $q = ($h7 + $q) >> 25; - /** @var int $q */ $q = ($h8 + $q) >> 26; - /** @var int $q */ $q = ($h9 + $q) >> 25; $h0 += self::mul($q, 19, 5); - /** @var int $carry0 */ $carry0 = $h0 >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; - /** @var int $carry1 */ $carry1 = $h1 >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; - /** @var int $carry2 */ $carry2 = $h2 >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; - /** @var int $carry3 */ $carry3 = $h3 >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; - /** @var int $carry4 */ $carry4 = $h4 >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry5 */ $carry5 = $h5 >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; - /** @var int $carry6 */ $carry6 = $h6 >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; - /** @var int $carry7 */ $carry7 = $h7 >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; - /** @var int $carry8 */ $carry8 = $h8 >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; - /** @var int $carry9 */ $carry9 = $h9 >> 25; $h9 -= $carry9 << 25; @@ -394,45 +342,25 @@ public static function fe_mul( ParagonIE_Sodium_Core_Curve25519_Fe $f, ParagonIE_Sodium_Core_Curve25519_Fe $g ) { - /** @var int $f0 */ $f0 = $f[0]; - /** @var int $f1 */ $f1 = $f[1]; - /** @var int $f2 */ $f2 = $f[2]; - /** @var int $f3 */ $f3 = $f[3]; - /** @var int $f4 */ $f4 = $f[4]; - /** @var int $f5 */ $f5 = $f[5]; - /** @var int $f6 */ $f6 = $f[6]; - /** @var int $f7 */ $f7 = $f[7]; - /** @var int $f8 */ $f8 = $f[8]; - /** @var int $f9 */ $f9 = $f[9]; - /** @var int $g0 */ $g0 = $g[0]; - /** @var int $g1 */ $g1 = $g[1]; - /** @var int $g2 */ $g2 = $g[2]; - /** @var int $g3 */ $g3 = $g[3]; - /** @var int $g4 */ $g4 = $g[4]; - /** @var int $g5 */ $g5 = $g[5]; - /** @var int $g6 */ $g6 = $g[6]; - /** @var int $g7 */ $g7 = $g[7]; - /** @var int $g8 */ $g8 = $g[8]; - /** @var int $g9 */ $g9 = $g[9]; $g1_19 = self::mul($g1, 19, 5); $g2_19 = self::mul($g2, 19, 5); @@ -443,15 +371,10 @@ public static function fe_mul( $g7_19 = self::mul($g7, 19, 5); $g8_19 = self::mul($g8, 19, 5); $g9_19 = self::mul($g9, 19, 5); - /** @var int $f1_2 */ $f1_2 = $f1 << 1; - /** @var int $f3_2 */ $f3_2 = $f3 << 1; - /** @var int $f5_2 */ $f5_2 = $f5 << 1; - /** @var int $f7_2 */ $f7_2 = $f7 << 1; - /** @var int $f9_2 */ $f9_2 = $f9 << 1; $f0g0 = self::mul($f0, $g0, 26); $f0g1 = self::mul($f0, $g1, 25); @@ -564,57 +487,45 @@ public static function fe_mul( $h8 = $f0g8 + $f1g7_2 + $f2g6 + $f3g5_2 + $f4g4 + $f5g3_2 + $f6g2 + $f7g1_2 + $f8g0 + $f9g9_38; $h9 = $f0g9 + $f1g8 + $f2g7 + $f3g6 + $f4g5 + $f5g4 + $f6g3 + $f7g2 + $f8g1 + $f9g0 ; - /** @var int $carry0 */ $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; - /** @var int $carry4 */ $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry1 */ $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; - /** @var int $carry5 */ $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; - /** @var int $carry2 */ $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; - /** @var int $carry6 */ $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; - /** @var int $carry3 */ $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; - /** @var int $carry7 */ $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; - /** @var int $carry4 */ $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry8 */ $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; - /** @var int $carry9 */ $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; - /** @var int $carry0 */ $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; @@ -678,82 +589,74 @@ public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f) $f8 = (int) $f[8]; $f9 = (int) $f[9]; - /** @var int $f0_2 */ $f0_2 = $f0 << 1; - /** @var int $f1_2 */ $f1_2 = $f1 << 1; - /** @var int $f2_2 */ $f2_2 = $f2 << 1; - /** @var int $f3_2 */ $f3_2 = $f3 << 1; - /** @var int $f4_2 */ $f4_2 = $f4 << 1; - /** @var int $f5_2 */ $f5_2 = $f5 << 1; - /** @var int $f6_2 */ $f6_2 = $f6 << 1; - /** @var int $f7_2 */ $f7_2 = $f7 << 1; $f5_38 = self::mul($f5, 38, 6); $f6_19 = self::mul($f6, 19, 5); $f7_38 = self::mul($f7, 38, 6); $f8_19 = self::mul($f8, 19, 5); $f9_38 = self::mul($f9, 38, 6); - $f0f0 = self::mul($f0, $f0, 25); - $f0f1_2 = self::mul($f0_2, $f1, 24); - $f0f2_2 = self::mul($f0_2, $f2, 25); - $f0f3_2 = self::mul($f0_2, $f3, 24); - $f0f4_2 = self::mul($f0_2, $f4, 25); - $f0f5_2 = self::mul($f0_2, $f5, 25); - $f0f6_2 = self::mul($f0_2, $f6, 25); - $f0f7_2 = self::mul($f0_2, $f7, 24); - $f0f8_2 = self::mul($f0_2, $f8, 25); - $f0f9_2 = self::mul($f0_2, $f9, 25); - $f1f1_2 = self::mul($f1_2, $f1, 24); - $f1f2_2 = self::mul($f1_2, $f2, 25); - $f1f3_4 = self::mul($f1_2, $f3_2, 25); - $f1f4_2 = self::mul($f1_2, $f4, 25); + $f0f0 = self::mul($f0, $f0, 26); + $f0f1_2 = self::mul($f0_2, $f1, 26); + $f0f2_2 = self::mul($f0_2, $f2, 26); + $f0f3_2 = self::mul($f0_2, $f3, 26); + $f0f4_2 = self::mul($f0_2, $f4, 26); + $f0f5_2 = self::mul($f0_2, $f5, 26); + $f0f6_2 = self::mul($f0_2, $f6, 26); + $f0f7_2 = self::mul($f0_2, $f7, 26); + $f0f8_2 = self::mul($f0_2, $f8, 26); + $f0f9_2 = self::mul($f0_2, $f9, 26); + $f1f1_2 = self::mul($f1_2, $f1, 26); + $f1f2_2 = self::mul($f1_2, $f2, 26); + $f1f3_4 = self::mul($f1_2, $f3_2, 26); + $f1f4_2 = self::mul($f1_2, $f4, 26); $f1f5_4 = self::mul($f1_2, $f5_2, 26); - $f1f6_2 = self::mul($f1_2, $f6, 25); - $f1f7_4 = self::mul($f1_2, $f7_2, 25); - $f1f8_2 = self::mul($f1_2, $f8, 25); - $f1f9_76 = self::mul($f9_38, $f1_2, 25); - $f2f2 = self::mul($f2, $f2, 25); - $f2f3_2 = self::mul($f2_2, $f3, 24); - $f2f4_2 = self::mul($f2_2, $f4, 25); - $f2f5_2 = self::mul($f2_2, $f5, 25); - $f2f6_2 = self::mul($f2_2, $f6, 25); - $f2f7_2 = self::mul($f2_2, $f7, 24); - $f2f8_38 = self::mul($f8_19, $f2_2, 26); - $f2f9_38 = self::mul($f9_38, $f2, 25); - $f3f3_2 = self::mul($f3_2, $f3, 24); - $f3f4_2 = self::mul($f3_2, $f4, 25); + $f1f6_2 = self::mul($f1_2, $f6, 26); + $f1f7_4 = self::mul($f1_2, $f7_2, 26); + $f1f8_2 = self::mul($f1_2, $f8, 26); + $f1f9_76 = self::mul($f9_38, $f1_2, 27); + $f2f2 = self::mul($f2, $f2, 27); + $f2f3_2 = self::mul($f2_2, $f3, 27); + $f2f4_2 = self::mul($f2_2, $f4, 27); + $f2f5_2 = self::mul($f2_2, $f5, 27); + $f2f6_2 = self::mul($f2_2, $f6, 27); + $f2f7_2 = self::mul($f2_2, $f7, 27); + $f2f8_38 = self::mul($f8_19, $f2_2, 27); + $f2f9_38 = self::mul($f9_38, $f2, 26); + $f3f3_2 = self::mul($f3_2, $f3, 26); + $f3f4_2 = self::mul($f3_2, $f4, 26); $f3f5_4 = self::mul($f3_2, $f5_2, 26); - $f3f6_2 = self::mul($f3_2, $f6, 25); - $f3f7_76 = self::mul($f7_38, $f3_2, 25); - $f3f8_38 = self::mul($f8_19, $f3_2, 25); - $f3f9_76 = self::mul($f9_38, $f3_2, 25); - $f4f4 = self::mul($f4, $f4, 25); - $f4f5_2 = self::mul($f4_2, $f5, 25); - $f4f6_38 = self::mul($f6_19, $f4_2, 26); - $f4f7_38 = self::mul($f7_38, $f4, 25); - $f4f8_38 = self::mul($f8_19, $f4_2, 26); - $f4f9_38 = self::mul($f9_38, $f4, 25); - $f5f5_38 = self::mul($f5_38, $f5, 25); + $f3f6_2 = self::mul($f3_2, $f6, 26); + $f3f7_76 = self::mul($f7_38, $f3_2, 26); + $f3f8_38 = self::mul($f8_19, $f3_2, 26); + $f3f9_76 = self::mul($f9_38, $f3_2, 26); + $f4f4 = self::mul($f4, $f4, 26); + $f4f5_2 = self::mul($f4_2, $f5, 26); + $f4f6_38 = self::mul($f6_19, $f4_2, 27); + $f4f7_38 = self::mul($f7_38, $f4, 26); + $f4f8_38 = self::mul($f8_19, $f4_2, 27); + $f4f9_38 = self::mul($f9_38, $f4, 26); + $f5f5_38 = self::mul($f5_38, $f5, 26); $f5f6_38 = self::mul($f6_19, $f5_2, 26); $f5f7_76 = self::mul($f7_38, $f5_2, 26); $f5f8_38 = self::mul($f8_19, $f5_2, 26); $f5f9_76 = self::mul($f9_38, $f5_2, 26); - $f6f6_19 = self::mul($f6_19, $f6, 25); - $f6f7_38 = self::mul($f7_38, $f6, 25); - $f6f8_38 = self::mul($f8_19, $f6_2, 26); - $f6f9_38 = self::mul($f9_38, $f6, 25); - $f7f7_38 = self::mul($f7_38, $f7, 24); - $f7f8_38 = self::mul($f8_19, $f7_2, 25); - $f7f9_76 = self::mul($f9_38, $f7_2, 25); - $f8f8_19 = self::mul($f8_19, $f8, 25); - $f8f9_38 = self::mul($f9_38, $f8, 25); - $f9f9_38 = self::mul($f9_38, $f9, 25); + $f6f6_19 = self::mul($f6_19, $f6, 26); + $f6f7_38 = self::mul($f7_38, $f6, 26); + $f6f8_38 = self::mul($f8_19, $f6_2, 27); + $f6f9_38 = self::mul($f9_38, $f6, 26); + $f7f7_38 = self::mul($f7_38, $f7, 26); + $f7f8_38 = self::mul($f8_19, $f7_2, 26); + $f7f9_76 = self::mul($f9_38, $f7_2, 26); + $f8f8_19 = self::mul($f8_19, $f8, 26); + $f8f9_38 = self::mul($f9_38, $f8, 26); + $f9f9_38 = self::mul($f9_38, $f9, 26); $h0 = $f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38; $h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38; $h2 = $f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19; @@ -765,57 +668,45 @@ public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f) $h8 = $f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38; $h9 = $f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2; - /** @var int $carry0 */ $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; - /** @var int $carry4 */ $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry1 */ $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; - /** @var int $carry5 */ $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; - /** @var int $carry2 */ $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; - /** @var int $carry6 */ $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; - /** @var int $carry3 */ $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; - /** @var int $carry7 */ $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; - /** @var int $carry4 */ $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry8 */ $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; - /** @var int $carry9 */ $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; - /** @var int $carry0 */ $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; @@ -860,21 +751,13 @@ public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f) $f8 = (int) $f[8]; $f9 = (int) $f[9]; - /** @var int $f0_2 */ $f0_2 = $f0 << 1; - /** @var int $f1_2 */ $f1_2 = $f1 << 1; - /** @var int $f2_2 */ $f2_2 = $f2 << 1; - /** @var int $f3_2 */ $f3_2 = $f3 << 1; - /** @var int $f4_2 */ $f4_2 = $f4 << 1; - /** @var int $f5_2 */ $f5_2 = $f5 << 1; - /** @var int $f6_2 */ $f6_2 = $f6 << 1; - /** @var int $f7_2 */ $f7_2 = $f7 << 1; $f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */ $f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */ @@ -937,78 +820,56 @@ public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f) $f8f9_38 = self::mul($f9_38, $f8, 24); $f9f9_38 = self::mul($f9_38, $f9, 24); - /** @var int $h0 */ $h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 + $f5f5_38) << 1; - /** @var int $h1 */ $h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38) << 1; - /** @var int $h2 */ $h2 = (int) ($f0f2_2 + $f1f1_2 + $f3f9_76 + $f4f8_38 + $f5f7_76 + $f6f6_19) << 1; - /** @var int $h3 */ $h3 = (int) ($f0f3_2 + $f1f2_2 + $f4f9_38 + $f5f8_38 + $f6f7_38) << 1; - /** @var int $h4 */ $h4 = (int) ($f0f4_2 + $f1f3_4 + $f2f2 + $f5f9_76 + $f6f8_38 + $f7f7_38) << 1; - /** @var int $h5 */ $h5 = (int) ($f0f5_2 + $f1f4_2 + $f2f3_2 + $f6f9_38 + $f7f8_38) << 1; - /** @var int $h6 */ $h6 = (int) ($f0f6_2 + $f1f5_4 + $f2f4_2 + $f3f3_2 + $f7f9_76 + $f8f8_19) << 1; - /** @var int $h7 */ $h7 = (int) ($f0f7_2 + $f1f6_2 + $f2f5_2 + $f3f4_2 + $f8f9_38) << 1; - /** @var int $h8 */ $h8 = (int) ($f0f8_2 + $f1f7_4 + $f2f6_2 + $f3f5_4 + $f4f4 + $f9f9_38) << 1; - /** @var int $h9 */ $h9 = (int) ($f0f9_2 + $f1f8_2 + $f2f7_2 + $f3f6_2 + $f4f5_2) << 1; - /** @var int $carry0 */ $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; - /** @var int $carry4 */ $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry1 */ $carry1 = ($h1 + (1 << 24)) >> 25; $h2 += $carry1; $h1 -= $carry1 << 25; - /** @var int $carry5 */ $carry5 = ($h5 + (1 << 24)) >> 25; $h6 += $carry5; $h5 -= $carry5 << 25; - /** @var int $carry2 */ $carry2 = ($h2 + (1 << 25)) >> 26; $h3 += $carry2; $h2 -= $carry2 << 26; - /** @var int $carry6 */ $carry6 = ($h6 + (1 << 25)) >> 26; $h7 += $carry6; $h6 -= $carry6 << 26; - /** @var int $carry3 */ $carry3 = ($h3 + (1 << 24)) >> 25; $h4 += $carry3; $h3 -= $carry3 << 25; - /** @var int $carry7 */ $carry7 = ($h7 + (1 << 24)) >> 25; $h8 += $carry7; $h7 -= $carry7 << 25; - /** @var int $carry4 */ $carry4 = ($h4 + (1 << 25)) >> 26; $h5 += $carry4; $h4 -= $carry4 << 26; - /** @var int $carry8 */ $carry8 = ($h8 + (1 << 25)) >> 26; $h9 += $carry8; $h8 -= $carry8 << 26; - /** @var int $carry9 */ $carry9 = ($h9 + (1 << 24)) >> 25; $h0 += self::mul($carry9, 19, 5); $h9 -= $carry9 << 25; - /** @var int $carry0 */ $carry0 = ($h0 + (1 << 25)) >> 26; $h1 += $carry0; $h0 -= $carry0 << 26; @@ -1585,9 +1446,9 @@ public static function ge_p3_to_cached(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p public static function ge_p3_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p) { return new ParagonIE_Sodium_Core_Curve25519_Ge_P2( - $p->X, - $p->Y, - $p->Z + self::fe_copy($p->X), + self::fe_copy($p->Y), + self::fe_copy($p->Z) ); } @@ -1644,7 +1505,7 @@ public static function ge_precomp_0() */ public static function equal($b, $c) { - return (int) ((($b ^ $c) - 1 & 0xffffffff) >> 31); + return (int) ((($b ^ $c) - 1) >> 31) & 1; } /** @@ -1658,7 +1519,7 @@ public static function equal($b, $c) public static function negative($char) { if (is_int($char)) { - return $char < 0 ? 1 : 0; + return ($char >> 63) & 1; } $x = self::chrToInt(self::substr($char, 0, 1)); return (int) ($x >> 63); @@ -1683,12 +1544,78 @@ public static function cmov( throw new InvalidArgumentException('Expected an integer.'); } return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp( - self::fe_cmov($t->yplusx, $u->yplusx, $b), + self::fe_cmov($t->yplusx, $u->yplusx, $b), self::fe_cmov($t->yminusx, $u->yminusx, $b), - self::fe_cmov($t->xy2d, $u->xy2d, $b) + self::fe_cmov($t->xy2d, $u->xy2d, $b) ); } + /** + * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t + * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u + * @param int $b + * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached + */ + public static function ge_cmov_cached( + ParagonIE_Sodium_Core_Curve25519_Ge_Cached $t, + ParagonIE_Sodium_Core_Curve25519_Ge_Cached $u, + $b + ) { + $b &= 1; + $ret = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(); + $ret->YplusX = self::fe_cmov($t->YplusX, $u->YplusX, $b); + $ret->YminusX = self::fe_cmov($t->YminusX, $u->YminusX, $b); + $ret->Z = self::fe_cmov($t->Z, $u->Z, $b); + $ret->T2d = self::fe_cmov($t->T2d, $u->T2d, $b); + return $ret; + } + + /** + * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $cached + * @param int $b + * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached + * @throws SodiumException + */ + public static function ge_cmov8_cached(array $cached, $b) + { + // const unsigned char bnegative = negative(b); + // const unsigned char babs = b - (((-bnegative) & b) * ((signed char) 1 << 1)); + $bnegative = self::negative($b); + $babs = $b - (((-$bnegative) & $b) << 1); + + // ge25519_cached_0(t); + $t = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( + self::fe_1(), + self::fe_1(), + self::fe_1(), + self::fe_0() + ); + + // ge25519_cmov_cached(t, &cached[0], equal(babs, 1)); + // ge25519_cmov_cached(t, &cached[1], equal(babs, 2)); + // ge25519_cmov_cached(t, &cached[2], equal(babs, 3)); + // ge25519_cmov_cached(t, &cached[3], equal(babs, 4)); + // ge25519_cmov_cached(t, &cached[4], equal(babs, 5)); + // ge25519_cmov_cached(t, &cached[5], equal(babs, 6)); + // ge25519_cmov_cached(t, &cached[6], equal(babs, 7)); + // ge25519_cmov_cached(t, &cached[7], equal(babs, 8)); + for ($x = 0; $x < 8; ++$x) { + $t = self::ge_cmov_cached($t, $cached[$x], self::equal($babs, $x + 1)); + } + + // fe25519_copy(minust.YplusX, t->YminusX); + // fe25519_copy(minust.YminusX, t->YplusX); + // fe25519_copy(minust.Z, t->Z); + // fe25519_neg(minust.T2d, t->T2d); + $minust = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached( + self::fe_copy($t->YminusX), + self::fe_copy($t->YplusX), + self::fe_copy($t->Z), + self::fe_neg($t->T2d) + ); + return self::ge_cmov_cached($t, $minust, $bnegative); + } + /** * @internal You should not use this directly from another application * @@ -1725,9 +1652,7 @@ public static function ge_select($pos = 0, $b = 0) throw new RangeException('Position is out of range [0, 31]'); } - /** @var int $bnegative */ $bnegative = self::negative($b); - /** @var int $babs */ $babs = $b - (((-$bnegative) & $b) << 1); $t = self::ge_precomp_0(); @@ -1925,6 +1850,145 @@ public static function ge_double_scalarmult_vartime( return $r; } + /** + * @internal You should not use this directly from another application + * + * @param string $a + * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p + * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 + * @throws SodiumException + * @throws TypeError + * @psalm-suppress MixedAssignment + * @psalm-suppress MixedOperand + */ + public static function ge_scalarmult($a, $p) + { + $e = array_fill(0, 64, 0); + + /** @var ParagonIE_Sodium_Core_Curve25519_Ge_Cached[] $pi */ + $pi = array(); + + // ge25519_p3_to_cached(&pi[1 - 1], p); /* p */ + $pi[0] = self::ge_p3_to_cached($p); + + // ge25519_p3_dbl(&t2, p); + // ge25519_p1p1_to_p3(&p2, &t2); + // ge25519_p3_to_cached(&pi[2 - 1], &p2); /* 2p = 2*p */ + $t2 = self::ge_p3_dbl($p); + $p2 = self::ge_p1p1_to_p3($t2); + $pi[1] = self::ge_p3_to_cached($p2); + + // ge25519_add_cached(&t3, p, &pi[2 - 1]); + // ge25519_p1p1_to_p3(&p3, &t3); + // ge25519_p3_to_cached(&pi[3 - 1], &p3); /* 3p = 2p+p */ + $t3 = self::ge_add($p, $pi[1]); + $p3 = self::ge_p1p1_to_p3($t3); + $pi[2] = self::ge_p3_to_cached($p3); + + // ge25519_p3_dbl(&t4, &p2); + // ge25519_p1p1_to_p3(&p4, &t4); + // ge25519_p3_to_cached(&pi[4 - 1], &p4); /* 4p = 2*2p */ + $t4 = self::ge_p3_dbl($p2); + $p4 = self::ge_p1p1_to_p3($t4); + $pi[3] = self::ge_p3_to_cached($p4); + + // ge25519_add_cached(&t5, p, &pi[4 - 1]); + // ge25519_p1p1_to_p3(&p5, &t5); + // ge25519_p3_to_cached(&pi[5 - 1], &p5); /* 5p = 4p+p */ + $t5 = self::ge_add($p, $pi[3]); + $p5 = self::ge_p1p1_to_p3($t5); + $pi[4] = self::ge_p3_to_cached($p5); + + // ge25519_p3_dbl(&t6, &p3); + // ge25519_p1p1_to_p3(&p6, &t6); + // ge25519_p3_to_cached(&pi[6 - 1], &p6); /* 6p = 2*3p */ + $t6 = self::ge_p3_dbl($p3); + $p6 = self::ge_p1p1_to_p3($t6); + $pi[5] = self::ge_p3_to_cached($p6); + + // ge25519_add_cached(&t7, p, &pi[6 - 1]); + // ge25519_p1p1_to_p3(&p7, &t7); + // ge25519_p3_to_cached(&pi[7 - 1], &p7); /* 7p = 6p+p */ + $t7 = self::ge_add($p, $pi[5]); + $p7 = self::ge_p1p1_to_p3($t7); + $pi[6] = self::ge_p3_to_cached($p7); + + // ge25519_p3_dbl(&t8, &p4); + // ge25519_p1p1_to_p3(&p8, &t8); + // ge25519_p3_to_cached(&pi[8 - 1], &p8); /* 8p = 2*4p */ + $t8 = self::ge_p3_dbl($p4); + $p8 = self::ge_p1p1_to_p3($t8); + $pi[7] = self::ge_p3_to_cached($p8); + + + // for (i = 0; i < 32; ++i) { + // e[2 * i + 0] = (a[i] >> 0) & 15; + // e[2 * i + 1] = (a[i] >> 4) & 15; + // } + for ($i = 0; $i < 32; ++$i) { + $e[($i << 1) ] = self::chrToInt($a[$i]) & 15; + $e[($i << 1) + 1] = (self::chrToInt($a[$i]) >> 4) & 15; + } + // /* each e[i] is between 0 and 15 */ + // /* e[63] is between 0 and 7 */ + + // carry = 0; + // for (i = 0; i < 63; ++i) { + // e[i] += carry; + // carry = e[i] + 8; + // carry >>= 4; + // e[i] -= carry * ((signed char) 1 << 4); + // } + $carry = 0; + for ($i = 0; $i < 63; ++$i) { + $e[$i] += $carry; + $carry = $e[$i] + 8; + $carry >>= 4; + $e[$i] -= $carry << 4; + } + // e[63] += carry; + // /* each e[i] is between -8 and 8 */ + $e[63] += $carry; + + // ge25519_p3_0(h); + $h = self::ge_p3_0(); + + // for (i = 63; i != 0; i--) { + for ($i = 63; $i != 0; --$i) { + // ge25519_cmov8_cached(&t, pi, e[i]); + $t = self::ge_cmov8_cached($pi, $e[$i]); + // ge25519_add_cached(&r, h, &t); + $r = self::ge_add($h, $t); + + // ge25519_p1p1_to_p2(&s, &r); + // ge25519_p2_dbl(&r, &s); + // ge25519_p1p1_to_p2(&s, &r); + // ge25519_p2_dbl(&r, &s); + // ge25519_p1p1_to_p2(&s, &r); + // ge25519_p2_dbl(&r, &s); + // ge25519_p1p1_to_p2(&s, &r); + // ge25519_p2_dbl(&r, &s); + $s = self::ge_p1p1_to_p2($r); + $r = self::ge_p2_dbl($s); + $s = self::ge_p1p1_to_p2($r); + $r = self::ge_p2_dbl($s); + $s = self::ge_p1p1_to_p2($r); + $r = self::ge_p2_dbl($s); + $s = self::ge_p1p1_to_p2($r); + $r = self::ge_p2_dbl($s); + + // ge25519_p1p1_to_p3(h, &r); /* *16 */ + $h = self::ge_p1p1_to_p3($r); /* *16 */ + } + + // ge25519_cmov8_cached(&t, pi, e[i]); + // ge25519_add_cached(&r, h, &t); + // ge25519_p1p1_to_p3(h, &r); + $t = self::ge_cmov8_cached($pi, $e[0]); + $r = self::ge_add($h, $t); + return self::ge_p1p1_to_p3($r); + } + /** * @internal You should not use this directly from another application * @@ -1942,23 +2006,18 @@ public static function ge_scalarmult_base($a) $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1(); for ($i = 0; $i < 32; ++$i) { - /** @var int $dbl */ $dbl = (int) $i << 1; $e[$dbl] = (int) self::chrToInt($a[$i]) & 15; $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) & 15; } - /** @var int $carry */ $carry = 0; for ($i = 0; $i < 63; ++$i) { $e[$i] += $carry; - /** @var int $carry */ $carry = $e[$i] + 8; - /** @var int $carry */ $carry >>= 4; $e[$i] -= $carry << 4; } - /** @var array $e */ $e[63] += (int) $carry; $h = self::ge_p3_0(); @@ -2002,79 +2061,43 @@ public static function ge_scalarmult_base($a) */ public static function sc_muladd($a, $b, $c) { - /** @var int $a0 */ $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); - /** @var int $a1 */ $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); - /** @var int $a2 */ $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); - /** @var int $a3 */ $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); - /** @var int $a4 */ $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); - /** @var int $a5 */ $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); - /** @var int $a6 */ $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); - /** @var int $a7 */ $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); - /** @var int $a8 */ $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); - /** @var int $a9 */ $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); - /** @var int $a10 */ $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); - /** @var int $a11 */ $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); - /** @var int $b0 */ $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); - /** @var int $b1 */ $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); - /** @var int $b2 */ $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); - /** @var int $b3 */ $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); - /** @var int $b4 */ $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); - /** @var int $b5 */ $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); - /** @var int $b6 */ $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); - /** @var int $b7 */ $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); - /** @var int $b8 */ $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); - /** @var int $b9 */ $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); - /** @var int $b10 */ $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); - /** @var int $b11 */ $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); - /** @var int $c0 */ $c0 = 2097151 & self::load_3(self::substr($c, 0, 3)); - /** @var int $c1 */ $c1 = 2097151 & (self::load_4(self::substr($c, 2, 4)) >> 5); - /** @var int $c2 */ $c2 = 2097151 & (self::load_3(self::substr($c, 5, 3)) >> 2); - /** @var int $c3 */ $c3 = 2097151 & (self::load_4(self::substr($c, 7, 4)) >> 7); - /** @var int $c4 */ $c4 = 2097151 & (self::load_4(self::substr($c, 10, 4)) >> 4); - /** @var int $c5 */ $c5 = 2097151 & (self::load_3(self::substr($c, 13, 3)) >> 1); - /** @var int $c6 */ $c6 = 2097151 & (self::load_4(self::substr($c, 15, 4)) >> 6); - /** @var int $c7 */ $c7 = 2097151 & (self::load_3(self::substr($c, 18, 3)) >> 3); - /** @var int $c8 */ $c8 = 2097151 & self::load_3(self::substr($c, 21, 3)); - /** @var int $c9 */ $c9 = 2097151 & (self::load_4(self::substr($c, 23, 4)) >> 5); - /** @var int $c10 */ $c10 = 2097151 & (self::load_3(self::substr($c, 26, 3)) >> 2); - /** @var int $c11 */ $c11 = (self::load_4(self::substr($c, 28, 4)) >> 7); /* Can't really avoid the pyramid here: */ @@ -2125,96 +2148,73 @@ public static function sc_muladd($a, $b, $c) $s22 = self::mul($a11, $b11, 24); $s23 = 0; - /** @var int $carry0 */ $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; - /** @var int $carry2 */ $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; - /** @var int $carry4 */ $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; - /** @var int $carry6 */ $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry8 */ $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry10 */ $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; - /** @var int $carry12 */ $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; - /** @var int $carry14 */ $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; - /** @var int $carry16 */ $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; - /** @var int $carry18 */ $carry18 = ($s18 + (1 << 20)) >> 21; $s19 += $carry18; $s18 -= $carry18 << 21; - /** @var int $carry20 */ $carry20 = ($s20 + (1 << 20)) >> 21; $s21 += $carry20; $s20 -= $carry20 << 21; - /** @var int $carry22 */ $carry22 = ($s22 + (1 << 20)) >> 21; $s23 += $carry22; $s22 -= $carry22 << 21; - /** @var int $carry1 */ $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; - /** @var int $carry3 */ $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; - /** @var int $carry5 */ $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; - /** @var int $carry7 */ $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry9 */ $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry11 */ $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; - /** @var int $carry13 */ $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; - /** @var int $carry15 */ $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; - /** @var int $carry17 */ $carry17 = ($s17 + (1 << 20)) >> 21; $s18 += $carry17; $s17 -= $carry17 << 21; - /** @var int $carry19 */ $carry19 = ($s19 + (1 << 20)) >> 21; $s20 += $carry19; $s19 -= $carry19 << 21; - /** @var int $carry21 */ $carry21 = ($s21 + (1 << 20)) >> 21; $s22 += $carry21; $s21 -= $carry21 << 21; @@ -2261,48 +2261,37 @@ public static function sc_muladd($a, $b, $c) $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); - /** @var int $carry6 */ $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry8 */ $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry10 */ $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; - /** @var int $carry12 */ $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; - /** @var int $carry14 */ $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; - /** @var int $carry16 */ $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; - /** @var int $carry7 */ $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry9 */ $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry11 */ $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; - /** @var int $carry13 */ $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; - /** @var int $carry15 */ $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; @@ -2350,52 +2339,40 @@ public static function sc_muladd($a, $b, $c) $s5 -= self::mul($s12, 683901, 20); $s12 = 0; - /** @var int $carry0 */ $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; - /** @var int $carry2 */ $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; - /** @var int $carry4 */ $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; - /** @var int $carry6 */ $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry8 */ $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry10 */ $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; - /** @var int $carry1 */ $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; - /** @var int $carry3 */ $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; - /** @var int $carry5 */ $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; - /** @var int $carry7 */ $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry9 */ $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry11 */ $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; @@ -2408,51 +2385,39 @@ public static function sc_muladd($a, $b, $c) $s5 -= self::mul($s12, 683901, 20); $s12 = 0; - /** @var int $carry0 */ $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; - /** @var int $carry1 */ $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; - /** @var int $carry2 */ $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; - /** @var int $carry3 */ $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; - /** @var int $carry4 */ $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; - /** @var int $carry5 */ $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; - /** @var int $carry6 */ $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry7 */ $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry8 */ $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry9 */ $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry10 */ $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; - /** @var int $carry11 */ $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; @@ -2464,47 +2429,36 @@ public static function sc_muladd($a, $b, $c) $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); - /** @var int $carry0 */ $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; - /** @var int $carry1 */ $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; - /** @var int $carry2 */ $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; - /** @var int $carry3 */ $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; - /** @var int $carry4 */ $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; - /** @var int $carry5 */ $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; - /** @var int $carry6 */ $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry7 */ $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry8 */ $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry9 */ $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry10 */ $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; @@ -2558,53 +2512,29 @@ public static function sc_muladd($a, $b, $c) */ public static function sc_reduce($s) { - /** @var int $s0 */ $s0 = 2097151 & self::load_3(self::substr($s, 0, 3)); - /** @var int $s1 */ $s1 = 2097151 & (self::load_4(self::substr($s, 2, 4)) >> 5); - /** @var int $s2 */ $s2 = 2097151 & (self::load_3(self::substr($s, 5, 3)) >> 2); - /** @var int $s3 */ $s3 = 2097151 & (self::load_4(self::substr($s, 7, 4)) >> 7); - /** @var int $s4 */ $s4 = 2097151 & (self::load_4(self::substr($s, 10, 4)) >> 4); - /** @var int $s5 */ $s5 = 2097151 & (self::load_3(self::substr($s, 13, 3)) >> 1); - /** @var int $s6 */ $s6 = 2097151 & (self::load_4(self::substr($s, 15, 4)) >> 6); - /** @var int $s7 */ $s7 = 2097151 & (self::load_3(self::substr($s, 18, 4)) >> 3); - /** @var int $s8 */ $s8 = 2097151 & self::load_3(self::substr($s, 21, 3)); - /** @var int $s9 */ $s9 = 2097151 & (self::load_4(self::substr($s, 23, 4)) >> 5); - /** @var int $s10 */ $s10 = 2097151 & (self::load_3(self::substr($s, 26, 3)) >> 2); - /** @var int $s11 */ $s11 = 2097151 & (self::load_4(self::substr($s, 28, 4)) >> 7); - /** @var int $s12 */ $s12 = 2097151 & (self::load_4(self::substr($s, 31, 4)) >> 4); - /** @var int $s13 */ $s13 = 2097151 & (self::load_3(self::substr($s, 34, 3)) >> 1); - /** @var int $s14 */ $s14 = 2097151 & (self::load_4(self::substr($s, 36, 4)) >> 6); - /** @var int $s15 */ $s15 = 2097151 & (self::load_3(self::substr($s, 39, 4)) >> 3); - /** @var int $s16 */ $s16 = 2097151 & self::load_3(self::substr($s, 42, 3)); - /** @var int $s17 */ $s17 = 2097151 & (self::load_4(self::substr($s, 44, 4)) >> 5); - /** @var int $s18 */ $s18 = 2097151 & (self::load_3(self::substr($s, 47, 3)) >> 2); - /** @var int $s19 */ $s19 = 2097151 & (self::load_4(self::substr($s, 49, 4)) >> 7); - /** @var int $s20 */ $s20 = 2097151 & (self::load_4(self::substr($s, 52, 4)) >> 4); - /** @var int $s21 */ $s21 = 2097151 & (self::load_3(self::substr($s, 55, 3)) >> 1); - /** @var int $s22 */ $s22 = 2097151 & (self::load_4(self::substr($s, 57, 4)) >> 6); - /** @var int $s23 */ $s23 = (self::load_4(self::substr($s, 60, 4)) >> 3); $s11 += self::mul($s23, 666643, 20); @@ -2649,48 +2579,37 @@ public static function sc_reduce($s) $s10 += self::mul($s18, 136657, 18); $s11 -= self::mul($s18, 683901, 20); - /** @var int $carry6 */ $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry8 */ $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry10 */ $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; - /** @var int $carry12 */ $carry12 = ($s12 + (1 << 20)) >> 21; $s13 += $carry12; $s12 -= $carry12 << 21; - /** @var int $carry14 */ $carry14 = ($s14 + (1 << 20)) >> 21; $s15 += $carry14; $s14 -= $carry14 << 21; - /** @var int $carry16 */ $carry16 = ($s16 + (1 << 20)) >> 21; $s17 += $carry16; $s16 -= $carry16 << 21; - /** @var int $carry7 */ $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry9 */ $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry11 */ $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; - /** @var int $carry13 */ $carry13 = ($s13 + (1 << 20)) >> 21; $s14 += $carry13; $s13 -= $carry13 << 21; - /** @var int $carry15 */ $carry15 = ($s15 + (1 << 20)) >> 21; $s16 += $carry15; $s15 -= $carry15 << 21; @@ -2738,52 +2657,40 @@ public static function sc_reduce($s) $s5 -= self::mul($s12, 683901, 20); $s12 = 0; - /** @var int $carry0 */ $carry0 = ($s0 + (1 << 20)) >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; - /** @var int $carry2 */ $carry2 = ($s2 + (1 << 20)) >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; - /** @var int $carry4 */ $carry4 = ($s4 + (1 << 20)) >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; - /** @var int $carry6 */ $carry6 = ($s6 + (1 << 20)) >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry8 */ $carry8 = ($s8 + (1 << 20)) >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry10 */ $carry10 = ($s10 + (1 << 20)) >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; - /** @var int $carry1 */ $carry1 = ($s1 + (1 << 20)) >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; - /** @var int $carry3 */ $carry3 = ($s3 + (1 << 20)) >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; - /** @var int $carry5 */ $carry5 = ($s5 + (1 << 20)) >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; - /** @var int $carry7 */ $carry7 = ($s7 + (1 << 20)) >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry9 */ $carry9 = ($s9 + (1 << 20)) >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry11 */ $carry11 = ($s11 + (1 << 20)) >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; @@ -2796,51 +2703,39 @@ public static function sc_reduce($s) $s5 -= self::mul($s12, 683901, 20); $s12 = 0; - /** @var int $carry0 */ $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; - /** @var int $carry1 */ $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; - /** @var int $carry2 */ $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; - /** @var int $carry3 */ $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; - /** @var int $carry4 */ $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; - /** @var int $carry5 */ $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; - /** @var int $carry6 */ $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry7 */ $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry8 */ $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry9 */ $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry10 */ $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; - /** @var int $carry11 */ $carry11 = $s11 >> 21; $s12 += $carry11; $s11 -= $carry11 << 21; @@ -2852,47 +2747,36 @@ public static function sc_reduce($s) $s4 += self::mul($s12, 136657, 18); $s5 -= self::mul($s12, 683901, 20); - /** @var int $carry0 */ $carry0 = $s0 >> 21; $s1 += $carry0; $s0 -= $carry0 << 21; - /** @var int $carry1 */ $carry1 = $s1 >> 21; $s2 += $carry1; $s1 -= $carry1 << 21; - /** @var int $carry2 */ $carry2 = $s2 >> 21; $s3 += $carry2; $s2 -= $carry2 << 21; - /** @var int $carry3 */ $carry3 = $s3 >> 21; $s4 += $carry3; $s3 -= $carry3 << 21; - /** @var int $carry4 */ $carry4 = $s4 >> 21; $s5 += $carry4; $s4 -= $carry4 << 21; - /** @var int $carry5 */ $carry5 = $s5 >> 21; $s6 += $carry5; $s5 -= $carry5 << 21; - /** @var int $carry6 */ $carry6 = $s6 >> 21; $s7 += $carry6; $s6 -= $carry6 << 21; - /** @var int $carry7 */ $carry7 = $s7 >> 21; $s8 += $carry7; $s7 -= $carry7 << 21; - /** @var int $carry8 */ $carry8 = $s8 >> 21; $s9 += $carry8; $s8 -= $carry8 << 21; - /** @var int $carry9 */ $carry9 = $s9 >> 21; $s10 += $carry9; $s9 -= $carry9 << 21; - /** @var int $carry10 */ $carry10 = $s10 >> 21; $s11 += $carry10; $s10 -= $carry10 << 21; @@ -2945,7 +2829,6 @@ public static function sc_reduce($s) */ public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A) { - /** @var array $aslide */ $aslide = array( 13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, @@ -2999,4 +2882,904 @@ public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A) # ge_p1p1_to_p3(r, &t); return self::ge_p1p1_to_p3($t); } + + /** + * @param string $a + * @param string $b + * @return string + */ + public static function sc25519_mul($a, $b) + { + // int64_t a0 = 2097151 & load_3(a); + // int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + // int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + // int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + // int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + // int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + // int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + // int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + // int64_t a8 = 2097151 & load_3(a + 21); + // int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + // int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + // int64_t a11 = (load_4(a + 28) >> 7); + $a0 = 2097151 & self::load_3(self::substr($a, 0, 3)); + $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >> 5); + $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >> 2); + $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >> 7); + $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >> 4); + $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >> 1); + $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >> 6); + $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >> 3); + $a8 = 2097151 & self::load_3(self::substr($a, 21, 3)); + $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >> 5); + $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3)) >> 2); + $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7); + + // int64_t b0 = 2097151 & load_3(b); + // int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + // int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + // int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + // int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + // int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + // int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + // int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + // int64_t b8 = 2097151 & load_3(b + 21); + // int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + // int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + // int64_t b11 = (load_4(b + 28) >> 7); + $b0 = 2097151 & self::load_3(self::substr($b, 0, 3)); + $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >> 5); + $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >> 2); + $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >> 7); + $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >> 4); + $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >> 1); + $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >> 6); + $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >> 3); + $b8 = 2097151 & self::load_3(self::substr($b, 21, 3)); + $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >> 5); + $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3)) >> 2); + $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7); + + // s0 = a0 * b0; + // s1 = a0 * b1 + a1 * b0; + // s2 = a0 * b2 + a1 * b1 + a2 * b0; + // s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; + // s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; + // s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; + // s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; + // s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + + // a6 * b1 + a7 * b0; + // s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + + // a6 * b2 + a7 * b1 + a8 * b0; + // s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + + // a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; + // s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + + // a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; + // s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + + // a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; + // s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + + // a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; + // s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + + // a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; + // s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + + // a9 * b5 + a10 * b4 + a11 * b3; + // s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + + // a10 * b5 + a11 * b4; + // s16 = + // a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; + // s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; + // s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; + // s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; + // s20 = a9 * b11 + a10 * b10 + a11 * b9; + // s21 = a10 * b11 + a11 * b10; + // s22 = a11 * b11; + // s23 = 0; + $s0 = self::mul($a0, $b0, 22); + $s1 = self::mul($a0, $b1, 22) + self::mul($a1, $b0, 22); + $s2 = self::mul($a0, $b2, 22) + self::mul($a1, $b1, 22) + self::mul($a2, $b0, 22); + $s3 = self::mul($a0, $b3, 22) + self::mul($a1, $b2, 22) + self::mul($a2, $b1, 22) + self::mul($a3, $b0, 22); + $s4 = self::mul($a0, $b4, 22) + self::mul($a1, $b3, 22) + self::mul($a2, $b2, 22) + self::mul($a3, $b1, 22) + + self::mul($a4, $b0, 22); + $s5 = self::mul($a0, $b5, 22) + self::mul($a1, $b4, 22) + self::mul($a2, $b3, 22) + self::mul($a3, $b2, 22) + + self::mul($a4, $b1, 22) + self::mul($a5, $b0, 22); + $s6 = self::mul($a0, $b6, 22) + self::mul($a1, $b5, 22) + self::mul($a2, $b4, 22) + self::mul($a3, $b3, 22) + + self::mul($a4, $b2, 22) + self::mul($a5, $b1, 22) + self::mul($a6, $b0, 22); + $s7 = self::mul($a0, $b7, 22) + self::mul($a1, $b6, 22) + self::mul($a2, $b5, 22) + self::mul($a3, $b4, 22) + + self::mul($a4, $b3, 22) + self::mul($a5, $b2, 22) + self::mul($a6, $b1, 22) + self::mul($a7, $b0, 22); + $s8 = self::mul($a0, $b8, 22) + self::mul($a1, $b7, 22) + self::mul($a2, $b6, 22) + self::mul($a3, $b5, 22) + + self::mul($a4, $b4, 22) + self::mul($a5, $b3, 22) + self::mul($a6, $b2, 22) + self::mul($a7, $b1, 22) + + self::mul($a8, $b0, 22); + $s9 = self::mul($a0, $b9, 22) + self::mul($a1, $b8, 22) + self::mul($a2, $b7, 22) + self::mul($a3, $b6, 22) + + self::mul($a4, $b5, 22) + self::mul($a5, $b4, 22) + self::mul($a6, $b3, 22) + self::mul($a7, $b2, 22) + + self::mul($a8, $b1, 22) + self::mul($a9, $b0, 22); + $s10 = self::mul($a0, $b10, 22) + self::mul($a1, $b9, 22) + self::mul($a2, $b8, 22) + self::mul($a3, $b7, 22) + + self::mul($a4, $b6, 22) + self::mul($a5, $b5, 22) + self::mul($a6, $b4, 22) + self::mul($a7, $b3, 22) + + self::mul($a8, $b2, 22) + self::mul($a9, $b1, 22) + self::mul($a10, $b0, 22); + $s11 = self::mul($a0, $b11, 22) + self::mul($a1, $b10, 22) + self::mul($a2, $b9, 22) + self::mul($a3, $b8, 22) + + self::mul($a4, $b7, 22) + self::mul($a5, $b6, 22) + self::mul($a6, $b5, 22) + self::mul($a7, $b4, 22) + + self::mul($a8, $b3, 22) + self::mul($a9, $b2, 22) + self::mul($a10, $b1, 22) + self::mul($a11, $b0, 22); + $s12 = self::mul($a1, $b11, 22) + self::mul($a2, $b10, 22) + self::mul($a3, $b9, 22) + self::mul($a4, $b8, 22) + + self::mul($a5, $b7, 22) + self::mul($a6, $b6, 22) + self::mul($a7, $b5, 22) + self::mul($a8, $b4, 22) + + self::mul($a9, $b3, 22) + self::mul($a10, $b2, 22) + self::mul($a11, $b1, 22); + $s13 = self::mul($a2, $b11, 22) + self::mul($a3, $b10, 22) + self::mul($a4, $b9, 22) + self::mul($a5, $b8, 22) + + self::mul($a6, $b7, 22) + self::mul($a7, $b6, 22) + self::mul($a8, $b5, 22) + self::mul($a9, $b4, 22) + + self::mul($a10, $b3, 22) + self::mul($a11, $b2, 22); + $s14 = self::mul($a3, $b11, 22) + self::mul($a4, $b10, 22) + self::mul($a5, $b9, 22) + self::mul($a6, $b8, 22) + + self::mul($a7, $b7, 22) + self::mul($a8, $b6, 22) + self::mul($a9, $b5, 22) + self::mul($a10, $b4, 22) + + self::mul($a11, $b3, 22); + $s15 = self::mul($a4, $b11, 22) + self::mul($a5, $b10, 22) + self::mul($a6, $b9, 22) + self::mul($a7, $b8, 22) + + self::mul($a8, $b7, 22) + self::mul($a9, $b6, 22) + self::mul($a10, $b5, 22) + self::mul($a11, $b4, 22); + $s16 = + self::mul($a5, $b11, 22) + self::mul($a6, $b10, 22) + self::mul($a7, $b9, 22) + self::mul($a8, $b8, 22) + + self::mul($a9, $b7, 22) + self::mul($a10, $b6, 22) + self::mul($a11, $b5, 22); + $s17 = self::mul($a6, $b11, 22) + self::mul($a7, $b10, 22) + self::mul($a8, $b9, 22) + self::mul($a9, $b8, 22) + + self::mul($a10, $b7, 22) + self::mul($a11, $b6, 22); + $s18 = self::mul($a7, $b11, 22) + self::mul($a8, $b10, 22) + self::mul($a9, $b9, 22) + self::mul($a10, $b8, 22) + + self::mul($a11, $b7, 22); + $s19 = self::mul($a8, $b11, 22) + self::mul($a9, $b10, 22) + self::mul($a10, $b9, 22) + + self::mul($a11, $b8, 22); + $s20 = self::mul($a9, $b11, 22) + self::mul($a10, $b10, 22) + self::mul($a11, $b9, 22); + $s21 = self::mul($a10, $b11, 22) + self::mul($a11, $b10, 22); + $s22 = self::mul($a11, $b11, 22); + $s23 = 0; + + // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; + // s1 += carry0; + // s0 -= carry0 * ((uint64_t) 1L << 21); + $carry0 = ($s0 + (1 << 20)) >> 21; + $s1 += $carry0; + $s0 -= $carry0 << 21; + // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; + // s3 += carry2; + // s2 -= carry2 * ((uint64_t) 1L << 21); + $carry2 = ($s2 + (1 << 20)) >> 21; + $s3 += $carry2; + $s2 -= $carry2 << 21; + // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; + // s5 += carry4; + // s4 -= carry4 * ((uint64_t) 1L << 21); + $carry4 = ($s4 + (1 << 20)) >> 21; + $s5 += $carry4; + $s4 -= $carry4 << 21; + // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; + // s7 += carry6; + // s6 -= carry6 * ((uint64_t) 1L << 21); + $carry6 = ($s6 + (1 << 20)) >> 21; + $s7 += $carry6; + $s6 -= $carry6 << 21; + // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; + // s9 += carry8; + // s8 -= carry8 * ((uint64_t) 1L << 21); + $carry8 = ($s8 + (1 << 20)) >> 21; + $s9 += $carry8; + $s8 -= $carry8 << 21; + // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; + // s11 += carry10; + // s10 -= carry10 * ((uint64_t) 1L << 21); + $carry10 = ($s10 + (1 << 20)) >> 21; + $s11 += $carry10; + $s10 -= $carry10 << 21; + // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; + // s13 += carry12; + // s12 -= carry12 * ((uint64_t) 1L << 21); + $carry12 = ($s12 + (1 << 20)) >> 21; + $s13 += $carry12; + $s12 -= $carry12 << 21; + // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; + // s15 += carry14; + // s14 -= carry14 * ((uint64_t) 1L << 21); + $carry14 = ($s14 + (1 << 20)) >> 21; + $s15 += $carry14; + $s14 -= $carry14 << 21; + // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; + // s17 += carry16; + // s16 -= carry16 * ((uint64_t) 1L << 21); + $carry16 = ($s16 + (1 << 20)) >> 21; + $s17 += $carry16; + $s16 -= $carry16 << 21; + // carry18 = (s18 + (int64_t) (1L << 20)) >> 21; + // s19 += carry18; + // s18 -= carry18 * ((uint64_t) 1L << 21); + $carry18 = ($s18 + (1 << 20)) >> 21; + $s19 += $carry18; + $s18 -= $carry18 << 21; + // carry20 = (s20 + (int64_t) (1L << 20)) >> 21; + // s21 += carry20; + // s20 -= carry20 * ((uint64_t) 1L << 21); + $carry20 = ($s20 + (1 << 20)) >> 21; + $s21 += $carry20; + $s20 -= $carry20 << 21; + // carry22 = (s22 + (int64_t) (1L << 20)) >> 21; + // s23 += carry22; + // s22 -= carry22 * ((uint64_t) 1L << 21); + $carry22 = ($s22 + (1 << 20)) >> 21; + $s23 += $carry22; + $s22 -= $carry22 << 21; + + // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; + // s2 += carry1; + // s1 -= carry1 * ((uint64_t) 1L << 21); + $carry1 = ($s1 + (1 << 20)) >> 21; + $s2 += $carry1; + $s1 -= $carry1 << 21; + // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; + // s4 += carry3; + // s3 -= carry3 * ((uint64_t) 1L << 21); + $carry3 = ($s3 + (1 << 20)) >> 21; + $s4 += $carry3; + $s3 -= $carry3 << 21; + // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; + // s6 += carry5; + // s5 -= carry5 * ((uint64_t) 1L << 21); + $carry5 = ($s5 + (1 << 20)) >> 21; + $s6 += $carry5; + $s5 -= $carry5 << 21; + // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; + // s8 += carry7; + // s7 -= carry7 * ((uint64_t) 1L << 21); + $carry7 = ($s7 + (1 << 20)) >> 21; + $s8 += $carry7; + $s7 -= $carry7 << 21; + // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; + // s10 += carry9; + // s9 -= carry9 * ((uint64_t) 1L << 21); + $carry9 = ($s9 + (1 << 20)) >> 21; + $s10 += $carry9; + $s9 -= $carry9 << 21; + // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; + // s12 += carry11; + // s11 -= carry11 * ((uint64_t) 1L << 21); + $carry11 = ($s11 + (1 << 20)) >> 21; + $s12 += $carry11; + $s11 -= $carry11 << 21; + // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; + // s14 += carry13; + // s13 -= carry13 * ((uint64_t) 1L << 21); + $carry13 = ($s13 + (1 << 20)) >> 21; + $s14 += $carry13; + $s13 -= $carry13 << 21; + // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; + // s16 += carry15; + // s15 -= carry15 * ((uint64_t) 1L << 21); + $carry15 = ($s15 + (1 << 20)) >> 21; + $s16 += $carry15; + $s15 -= $carry15 << 21; + // carry17 = (s17 + (int64_t) (1L << 20)) >> 21; + // s18 += carry17; + // s17 -= carry17 * ((uint64_t) 1L << 21); + $carry17 = ($s17 + (1 << 20)) >> 21; + $s18 += $carry17; + $s17 -= $carry17 << 21; + // carry19 = (s19 + (int64_t) (1L << 20)) >> 21; + // s20 += carry19; + // s19 -= carry19 * ((uint64_t) 1L << 21); + $carry19 = ($s19 + (1 << 20)) >> 21; + $s20 += $carry19; + $s19 -= $carry19 << 21; + // carry21 = (s21 + (int64_t) (1L << 20)) >> 21; + // s22 += carry21; + // s21 -= carry21 * ((uint64_t) 1L << 21); + $carry21 = ($s21 + (1 << 20)) >> 21; + $s22 += $carry21; + $s21 -= $carry21 << 21; + + // s11 += s23 * 666643; + // s12 += s23 * 470296; + // s13 += s23 * 654183; + // s14 -= s23 * 997805; + // s15 += s23 * 136657; + // s16 -= s23 * 683901; + $s11 += self::mul($s23, 666643, 20); + $s12 += self::mul($s23, 470296, 19); + $s13 += self::mul($s23, 654183, 20); + $s14 -= self::mul($s23, 997805, 20); + $s15 += self::mul($s23, 136657, 18); + $s16 -= self::mul($s23, 683901, 20); + + // s10 += s22 * 666643; + // s11 += s22 * 470296; + // s12 += s22 * 654183; + // s13 -= s22 * 997805; + // s14 += s22 * 136657; + // s15 -= s22 * 683901; + $s10 += self::mul($s22, 666643, 20); + $s11 += self::mul($s22, 470296, 19); + $s12 += self::mul($s22, 654183, 20); + $s13 -= self::mul($s22, 997805, 20); + $s14 += self::mul($s22, 136657, 18); + $s15 -= self::mul($s22, 683901, 20); + + // s9 += s21 * 666643; + // s10 += s21 * 470296; + // s11 += s21 * 654183; + // s12 -= s21 * 997805; + // s13 += s21 * 136657; + // s14 -= s21 * 683901; + $s9 += self::mul($s21, 666643, 20); + $s10 += self::mul($s21, 470296, 19); + $s11 += self::mul($s21, 654183, 20); + $s12 -= self::mul($s21, 997805, 20); + $s13 += self::mul($s21, 136657, 18); + $s14 -= self::mul($s21, 683901, 20); + + // s8 += s20 * 666643; + // s9 += s20 * 470296; + // s10 += s20 * 654183; + // s11 -= s20 * 997805; + // s12 += s20 * 136657; + // s13 -= s20 * 683901; + $s8 += self::mul($s20, 666643, 20); + $s9 += self::mul($s20, 470296, 19); + $s10 += self::mul($s20, 654183, 20); + $s11 -= self::mul($s20, 997805, 20); + $s12 += self::mul($s20, 136657, 18); + $s13 -= self::mul($s20, 683901, 20); + + // s7 += s19 * 666643; + // s8 += s19 * 470296; + // s9 += s19 * 654183; + // s10 -= s19 * 997805; + // s11 += s19 * 136657; + // s12 -= s19 * 683901; + $s7 += self::mul($s19, 666643, 20); + $s8 += self::mul($s19, 470296, 19); + $s9 += self::mul($s19, 654183, 20); + $s10 -= self::mul($s19, 997805, 20); + $s11 += self::mul($s19, 136657, 18); + $s12 -= self::mul($s19, 683901, 20); + + // s6 += s18 * 666643; + // s7 += s18 * 470296; + // s8 += s18 * 654183; + // s9 -= s18 * 997805; + // s10 += s18 * 136657; + // s11 -= s18 * 683901; + $s6 += self::mul($s18, 666643, 20); + $s7 += self::mul($s18, 470296, 19); + $s8 += self::mul($s18, 654183, 20); + $s9 -= self::mul($s18, 997805, 20); + $s10 += self::mul($s18, 136657, 18); + $s11 -= self::mul($s18, 683901, 20); + + // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; + // s7 += carry6; + // s6 -= carry6 * ((uint64_t) 1L << 21); + $carry6 = ($s6 + (1 << 20)) >> 21; + $s7 += $carry6; + $s6 -= $carry6 << 21; + // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; + // s9 += carry8; + // s8 -= carry8 * ((uint64_t) 1L << 21); + $carry8 = ($s8 + (1 << 20)) >> 21; + $s9 += $carry8; + $s8 -= $carry8 << 21; + // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; + // s11 += carry10; + // s10 -= carry10 * ((uint64_t) 1L << 21); + $carry10 = ($s10 + (1 << 20)) >> 21; + $s11 += $carry10; + $s10 -= $carry10 << 21; + // carry12 = (s12 + (int64_t) (1L << 20)) >> 21; + // s13 += carry12; + // s12 -= carry12 * ((uint64_t) 1L << 21); + $carry12 = ($s12 + (1 << 20)) >> 21; + $s13 += $carry12; + $s12 -= $carry12 << 21; + // carry14 = (s14 + (int64_t) (1L << 20)) >> 21; + // s15 += carry14; + // s14 -= carry14 * ((uint64_t) 1L << 21); + $carry14 = ($s14 + (1 << 20)) >> 21; + $s15 += $carry14; + $s14 -= $carry14 << 21; + // carry16 = (s16 + (int64_t) (1L << 20)) >> 21; + // s17 += carry16; + // s16 -= carry16 * ((uint64_t) 1L << 21); + $carry16 = ($s16 + (1 << 20)) >> 21; + $s17 += $carry16; + $s16 -= $carry16 << 21; + + // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; + // s8 += carry7; + // s7 -= carry7 * ((uint64_t) 1L << 21); + $carry7 = ($s7 + (1 << 20)) >> 21; + $s8 += $carry7; + $s7 -= $carry7 << 21; + // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; + // s10 += carry9; + // s9 -= carry9 * ((uint64_t) 1L << 21); + $carry9 = ($s9 + (1 << 20)) >> 21; + $s10 += $carry9; + $s9 -= $carry9 << 21; + // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; + // s12 += carry11; + // s11 -= carry11 * ((uint64_t) 1L << 21); + $carry11 = ($s11 + (1 << 20)) >> 21; + $s12 += $carry11; + $s11 -= $carry11 << 21; + // carry13 = (s13 + (int64_t) (1L << 20)) >> 21; + // s14 += carry13; + // s13 -= carry13 * ((uint64_t) 1L << 21); + $carry13 = ($s13 + (1 << 20)) >> 21; + $s14 += $carry13; + $s13 -= $carry13 << 21; + // carry15 = (s15 + (int64_t) (1L << 20)) >> 21; + // s16 += carry15; + // s15 -= carry15 * ((uint64_t) 1L << 21); + $carry15 = ($s15 + (1 << 20)) >> 21; + $s16 += $carry15; + $s15 -= $carry15 << 21; + + // s5 += s17 * 666643; + // s6 += s17 * 470296; + // s7 += s17 * 654183; + // s8 -= s17 * 997805; + // s9 += s17 * 136657; + // s10 -= s17 * 683901; + $s5 += self::mul($s17, 666643, 20); + $s6 += self::mul($s17, 470296, 19); + $s7 += self::mul($s17, 654183, 20); + $s8 -= self::mul($s17, 997805, 20); + $s9 += self::mul($s17, 136657, 18); + $s10 -= self::mul($s17, 683901, 20); + + // s4 += s16 * 666643; + // s5 += s16 * 470296; + // s6 += s16 * 654183; + // s7 -= s16 * 997805; + // s8 += s16 * 136657; + // s9 -= s16 * 683901; + $s4 += self::mul($s16, 666643, 20); + $s5 += self::mul($s16, 470296, 19); + $s6 += self::mul($s16, 654183, 20); + $s7 -= self::mul($s16, 997805, 20); + $s8 += self::mul($s16, 136657, 18); + $s9 -= self::mul($s16, 683901, 20); + + // s3 += s15 * 666643; + // s4 += s15 * 470296; + // s5 += s15 * 654183; + // s6 -= s15 * 997805; + // s7 += s15 * 136657; + // s8 -= s15 * 683901; + $s3 += self::mul($s15, 666643, 20); + $s4 += self::mul($s15, 470296, 19); + $s5 += self::mul($s15, 654183, 20); + $s6 -= self::mul($s15, 997805, 20); + $s7 += self::mul($s15, 136657, 18); + $s8 -= self::mul($s15, 683901, 20); + + // s2 += s14 * 666643; + // s3 += s14 * 470296; + // s4 += s14 * 654183; + // s5 -= s14 * 997805; + // s6 += s14 * 136657; + // s7 -= s14 * 683901; + $s2 += self::mul($s14, 666643, 20); + $s3 += self::mul($s14, 470296, 19); + $s4 += self::mul($s14, 654183, 20); + $s5 -= self::mul($s14, 997805, 20); + $s6 += self::mul($s14, 136657, 18); + $s7 -= self::mul($s14, 683901, 20); + + // s1 += s13 * 666643; + // s2 += s13 * 470296; + // s3 += s13 * 654183; + // s4 -= s13 * 997805; + // s5 += s13 * 136657; + // s6 -= s13 * 683901; + $s1 += self::mul($s13, 666643, 20); + $s2 += self::mul($s13, 470296, 19); + $s3 += self::mul($s13, 654183, 20); + $s4 -= self::mul($s13, 997805, 20); + $s5 += self::mul($s13, 136657, 18); + $s6 -= self::mul($s13, 683901, 20); + + // s0 += s12 * 666643; + // s1 += s12 * 470296; + // s2 += s12 * 654183; + // s3 -= s12 * 997805; + // s4 += s12 * 136657; + // s5 -= s12 * 683901; + // s12 = 0; + $s0 += self::mul($s12, 666643, 20); + $s1 += self::mul($s12, 470296, 19); + $s2 += self::mul($s12, 654183, 20); + $s3 -= self::mul($s12, 997805, 20); + $s4 += self::mul($s12, 136657, 18); + $s5 -= self::mul($s12, 683901, 20); + $s12 = 0; + + // carry0 = (s0 + (int64_t) (1L << 20)) >> 21; + // s1 += carry0; + // s0 -= carry0 * ((uint64_t) 1L << 21); + $carry0 = ($s0 + (1 << 20)) >> 21; + $s1 += $carry0; + $s0 -= $carry0 << 21; + // carry2 = (s2 + (int64_t) (1L << 20)) >> 21; + // s3 += carry2; + // s2 -= carry2 * ((uint64_t) 1L << 21); + $carry2 = ($s2 + (1 << 20)) >> 21; + $s3 += $carry2; + $s2 -= $carry2 << 21; + // carry4 = (s4 + (int64_t) (1L << 20)) >> 21; + // s5 += carry4; + // s4 -= carry4 * ((uint64_t) 1L << 21); + $carry4 = ($s4 + (1 << 20)) >> 21; + $s5 += $carry4; + $s4 -= $carry4 << 21; + // carry6 = (s6 + (int64_t) (1L << 20)) >> 21; + // s7 += carry6; + // s6 -= carry6 * ((uint64_t) 1L << 21); + $carry6 = ($s6 + (1 << 20)) >> 21; + $s7 += $carry6; + $s6 -= $carry6 << 21; + // carry8 = (s8 + (int64_t) (1L << 20)) >> 21; + // s9 += carry8; + // s8 -= carry8 * ((uint64_t) 1L << 21); + $carry8 = ($s8 + (1 << 20)) >> 21; + $s9 += $carry8; + $s8 -= $carry8 << 21; + // carry10 = (s10 + (int64_t) (1L << 20)) >> 21; + // s11 += carry10; + // s10 -= carry10 * ((uint64_t) 1L << 21); + $carry10 = ($s10 + (1 << 20)) >> 21; + $s11 += $carry10; + $s10 -= $carry10 << 21; + + // carry1 = (s1 + (int64_t) (1L << 20)) >> 21; + // s2 += carry1; + // s1 -= carry1 * ((uint64_t) 1L << 21); + $carry1 = ($s1 + (1 << 20)) >> 21; + $s2 += $carry1; + $s1 -= $carry1 << 21; + // carry3 = (s3 + (int64_t) (1L << 20)) >> 21; + // s4 += carry3; + // s3 -= carry3 * ((uint64_t) 1L << 21); + $carry3 = ($s3 + (1 << 20)) >> 21; + $s4 += $carry3; + $s3 -= $carry3 << 21; + // carry5 = (s5 + (int64_t) (1L << 20)) >> 21; + // s6 += carry5; + // s5 -= carry5 * ((uint64_t) 1L << 21); + $carry5 = ($s5 + (1 << 20)) >> 21; + $s6 += $carry5; + $s5 -= $carry5 << 21; + // carry7 = (s7 + (int64_t) (1L << 20)) >> 21; + // s8 += carry7; + // s7 -= carry7 * ((uint64_t) 1L << 21); + $carry7 = ($s7 + (1 << 20)) >> 21; + $s8 += $carry7; + $s7 -= $carry7 << 21; + // carry9 = (s9 + (int64_t) (1L << 20)) >> 21; + // s10 += carry9; + // s9 -= carry9 * ((uint64_t) 1L << 21); + $carry9 = ($s9 + (1 << 20)) >> 21; + $s10 += $carry9; + $s9 -= $carry9 << 21; + // carry11 = (s11 + (int64_t) (1L << 20)) >> 21; + // s12 += carry11; + // s11 -= carry11 * ((uint64_t) 1L << 21); + $carry11 = ($s11 + (1 << 20)) >> 21; + $s12 += $carry11; + $s11 -= $carry11 << 21; + + // s0 += s12 * 666643; + // s1 += s12 * 470296; + // s2 += s12 * 654183; + // s3 -= s12 * 997805; + // s4 += s12 * 136657; + // s5 -= s12 * 683901; + // s12 = 0; + $s0 += self::mul($s12, 666643, 20); + $s1 += self::mul($s12, 470296, 19); + $s2 += self::mul($s12, 654183, 20); + $s3 -= self::mul($s12, 997805, 20); + $s4 += self::mul($s12, 136657, 18); + $s5 -= self::mul($s12, 683901, 20); + $s12 = 0; + + // carry0 = s0 >> 21; + // s1 += carry0; + // s0 -= carry0 * ((uint64_t) 1L << 21); + $carry0 = $s0 >> 21; + $s1 += $carry0; + $s0 -= $carry0 << 21; + // carry1 = s1 >> 21; + // s2 += carry1; + // s1 -= carry1 * ((uint64_t) 1L << 21); + $carry1 = $s1 >> 21; + $s2 += $carry1; + $s1 -= $carry1 << 21; + // carry2 = s2 >> 21; + // s3 += carry2; + // s2 -= carry2 * ((uint64_t) 1L << 21); + $carry2 = $s2 >> 21; + $s3 += $carry2; + $s2 -= $carry2 << 21; + // carry3 = s3 >> 21; + // s4 += carry3; + // s3 -= carry3 * ((uint64_t) 1L << 21); + $carry3 = $s3 >> 21; + $s4 += $carry3; + $s3 -= $carry3 << 21; + // carry4 = s4 >> 21; + // s5 += carry4; + // s4 -= carry4 * ((uint64_t) 1L << 21); + $carry4 = $s4 >> 21; + $s5 += $carry4; + $s4 -= $carry4 << 21; + // carry5 = s5 >> 21; + // s6 += carry5; + // s5 -= carry5 * ((uint64_t) 1L << 21); + $carry5 = $s5 >> 21; + $s6 += $carry5; + $s5 -= $carry5 << 21; + // carry6 = s6 >> 21; + // s7 += carry6; + // s6 -= carry6 * ((uint64_t) 1L << 21); + $carry6 = $s6 >> 21; + $s7 += $carry6; + $s6 -= $carry6 << 21; + // carry7 = s7 >> 21; + // s8 += carry7; + // s7 -= carry7 * ((uint64_t) 1L << 21); + $carry7 = $s7 >> 21; + $s8 += $carry7; + $s7 -= $carry7 << 21; + // carry8 = s8 >> 21; + // s9 += carry8; + // s8 -= carry8 * ((uint64_t) 1L << 21); + $carry8 = $s8 >> 21; + $s9 += $carry8; + $s8 -= $carry8 << 21; + // carry9 = s9 >> 21; + // s10 += carry9; + // s9 -= carry9 * ((uint64_t) 1L << 21); + $carry9 = $s9 >> 21; + $s10 += $carry9; + $s9 -= $carry9 << 21; + // carry10 = s10 >> 21; + // s11 += carry10; + // s10 -= carry10 * ((uint64_t) 1L << 21); + $carry10 = $s10 >> 21; + $s11 += $carry10; + $s10 -= $carry10 << 21; + // carry11 = s11 >> 21; + // s12 += carry11; + // s11 -= carry11 * ((uint64_t) 1L << 21); + $carry11 = $s11 >> 21; + $s12 += $carry11; + $s11 -= $carry11 << 21; + + // s0 += s12 * 666643; + // s1 += s12 * 470296; + // s2 += s12 * 654183; + // s3 -= s12 * 997805; + // s4 += s12 * 136657; + // s5 -= s12 * 683901; + $s0 += self::mul($s12, 666643, 20); + $s1 += self::mul($s12, 470296, 19); + $s2 += self::mul($s12, 654183, 20); + $s3 -= self::mul($s12, 997805, 20); + $s4 += self::mul($s12, 136657, 18); + $s5 -= self::mul($s12, 683901, 20); + + // carry0 = s0 >> 21; + // s1 += carry0; + // s0 -= carry0 * ((uint64_t) 1L << 21); + $carry0 = $s0 >> 21; + $s1 += $carry0; + $s0 -= $carry0 << 21; + // carry1 = s1 >> 21; + // s2 += carry1; + // s1 -= carry1 * ((uint64_t) 1L << 21); + $carry1 = $s1 >> 21; + $s2 += $carry1; + $s1 -= $carry1 << 21; + // carry2 = s2 >> 21; + // s3 += carry2; + // s2 -= carry2 * ((uint64_t) 1L << 21); + $carry2 = $s2 >> 21; + $s3 += $carry2; + $s2 -= $carry2 << 21; + // carry3 = s3 >> 21; + // s4 += carry3; + // s3 -= carry3 * ((uint64_t) 1L << 21); + $carry3 = $s3 >> 21; + $s4 += $carry3; + $s3 -= $carry3 << 21; + // carry4 = s4 >> 21; + // s5 += carry4; + // s4 -= carry4 * ((uint64_t) 1L << 21); + $carry4 = $s4 >> 21; + $s5 += $carry4; + $s4 -= $carry4 << 21; + // carry5 = s5 >> 21; + // s6 += carry5; + // s5 -= carry5 * ((uint64_t) 1L << 21); + $carry5 = $s5 >> 21; + $s6 += $carry5; + $s5 -= $carry5 << 21; + // carry6 = s6 >> 21; + // s7 += carry6; + // s6 -= carry6 * ((uint64_t) 1L << 21); + $carry6 = $s6 >> 21; + $s7 += $carry6; + $s6 -= $carry6 << 21; + // carry7 = s7 >> 21; + // s8 += carry7; + // s7 -= carry7 * ((uint64_t) 1L << 21); + $carry7 = $s7 >> 21; + $s8 += $carry7; + $s7 -= $carry7 << 21; + // carry8 = s8 >> 21; + // s9 += carry8; + // s8 -= carry8 * ((uint64_t) 1L << 21); + $carry8 = $s8 >> 21; + $s9 += $carry8; + $s8 -= $carry8 << 21; + // carry9 = s9 >> 21; + // s10 += carry9; + // s9 -= carry9 * ((uint64_t) 1L << 21); + $carry9 = $s9 >> 21; + $s10 += $carry9; + $s9 -= $carry9 << 21; + // carry10 = s10 >> 21; + // s11 += carry10; + // s10 -= carry10 * ((uint64_t) 1L << 21); + $carry10 = $s10 >> 21; + $s11 += $carry10; + $s10 -= $carry10 << 21; + + $s = array_fill(0, 32, 0); + // s[0] = s0 >> 0; + $s[0] = $s0 >> 0; + // s[1] = s0 >> 8; + $s[1] = $s0 >> 8; + // s[2] = (s0 >> 16) | (s1 * ((uint64_t) 1 << 5)); + $s[2] = ($s0 >> 16) | ($s1 << 5); + // s[3] = s1 >> 3; + $s[3] = $s1 >> 3; + // s[4] = s1 >> 11; + $s[4] = $s1 >> 11; + // s[5] = (s1 >> 19) | (s2 * ((uint64_t) 1 << 2)); + $s[5] = ($s1 >> 19) | ($s2 << 2); + // s[6] = s2 >> 6; + $s[6] = $s2 >> 6; + // s[7] = (s2 >> 14) | (s3 * ((uint64_t) 1 << 7)); + $s[7] = ($s2 >> 14) | ($s3 << 7); + // s[8] = s3 >> 1; + $s[8] = $s3 >> 1; + // s[9] = s3 >> 9; + $s[9] = $s3 >> 9; + // s[10] = (s3 >> 17) | (s4 * ((uint64_t) 1 << 4)); + $s[10] = ($s3 >> 17) | ($s4 << 4); + // s[11] = s4 >> 4; + $s[11] = $s4 >> 4; + // s[12] = s4 >> 12; + $s[12] = $s4 >> 12; + // s[13] = (s4 >> 20) | (s5 * ((uint64_t) 1 << 1)); + $s[13] = ($s4 >> 20) | ($s5 << 1); + // s[14] = s5 >> 7; + $s[14] = $s5 >> 7; + // s[15] = (s5 >> 15) | (s6 * ((uint64_t) 1 << 6)); + $s[15] = ($s5 >> 15) | ($s6 << 6); + // s[16] = s6 >> 2; + $s[16] = $s6 >> 2; + // s[17] = s6 >> 10; + $s[17] = $s6 >> 10; + // s[18] = (s6 >> 18) | (s7 * ((uint64_t) 1 << 3)); + $s[18] = ($s6 >> 18) | ($s7 << 3); + // s[19] = s7 >> 5; + $s[19] = $s7 >> 5; + // s[20] = s7 >> 13; + $s[20] = $s7 >> 13; + // s[21] = s8 >> 0; + $s[21] = $s8 >> 0; + // s[22] = s8 >> 8; + $s[22] = $s8 >> 8; + // s[23] = (s8 >> 16) | (s9 * ((uint64_t) 1 << 5)); + $s[23] = ($s8 >> 16) | ($s9 << 5); + // s[24] = s9 >> 3; + $s[24] = $s9 >> 3; + // s[25] = s9 >> 11; + $s[25] = $s9 >> 11; + // s[26] = (s9 >> 19) | (s10 * ((uint64_t) 1 << 2)); + $s[26] = ($s9 >> 19) | ($s10 << 2); + // s[27] = s10 >> 6; + $s[27] = $s10 >> 6; + // s[28] = (s10 >> 14) | (s11 * ((uint64_t) 1 << 7)); + $s[28] = ($s10 >> 14) | ($s11 << 7); + // s[29] = s11 >> 1; + $s[29] = $s11 >> 1; + // s[30] = s11 >> 9; + $s[30] = $s11 >> 9; + // s[31] = s11 >> 17; + $s[31] = $s11 >> 17; + return self::intArrayToString($s); + } + + /** + * @param string $s + * @return string + */ + public static function sc25519_sq($s) + { + return self::sc25519_mul($s, $s); + } + + /** + * @param string $s + * @param int $n + * @param string $a + * @return string + */ + public static function sc25519_sqmul($s, $n, $a) + { + for ($i = 0; $i < $n; ++$i) { + $s = self::sc25519_sq($s); + } + return self::sc25519_mul($s, $a); + } + + /** + * @param string $s + * @return string + */ + public static function sc25519_invert($s) + { + $_10 = self::sc25519_sq($s); + $_11 = self::sc25519_mul($s, $_10); + $_100 = self::sc25519_mul($s, $_11); + $_1000 = self::sc25519_sq($_100); + $_1010 = self::sc25519_mul($_10, $_1000); + $_1011 = self::sc25519_mul($s, $_1010); + $_10000 = self::sc25519_sq($_1000); + $_10110 = self::sc25519_sq($_1011); + $_100000 = self::sc25519_mul($_1010, $_10110); + $_100110 = self::sc25519_mul($_10000, $_10110); + $_1000000 = self::sc25519_sq($_100000); + $_1010000 = self::sc25519_mul($_10000, $_1000000); + $_1010011 = self::sc25519_mul($_11, $_1010000); + $_1100011 = self::sc25519_mul($_10000, $_1010011); + $_1100111 = self::sc25519_mul($_100, $_1100011); + $_1101011 = self::sc25519_mul($_100, $_1100111); + $_10010011 = self::sc25519_mul($_1000000, $_1010011); + $_10010111 = self::sc25519_mul($_100, $_10010011); + $_10111101 = self::sc25519_mul($_100110, $_10010111); + $_11010011 = self::sc25519_mul($_10110, $_10111101); + $_11100111 = self::sc25519_mul($_1010000, $_10010111); + $_11101011 = self::sc25519_mul($_100, $_11100111); + $_11110101 = self::sc25519_mul($_1010, $_11101011); + + $recip = self::sc25519_mul($_1011, $_11110101); + $recip = self::sc25519_sqmul($recip, 126, $_1010011); + $recip = self::sc25519_sqmul($recip, 9, $_10); + $recip = self::sc25519_mul($recip, $_11110101); + $recip = self::sc25519_sqmul($recip, 7, $_1100111); + $recip = self::sc25519_sqmul($recip, 9, $_11110101); + $recip = self::sc25519_sqmul($recip, 11, $_10111101); + $recip = self::sc25519_sqmul($recip, 8, $_11100111); + $recip = self::sc25519_sqmul($recip, 9, $_1101011); + $recip = self::sc25519_sqmul($recip, 6, $_1011); + $recip = self::sc25519_sqmul($recip, 14, $_10010011); + $recip = self::sc25519_sqmul($recip, 10, $_1100011); + $recip = self::sc25519_sqmul($recip, 9, $_10010111); + $recip = self::sc25519_sqmul($recip, 10, $_11110101); + $recip = self::sc25519_sqmul($recip, 8, $_11010011); + return self::sc25519_sqmul($recip, 8, $_11101011); + } + + /** + * @param string $s + * @return string + */ + public static function clamp($s) + { + $s_ = self::stringToIntArray($s); + $s_[0] &= 248; + $s_[31] |= 64; + $s_[31] &= 128; + return self::intArrayToString($s_); + } } diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/Fe.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/Fe.php index 881e3695a1045..527096565a3ad 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/Fe.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/Fe.php @@ -12,7 +12,7 @@ class ParagonIE_Sodium_Core_Curve25519_Fe implements ArrayAccess { /** - * @var array + * @var array */ protected $container = array(); @@ -24,7 +24,7 @@ class ParagonIE_Sodium_Core_Curve25519_Fe implements ArrayAccess /** * @internal You should not use this directly from another application * - * @param array $array + * @param array $array * @param bool $save_indexes * @return self */ @@ -37,6 +37,7 @@ public static function fromArray($array, $save_indexes = null) $keys = range(0, $count - 1); } $array = array_values($array); + /** @var array $keys */ $obj = new ParagonIE_Sodium_Core_Curve25519_Fe(); if ($save_indexes) { @@ -54,11 +55,12 @@ public static function fromArray($array, $save_indexes = null) /** * @internal You should not use this directly from another application * - * @param mixed $offset - * @param mixed $value + * @param int|null $offset + * @param int $value * @return void * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($value)) { @@ -74,10 +76,11 @@ public function offsetSet($offset, $value) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return bool * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); @@ -86,10 +89,11 @@ public function offsetExists($offset) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return void * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); @@ -98,15 +102,17 @@ public function offsetUnset($offset) /** * @internal You should not use this directly from another application * - * @param mixed $offset - * @return mixed|null + * @param int $offset + * @return int * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetGet($offset) { - return isset($this->container[$offset]) - ? $this->container[$offset] - : null; + if (!isset($this->container[$offset])) { + $this->container[$offset] = 0; + } + return (int) ($this->container[$offset]); } /** diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/H.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/H.php index 37ad497dc38d6..a2fbbf9f69b97 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/H.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Curve25519/H.php @@ -1464,4 +1464,86 @@ class ParagonIE_Sodium_Core_Curve25519_H extends ParagonIE_Sodium_Core_Util 326686, 11406482 ); + + /** + * 1 / sqrt(a - d) + * + * @var array + */ + protected static $invsqrtamd = array( + 6111485, + 4156064, + -27798727, + 12243468, + -25904040, + 120897, + 20826367, + -7060776, + 6093568, + -1986012 + ); + + /** + * sqrt(ad - 1) with a = -1 (mod p) + * + * @var array + */ + protected static $sqrtadm1 = array( + 24849947, + -153582, + -23613485, + 6347715, + -21072328, + -667138, + -25271143, + -15367704, + -870347, + 14525639 + ); + + /** + * 1 - d ^ 2 + * + * @var array + */ + protected static $onemsqd = array( + 6275446, + -16617371, + -22938544, + -3773710, + 11667077, + 7397348, + -27922721, + 1766195, + -24433858, + 672203 + ); + + /** + * (d - 1) ^ 2 + * @var array + */ + protected static $sqdmone = array( + 15551795, + -11097455, + -13425098, + -10125071, + -11896535, + 10178284, + -26634327, + 4729244, + -5282110, + -10116402 + ); + + + /* + * 2^252+27742317777372353535851937790883648493 + static const unsigned char L[] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, + 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 + }; + */ + const L = "\xed\xd3\xf5\x5c\x1a\x63\x12\x58\xd6\x9c\xf7\xa2\xde\xf9\xde\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"; } diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Ed25519.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Ed25519.php index 68e193b7892ad..f135b1c611914 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/Ed25519.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Ed25519.php @@ -11,6 +11,7 @@ abstract class ParagonIE_Sodium_Core_Ed25519 extends ParagonIE_Sodium_Core_Curve { const KEYPAIR_BYTES = 96; const SEED_BYTES = 32; + const SCALAR_BYTES = 32; /** * @internal You should not use this directly from another application @@ -276,7 +277,7 @@ public static function verify_detached($sig, $message, $pk) if (self::strlen($sig) < 64) { throw new SodiumException('Signature is too short'); } - if (self::check_S_lt_L(self::substr($sig, 32, 32))) { + if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) { throw new SodiumException('S < L - Invalid signature'); } if (self::small_order($sig)) { @@ -376,8 +377,8 @@ public static function check_S_lt_L($S) */ public static function small_order($R) { - /** @var array> $blacklist */ - $blacklist = array( + /** @var array> $blocklist */ + $blocklist = array( /* 0 (order 4) */ array( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -463,13 +464,13 @@ public static function small_order($R) 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ) ); - /** @var int $countBlacklist */ - $countBlacklist = count($blacklist); + /** @var int $countBlocklist */ + $countBlocklist = count($blocklist); - for ($i = 0; $i < $countBlacklist; ++$i) { + for ($i = 0; $i < $countBlocklist; ++$i) { $c = 0; for ($j = 0; $j < 32; ++$j) { - $c |= self::chrToInt($R[$j]) ^ (int) $blacklist[$i][$j]; + $c |= self::chrToInt($R[$j]) ^ (int) $blocklist[$i][$j]; } if ($c === 0) { return true; @@ -477,4 +478,74 @@ public static function small_order($R) } return false; } + + /** + * @param string $s + * @return string + * @throws SodiumException + */ + public static function scalar_complement($s) + { + $t_ = self::L . str_repeat("\x00", 32); + sodium_increment($t_); + $s_ = $s . str_repeat("\x00", 32); + ParagonIE_Sodium_Compat::sub($t_, $s_); + return self::sc_reduce($t_); + } + + /** + * @return string + * @throws SodiumException + */ + public static function scalar_random() + { + do { + $r = ParagonIE_Sodium_Compat::randombytes_buf(self::SCALAR_BYTES); + $r[self::SCALAR_BYTES - 1] = self::intToChr( + self::chrToInt($r[self::SCALAR_BYTES - 1]) & 0x1f + ); + } while ( + !self::check_S_lt_L($r) || ParagonIE_Sodium_Compat::is_zero($r) + ); + return $r; + } + + /** + * @param string $s + * @return string + * @throws SodiumException + */ + public static function scalar_negate($s) + { + $t_ = self::L . str_repeat("\x00", 32) ; + $s_ = $s . str_repeat("\x00", 32) ; + ParagonIE_Sodium_Compat::sub($t_, $s_); + return self::sc_reduce($t_); + } + + /** + * @param string $a + * @param string $b + * @return string + * @throws SodiumException + */ + public static function scalar_add($a, $b) + { + $a_ = $a . str_repeat("\x00", 32); + $b_ = $b . str_repeat("\x00", 32); + ParagonIE_Sodium_Compat::add($a_, $b_); + return self::sc_reduce($a_); + } + + /** + * @param string $x + * @param string $y + * @return string + * @throws SodiumException + */ + public static function scalar_sub($x, $y) + { + $yn = self::scalar_negate($y); + return self::scalar_add($x, $yn); + } } diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Poly1305/State.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Poly1305/State.php index 9954bad3a84b4..4b64e04078c2e 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/Poly1305/State.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Poly1305/State.php @@ -79,6 +79,29 @@ public function __construct($key = '') $this->final = false; } + /** + * Zero internal buffer upon destruction + */ + public function __destruct() + { + $this->r[0] ^= $this->r[0]; + $this->r[1] ^= $this->r[1]; + $this->r[2] ^= $this->r[2]; + $this->r[3] ^= $this->r[3]; + $this->r[4] ^= $this->r[4]; + $this->h[0] ^= $this->h[0]; + $this->h[1] ^= $this->h[1]; + $this->h[2] ^= $this->h[2]; + $this->h[3] ^= $this->h[3]; + $this->h[4] ^= $this->h[4]; + $this->pad[0] ^= $this->pad[0]; + $this->pad[1] ^= $this->pad[1]; + $this->pad[2] ^= $this->pad[2]; + $this->pad[3] ^= $this->pad[3]; + $this->leftover = 0; + $this->final = true; + } + /** * @internal You should not use this directly from another application * @@ -90,6 +113,9 @@ public function __construct($key = '') public function update($message = '') { $bytes = self::strlen($message); + if ($bytes < 1) { + return $this; + } /* handle leftover */ if ($this->leftover) { @@ -111,7 +137,7 @@ public function update($message = '') } $this->blocks( - static::intArrayToString($this->buffer), + self::intArrayToString($this->buffer), ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ); $this->leftover = 0; @@ -296,7 +322,7 @@ public function finish() $this->final = true; $this->blocks( self::substr( - static::intArrayToString($this->buffer), + self::intArrayToString($this->buffer), 0, ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE ), diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Ristretto255.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Ristretto255.php new file mode 100644 index 0000000000000..2727260d2163a --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Ristretto255.php @@ -0,0 +1,707 @@ +> 31) & 1; + } + + + /** + * @param ParagonIE_Sodium_Core_Curve25519_Fe $u + * @param ParagonIE_Sodium_Core_Curve25519_Fe $v + * @return array{x: ParagonIE_Sodium_Core_Curve25519_Fe, nonsquare: int} + * + * @throws SodiumException + */ + public static function ristretto255_sqrt_ratio_m1( + ParagonIE_Sodium_Core_Curve25519_Fe $u, + ParagonIE_Sodium_Core_Curve25519_Fe $v + ) { + $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); + + $v3 = self::fe_mul( + self::fe_sq($v), + $v + ); /* v3 = v^3 */ + $x = self::fe_mul( + self::fe_mul( + self::fe_sq($v3), + $u + ), + $v + ); /* x = uv^7 */ + + $x = self::fe_mul( + self::fe_mul( + self::fe_pow22523($x), /* x = (uv^7)^((q-5)/8) */ + $v3 + ), + $u + ); /* x = uv^3(uv^7)^((q-5)/8) */ + + $vxx = self::fe_mul( + self::fe_sq($x), + $v + ); /* vx^2 */ + + $m_root_check = self::fe_sub($vxx, $u); /* vx^2-u */ + $p_root_check = self::fe_add($vxx, $u); /* vx^2+u */ + $f_root_check = self::fe_mul($u, $sqrtm1); /* u*sqrt(-1) */ + $f_root_check = self::fe_add($vxx, $f_root_check); /* vx^2+u*sqrt(-1) */ + + $has_m_root = self::fe_iszero($m_root_check); + $has_p_root = self::fe_iszero($p_root_check); + $has_f_root = self::fe_iszero($f_root_check); + + $x_sqrtm1 = self::fe_mul($x, $sqrtm1); /* x*sqrt(-1) */ + + $x = self::fe_abs( + self::fe_cmov($x, $x_sqrtm1, $has_p_root | $has_f_root) + ); + return array( + 'x' => $x, + 'nonsquare' => $has_m_root | $has_p_root + ); + } + + /** + * @param string $s + * @return int + * @throws SodiumException + */ + public static function ristretto255_point_is_canonical($s) + { + $c = (self::chrToInt($s[31]) & 0x7f) ^ 0x7f; + for ($i = 30; $i > 0; --$i) { + $c |= self::chrToInt($s[$i]) ^ 0xff; + } + $c = ($c - 1) >> 8; + $d = (0xed - 1 - self::chrToInt($s[0])) >> 8; + $e = self::chrToInt($s[31]) >> 7; + + return 1 - ((($c & $d) | $e | self::chrToInt($s[0])) & 1); + } + + /** + * @param string $s + * @param bool $skipCanonicalCheck + * @return array{h: ParagonIE_Sodium_Core_Curve25519_Ge_P3, res: int} + * @throws SodiumException + */ + public static function ristretto255_frombytes($s, $skipCanonicalCheck = false) + { + if (!$skipCanonicalCheck) { + if (!self::ristretto255_point_is_canonical($s)) { + throw new SodiumException('S is not canonical'); + } + } + + $s_ = self::fe_frombytes($s); + $ss = self::fe_sq($s_); /* ss = s^2 */ + + $u1 = self::fe_sub(self::fe_1(), $ss); /* u1 = 1-ss */ + $u1u1 = self::fe_sq($u1); /* u1u1 = u1^2 */ + + $u2 = self::fe_add(self::fe_1(), $ss); /* u2 = 1+ss */ + $u2u2 = self::fe_sq($u2); /* u2u2 = u2^2 */ + + $v = self::fe_mul( + ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d), + $u1u1 + ); /* v = d*u1^2 */ + $v = self::fe_neg($v); /* v = -d*u1^2 */ + $v = self::fe_sub($v, $u2u2); /* v = -(d*u1^2)-u2^2 */ + $v_u2u2 = self::fe_mul($v, $u2u2); /* v_u2u2 = v*u2^2 */ + + // fe25519_1(one); + // notsquare = ristretto255_sqrt_ratio_m1(inv_sqrt, one, v_u2u2); + $one = self::fe_1(); + $result = self::ristretto255_sqrt_ratio_m1($one, $v_u2u2); + $inv_sqrt = $result['x']; + $notsquare = $result['nonsquare']; + + $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(); + + $h->X = self::fe_mul($inv_sqrt, $u2); + $h->Y = self::fe_mul(self::fe_mul($inv_sqrt, $h->X), $v); + + $h->X = self::fe_mul($h->X, $s_); + $h->X = self::fe_abs( + self::fe_add($h->X, $h->X) + ); + $h->Y = self::fe_mul($u1, $h->Y); + $h->Z = self::fe_1(); + $h->T = self::fe_mul($h->X, $h->Y); + + $res = - ((1 - $notsquare) | self::fe_isnegative($h->T) | self::fe_iszero($h->Y)); + return array('h' => $h, 'res' => $res); + } + + /** + * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h + * @return string + * @throws SodiumException + */ + public static function ristretto255_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h) + { + $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); + $invsqrtamd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$invsqrtamd); + + $u1 = self::fe_add($h->Z, $h->Y); /* u1 = Z+Y */ + $zmy = self::fe_sub($h->Z, $h->Y); /* zmy = Z-Y */ + $u1 = self::fe_mul($u1, $zmy); /* u1 = (Z+Y)*(Z-Y) */ + $u2 = self::fe_mul($h->X, $h->Y); /* u2 = X*Y */ + + $u1_u2u2 = self::fe_mul(self::fe_sq($u2), $u1); /* u1_u2u2 = u1*u2^2 */ + $one = self::fe_1(); + + // fe25519_1(one); + // (void) ristretto255_sqrt_ratio_m1(inv_sqrt, one, u1_u2u2); + $result = self::ristretto255_sqrt_ratio_m1($one, $u1_u2u2); + $inv_sqrt = $result['x']; + + $den1 = self::fe_mul($inv_sqrt, $u1); /* den1 = inv_sqrt*u1 */ + $den2 = self::fe_mul($inv_sqrt, $u2); /* den2 = inv_sqrt*u2 */ + $z_inv = self::fe_mul($h->T, self::fe_mul($den1, $den2)); /* z_inv = den1*den2*T */ + + $ix = self::fe_mul($h->X, $sqrtm1); /* ix = X*sqrt(-1) */ + $iy = self::fe_mul($h->Y, $sqrtm1); /* iy = Y*sqrt(-1) */ + $eden = self::fe_mul($den1, $invsqrtamd); + + $t_z_inv = self::fe_mul($h->T, $z_inv); /* t_z_inv = T*z_inv */ + $rotate = self::fe_isnegative($t_z_inv); + + $x_ = self::fe_copy($h->X); + $y_ = self::fe_copy($h->Y); + $den_inv = self::fe_copy($den2); + + $x_ = self::fe_cmov($x_, $iy, $rotate); + $y_ = self::fe_cmov($y_, $ix, $rotate); + $den_inv = self::fe_cmov($den_inv, $eden, $rotate); + + $x_z_inv = self::fe_mul($x_, $z_inv); + $y_ = self::fe_cneg($y_, self::fe_isnegative($x_z_inv)); + + + // fe25519_sub(s_, h->Z, y_); + // fe25519_mul(s_, den_inv, s_); + // fe25519_abs(s_, s_); + // fe25519_tobytes(s, s_); + return self::fe_tobytes( + self::fe_abs( + self::fe_mul( + $den_inv, + self::fe_sub($h->Z, $y_) + ) + ) + ); + } + + /** + * @param ParagonIE_Sodium_Core_Curve25519_Fe $t + * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3 + * + * @throws SodiumException + */ + public static function ristretto255_elligator(ParagonIE_Sodium_Core_Curve25519_Fe $t) + { + $sqrtm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1); + $onemsqd = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$onemsqd); + $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d); + $sqdmone = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqdmone); + $sqrtadm1 = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtadm1); + + $one = self::fe_1(); + $r = self::fe_mul($sqrtm1, self::fe_sq($t)); /* r = sqrt(-1)*t^2 */ + $u = self::fe_mul(self::fe_add($r, $one), $onemsqd); /* u = (r+1)*(1-d^2) */ + $c = self::fe_neg(self::fe_1()); /* c = -1 */ + $rpd = self::fe_add($r, $d); /* rpd = r+d */ + + $v = self::fe_mul( + self::fe_sub( + $c, + self::fe_mul($r, $d) + ), + $rpd + ); /* v = (c-r*d)*(r+d) */ + + $result = self::ristretto255_sqrt_ratio_m1($u, $v); + $s = $result['x']; + $wasnt_square = 1 - $result['nonsquare']; + + $s_prime = self::fe_neg( + self::fe_abs( + self::fe_mul($s, $t) + ) + ); /* s_prime = -|s*t| */ + $s = self::fe_cmov($s, $s_prime, $wasnt_square); + $c = self::fe_cmov($c, $r, $wasnt_square); + + // fe25519_sub(n, r, one); /* n = r-1 */ + // fe25519_mul(n, n, c); /* n = c*(r-1) */ + // fe25519_mul(n, n, ed25519_sqdmone); /* n = c*(r-1)*(d-1)^2 */ + // fe25519_sub(n, n, v); /* n = c*(r-1)*(d-1)^2-v */ + $n = self::fe_sub( + self::fe_mul( + self::fe_mul( + self::fe_sub($r, $one), + $c + ), + $sqdmone + ), + $v + ); /* n = c*(r-1)*(d-1)^2-v */ + + $w0 = self::fe_mul( + self::fe_add($s, $s), + $v + ); /* w0 = 2s*v */ + + $w1 = self::fe_mul($n, $sqrtadm1); /* w1 = n*sqrt(ad-1) */ + $ss = self::fe_sq($s); /* ss = s^2 */ + $w2 = self::fe_sub($one, $ss); /* w2 = 1-s^2 */ + $w3 = self::fe_add($one, $ss); /* w3 = 1+s^2 */ + + return new ParagonIE_Sodium_Core_Curve25519_Ge_P3( + self::fe_mul($w0, $w3), + self::fe_mul($w2, $w1), + self::fe_mul($w1, $w3), + self::fe_mul($w0, $w2) + ); + } + + /** + * @param string $h + * @return string + * @throws SodiumException + */ + public static function ristretto255_from_hash($h) + { + if (self::strlen($h) !== 64) { + throw new SodiumException('Hash must be 64 bytes'); + } + //fe25519_frombytes(r0, h); + //fe25519_frombytes(r1, h + 32); + $r0 = self::fe_frombytes(self::substr($h, 0, 32)); + $r1 = self::fe_frombytes(self::substr($h, 32, 32)); + + //ristretto255_elligator(&p0, r0); + //ristretto255_elligator(&p1, r1); + $p0 = self::ristretto255_elligator($r0); + $p1 = self::ristretto255_elligator($r1); + + //ge25519_p3_to_cached(&p1_cached, &p1); + //ge25519_add_cached(&p_p1p1, &p0, &p1_cached); + $p_p1p1 = self::ge_add( + $p0, + self::ge_p3_to_cached($p1) + ); + + //ge25519_p1p1_to_p3(&p, &p_p1p1); + //ristretto255_p3_tobytes(s, &p); + return self::ristretto255_p3_tobytes( + self::ge_p1p1_to_p3($p_p1p1) + ); + } + + /** + * @param string $p + * @return int + * @throws SodiumException + */ + public static function is_valid_point($p) + { + $result = self::ristretto255_frombytes($p); + if ($result['res'] !== 0) { + return 0; + } + return 1; + } + + /** + * @param string $p + * @param string $q + * @return string + * @throws SodiumException + */ + public static function ristretto255_add($p, $q) + { + $p_res = self::ristretto255_frombytes($p); + $q_res = self::ristretto255_frombytes($q); + if ($p_res['res'] !== 0 || $q_res['res'] !== 0) { + throw new SodiumException('Could not add points'); + } + $p_p3 = $p_res['h']; + $q_p3 = $q_res['h']; + $q_cached = self::ge_p3_to_cached($q_p3); + $r_p1p1 = self::ge_add($p_p3, $q_cached); + $r_p3 = self::ge_p1p1_to_p3($r_p1p1); + return self::ristretto255_p3_tobytes($r_p3); + } + + /** + * @param string $p + * @param string $q + * @return string + * @throws SodiumException + */ + public static function ristretto255_sub($p, $q) + { + $p_res = self::ristretto255_frombytes($p); + $q_res = self::ristretto255_frombytes($q); + if ($p_res['res'] !== 0 || $q_res['res'] !== 0) { + throw new SodiumException('Could not add points'); + } + $p_p3 = $p_res['h']; + $q_p3 = $q_res['h']; + $q_cached = self::ge_p3_to_cached($q_p3); + $r_p1p1 = self::ge_sub($p_p3, $q_cached); + $r_p3 = self::ge_p1p1_to_p3($r_p1p1); + return self::ristretto255_p3_tobytes($r_p3); + } + + + /** + * @param int $hLen + * @param ?string $ctx + * @param string $msg + * @return string + * @throws SodiumException + * @psalm-suppress PossiblyInvalidArgument hash API + */ + protected static function h2c_string_to_hash_sha256($hLen, $ctx, $msg) + { + $h = array_fill(0, $hLen, 0); + $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0; + if ($hLen > 0xff) { + throw new SodiumException('Hash must be less than 256 bytes'); + } + + if ($ctx_len > 0xff) { + $st = hash_init('sha256'); + self::hash_update($st, "H2C-OVERSIZE-DST-"); + self::hash_update($st, $ctx); + $ctx = hash_final($st, true); + $ctx_len = 32; + } + $t = array(0, $hLen, 0); + $ux = str_repeat("\0", 64); + $st = hash_init('sha256'); + self::hash_update($st, $ux); + self::hash_update($st, $msg); + self::hash_update($st, self::intArrayToString($t)); + self::hash_update($st, $ctx); + self::hash_update($st, self::intToChr($ctx_len)); + $u0 = hash_final($st, true); + + for ($i = 0; $i < $hLen; $i += 64) { + $ux = self::xorStrings($ux, $u0); + ++$t[2]; + $st = hash_init('sha256'); + self::hash_update($st, $ux); + self::hash_update($st, self::intToChr($t[2])); + self::hash_update($st, $ctx); + self::hash_update($st, self::intToChr($ctx_len)); + $ux = hash_final($st, true); + $amount = min($hLen - $i, 64); + for ($j = 0; $j < $amount; ++$j) { + $h[$i + $j] = self::chrToInt($ux[$i]); + } + } + return self::intArrayToString(array_slice($h, 0, $hLen)); + } + + /** + * @param int $hLen + * @param ?string $ctx + * @param string $msg + * @return string + * @throws SodiumException + * @psalm-suppress PossiblyInvalidArgument hash API + */ + protected static function h2c_string_to_hash_sha512($hLen, $ctx, $msg) + { + $h = array_fill(0, $hLen, 0); + $ctx_len = !is_null($ctx) ? self::strlen($ctx) : 0; + if ($hLen > 0xff) { + throw new SodiumException('Hash must be less than 256 bytes'); + } + + if ($ctx_len > 0xff) { + $st = hash_init('sha256'); + self::hash_update($st, "H2C-OVERSIZE-DST-"); + self::hash_update($st, $ctx); + $ctx = hash_final($st, true); + $ctx_len = 32; + } + $t = array(0, $hLen, 0); + $ux = str_repeat("\0", 128); + $st = hash_init('sha512'); + self::hash_update($st, $ux); + self::hash_update($st, $msg); + self::hash_update($st, self::intArrayToString($t)); + self::hash_update($st, $ctx); + self::hash_update($st, self::intToChr($ctx_len)); + $u0 = hash_final($st, true); + + for ($i = 0; $i < $hLen; $i += 128) { + $ux = self::xorStrings($ux, $u0); + ++$t[2]; + $st = hash_init('sha512'); + self::hash_update($st, $ux); + self::hash_update($st, self::intToChr($t[2])); + self::hash_update($st, $ctx); + self::hash_update($st, self::intToChr($ctx_len)); + $ux = hash_final($st, true); + $amount = min($hLen - $i, 128); + for ($j = 0; $j < $amount; ++$j) { + $h[$i + $j] = self::chrToInt($ux[$i]); + } + } + return self::intArrayToString(array_slice($h, 0, $hLen)); + } + + /** + * @param int $hLen + * @param ?string $ctx + * @param string $msg + * @param int $hash_alg + * @return string + * @throws SodiumException + */ + public static function h2c_string_to_hash($hLen, $ctx, $msg, $hash_alg) + { + switch ($hash_alg) { + case self::CORE_H2C_SHA256: + return self::h2c_string_to_hash_sha256($hLen, $ctx, $msg); + case self::CORE_H2C_SHA512: + return self::h2c_string_to_hash_sha512($hLen, $ctx, $msg); + default: + throw new SodiumException('Invalid H2C hash algorithm'); + } + } + + /** + * @param ?string $ctx + * @param string $msg + * @param int $hash_alg + * @return string + * @throws SodiumException + */ + protected static function _string_to_element($ctx, $msg, $hash_alg) + { + return self::ristretto255_from_hash( + self::h2c_string_to_hash(self::crypto_core_ristretto255_HASHBYTES, $ctx, $msg, $hash_alg) + ); + } + + /** + * @return string + * @throws SodiumException + * @throws Exception + */ + public static function ristretto255_random() + { + return self::ristretto255_from_hash( + ParagonIE_Sodium_Compat::randombytes_buf(self::crypto_core_ristretto255_HASHBYTES) + ); + } + + /** + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_random() + { + return self::scalar_random(); + } + + /** + * @param string $s + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_complement($s) + { + return self::scalar_complement($s); + } + + + /** + * @param string $s + * @return string + */ + public static function ristretto255_scalar_invert($s) + { + return self::sc25519_invert($s); + } + + /** + * @param string $s + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_negate($s) + { + return self::scalar_negate($s); + } + + /** + * @param string $x + * @param string $y + * @return string + */ + public static function ristretto255_scalar_add($x, $y) + { + return self::scalar_add($x, $y); + } + + /** + * @param string $x + * @param string $y + * @return string + */ + public static function ristretto255_scalar_sub($x, $y) + { + return self::scalar_sub($x, $y); + } + + /** + * @param string $x + * @param string $y + * @return string + */ + public static function ristretto255_scalar_mul($x, $y) + { + return self::sc25519_mul($x, $y); + } + + /** + * @param string $ctx + * @param string $msg + * @param int $hash_alg + * @return string + * @throws SodiumException + */ + public static function ristretto255_scalar_from_string($ctx, $msg, $hash_alg) + { + $h = array_fill(0, 64, 0); + $h_be = self::stringToIntArray( + self::h2c_string_to_hash( + self::HASH_SC_L, $ctx, $msg, $hash_alg + ) + ); + + for ($i = 0; $i < self::HASH_SC_L; ++$i) { + $h[$i] = $h_be[self::HASH_SC_L - 1 - $i]; + } + return self::ristretto255_scalar_reduce(self::intArrayToString($h)); + } + + /** + * @param string $s + * @return string + */ + public static function ristretto255_scalar_reduce($s) + { + return self::sc_reduce($s); + } + + /** + * @param string $n + * @param string $p + * @return string + * @throws SodiumException + */ + public static function scalarmult_ristretto255($n, $p) + { + if (self::strlen($n) !== 32) { + throw new SodiumException('Scalar must be 32 bytes, ' . self::strlen($p) . ' given.'); + } + if (self::strlen($p) !== 32) { + throw new SodiumException('Point must be 32 bytes, ' . self::strlen($p) . ' given.'); + } + $result = self::ristretto255_frombytes($p); + if ($result['res'] !== 0) { + throw new SodiumException('Could not multiply points'); + } + $P = $result['h']; + + $t = self::stringToIntArray($n); + $t[31] &= 0x7f; + $Q = self::ge_scalarmult(self::intArrayToString($t), $P); + $q = self::ristretto255_p3_tobytes($Q); + if (ParagonIE_Sodium_Compat::is_zero($q)) { + throw new SodiumException('An unknown error has occurred'); + } + return $q; + } + + /** + * @param string $n + * @return string + * @throws SodiumException + */ + public static function scalarmult_ristretto255_base($n) + { + $t = self::stringToIntArray($n); + $t[31] &= 0x7f; + $Q = self::ge_scalarmult_base(self::intArrayToString($t)); + $q = self::ristretto255_p3_tobytes($Q); + if (ParagonIE_Sodium_Compat::is_zero($q)) { + throw new SodiumException('An unknown error has occurred'); + } + return $q; + } +} diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/SecretStream/State.php b/libraries/vendor/paragonie/sodium_compat/src/Core/SecretStream/State.php new file mode 100644 index 0000000000000..2412f6549e811 --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/SecretStream/State.php @@ -0,0 +1,163 @@ +key = $key; + $this->counter = 1; + if (is_null($nonce)) { + $nonce = str_repeat("\0", 12); + } + $this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);; + $this->_pad = str_repeat("\0", 4); + } + + /** + * @return self + */ + public function counterReset() + { + $this->counter = 1; + $this->_pad = str_repeat("\0", 4); + return $this; + } + + /** + * @return string + */ + public function getKey() + { + return $this->key; + } + + /** + * @return string + */ + public function getCounter() + { + return ParagonIE_Sodium_Core_Util::store32_le($this->counter); + } + + /** + * @return string + */ + public function getNonce() + { + if (!is_string($this->nonce)) { + $this->nonce = str_repeat("\0", 12); + } + if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) { + $this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT); + } + return $this->nonce; + } + + /** + * @return string + */ + public function getCombinedNonce() + { + return $this->getCounter() . + ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8); + } + + /** + * @return self + */ + public function incrementCounter() + { + ++$this->counter; + return $this; + } + + /** + * @return bool + */ + public function needsRekey() + { + return ($this->counter & 0xffff) === 0; + } + + /** + * @param string $newKeyAndNonce + * @return self + */ + public function rekey($newKeyAndNonce) + { + $this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 0, 32); + $this->nonce = str_pad( + ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32), + 12, + "\0", + STR_PAD_RIGHT + ); + return $this; + } + + /** + * @param string $str + * @return self + */ + public function xorNonce($str) + { + $this->nonce = ParagonIE_Sodium_Core_Util::xorStrings( + $this->getNonce(), + str_pad( + ParagonIE_Sodium_Core_Util::substr($str, 0, 8), + 12, + "\0", + STR_PAD_RIGHT + ) + ); + return $this; + } + + /** + * @param string $string + * @return self + */ + public static function fromString($string) + { + $state = new ParagonIE_Sodium_Core_SecretStream_State( + ParagonIE_Sodium_Core_Util::substr($string, 0, 32) + ); + $state->counter = ParagonIE_Sodium_Core_Util::load_4( + ParagonIE_Sodium_Core_Util::substr($string, 32, 4) + ); + $state->nonce = ParagonIE_Sodium_Core_Util::substr($string, 36, 12); + $state->_pad = ParagonIE_Sodium_Core_Util::substr($string, 48, 8); + return $state; + } + + /** + * @return string + */ + public function toString() + { + return $this->key . + $this->getCounter() . + $this->nonce . + $this->_pad; + } +} diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/SipHash.php b/libraries/vendor/paragonie/sodium_compat/src/Core/SipHash.php index 7d3981620efaa..90c3b696122df 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/SipHash.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/SipHash.php @@ -16,6 +16,7 @@ class ParagonIE_Sodium_Core_SipHash extends ParagonIE_Sodium_Core_Util * * @param int[] $v * @return int[] + * */ public static function sipRound(array $v) { @@ -26,27 +27,27 @@ public static function sipRound(array $v) ); # v1=ROTL(v1,13); - list($v[2], $v[3]) = self::rotl_64($v[2], $v[3], 13); + list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 13); # v1 ^= v0; - $v[2] ^= $v[0]; - $v[3] ^= $v[1]; + $v[2] = (int) $v[2] ^ (int) $v[0]; + $v[3] = (int) $v[3] ^ (int) $v[1]; # v0=ROTL(v0,32); list($v[0], $v[1]) = self::rotl_64((int) $v[0], (int) $v[1], 32); # v2 += v3; list($v[4], $v[5]) = self::add( - array($v[4], $v[5]), - array($v[6], $v[7]) + array((int) $v[4], (int) $v[5]), + array((int) $v[6], (int) $v[7]) ); # v3=ROTL(v3,16); - list($v[6], $v[7]) = self::rotl_64($v[6], $v[7], 16); + list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 16); # v3 ^= v2; - $v[6] ^= $v[4]; - $v[7] ^= $v[5]; + $v[6] = (int) $v[6] ^ (int) $v[4]; + $v[7] = (int) $v[7] ^ (int) $v[5]; # v0 += v3; list($v[0], $v[1]) = self::add( @@ -58,8 +59,8 @@ public static function sipRound(array $v) list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 21); # v3 ^= v0; - $v[6] ^= $v[0]; - $v[7] ^= $v[1]; + $v[6] = (int) $v[6] ^ (int) $v[0]; + $v[7] = (int) $v[7] ^ (int) $v[1]; # v2 += v1; list($v[4], $v[5]) = self::add( @@ -71,8 +72,8 @@ public static function sipRound(array $v) list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 17); # v1 ^= v2;; - $v[2] ^= $v[4]; - $v[3] ^= $v[5]; + $v[2] = (int) $v[2] ^ (int) $v[4]; + $v[3] = (int) $v[3] ^ (int) $v[5]; # v2=ROTL(v2,32) list($v[4], $v[5]) = self::rotl_64((int) $v[4], (int) $v[5], 32); diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/Util.php b/libraries/vendor/paragonie/sodium_compat/src/Core/Util.php index 5caa3ffa32657..bde9df1106427 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/Util.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/Util.php @@ -286,6 +286,22 @@ public static function hashEquals($left, $right) return $left === $right; } + /** + * Catch hash_update() failures and throw instead of silently proceeding + * + * @param HashContext|resource &$hs + * @param string $data + * @return void + * @throws SodiumException + * @psalm-suppress PossiblyInvalidArgument + */ + protected static function hash_update(&$hs, $data) + { + if (!hash_update($hs, $data)) { + throw new SodiumException('hash_update() failed'); + } + } + /** * Convert a hexadecimal string into a binary string without cache-timing * leaks @@ -570,6 +586,7 @@ public static function mul($a, $b, $size = 0) $a <<= 1; $b >>= 1; } + $c = (int) @($c & -1); /** * If $b was negative, we then apply the same value to $c here. @@ -817,7 +834,7 @@ public static function substr($str, $start = 0, $length = null) } else { $sub = (string) substr($str, $start, $length); } - if (isset($sub)) { + if ($sub !== '') { return $sub; } return ''; @@ -903,6 +920,9 @@ public static function xorStrings($a, $b) * * @internal You should not use this directly from another application * + * Note: MB_OVERLOAD_STRING === 2, but we don't reference the constant + * (for nuisance-free PHP 8 support) + * * @return bool */ protected static function isMbStringOverride() @@ -910,9 +930,15 @@ protected static function isMbStringOverride() static $mbstring = null; if ($mbstring === null) { + if (!defined('MB_OVERLOAD_STRING')) { + $mbstring = false; + return $mbstring; + } $mbstring = extension_loaded('mbstring') + && defined('MB_OVERLOAD_STRING') && - ((int) (ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING); + ((int) (ini_get('mbstring.func_overload')) & 2); + // MB_OVERLOAD_STRING === 2 } /** @var bool $mbstring */ diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core/XChaCha20.php b/libraries/vendor/paragonie/sodium_compat/src/Core/XChaCha20.php index a9b203ce57765..39e717b79a795 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core/XChaCha20.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core/XChaCha20.php @@ -36,6 +36,33 @@ public static function stream($len = 64, $nonce = '', $key = '') ); } + /** + * @internal You should not use this directly from another application + * + * @param int $len + * @param string $nonce + * @param string $key + * @return string + * @throws SodiumException + * @throws TypeError + */ + public static function ietfStream($len = 64, $nonce = '', $key = '') + { + if (self::strlen($nonce) !== 24) { + throw new SodiumException('Nonce must be 24 bytes long'); + } + return self::encryptBytes( + new ParagonIE_Sodium_Core_ChaCha20_IetfCtx( + self::hChaCha20( + self::substr($nonce, 0, 16), + $key + ), + "\x00\x00\x00\x00" . self::substr($nonce, 16, 8) + ), + str_repeat("\x00", $len) + ); + } + /** * @internal You should not use this directly from another application * @@ -61,4 +88,30 @@ public static function streamXorIc($message, $nonce = '', $key = '', $ic = '') $message ); } + + /** + * @internal You should not use this directly from another application + * + * @param string $message + * @param string $nonce + * @param string $key + * @param string $ic + * @return string + * @throws SodiumException + * @throws TypeError + */ + public static function ietfStreamXorIc($message, $nonce = '', $key = '', $ic = '') + { + if (self::strlen($nonce) !== 24) { + throw new SodiumException('Nonce must be 24 bytes long'); + } + return self::encryptBytes( + new ParagonIE_Sodium_Core_ChaCha20_IetfCtx( + self::hChaCha20(self::substr($nonce, 0, 16), $key), + "\x00\x00\x00\x00" . self::substr($nonce, 16, 8), + $ic + ), + $message + ); + } } diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/BLAKE2b.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/BLAKE2b.php index ee7f415d3a457..0fed21a25f020 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/BLAKE2b.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/BLAKE2b.php @@ -223,12 +223,13 @@ public static function pseudoConstructor() */ protected static function context() { - $ctx = new SplFixedArray(5); + $ctx = new SplFixedArray(6); $ctx[0] = new SplFixedArray(8); // h $ctx[1] = new SplFixedArray(2); // t $ctx[2] = new SplFixedArray(2); // f $ctx[3] = new SplFixedArray(256); // buf $ctx[4] = 0; // buflen + $ctx[5] = 0; // last_node (uint8_t) for ($i = 8; $i--;) { $ctx[0][$i] = self::$iv[$i]; @@ -482,6 +483,8 @@ public static function finish(SplFixedArray $ctx, SplFixedArray $out) * * @param SplFixedArray|null $key * @param int $outlen + * @param SplFixedArray|null $salt + * @param SplFixedArray|null $personal * @return SplFixedArray * @throws SodiumException * @throws TypeError @@ -491,8 +494,12 @@ public static function finish(SplFixedArray $ctx, SplFixedArray $out) * @psalm-suppress MixedArrayAssignment * @psalm-suppress MixedMethodCall */ - public static function init($key = null, $outlen = 64) - { + public static function init( + $key = null, + $outlen = 64, + $salt = null, + $personal = null + ) { self::pseudoConstructor(); $klen = 0; @@ -510,6 +517,7 @@ public static function init($key = null, $outlen = 64) $ctx = self::context(); $p = new SplFixedArray(64); + // Zero our param buffer... for ($i = 64; --$i;) { $p[$i] = 0; } @@ -519,11 +527,34 @@ public static function init($key = null, $outlen = 64) $p[2] = 1; // fanout $p[3] = 1; // depth + if ($salt instanceof SplFixedArray) { + // salt: [32] through [47] + for ($i = 0; $i < 16; ++$i) { + $p[32 + $i] = (int) $salt[$i]; + } + } + if ($personal instanceof SplFixedArray) { + // personal: [48] through [63] + for ($i = 0; $i < 16; ++$i) { + $p[48 + $i] = (int) $personal[$i]; + } + } + $ctx[0][0] = self::xor64( $ctx[0][0], self::load64($p, 0) ); + if ($salt instanceof SplFixedArray || $personal instanceof SplFixedArray) { + // We need to do what blake2b_init_param() does: + for ($i = 1; $i < 8; ++$i) { + $ctx[0][$i] = self::xor64( + $ctx[0][$i], + self::load64($p, $i << 3) + ); + } + } + if ($klen > 0 && $key instanceof SplFixedArray) { $block = new SplFixedArray(128); for ($i = 128; $i--;) { @@ -533,6 +564,7 @@ public static function init($key = null, $outlen = 64) $block[$i] = $key[$i]; } self::update($ctx, $block, 128); + $ctx[4] = 128; } return $ctx; @@ -545,6 +577,7 @@ public static function init($key = null, $outlen = 64) * * @param string $str * @return SplFixedArray + * @psalm-suppress MixedArgumentTypeCoercion */ public static function stringToSplFixedArray($str = '') { @@ -574,7 +607,7 @@ public static function SplFixedArrayToString(SplFixedArray $a) /** * @internal You should not use this directly from another application * - * @param SplFixedArray[SplFixedArray] $ctx + * @param SplFixedArray $ctx * @return string * @throws TypeError * @psalm-suppress MixedArgument @@ -595,7 +628,7 @@ public static function contextToString(SplFixedArray $ctx) } /** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */ $ctxAi = $ctxA[$i]; - $str .= $ctxAi->toString(); + $str .= $ctxAi->toReverseString(); } # uint64_t t[2]; @@ -608,8 +641,8 @@ public static function contextToString(SplFixedArray $ctx) /** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */ $ctxA2 = $ctxA[1]; - $str .= $ctxA1->toString(); - $str .= $ctxA2->toString(); + $str .= $ctxA1->toReverseString(); + $str .= $ctxA2->toReverseString(); } # uint8_t buf[2 * 128]; @@ -624,13 +657,16 @@ public static function contextToString(SplFixedArray $ctx) self::intToChr(($ctx4 >> 8) & 0xff), self::intToChr(($ctx4 >> 16) & 0xff), self::intToChr(($ctx4 >> 24) & 0xff), + "\x00\x00\x00\x00" + /* self::intToChr(($ctx4 >> 32) & 0xff), self::intToChr(($ctx4 >> 40) & 0xff), self::intToChr(($ctx4 >> 48) & 0xff), self::intToChr(($ctx4 >> 56) & 0xff) + */ )); # uint8_t last_node; - return $str . "\x00"; + return $str . self::intToChr($ctx[5]) . str_repeat("\x00", 23); } /** @@ -652,7 +688,7 @@ public static function stringToContext($string) # uint64_t h[8]; for ($i = 0; $i < 8; ++$i) { - $ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromString( + $ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($string, (($i << 3) + 0), 8) ); } @@ -660,10 +696,10 @@ public static function stringToContext($string) # uint64_t t[2]; # uint64_t f[2]; for ($i = 1; $i < 3; ++$i) { - $ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromString( + $ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($string, 72 + (($i - 1) << 4), 8) ); - $ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromString( + $ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromReverseString( self::substr($string, 64 + (($i - 1) << 4), 8) ); } @@ -671,7 +707,6 @@ public static function stringToContext($string) # uint8_t buf[2 * 128]; $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96, 256)); - # uint8_t buf[2 * 128]; $int = 0; for ($i = 0; $i < 8; ++$i) { diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/ChaCha20/Ctx.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/ChaCha20/Ctx.php index 996acf23e5cfc..37b058f2503a9 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/ChaCha20/Ctx.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/ChaCha20/Ctx.php @@ -70,6 +70,7 @@ public function __construct($key = '', $iv = '', $counter = '') * @param int|ParagonIE_Sodium_Core32_Int32 $value * @return void */ + #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!is_int($offset)) { @@ -89,10 +90,11 @@ public function offsetSet($offset, $value) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return bool * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); @@ -101,10 +103,11 @@ public function offsetExists($offset) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return void * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); @@ -113,10 +116,11 @@ public function offsetUnset($offset) /** * @internal You should not use this directly from another application * - * @param mixed $offset + * @param int $offset * @return mixed|null * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetGet($offset) { return isset($this->container[$offset]) diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Fe.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Fe.php index 5fe10f72d27b8..27537a6f1ac71 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Fe.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Fe.php @@ -104,6 +104,7 @@ public static function fromIntArray($array, $save_indexes = null) * @throws SodiumException * @throws TypeError */ + #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if (!($value instanceof ParagonIE_Sodium_Core32_Int32)) { @@ -124,6 +125,7 @@ public function offsetSet($offset, $value) * @return bool * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->container[$offset]); @@ -136,6 +138,7 @@ public function offsetExists($offset) * @return void * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->container[$offset]); @@ -148,6 +151,7 @@ public function offsetUnset($offset) * @return ParagonIE_Sodium_Core32_Int32 * @psalm-suppress MixedArrayOffset */ + #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->container[$offset])) { diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/Ed25519.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/Ed25519.php index 9bb31abdf259b..3cb64225474c1 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/Ed25519.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/Ed25519.php @@ -207,6 +207,7 @@ public static function sign_open($message, $pk) * @return string * @throws SodiumException * @throws TypeError + * @psalm-suppress PossiblyInvalidArgument */ public static function sign_detached($message, $sk) { @@ -224,8 +225,8 @@ public static function sign_detached($message, $sk) # crypto_hash_sha512_update(&hs, m, mlen); # crypto_hash_sha512_final(&hs, nonce); $hs = hash_init('sha512'); - hash_update($hs, self::substr($az, 32, 32)); - hash_update($hs, $message); + self::hash_update($hs, self::substr($az, 32, 32)); + self::hash_update($hs, $message); $nonceHash = hash_final($hs, true); # memmove(sig + 32, sk + 32, 32); @@ -244,9 +245,9 @@ public static function sign_detached($message, $sk) # crypto_hash_sha512_update(&hs, m, mlen); # crypto_hash_sha512_final(&hs, hram); $hs = hash_init('sha512'); - hash_update($hs, self::substr($sig, 0, 32)); - hash_update($hs, self::substr($pk, 0, 32)); - hash_update($hs, $message); + self::hash_update($hs, self::substr($sig, 0, 32)); + self::hash_update($hs, self::substr($pk, 0, 32)); + self::hash_update($hs, $message); $hramHash = hash_final($hs, true); # sc_reduce(hram); @@ -278,7 +279,7 @@ public static function verify_detached($sig, $message, $pk) if (self::strlen($sig) < 64) { throw new SodiumException('Signature is too short'); } - if (self::check_S_lt_L(self::substr($sig, 32, 32))) { + if ((self::chrToInt($sig[63]) & 240) && self::check_S_lt_L(self::substr($sig, 32, 32))) { throw new SodiumException('S < L - Invalid signature'); } if (self::small_order($sig)) { @@ -378,7 +379,7 @@ public static function check_S_lt_L($S) */ public static function small_order($R) { - static $blacklist = array( + static $blocklist = array( /* 0 (order 4) */ array( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -464,13 +465,13 @@ public static function small_order($R) 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ) ); - /** @var array> $blacklist */ - $countBlacklist = count($blacklist); + /** @var array> $blocklist */ + $countBlocklist = count($blocklist); - for ($i = 0; $i < $countBlacklist; ++$i) { + for ($i = 0; $i < $countBlocklist; ++$i) { $c = 0; for ($j = 0; $j < 32; ++$j) { - $c |= self::chrToInt($R[$j]) ^ $blacklist[$i][$j]; + $c |= self::chrToInt($R[$j]) ^ $blocklist[$i][$j]; } if ($c === 0) { return true; diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/Int32.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/Int32.php index 68c4b55f44e87..c3a17900a5929 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/Int32.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/Int32.php @@ -150,6 +150,136 @@ public function mask($m = 0) ); } + /** + * @param array $a + * @param array $b + * @param int $baseLog2 + * @return array + */ + public function multiplyLong(array $a, array $b, $baseLog2 = 16) + { + $a_l = count($a); + $b_l = count($b); + /** @var array $r */ + $r = array_fill(0, $a_l + $b_l + 1, 0); + $base = 1 << $baseLog2; + for ($i = 0; $i < $a_l; ++$i) { + $a_i = $a[$i]; + for ($j = 0; $j < $a_l; ++$j) { + $b_j = $b[$j]; + $product = ($a_i * $b_j) + $r[$i + $j]; + $carry = ($product >> $baseLog2 & 0xffff); + $r[$i + $j] = ($product - (int) ($carry * $base)) & 0xffff; + $r[$i + $j + 1] += $carry; + } + } + return array_slice($r, 0, 5); + } + + /** + * @param int $int + * @return ParagonIE_Sodium_Core32_Int32 + */ + public function mulIntFast($int) + { + // Handle negative numbers + $aNeg = ($this->limbs[0] >> 15) & 1; + $bNeg = ($int >> 31) & 1; + $a = array_reverse($this->limbs); + $b = array( + $int & 0xffff, + ($int >> 16) & 0xffff + ); + if ($aNeg) { + for ($i = 0; $i < 2; ++$i) { + $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; + } + ++$a[0]; + } + if ($bNeg) { + for ($i = 0; $i < 2; ++$i) { + $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; + } + ++$b[0]; + } + // Multiply + $res = $this->multiplyLong($a, $b); + + // Re-apply negation to results + if ($aNeg !== $bNeg) { + for ($i = 0; $i < 2; ++$i) { + $res[$i] = (0xffff ^ $res[$i]) & 0xffff; + } + // Handle integer overflow + $c = 1; + for ($i = 0; $i < 2; ++$i) { + $res[$i] += $c; + $c = $res[$i] >> 16; + $res[$i] &= 0xffff; + } + } + + // Return our values + $return = new ParagonIE_Sodium_Core32_Int32(); + $return->limbs = array( + $res[1] & 0xffff, + $res[0] & 0xffff + ); + if (count($res) > 2) { + $return->overflow = $res[2] & 0xffff; + } + $return->unsignedInt = $this->unsignedInt; + return $return; + } + + /** + * @param ParagonIE_Sodium_Core32_Int32 $right + * @return ParagonIE_Sodium_Core32_Int32 + */ + public function mulInt32Fast(ParagonIE_Sodium_Core32_Int32 $right) + { + $aNeg = ($this->limbs[0] >> 15) & 1; + $bNeg = ($right->limbs[0] >> 15) & 1; + + $a = array_reverse($this->limbs); + $b = array_reverse($right->limbs); + if ($aNeg) { + for ($i = 0; $i < 2; ++$i) { + $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; + } + ++$a[0]; + } + if ($bNeg) { + for ($i = 0; $i < 2; ++$i) { + $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; + } + ++$b[0]; + } + $res = $this->multiplyLong($a, $b); + if ($aNeg !== $bNeg) { + if ($aNeg !== $bNeg) { + for ($i = 0; $i < 2; ++$i) { + $res[$i] = ($res[$i] ^ 0xffff) & 0xffff; + } + $c = 1; + for ($i = 0; $i < 2; ++$i) { + $res[$i] += $c; + $c = $res[$i] >> 16; + $res[$i] &= 0xffff; + } + } + } + $return = new ParagonIE_Sodium_Core32_Int32(); + $return->limbs = array( + $res[1] & 0xffff, + $res[0] & 0xffff + ); + if (count($res) > 2) { + $return->overflow = $res[2]; + } + return $return; + } + /** * @param int $int * @param int $size @@ -161,6 +291,9 @@ public function mulInt($int = 0, $size = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); + if (ParagonIE_Sodium_Compat::$fastMult) { + return $this->mulIntFast((int) $int); + } /** @var int $int */ $int = (int) $int; /** @var int $size */ @@ -218,6 +351,9 @@ public function mulInt($int = 0, $size = 0) public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); + if (ParagonIE_Sodium_Compat::$fastMult) { + return $this->mulInt32Fast($int); + } if (!$size) { $size = 31; } @@ -491,7 +627,7 @@ public function shiftRight($c = 0) /** @var int $c */ return $this->shiftLeft(-$c); } else { - if (is_null($c)) { + if (!is_int($c)) { throw new TypeError(); } /** @var int $c */ diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/Int64.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/Int64.php index cc7b69f86dc08..dd06a3fbeb39a 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/Int64.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/Int64.php @@ -205,6 +205,9 @@ public function mask64($hi = 0, $lo = 0) */ public function mulInt($int = 0, $size = 0) { + if (ParagonIE_Sodium_Compat::$fastMult) { + return $this->mulIntFast($int); + } ParagonIE_Sodium_Core32_Util::declareScalarType($int, 'int', 1); ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); /** @var int $int */ @@ -268,11 +271,11 @@ public function mulInt($int = 0, $size = 0) $a3 &= 0xffff; $int >>= 1; - $return->limbs[0] = $ret0; - $return->limbs[1] = $ret1; - $return->limbs[2] = $ret2; - $return->limbs[3] = $ret3; } + $return->limbs[0] = $ret0; + $return->limbs[1] = $ret1; + $return->limbs[2] = $ret2; + $return->limbs[3] = $ret3; return $return; } @@ -317,6 +320,142 @@ public static function ctSelect( ); } + /** + * @param array $a + * @param array $b + * @param int $baseLog2 + * @return array + */ + public function multiplyLong(array $a, array $b, $baseLog2 = 16) + { + $a_l = count($a); + $b_l = count($b); + /** @var array $r */ + $r = array_fill(0, $a_l + $b_l + 1, 0); + $base = 1 << $baseLog2; + for ($i = 0; $i < $a_l; ++$i) { + $a_i = $a[$i]; + for ($j = 0; $j < $a_l; ++$j) { + $b_j = $b[$j]; + $product = ($a_i * $b_j) + $r[$i + $j]; + $carry = ($product >> $baseLog2 & 0xffff); + $r[$i + $j] = ($product - (int) ($carry * $base)) & 0xffff; + $r[$i + $j + 1] += $carry; + } + } + return array_slice($r, 0, 5); + } + + /** + * @param int $int + * @return ParagonIE_Sodium_Core32_Int64 + */ + public function mulIntFast($int) + { + // Handle negative numbers + $aNeg = ($this->limbs[0] >> 15) & 1; + $bNeg = ($int >> 31) & 1; + $a = array_reverse($this->limbs); + $b = array( + $int & 0xffff, + ($int >> 16) & 0xffff, + -$bNeg & 0xffff, + -$bNeg & 0xffff + ); + if ($aNeg) { + for ($i = 0; $i < 4; ++$i) { + $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; + } + ++$a[0]; + } + if ($bNeg) { + for ($i = 0; $i < 4; ++$i) { + $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; + } + ++$b[0]; + } + // Multiply + $res = $this->multiplyLong($a, $b); + + // Re-apply negation to results + if ($aNeg !== $bNeg) { + for ($i = 0; $i < 4; ++$i) { + $res[$i] = (0xffff ^ $res[$i]) & 0xffff; + } + // Handle integer overflow + $c = 1; + for ($i = 0; $i < 4; ++$i) { + $res[$i] += $c; + $c = $res[$i] >> 16; + $res[$i] &= 0xffff; + } + } + + // Return our values + $return = new ParagonIE_Sodium_Core32_Int64(); + $return->limbs = array( + $res[3] & 0xffff, + $res[2] & 0xffff, + $res[1] & 0xffff, + $res[0] & 0xffff + ); + if (count($res) > 4) { + $return->overflow = $res[4] & 0xffff; + } + $return->unsignedInt = $this->unsignedInt; + return $return; + } + + /** + * @param ParagonIE_Sodium_Core32_Int64 $right + * @return ParagonIE_Sodium_Core32_Int64 + */ + public function mulInt64Fast(ParagonIE_Sodium_Core32_Int64 $right) + { + $aNeg = ($this->limbs[0] >> 15) & 1; + $bNeg = ($right->limbs[0] >> 15) & 1; + + $a = array_reverse($this->limbs); + $b = array_reverse($right->limbs); + if ($aNeg) { + for ($i = 0; $i < 4; ++$i) { + $a[$i] = ($a[$i] ^ 0xffff) & 0xffff; + } + ++$a[0]; + } + if ($bNeg) { + for ($i = 0; $i < 4; ++$i) { + $b[$i] = ($b[$i] ^ 0xffff) & 0xffff; + } + ++$b[0]; + } + $res = $this->multiplyLong($a, $b); + if ($aNeg !== $bNeg) { + if ($aNeg !== $bNeg) { + for ($i = 0; $i < 4; ++$i) { + $res[$i] = ($res[$i] ^ 0xffff) & 0xffff; + } + $c = 1; + for ($i = 0; $i < 4; ++$i) { + $res[$i] += $c; + $c = $res[$i] >> 16; + $res[$i] &= 0xffff; + } + } + } + $return = new ParagonIE_Sodium_Core32_Int64(); + $return->limbs = array( + $res[3] & 0xffff, + $res[2] & 0xffff, + $res[1] & 0xffff, + $res[0] & 0xffff + ); + if (count($res) > 4) { + $return->overflow = $res[4]; + } + return $return; + } + /** * @param ParagonIE_Sodium_Core32_Int64 $int * @param int $size @@ -327,6 +466,9 @@ public static function ctSelect( */ public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0) { + if (ParagonIE_Sodium_Compat::$fastMult) { + return $this->mulInt64Fast($int); + } ParagonIE_Sodium_Core32_Util::declareScalarType($size, 'int', 2); if (!$size) { $size = 63; @@ -566,7 +708,7 @@ public function shiftLeft($c = 0) /** @var int $c */ return $this->shiftRight(-$c); } else { - if (is_null($c)) { + if (!is_int($c)) { throw new TypeError(); } /** @var int $carry */ @@ -591,10 +733,11 @@ public function shiftLeft($c = 0) public function shiftRight($c = 0) { ParagonIE_Sodium_Core32_Util::declareScalarType($c, 'int', 1); + $c = (int) $c; + /** @var int $c */ $return = new ParagonIE_Sodium_Core32_Int64(); $return->unsignedInt = $this->unsignedInt; $c &= 63; - /** @var int $c */ $negative = -(($this->limbs[0] >> 15) & 1); if ($c >= 16) { diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/Poly1305/State.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/Poly1305/State.php index e87acf1a3a360..d80e1ff9812ce 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/Poly1305/State.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/Poly1305/State.php @@ -142,7 +142,7 @@ public function update($message = '') } $this->blocks( - static::intArrayToString($this->buffer), + self::intArrayToString($this->buffer), ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE ); $this->leftover = 0; @@ -346,7 +346,7 @@ public function finish() $this->final = true; $this->blocks( self::substr( - static::intArrayToString($this->buffer), + self::intArrayToString($this->buffer), 0, ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE ), diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/SecretStream/State.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/SecretStream/State.php new file mode 100644 index 0000000000000..6f20486297bf3 --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/SecretStream/State.php @@ -0,0 +1,163 @@ +key = $key; + $this->counter = 1; + if (is_null($nonce)) { + $nonce = str_repeat("\0", 12); + } + $this->nonce = str_pad($nonce, 12, "\0", STR_PAD_RIGHT);; + $this->_pad = str_repeat("\0", 4); + } + + /** + * @return self + */ + public function counterReset() + { + $this->counter = 1; + $this->_pad = str_repeat("\0", 4); + return $this; + } + + /** + * @return string + */ + public function getKey() + { + return $this->key; + } + + /** + * @return string + */ + public function getCounter() + { + return ParagonIE_Sodium_Core32_Util::store32_le($this->counter); + } + + /** + * @return string + */ + public function getNonce() + { + if (!is_string($this->nonce)) { + $this->nonce = str_repeat("\0", 12); + } + if (ParagonIE_Sodium_Core32_Util::strlen($this->nonce) !== 12) { + $this->nonce = str_pad($this->nonce, 12, "\0", STR_PAD_RIGHT); + } + return $this->nonce; + } + + /** + * @return string + */ + public function getCombinedNonce() + { + return $this->getCounter() . + ParagonIE_Sodium_Core32_Util::substr($this->getNonce(), 0, 8); + } + + /** + * @return self + */ + public function incrementCounter() + { + ++$this->counter; + return $this; + } + + /** + * @return bool + */ + public function needsRekey() + { + return ($this->counter & 0xffff) === 0; + } + + /** + * @param string $newKeyAndNonce + * @return self + */ + public function rekey($newKeyAndNonce) + { + $this->key = ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 0, 32); + $this->nonce = str_pad( + ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 32), + 12, + "\0", + STR_PAD_RIGHT + ); + return $this; + } + + /** + * @param string $str + * @return self + */ + public function xorNonce($str) + { + $this->nonce = ParagonIE_Sodium_Core32_Util::xorStrings( + $this->getNonce(), + str_pad( + ParagonIE_Sodium_Core32_Util::substr($str, 0, 8), + 12, + "\0", + STR_PAD_RIGHT + ) + ); + return $this; + } + + /** + * @param string $string + * @return self + */ + public static function fromString($string) + { + $state = new ParagonIE_Sodium_Core32_SecretStream_State( + ParagonIE_Sodium_Core32_Util::substr($string, 0, 32) + ); + $state->counter = ParagonIE_Sodium_Core32_Util::load_4( + ParagonIE_Sodium_Core32_Util::substr($string, 32, 4) + ); + $state->nonce = ParagonIE_Sodium_Core32_Util::substr($string, 36, 12); + $state->_pad = ParagonIE_Sodium_Core32_Util::substr($string, 48, 8); + return $state; + } + + /** + * @return string + */ + public function toString() + { + return $this->key . + $this->getCounter() . + $this->nonce . + $this->_pad; + } +} diff --git a/libraries/vendor/paragonie/sodium_compat/src/Core32/X25519.php b/libraries/vendor/paragonie/sodium_compat/src/Core32/X25519.php index fd4b056a81a6b..2cc000d9fa7b8 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Core32/X25519.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Core32/X25519.php @@ -102,58 +102,48 @@ public static function fe_cswap( */ public static function fe_mul121666(ParagonIE_Sodium_Core32_Curve25519_Fe $f) { - /** @var array $h */ + /** @var array $h */ $h = array(); for ($i = 0; $i < 10; ++$i) { $h[$i] = $f[$i]->toInt64()->mulInt(121666, 17); } - /** @var ParagonIE_Sodium_Core32_Int32 $carry9 */ $carry9 = $h[9]->addInt(1 << 24)->shiftRight(25); $h[0] = $h[0]->addInt64($carry9->mulInt(19, 5)); $h[9] = $h[9]->subInt64($carry9->shiftLeft(25)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry1 */ $carry1 = $h[1]->addInt(1 << 24)->shiftRight(25); $h[2] = $h[2]->addInt64($carry1); $h[1] = $h[1]->subInt64($carry1->shiftLeft(25)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry3 */ $carry3 = $h[3]->addInt(1 << 24)->shiftRight(25); $h[4] = $h[4]->addInt64($carry3); $h[3] = $h[3]->subInt64($carry3->shiftLeft(25)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry5 */ $carry5 = $h[5]->addInt(1 << 24)->shiftRight(25); $h[6] = $h[6]->addInt64($carry5); $h[5] = $h[5]->subInt64($carry5->shiftLeft(25)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry7 */ $carry7 = $h[7]->addInt(1 << 24)->shiftRight(25); $h[8] = $h[8]->addInt64($carry7); $h[7] = $h[7]->subInt64($carry7->shiftLeft(25)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry0 */ $carry0 = $h[0]->addInt(1 << 25)->shiftRight(26); $h[1] = $h[1]->addInt64($carry0); $h[0] = $h[0]->subInt64($carry0->shiftLeft(26)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry2 */ $carry2 = $h[2]->addInt(1 << 25)->shiftRight(26); $h[3] = $h[3]->addInt64($carry2); $h[2] = $h[2]->subInt64($carry2->shiftLeft(26)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry4 */ $carry4 = $h[4]->addInt(1 << 25)->shiftRight(26); $h[5] = $h[5]->addInt64($carry4); $h[4] = $h[4]->subInt64($carry4->shiftLeft(26)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry6 */ $carry6 = $h[6]->addInt(1 << 25)->shiftRight(26); $h[7] = $h[7]->addInt64($carry6); $h[6] = $h[6]->subInt64($carry6->shiftLeft(26)); - /** @var ParagonIE_Sodium_Core32_Int32 $carry8 */ $carry8 = $h[8]->addInt(1 << 25)->shiftRight(26); $h[9] = $h[9]->addInt64($carry8); $h[8] = $h[8]->subInt64($carry8->shiftLeft(26)); @@ -161,8 +151,9 @@ public static function fe_mul121666(ParagonIE_Sodium_Core32_Curve25519_Fe $f) for ($i = 0; $i < 10; ++$i) { $h[$i] = $h[$i]->toInt32(); } - /** @var array $h */ - return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h); + /** @var array $h2 */ + $h2 = $h; + return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h2); } /** diff --git a/libraries/vendor/paragonie/sodium_compat/src/Crypto.php b/libraries/vendor/paragonie/sodium_compat/src/Crypto.php index 2e3383ff6f7f0..7e980f4f7c532 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Crypto.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Crypto.php @@ -777,6 +777,53 @@ public static function generichash_init($key = '', $outputLength = 32) return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx); } + /** + * Initialize a hashing context for BLAKE2b. + * + * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. + * + * @param string $key + * @param int $outputLength + * @param string $salt + * @param string $personal + * @return string + * @throws RangeException + * @throws SodiumException + * @throws TypeError + */ + public static function generichash_init_salt_personal( + $key = '', + $outputLength = 32, + $salt = '', + $personal = '' + ) { + // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is initialized + ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor(); + + $k = null; + if (!empty($key)) { + $k = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key); + if ($k->count() > ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) { + throw new RangeException('Invalid key size'); + } + } + if (!empty($salt)) { + $s = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($salt); + } else { + $s = null; + } + if (!empty($salt)) { + $p = ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($personal); + } else { + $p = null; + } + + /** @var SplFixedArray $ctx */ + $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength, $s, $p); + + return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx); + } + /** * Update a hashing context for BLAKE2b with $message * @@ -1185,6 +1232,362 @@ public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $ke return $m; } + /** + * @param string $key + * @return array Returns a state and a header. + * @throws Exception + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_init_push($key) + { + # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES); + $out = random_bytes(24); + + # crypto_core_hchacha20(state->k, out, k, NULL); + $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20($out, $key); + $state = new ParagonIE_Sodium_Core_SecretStream_State( + $subkey, + ParagonIE_Sodium_Core_Util::substr($out, 16, 8) . str_repeat("\0", 4) + ); + + # _crypto_secretstream_xchacha20poly1305_counter_reset(state); + $state->counterReset(); + + # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + # memset(state->_pad, 0, sizeof state->_pad); + return array( + $state->toString(), + $out + ); + } + + /** + * @param string $key + * @param string $header + * @return string Returns a state. + * @throws Exception + */ + public static function secretstream_xchacha20poly1305_init_pull($key, $header) + { + # crypto_core_hchacha20(state->k, in, k, NULL); + $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20( + ParagonIE_Sodium_Core_Util::substr($header, 0, 16), + $key + ); + $state = new ParagonIE_Sodium_Core_SecretStream_State( + $subkey, + ParagonIE_Sodium_Core_Util::substr($header, 16) + ); + $state->counterReset(); + # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + # memset(state->_pad, 0, sizeof state->_pad); + # return 0; + return $state->toString(); + } + + /** + * @param string $state + * @param string $msg + * @param string $aad + * @param int $tag + * @return string + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0) + { + $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state); + # crypto_onetimeauth_poly1305_state poly1305_state; + # unsigned char block[64U]; + # unsigned char slen[8U]; + # unsigned char *c; + # unsigned char *mac; + + $msglen = ParagonIE_Sodium_Core_Util::strlen($msg); + $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad); + + if ((($msglen + 63) >> 6) > 0xfffffffe) { + throw new SodiumException( + 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' + ); + } + + # if (outlen_p != NULL) { + # *outlen_p = 0U; + # } + # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { + # sodium_misuse(); + # } + + # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); + # crypto_onetimeauth_poly1305_init(&poly1305_state, block); + # sodium_memzero(block, sizeof block); + $auth = new ParagonIE_Sodium_Core_Poly1305_State( + ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); + $auth->update($aad); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, + # (0x10 - adlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); + + # memset(block, 0, sizeof block); + # block[0] = tag; + # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, + # state->nonce, 1U, state->k); + $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( + ParagonIE_Sodium_Core_Util::intToChr($tag) . str_repeat("\0", 63), + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core_Util::store64_le(1) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); + $auth->update($block); + + # out[0] = block[0]; + $out = $block[0]; + # c = out + (sizeof tag); + # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k); + $cipher = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( + $msg, + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core_Util::store64_le(2) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); + $auth->update($cipher); + + $out .= $cipher; + unset($cipher); + + # crypto_onetimeauth_poly1305_update + # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); + + # STORE64_LE(slen, (uint64_t) adlen); + $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $auth->update($slen); + + # STORE64_LE(slen, (sizeof block) + mlen); + $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $auth->update($slen); + + # mac = c + mlen; + # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); + $mac = $auth->finish(); + $out .= $mac; + + # sodium_memzero(&poly1305_state, sizeof poly1305_state); + unset($auth); + + + # XOR_BUF(STATE_INONCE(state), mac, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + $st->xorNonce($mac); + + # sodium_increment(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); + $st->incrementCounter(); + // Overwrite by reference: + $state = $st->toString(); + + /** @var bool $rekey */ + $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; + # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || + # sodium_is_zero(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { + # crypto_secretstream_xchacha20poly1305_rekey(state); + # } + if ($rekey || $st->needsRekey()) { + // DO REKEY + self::secretstream_xchacha20poly1305_rekey($state); + } + # if (outlen_p != NULL) { + # *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen; + # } + return $out; + } + + /** + * @param string $state + * @param string $cipher + * @param string $aad + * @return bool|array{0: string, 1: int} + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '') + { + $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state); + + $cipherlen = ParagonIE_Sodium_Core_Util::strlen($cipher); + # mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES; + $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES; + $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad); + + # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { + # sodium_misuse(); + # } + if ((($msglen + 63) >> 6) > 0xfffffffe) { + throw new SodiumException( + 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' + ); + } + + # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); + # crypto_onetimeauth_poly1305_init(&poly1305_state, block); + # sodium_memzero(block, sizeof block); + $auth = new ParagonIE_Sodium_Core_Poly1305_State( + ParagonIE_Sodium_Core_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); + $auth->update($aad); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, + # (0x10 - adlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); + + + # memset(block, 0, sizeof block); + # block[0] = in[0]; + # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, + # state->nonce, 1U, state->k); + $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( + $cipher[0] . str_repeat("\0", 63), + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core_Util::store64_le(1) + ); + # tag = block[0]; + # block[0] = in[0]; + # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); + $tag = ParagonIE_Sodium_Core_Util::chrToInt($block[0]); + $block[0] = $cipher[0]; + $auth->update($block); + + + # c = in + (sizeof tag); + # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); + $auth->update(ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen)); + + # crypto_onetimeauth_poly1305_update + # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); + + # STORE64_LE(slen, (uint64_t) adlen); + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen); + $auth->update($slen); + + # STORE64_LE(slen, (sizeof block) + mlen); + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen); + $auth->update($slen); + + # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); + # sodium_memzero(&poly1305_state, sizeof poly1305_state); + $mac = $auth->finish(); + + # stored_mac = c + mlen; + # if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) { + # sodium_memzero(mac, sizeof mac); + # return -1; + # } + + $stored = ParagonIE_Sodium_Core_Util::substr($cipher, $msglen + 1, 16); + if (!ParagonIE_Sodium_Core_Util::hashEquals($mac, $stored)) { + return false; + } + + # crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k); + $out = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( + ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen), + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core_Util::store64_le(2) + ); + + # XOR_BUF(STATE_INONCE(state), mac, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + $st->xorNonce($mac); + + # sodium_increment(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); + $st->incrementCounter(); + + # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || + # sodium_is_zero(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { + # crypto_secretstream_xchacha20poly1305_rekey(state); + # } + + // Overwrite by reference: + $state = $st->toString(); + + /** @var bool $rekey */ + $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; + if ($rekey || $st->needsRekey()) { + // DO REKEY + self::secretstream_xchacha20poly1305_rekey($state); + } + return array($out, $tag); + } + + /** + * @param string $state + * @return void + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_rekey(&$state) + { + $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state); + # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + + # crypto_secretstream_xchacha20poly1305_INONCEBYTES]; + # size_t i; + # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { + # new_key_and_inonce[i] = state->k[i]; + # } + $new_key_and_inonce = $st->getKey(); + + # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { + # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] = + # STATE_INONCE(state)[i]; + # } + $new_key_and_inonce .= ParagonIE_Sodium_Core_Util::substR($st->getNonce(), 0, 8); + + # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, + # sizeof new_key_and_inonce, + # state->nonce, state->k); + + $st->rekey(ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc( + $new_key_and_inonce, + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core_Util::store64_le(0) + )); + + # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { + # state->k[i] = new_key_and_inonce[i]; + # } + # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { + # STATE_INONCE(state)[i] = + # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]; + # } + # _crypto_secretstream_xchacha20poly1305_counter_reset(state); + $st->counterReset(); + + $state = $st->toString(); + } + /** * Detached Ed25519 signature. * diff --git a/libraries/vendor/paragonie/sodium_compat/src/Crypto32.php b/libraries/vendor/paragonie/sodium_compat/src/Crypto32.php index e76803dd8fae3..34c0d7a3949fa 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/Crypto32.php +++ b/libraries/vendor/paragonie/sodium_compat/src/Crypto32.php @@ -776,6 +776,53 @@ public static function generichash_init($key = '', $outputLength = 32) return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx); } + /** + * Initialize a hashing context for BLAKE2b. + * + * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. + * + * @param string $key + * @param int $outputLength + * @param string $salt + * @param string $personal + * @return string + * @throws RangeException + * @throws SodiumException + * @throws TypeError + */ + public static function generichash_init_salt_personal( + $key = '', + $outputLength = 32, + $salt = '', + $personal = '' + ) { + // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized + ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor(); + + $k = null; + if (!empty($key)) { + $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key); + if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) { + throw new RangeException('Invalid key size'); + } + } + if (!empty($salt)) { + $s = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($salt); + } else { + $s = null; + } + if (!empty($salt)) { + $p = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($personal); + } else { + $p = null; + } + + /** @var SplFixedArray $ctx */ + $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength, $s, $p); + + return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx); + } + /** * Update a hashing context for BLAKE2b with $message * @@ -1184,6 +1231,362 @@ public static function secretbox_xchacha20poly1305_open($ciphertext, $nonce, $ke return $m; } + /** + * @param string $key + * @return array Returns a state and a header. + * @throws Exception + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_init_push($key) + { + # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES); + $out = random_bytes(24); + + # crypto_core_hchacha20(state->k, out, k, NULL); + $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20($out, $key); + $state = new ParagonIE_Sodium_Core32_SecretStream_State( + $subkey, + ParagonIE_Sodium_Core32_Util::substr($out, 16, 8) . str_repeat("\0", 4) + ); + + # _crypto_secretstream_xchacha20poly1305_counter_reset(state); + $state->counterReset(); + + # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + # memset(state->_pad, 0, sizeof state->_pad); + return array( + $state->toString(), + $out + ); + } + + /** + * @param string $key + * @param string $header + * @return string Returns a state. + * @throws Exception + */ + public static function secretstream_xchacha20poly1305_init_pull($key, $header) + { + # crypto_core_hchacha20(state->k, in, k, NULL); + $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20( + ParagonIE_Sodium_Core32_Util::substr($header, 0, 16), + $key + ); + $state = new ParagonIE_Sodium_Core32_SecretStream_State( + $subkey, + ParagonIE_Sodium_Core32_Util::substr($header, 16) + ); + $state->counterReset(); + # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + # memset(state->_pad, 0, sizeof state->_pad); + # return 0; + return $state->toString(); + } + + /** + * @param string $state + * @param string $msg + * @param string $aad + * @param int $tag + * @return string + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0) + { + $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); + # crypto_onetimeauth_poly1305_state poly1305_state; + # unsigned char block[64U]; + # unsigned char slen[8U]; + # unsigned char *c; + # unsigned char *mac; + + $msglen = ParagonIE_Sodium_Core32_Util::strlen($msg); + $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad); + + if ((($msglen + 63) >> 6) > 0xfffffffe) { + throw new SodiumException( + 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' + ); + } + + # if (outlen_p != NULL) { + # *outlen_p = 0U; + # } + # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { + # sodium_misuse(); + # } + + # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); + # crypto_onetimeauth_poly1305_init(&poly1305_state, block); + # sodium_memzero(block, sizeof block); + $auth = new ParagonIE_Sodium_Core32_Poly1305_State( + ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); + $auth->update($aad); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, + # (0x10 - adlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); + + # memset(block, 0, sizeof block); + # block[0] = tag; + # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, + # state->nonce, 1U, state->k); + $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( + ParagonIE_Sodium_Core32_Util::intToChr($tag) . str_repeat("\0", 63), + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core32_Util::store64_le(1) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); + $auth->update($block); + + # out[0] = block[0]; + $out = $block[0]; + # c = out + (sizeof tag); + # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k); + $cipher = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( + $msg, + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core32_Util::store64_le(2) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); + $auth->update($cipher); + + $out .= $cipher; + unset($cipher); + + # crypto_onetimeauth_poly1305_update + # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); + + # STORE64_LE(slen, (uint64_t) adlen); + $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $auth->update($slen); + + # STORE64_LE(slen, (sizeof block) + mlen); + $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $auth->update($slen); + + # mac = c + mlen; + # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); + $mac = $auth->finish(); + $out .= $mac; + + # sodium_memzero(&poly1305_state, sizeof poly1305_state); + unset($auth); + + + # XOR_BUF(STATE_INONCE(state), mac, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + $st->xorNonce($mac); + + # sodium_increment(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); + $st->incrementCounter(); + // Overwrite by reference: + $state = $st->toString(); + + /** @var bool $rekey */ + $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; + # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || + # sodium_is_zero(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { + # crypto_secretstream_xchacha20poly1305_rekey(state); + # } + if ($rekey || $st->needsRekey()) { + // DO REKEY + self::secretstream_xchacha20poly1305_rekey($state); + } + # if (outlen_p != NULL) { + # *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen; + # } + return $out; + } + + /** + * @param string $state + * @param string $cipher + * @param string $aad + * @return bool|array{0: string, 1: int} + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '') + { + $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); + + $cipherlen = ParagonIE_Sodium_Core32_Util::strlen($cipher); + # mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES; + $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES; + $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad); + + # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { + # sodium_misuse(); + # } + if ((($msglen + 63) >> 6) > 0xfffffffe) { + throw new SodiumException( + 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' + ); + } + + # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); + # crypto_onetimeauth_poly1305_init(&poly1305_state, block); + # sodium_memzero(block, sizeof block); + $auth = new ParagonIE_Sodium_Core32_Poly1305_State( + ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) + ); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); + $auth->update($aad); + + # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, + # (0x10 - adlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); + + + # memset(block, 0, sizeof block); + # block[0] = in[0]; + # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, + # state->nonce, 1U, state->k); + $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( + $cipher[0] . str_repeat("\0", 63), + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core32_Util::store64_le(1) + ); + # tag = block[0]; + # block[0] = in[0]; + # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); + $tag = ParagonIE_Sodium_Core32_Util::chrToInt($block[0]); + $block[0] = $cipher[0]; + $auth->update($block); + + + # c = in + (sizeof tag); + # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); + $auth->update(ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen)); + + # crypto_onetimeauth_poly1305_update + # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); + $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); + + # STORE64_LE(slen, (uint64_t) adlen); + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen); + $auth->update($slen); + + # STORE64_LE(slen, (sizeof block) + mlen); + # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); + $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen); + $auth->update($slen); + + # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); + # sodium_memzero(&poly1305_state, sizeof poly1305_state); + $mac = $auth->finish(); + + # stored_mac = c + mlen; + # if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) { + # sodium_memzero(mac, sizeof mac); + # return -1; + # } + + $stored = ParagonIE_Sodium_Core32_Util::substr($cipher, $msglen + 1, 16); + if (!ParagonIE_Sodium_Core32_Util::hashEquals($mac, $stored)) { + return false; + } + + # crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k); + $out = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( + ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen), + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core32_Util::store64_le(2) + ); + + # XOR_BUF(STATE_INONCE(state), mac, + # crypto_secretstream_xchacha20poly1305_INONCEBYTES); + $st->xorNonce($mac); + + # sodium_increment(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); + $st->incrementCounter(); + + # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || + # sodium_is_zero(STATE_COUNTER(state), + # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { + # crypto_secretstream_xchacha20poly1305_rekey(state); + # } + + // Overwrite by reference: + $state = $st->toString(); + + /** @var bool $rekey */ + $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; + if ($rekey || $st->needsRekey()) { + // DO REKEY + self::secretstream_xchacha20poly1305_rekey($state); + } + return array($out, $tag); + } + + /** + * @param string $state + * @return void + * @throws SodiumException + */ + public static function secretstream_xchacha20poly1305_rekey(&$state) + { + $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); + # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + + # crypto_secretstream_xchacha20poly1305_INONCEBYTES]; + # size_t i; + # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { + # new_key_and_inonce[i] = state->k[i]; + # } + $new_key_and_inonce = $st->getKey(); + + # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { + # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] = + # STATE_INONCE(state)[i]; + # } + $new_key_and_inonce .= ParagonIE_Sodium_Core32_Util::substR($st->getNonce(), 0, 8); + + # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, + # sizeof new_key_and_inonce, + # state->nonce, state->k); + + $st->rekey(ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( + $new_key_and_inonce, + $st->getCombinedNonce(), + $st->getKey(), + ParagonIE_Sodium_Core32_Util::store64_le(0) + )); + + # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { + # state->k[i] = new_key_and_inonce[i]; + # } + # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { + # STATE_INONCE(state)[i] = + # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]; + # } + # _crypto_secretstream_xchacha20poly1305_counter_reset(state); + $st->counterReset(); + + $state = $st->toString(); + } + /** * Detached Ed25519 signature. * diff --git a/libraries/vendor/paragonie/sodium_compat/src/File.php b/libraries/vendor/paragonie/sodium_compat/src/File.php index e675593c314e6..d71bc7e5add34 100644 --- a/libraries/vendor/paragonie/sodium_compat/src/File.php +++ b/libraries/vendor/paragonie/sodium_compat/src/File.php @@ -141,7 +141,9 @@ public static function box_open($inputFile, $outputFile, $nonce, $keypair) ParagonIE_Sodium_Compat::memzero($nonce); ParagonIE_Sodium_Compat::memzero($ephKeypair); } catch (SodiumException $ex) { - unset($ephKeypair); + if (isset($ephKeypair)) { + unset($ephKeypair); + } } return $res; } @@ -241,6 +243,7 @@ public static function box_seal($inputFile, $outputFile, $publicKey) ParagonIE_Sodium_Compat::memzero($nonce); ParagonIE_Sodium_Compat::memzero($ephKeypair); } catch (SodiumException $ex) { + /** @psalm-suppress PossiblyUndefinedVariable */ unset($ephKeypair); } return $res; @@ -328,7 +331,9 @@ public static function box_seal_open($inputFile, $outputFile, $ecdhKeypair) ParagonIE_Sodium_Compat::memzero($nonce); ParagonIE_Sodium_Compat::memzero($ephKeypair); } catch (SodiumException $ex) { - unset($ephKeypair); + if (isset($ephKeypair)) { + unset($ephKeypair); + } } return $res; } @@ -537,6 +542,7 @@ public static function secretbox_open($inputFile, $outputFile, $nonce, $key) try { ParagonIE_Sodium_Compat::memzero($key); } catch (SodiumException $ex) { + /** @psalm-suppress PossiblyUndefinedVariable */ unset($key); } return $res; @@ -590,9 +596,8 @@ public static function sign($filePath, $secretKey) $az[0] = self::intToChr(self::chrToInt($az[0]) & 248); $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64); - /** @var resource $hs */ $hs = hash_init('sha512'); - hash_update($hs, self::substr($az, 32, 32)); + self::hash_update($hs, self::substr($az, 32, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); @@ -610,10 +615,9 @@ public static function sign($filePath, $secretKey) ParagonIE_Sodium_Core_Ed25519::ge_scalarmult_base($nonce) ); - /** @var resource $hs */ $hs = hash_init('sha512'); - hash_update($hs, self::substr($sig, 0, 32)); - hash_update($hs, self::substr($pk, 0, 32)); + self::hash_update($hs, self::substr($sig, 0, 32)); + self::hash_update($hs, self::substr($pk, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); @@ -681,7 +685,11 @@ public static function verify($sig, $filePath, $publicKey) } /* Security checks */ - if (ParagonIE_Sodium_Core_Ed25519::check_S_lt_L(self::substr($sig, 32, 32))) { + if ( + (ParagonIE_Sodium_Core_Ed25519::chrToInt($sig[63]) & 240) + && + ParagonIE_Sodium_Core_Ed25519::check_S_lt_L(self::substr($sig, 32, 32)) + ) { throw new SodiumException('S < L - Invalid signature'); } if (ParagonIE_Sodium_Core_Ed25519::small_order($sig)) { @@ -719,10 +727,9 @@ public static function verify($sig, $filePath, $publicKey) /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */ $A = ParagonIE_Sodium_Core_Ed25519::ge_frombytes_negate_vartime($publicKey); - /** @var resource $hs */ $hs = hash_init('sha512'); - hash_update($hs, self::substr($sig, 0, 32)); - hash_update($hs, self::substr($publicKey, 0, 32)); + self::hash_update($hs, self::substr($sig, 0, 32)); + self::hash_update($hs, self::substr($publicKey, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); /** @var string $hDigest */ @@ -844,7 +851,7 @@ protected static function secretbox_encrypt($ifp, $ofp, $mlen, $nonce, $key) if (!is_string($plaintext)) { throw new SodiumException('Could not read input file'); } - $first32 = ftell($ifp); + $first32 = self::ftell($ifp); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key); @@ -878,7 +885,7 @@ protected static function secretbox_encrypt($ifp, $ofp, $mlen, $nonce, $key) ); // Pre-write 16 blank bytes for the Poly1305 tag - $start = ftell($ofp); + $start = self::ftell($ofp); fwrite($ofp, str_repeat("\x00", 16)); /** @var string $c */ @@ -929,7 +936,7 @@ protected static function secretbox_encrypt($ifp, $ofp, $mlen, $nonce, $key) $block0 = null; $subkey = null; } - $end = ftell($ofp); + $end = self::ftell($ofp); /* * Write the Poly1305 authentication tag that provides integrity @@ -1046,7 +1053,7 @@ protected static function onetimeauth_verify( $mlen = 0 ) { /** @var int $pos */ - $pos = ftell($ifp); + $pos = self::ftell($ifp); /** @var int $iter */ $iter = 1; @@ -1076,10 +1083,10 @@ protected static function onetimeauth_verify( * Update a hash context with the contents of a file, without * loading the entire file into memory. * - * @param resource|object $hash + * @param resource|HashContext $hash * @param resource $fp * @param int $size - * @return mixed (resource on PHP < 7.2, object on PHP >= 7.2) + * @return resource|object Resource on PHP < 7.2, HashContext object on PHP >= 7.2 * @throws SodiumException * @throws TypeError * @psalm-suppress PossiblyInvalidArgument @@ -1095,12 +1102,12 @@ public static function updateHashWithFile($hash, $fp, $size = 0) if (!is_resource($hash)) { throw new TypeError('Argument 1 must be a resource, ' . gettype($hash) . ' given.'); } - } else { if (!is_object($hash)) { throw new TypeError('Argument 1 must be an object (PHP 7.2+), ' . gettype($hash) . ' given.'); } } + if (!is_resource($fp)) { throw new TypeError('Argument 2 must be a resource, ' . gettype($fp) . ' given.'); } @@ -1109,7 +1116,7 @@ public static function updateHashWithFile($hash, $fp, $size = 0) } /** @var int $originalPosition */ - $originalPosition = ftell($fp); + $originalPosition = self::ftell($fp); // Move file pointer to beginning of file fseek($fp, 0, SEEK_SET); @@ -1126,7 +1133,7 @@ public static function updateHashWithFile($hash, $fp, $size = 0) } /** @var string $message */ /** @psalm-suppress InvalidArgument */ - hash_update($hash, $message); + self::hash_update($hash, $message); } // Reset file pointer's position fseek($fp, $originalPosition, SEEK_SET); @@ -1167,9 +1174,8 @@ private static function sign_core32($filePath, $secretKey) $az[0] = self::intToChr(self::chrToInt($az[0]) & 248); $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64); - /** @var resource $hs */ $hs = hash_init('sha512'); - hash_update($hs, self::substr($az, 32, 32)); + self::hash_update($hs, self::substr($az, 32, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); @@ -1187,10 +1193,9 @@ private static function sign_core32($filePath, $secretKey) ParagonIE_Sodium_Core32_Ed25519::ge_scalarmult_base($nonce) ); - /** @var resource $hs */ $hs = hash_init('sha512'); - hash_update($hs, self::substr($sig, 0, 32)); - hash_update($hs, self::substr($pk, 0, 32)); + self::hash_update($hs, self::substr($sig, 0, 32)); + self::hash_update($hs, self::substr($pk, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); @@ -1272,10 +1277,9 @@ public static function verify_core32($sig, $filePath, $publicKey) /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */ $A = ParagonIE_Sodium_Core32_Ed25519::ge_frombytes_negate_vartime($publicKey); - /** @var resource $hs */ $hs = hash_init('sha512'); - hash_update($hs, self::substr($sig, 0, 32)); - hash_update($hs, self::substr($publicKey, 0, 32)); + self::hash_update($hs, self::substr($sig, 0, 32)); + self::hash_update($hs, self::substr($publicKey, 0, 32)); /** @var resource $hs */ $hs = self::updateHashWithFile($hs, $fp, $size); /** @var string $hDigest */ @@ -1320,7 +1324,7 @@ protected static function secretbox_encrypt_core32($ifp, $ofp, $mlen, $nonce, $k if (!is_string($plaintext)) { throw new SodiumException('Could not read input file'); } - $first32 = ftell($ifp); + $first32 = self::ftell($ifp); /** @var string $subkey */ $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key); @@ -1354,7 +1358,7 @@ protected static function secretbox_encrypt_core32($ifp, $ofp, $mlen, $nonce, $k ); // Pre-write 16 blank bytes for the Poly1305 tag - $start = ftell($ofp); + $start = self::ftell($ofp); fwrite($ofp, str_repeat("\x00", 16)); /** @var string $c */ @@ -1405,7 +1409,7 @@ protected static function secretbox_encrypt_core32($ifp, $ofp, $mlen, $nonce, $k $block0 = null; $subkey = null; } - $end = ftell($ofp); + $end = self::ftell($ofp); /* * Write the Poly1305 authentication tag that provides integrity @@ -1521,13 +1525,7 @@ protected static function onetimeauth_verify_core32( $mlen = 0 ) { /** @var int $pos */ - $pos = ftell($ifp); - - /** @var int $iter */ - $iter = 1; - - /** @var int $incr */ - $incr = self::BUFFER_SIZE >> 6; + $pos = self::ftell($ifp); while ($mlen > 0) { $blockSize = $mlen > self::BUFFER_SIZE @@ -1539,11 +1537,24 @@ protected static function onetimeauth_verify_core32( } $state->update($ciphertext); $mlen -= $blockSize; - $iter += $incr; } $res = ParagonIE_Sodium_Core32_Util::verify_16($tag, $state->finish()); fseek($ifp, $pos, SEEK_SET); return $res; } + + /** + * @param resource $resource + * @return int + * @throws SodiumException + */ + private static function ftell($resource) + { + $return = ftell($resource); + if (!is_int($return)) { + throw new SodiumException('ftell() returned false'); + } + return (int) $return; + } } diff --git a/libraries/vendor/paragonie/sodium_compat/src/PHP52/SplFixedArray.php b/libraries/vendor/paragonie/sodium_compat/src/PHP52/SplFixedArray.php new file mode 100644 index 0000000000000..c333ad4fad42b --- /dev/null +++ b/libraries/vendor/paragonie/sodium_compat/src/PHP52/SplFixedArray.php @@ -0,0 +1,189 @@ + */ + private $internalArray = array(); + + /** @var int $size */ + private $size = 0; + + /** + * SplFixedArray constructor. + * @param int $size + */ + public function __construct($size = 0) + { + $this->size = $size; + $this->internalArray = array(); + } + + /** + * @return int + */ + public function count() + { + return count($this->internalArray); + } + + /** + * @return array + */ + public function toArray() + { + ksort($this->internalArray); + return (array) $this->internalArray; + } + + /** + * @param array $array + * @param bool $save_indexes + * @return SplFixedArray + * @psalm-suppress MixedAssignment + */ + public static function fromArray(array $array, $save_indexes = true) + { + $self = new SplFixedArray(count($array)); + if($save_indexes) { + foreach($array as $key => $value) { + $self[(int) $key] = $value; + } + } else { + $i = 0; + foreach (array_values($array) as $value) { + $self[$i] = $value; + $i++; + } + } + return $self; + } + + /** + * @return int + */ + public function getSize() + { + return $this->size; + } + + /** + * @param int $size + * @return bool + */ + public function setSize($size) + { + $this->size = $size; + return true; + } + + /** + * @param string|int $index + * @return bool + */ + public function offsetExists($index) + { + return array_key_exists((int) $index, $this->internalArray); + } + + /** + * @param string|int $index + * @return mixed + */ + public function offsetGet($index) + { + /** @psalm-suppress MixedReturnStatement */ + return $this->internalArray[(int) $index]; + } + + /** + * @param string|int $index + * @param mixed $newval + * @psalm-suppress MixedAssignment + */ + public function offsetSet($index, $newval) + { + $this->internalArray[(int) $index] = $newval; + } + + /** + * @param string|int $index + */ + public function offsetUnset($index) + { + unset($this->internalArray[(int) $index]); + } + + /** + * Rewind iterator back to the start + * @link https://php.net/manual/en/splfixedarray.rewind.php + * @return void + * @since 5.3.0 + */ + public function rewind() + { + reset($this->internalArray); + } + + /** + * Return current array entry + * @link https://php.net/manual/en/splfixedarray.current.php + * @return mixed The current element value. + * @since 5.3.0 + */ + public function current() + { + /** @psalm-suppress MixedReturnStatement */ + return current($this->internalArray); + } + + /** + * Return current array index + * @return int The current array index. + */ + public function key() + { + return key($this->internalArray); + } + + /** + * @return void + */ + public function next() + { + next($this->internalArray); + } + + /** + * Check whether the array contains more elements + * @link https://php.net/manual/en/splfixedarray.valid.php + * @return bool true if the array contains any more elements, false otherwise. + */ + public function valid() + { + if (empty($this->internalArray)) { + return false; + } + $result = next($this->internalArray) !== false; + prev($this->internalArray); + return $result; + } + + /** + * Do nothing. + */ + public function __wakeup() + { + // NOP + } +} \ No newline at end of file