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 0000000000000000000000000000000000000000..08a2ddb95b4bbe40f800d52f3eb7a09b0265c23a --- /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 b2e9bf76c6272ff1c668338e3f3e175b9c1da853..eadddda5619afaedb4fe224ecc3d4fdc33db1a87 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'] = [