From 4bc35d24e8b4104273a9136abb2fefb6ed190828 Mon Sep 17 00:00:00 2001 From: Andreas Fernandez <a.fernandez@scripting-base.de> Date: Fri, 17 Jun 2022 22:13:43 +0200 Subject: [PATCH] [TASK] Use unsafe but faster password hashing in `RecoveryCodeTest` `RecoveryCodeTest` now uses a `NoopPasswordHash` implementation, that uses sha1 internally. It's obviously not as secure as the til today configured argon2 algorithm, but still fine for testing reasons, which greatly improves the test runtime. Resolves: #97788 Releases: main, 11.5 Change-Id: Ic7ee62f7dea3eedb2e792b88bec293e556454556 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/74958 Tested-by: core-ci <typo3@b13.com> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> --- .../PasswordHashing/NoopPasswordHash.php | 76 +++++++++++++++++++ .../Mfa/Provider/RecoveryCodesTest.php | 39 ++++------ 2 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 typo3/sysext/core/Tests/Fixtures/Crypto/PasswordHashing/NoopPasswordHash.php diff --git a/typo3/sysext/core/Tests/Fixtures/Crypto/PasswordHashing/NoopPasswordHash.php b/typo3/sysext/core/Tests/Fixtures/Crypto/PasswordHashing/NoopPasswordHash.php new file mode 100644 index 000000000000..08a2ddb95b4b --- /dev/null +++ b/typo3/sysext/core/Tests/Fixtures/Crypto/PasswordHashing/NoopPasswordHash.php @@ -0,0 +1,76 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Tests\Fixtures\Crypto\PasswordHashing; + +use TYPO3\CMS\Core\Core\Environment; +use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashInterface; + +/** + * A special noop password "hashing" algorithm to be used in tests only - it is unsecure and optimized for speed. + * + * @internal + */ +class NoopPasswordHash implements PasswordHashInterface +{ + protected const PREFIX = '$SHA1$'; + + public function __construct() + { + if (!Environment::getContext()->isTesting()) { + throw new \LogicException( + sprintf('The password hashing algorithm %s must not be used outside of testing context!', __CLASS__), + 1655551062 + ); + } + } + + public function checkPassword(string $plainPW, string $saltedHashPW): bool + { + return $this->getHashedPassword($plainPW) === $saltedHashPW; + } + + public function isAvailable(): bool + { + return true; + } + + public function getHashedPassword(string $password) + { + return self::PREFIX . sha1($password); + } + + public function isHashUpdateNeeded(string $passString): bool + { + return false; + } + + public function isValidSaltedPW(string $saltedPW): bool + { + return !strncmp(self::PREFIX, $saltedPW, strlen(self::PREFIX)); + } + + public static function registerNoopPasswordHash(): void + { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['availablePasswordHashAlgorithms'][__CLASS__] = __CLASS__; + } + + public static function unregisterNoopPasswordHash(): void + { + unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['availablePasswordHashAlgorithms'][__CLASS__]); + } +} diff --git a/typo3/sysext/core/Tests/Unit/Authentication/Mfa/Provider/RecoveryCodesTest.php b/typo3/sysext/core/Tests/Unit/Authentication/Mfa/Provider/RecoveryCodesTest.php index b2e9bf76c627..eadddda5619a 100644 --- a/typo3/sysext/core/Tests/Unit/Authentication/Mfa/Provider/RecoveryCodesTest.php +++ b/typo3/sysext/core/Tests/Unit/Authentication/Mfa/Provider/RecoveryCodesTest.php @@ -18,8 +18,8 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Tests\Unit\Authentication\Mfa\Provider; use TYPO3\CMS\Core\Authentication\Mfa\Provider\RecoveryCodes; -use TYPO3\CMS\Core\Crypto\PasswordHashing\Argon2iPasswordHash; use TYPO3\CMS\Core\Crypto\PasswordHashing\BcryptPasswordHash; +use TYPO3\CMS\Core\Tests\Fixtures\Crypto\PasswordHashing\NoopPasswordHash; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; @@ -30,22 +30,26 @@ class RecoveryCodesTest extends UnitTestCase protected function setUp(): void { parent::setUp(); + + NoopPasswordHash::registerNoopPasswordHash(); $this->subject = GeneralUtility::makeInstance(RecoveryCodes::class, 'BE'); } + protected function tearDown(): void + { + NoopPasswordHash::unregisterNoopPasswordHash(); + + parent::tearDown(); + } + /** * @test */ public function generateRecoveryCodesTest(): void { $GLOBALS['TYPO3_CONF_VARS']['BE']['passwordHashing'] = [ - 'className' => Argon2iPasswordHash::class, - 'options' => [ - // Reduce default costs for quicker unit tests - 'memory_cost' => 65536, - 'time_cost' => 4, - 'threads' => 2, - ], + 'className' => NoopPasswordHash::class, + 'options' => [], ]; $codes = $this->subject->generateRecoveryCodes(); @@ -54,7 +58,7 @@ class RecoveryCodesTest extends UnitTestCase $plainCodes = array_keys($codes); $hashedCodes = array_values($codes); - $hashInstance = (new Argon2iPasswordHash()); + $hashInstance = (new NoopPasswordHash()); foreach ($hashedCodes as $key => $code) { self::assertTrue($hashInstance->isValidSaltedPW($code)); @@ -123,13 +127,8 @@ class RecoveryCodesTest extends UnitTestCase public function verifyRecoveryCodeTest(): void { $GLOBALS['TYPO3_CONF_VARS']['BE']['passwordHashing'] = [ - 'className' => Argon2iPasswordHash::class, - 'options' => [ - // Reduce default costs for quicker unit tests - 'memory_cost' => 65536, - 'time_cost' => 4, - 'threads' => 2, - ], + 'className' => NoopPasswordHash::class, + 'options' => [], ]; $recoveryCode = '18742989'; @@ -156,13 +155,7 @@ class RecoveryCodesTest extends UnitTestCase public function verifyRecoveryCodeUsesTheCorrectHashInstanceTest(): void { $code = '18742989'; - $argonOptionsSpeedup = [ - // Reduce default costs for quicker unit tests - 'memory_cost' => 65536, - 'time_cost' => 4, - 'threads' => 2, - ]; - $codes = [(new Argon2iPasswordHash($argonOptionsSpeedup))->getHashedPassword($code)]; + $codes = [(new NoopPasswordHash())->getHashedPassword($code)]; // Ensure we have another default hash instance $GLOBALS['TYPO3_CONF_VARS']['BE']['passwordHashing'] = [ -- GitLab