diff --git a/composer.json b/composer.json index 6692903609e996c0539370d97ca8ee4aec341ea4..c760a33a458ddb102997fdc0b0714a5768521ff3 100644 --- a/composer.json +++ b/composer.json @@ -84,6 +84,7 @@ "typo3/sysext/info/Migrations/Code/ClassAliasMap.php", "typo3/sysext/lowlevel/Migrations/Code/ClassAliasMap.php", "typo3/sysext/reports/Migrations/Code/ClassAliasMap.php", + "typo3/sysext/saltedpasswords/Migrations/Code/ClassAliasMap.php", "typo3/sysext/workspaces/Migrations/Code/ClassAliasMap.php" ] }, diff --git a/composer.lock b/composer.lock index 5c96b5518d6979b243403f80701ba95f2426abaf..bf4b2b582b024370ac3ca98cdf52ac282ae2b215 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "6b0c9ff22949275bc4d6c60fd2f62f2b", + "content-hash": "ee8fd70e59c3f86ff7728b866e54149c", "packages": [ { "name": "cogpowered/finediff", diff --git a/typo3/sysext/core/Documentation/Changelog/9.0/Breaking-83294-SaltedPasswordsCustomSaltingsMustUseTheSaltInterface.rst b/typo3/sysext/core/Documentation/Changelog/9.0/Breaking-83294-SaltedPasswordsCustomSaltingsMustUseTheSaltInterface.rst new file mode 100644 index 0000000000000000000000000000000000000000..ff49c77396fe2e2b28de51a195aafbc8c8a62b22 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/9.0/Breaking-83294-SaltedPasswordsCustomSaltingsMustUseTheSaltInterface.rst @@ -0,0 +1,39 @@ +.. include:: ../../Includes.txt + +=============================================================================== +Breaking: #83294 - Salted Passwords: Custom saltings must use the SaltInterface +=============================================================================== + +See :issue:`83294` + +Description +=========== + +The salted passwords factory allowed to register custom saltings has been changed. All custom salts +need to implement :php:`TYPO3\CMS\SaltedPasswords\Salt\SaltInterface`. Before, this was +handled by extending from :php:`TYPO3\CMS\SaltedPasswords\Salt\AbstractSalt`, which has been renamed to +:php:`TYPO3\CMS\SaltedPasswords\Salt\AbstractComposedSalt` when the salting is implemented. + + +Impact +====== + +When writing custom salts for TYPO3, they need to implement the SaltInterface. + +If extending from :php:`AbstractSalt`, custom salt now need to extend from :php:`AbstractComposedSalt` and +implement the additional method :php:`getSaltLength()` and :php:`isValidSalt($salt)`. + + +Affected Installations +====================== + +TYPO3 installations using custom salts for `EXT:saltedpasswords`. + + +Migration +========= + +Switch to the new implemention details mentioned above, and change your custom salt to fit +to the :php:`SaltInterface` API. + +.. index:: PHP-API, NotScanned \ No newline at end of file diff --git a/typo3/sysext/saltedpasswords/Classes/Evaluation/Evaluator.php b/typo3/sysext/saltedpasswords/Classes/Evaluation/Evaluator.php index 4d33b28fdcd9f9838d6998ca0ef6b6629a7af301..58ecf7faa7dc84a64c2a744c0121a3f30f3559e9 100644 --- a/typo3/sysext/saltedpasswords/Classes/Evaluation/Evaluator.php +++ b/typo3/sysext/saltedpasswords/Classes/Evaluation/Evaluator.php @@ -14,6 +14,9 @@ namespace TYPO3\CMS\Saltedpasswords\Evaluation; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Saltedpasswords\Salt\SaltFactory; +use TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility; + /** * Class implementing salted evaluation methods. */ @@ -49,20 +52,19 @@ class Evaluator */ public function evaluateFieldValue($value, $is_in, &$set) { - $isEnabled = $this->mode ? \TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility::isUsageEnabled($this->mode) : \TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility::isUsageEnabled(); + $isEnabled = $this->mode ? SaltedPasswordsUtility::isUsageEnabled($this->mode) : SaltedPasswordsUtility::isUsageEnabled(); if ($isEnabled) { $isMD5 = preg_match('/[0-9abcdef]{32,32}/', $value); $hashingMethod = substr($value, 0, 2); $isDeprecatedSaltedHash = ($hashingMethod === 'C$' || $hashingMethod === 'M$'); - /** @var $objInstanceSaltedPW \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface */ - $objInstanceSaltedPW = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance(null, $this->mode); + $objInstanceSaltedPW = SaltFactory::getSaltingInstance(null, $this->mode); if ($isMD5) { $set = true; $value = 'M' . $objInstanceSaltedPW->getHashedPassword($value); } else { // Determine method used for the (possibly) salted hashed password $tempValue = $isDeprecatedSaltedHash ? substr($value, 1) : $value; - $tempObjInstanceSaltedPW = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($tempValue); + $tempObjInstanceSaltedPW = SaltFactory::getSaltingInstance($tempValue); if (!is_object($tempObjInstanceSaltedPW)) { $set = true; $value = $objInstanceSaltedPW->getHashedPassword($value); diff --git a/typo3/sysext/saltedpasswords/Classes/Salt/AbstractSalt.php b/typo3/sysext/saltedpasswords/Classes/Salt/AbstractComposedSalt.php similarity index 73% rename from typo3/sysext/saltedpasswords/Classes/Salt/AbstractSalt.php rename to typo3/sysext/saltedpasswords/Classes/Salt/AbstractComposedSalt.php index 069df622a7d6cd101fd672b3899ea696095709a8..3d1829f78c82c6824d787ea1b979216a96e500f0 100644 --- a/typo3/sysext/saltedpasswords/Classes/Salt/AbstractSalt.php +++ b/typo3/sysext/saltedpasswords/Classes/Salt/AbstractComposedSalt.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); namespace TYPO3\CMS\Saltedpasswords\Salt; /* @@ -16,9 +17,9 @@ namespace TYPO3\CMS\Saltedpasswords\Salt; /** * Abstract class with methods needed to be extended - * in a salted hashing class. + * in a salted hashing class that composes an own salted password hash. */ -abstract class AbstractSalt +abstract class AbstractComposedSalt implements SaltInterface { /** * Method applies settings (prefix, optional hash count, optional suffix) @@ -27,28 +28,43 @@ abstract class AbstractSalt * @param string $salt A salt to apply setting to * @return string Salt with setting */ - abstract protected function applySettingsToSalt($salt); + abstract protected function applySettingsToSalt(string $salt): string; /** * Generates a random base salt settings for the hash. * * @return string A string containing settings and a random salt */ - abstract protected function getGeneratedSalt(); + abstract protected function getGeneratedSalt(): string; /** * Returns a string for mapping an int to the corresponding base 64 character. * * @return string String for mapping an int to the corresponding base 64 character */ - abstract protected function getItoa64(); + abstract protected function getItoa64(): string; /** * Returns setting string to indicate type of hashing method. * * @return string Setting string of hashing method */ - abstract protected function getSetting(); + abstract protected function getSetting(): string; + + /** + * Returns length of required salt. + * + * @return int Length of required salt + */ + abstract public function getSaltLength(): int; + + /** + * Method determines if a given string is a valid salt + * + * @param string $salt String to check + * @return bool TRUE if it's valid salt, otherwise FALSE + */ + abstract public function isValidSalt(string $salt): bool; /** * Encodes bytes into printable base 64 using the *nix standard from crypt(). @@ -57,7 +73,7 @@ abstract class AbstractSalt * @param int $count The number of characters (bytes) to encode. * @return string Encoded string */ - public function base64Encode($input, $count) + public function base64Encode(string $input, int $count): string { $output = ''; $i = 0; @@ -91,7 +107,7 @@ abstract class AbstractSalt * @param int $byteLength Length of bytes to calculate in base64 chars * @return int Required length of base64 characters */ - protected function getLengthBase64FromBytes($byteLength) + protected function getLengthBase64FromBytes(int $byteLength): int { // Calculates bytes in bits in base64 return (int)ceil($byteLength * 8 / 6); diff --git a/typo3/sysext/saltedpasswords/Classes/Salt/BlowfishSalt.php b/typo3/sysext/saltedpasswords/Classes/Salt/BlowfishSalt.php index 18cdbb23605f7abfb1ba2a7f588db60d59ed8354..58b0cd6259039b6391e61a2e44240da0c1a9fa6a 100644 --- a/typo3/sysext/saltedpasswords/Classes/Salt/BlowfishSalt.php +++ b/typo3/sysext/saltedpasswords/Classes/Salt/BlowfishSalt.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); namespace TYPO3\CMS\Saltedpasswords\Salt; /* @@ -87,7 +88,7 @@ class BlowfishSalt extends Md5Salt * @param string $salt A salt to apply setting to * @return string Salt with setting */ - protected function applySettingsToSalt($salt) + protected function applySettingsToSalt(string $salt): string { $saltWithSettings = $salt; $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -104,7 +105,7 @@ class BlowfishSalt extends Md5Salt * @param string $setting Complete hash or a hash's setting string or to get log2 iteration count from * @return int Used hashcount for given hash string */ - protected function getCountLog2($setting) + protected function getCountLog2(string $setting): int { $countLog2 = null; $setting = substr($setting, strlen($this->getSetting())); @@ -124,7 +125,7 @@ class BlowfishSalt extends Md5Salt * @see $hashCount * @see setHashCount() */ - public function getHashCount() + public function getHashCount(): int { return isset(self::$hashCount) ? self::$hashCount : self::HASH_COUNT; } @@ -137,7 +138,7 @@ class BlowfishSalt extends Md5Salt * @see $maxHashCount * @see setMaxHashCount() */ - public function getMaxHashCount() + public function getMaxHashCount(): int { return isset(self::$maxHashCount) ? self::$maxHashCount : self::MAX_HASH_COUNT; } @@ -147,9 +148,9 @@ class BlowfishSalt extends Md5Salt * * @return bool Method available */ - public function isAvailable() + public function isAvailable(): bool { - return CRYPT_BLOWFISH; + return (bool)CRYPT_BLOWFISH; } /** @@ -160,7 +161,7 @@ class BlowfishSalt extends Md5Salt * @see $minHashCount * @see setMinHashCount() */ - public function getMinHashCount() + public function getMinHashCount(): int { return isset(self::$minHashCount) ? self::$minHashCount : self::MIN_HASH_COUNT; } @@ -173,7 +174,7 @@ class BlowfishSalt extends Md5Salt * * @return int Length of a Blowfish salt in bytes */ - public function getSaltLength() + public function getSaltLength(): int { return self::$saltLengthBlowfish; } @@ -186,7 +187,7 @@ class BlowfishSalt extends Md5Salt * * @return string Setting string of Blowfish salted hashes */ - public function getSetting() + public function getSetting(): string { return self::$settingBlowfish; } @@ -202,7 +203,7 @@ class BlowfishSalt extends Md5Salt * @param string $saltedPW Salted hash to check if it needs an update * @return bool TRUE if salted hash needs an update, otherwise FALSE */ - public function isHashUpdateNeeded($saltedPW) + public function isHashUpdateNeeded(string $saltedPW): bool { // Check whether this was an updated password. if (strncmp($saltedPW, '$2', 2) || !$this->isValidSalt($saltedPW)) { @@ -222,7 +223,7 @@ class BlowfishSalt extends Md5Salt * @param string $salt String to check * @return bool TRUE if it's valid salt, otherwise FALSE */ - public function isValidSalt($salt) + public function isValidSalt(string $salt): bool { $isValid = ($skip = false); $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -252,7 +253,7 @@ class BlowfishSalt extends Md5Salt * @param string $saltedPW String to check * @return bool TRUE if it's valid salted hashed password, otherwise FALSE */ - public function isValidSaltedPW($saltedPW) + public function isValidSaltedPW(string $saltedPW): bool { $isValid = !strncmp($this->getSetting(), $saltedPW, strlen($this->getSetting())); if ($isValid) { @@ -269,9 +270,9 @@ class BlowfishSalt extends Md5Salt * @see $hashCount * @see getHashCount() */ - public function setHashCount($hashCount = null) + public function setHashCount(int $hashCount = null) { - self::$hashCount = !is_null($hashCount) && is_int($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT; + self::$hashCount = !is_null($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT; } /** @@ -282,9 +283,9 @@ class BlowfishSalt extends Md5Salt * @see $maxHashCount * @see getMaxHashCount() */ - public function setMaxHashCount($maxHashCount = null) + public function setMaxHashCount(int $maxHashCount = null) { - self::$maxHashCount = !is_null($maxHashCount) && is_int($maxHashCount) ? $maxHashCount : self::MAX_HASH_COUNT; + self::$maxHashCount = $maxHashCount ?? self::MAX_HASH_COUNT; } /** @@ -295,8 +296,8 @@ class BlowfishSalt extends Md5Salt * @see $minHashCount * @see getMinHashCount() */ - public function setMinHashCount($minHashCount = null) + public function setMinHashCount(int $minHashCount = null) { - self::$minHashCount = !is_null($minHashCount) && is_int($minHashCount) ? $minHashCount : self::MIN_HASH_COUNT; + self::$minHashCount = $minHashCount ?? self::MIN_HASH_COUNT; } } diff --git a/typo3/sysext/saltedpasswords/Classes/Salt/Md5Salt.php b/typo3/sysext/saltedpasswords/Classes/Salt/Md5Salt.php index 0543b4380942e641896f97c1d2cd8d28c63423a4..fb5576cab56967183dc60c499877da41a4bde878 100644 --- a/typo3/sysext/saltedpasswords/Classes/Salt/Md5Salt.php +++ b/typo3/sysext/saltedpasswords/Classes/Salt/Md5Salt.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); namespace TYPO3\CMS\Saltedpasswords\Salt; /* @@ -24,7 +25,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; * MD5 salted hashing with PHP's crypt() should be available * on most of the systems. */ -class Md5Salt extends AbstractSalt implements SaltInterface +class Md5Salt extends AbstractComposedSalt { /** * Keeps a string for mapping an int to the corresponding @@ -59,7 +60,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * @param string $salt A salt to apply setting to * @return string Salt with setting */ - protected function applySettingsToSalt($salt) + protected function applySettingsToSalt(string $salt): string { $saltWithSettings = $salt; $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -78,7 +79,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * @param string $saltedHashPW salted hash to compare plain-text password with * @return bool TRUE, if plain-text password matches the salted hash, otherwise FALSE */ - public function checkPassword($plainPW, $saltedHashPW) + public function checkPassword(string $plainPW, string $saltedHashPW): bool { $isCorrect = false; if ($this->isValidSalt($saltedHashPW)) { @@ -98,7 +99,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * * @return string A character string containing settings and a random salt */ - protected function getGeneratedSalt() + protected function getGeneratedSalt(): string { $randomBytes = GeneralUtility::makeInstance(Random::class)->generateRandomBytes($this->getSaltLength()); return $this->base64Encode($randomBytes, $this->getSaltLength()); @@ -111,7 +112,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * @param string $salt Optional custom salt with setting to use * @return string Salted hashed password */ - public function getHashedPassword($password, $salt = null) + public function getHashedPassword(string $password, string $salt = null) { $saltedPW = null; if (!empty($password)) { @@ -128,7 +129,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * * @return string String for mapping an int to the corresponding base 64 character */ - protected function getItoa64() + protected function getItoa64(): string { return self::ITOA64; } @@ -138,9 +139,9 @@ class Md5Salt extends AbstractSalt implements SaltInterface * * @return bool Method available */ - public function isAvailable() + public function isAvailable(): bool { - return CRYPT_MD5; + return (bool)CRYPT_MD5; } /** @@ -148,7 +149,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * * @return int Length of a MD5 salt in bytes */ - public function getSaltLength() + public function getSaltLength(): int { return self::$saltLengthMD5; } @@ -158,7 +159,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * * @return string Suffix of a salt */ - protected function getSaltSuffix() + protected function getSaltSuffix(): string { return self::$saltSuffixMD5; } @@ -168,7 +169,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * * @return string Setting string of MD5 salted hashes */ - public function getSetting() + public function getSetting(): string { return self::$settingMD5; } @@ -185,7 +186,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * @param string $passString Salted hash to check if it needs an update * @return bool TRUE if salted hash needs an update, otherwise FALSE */ - public function isHashUpdateNeeded($passString) + public function isHashUpdateNeeded(string $passString): bool { return false; } @@ -196,7 +197,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * @param string $salt String to check * @return bool TRUE if it's valid salt, otherwise FALSE */ - public function isValidSalt($salt) + public function isValidSalt(string $salt): bool { $isValid = ($skip = false); $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -226,7 +227,7 @@ class Md5Salt extends AbstractSalt implements SaltInterface * @param string $saltedPW String to check * @return bool TRUE if it's valid salted hashed password, otherwise FALSE */ - public function isValidSaltedPW($saltedPW) + public function isValidSaltedPW(string $saltedPW): bool { $isValid = !strncmp($this->getSetting(), $saltedPW, strlen($this->getSetting())); if ($isValid) { diff --git a/typo3/sysext/saltedpasswords/Classes/Salt/Pbkdf2Salt.php b/typo3/sysext/saltedpasswords/Classes/Salt/Pbkdf2Salt.php index 55784725ab4d9a1fc626f403fad70cbccb4a1e16..ab80faadb3422d156cbd5c491b25cfef4523a36f 100644 --- a/typo3/sysext/saltedpasswords/Classes/Salt/Pbkdf2Salt.php +++ b/typo3/sysext/saltedpasswords/Classes/Salt/Pbkdf2Salt.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); namespace TYPO3\CMS\Saltedpasswords\Salt; /* @@ -21,7 +22,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; * Class that implements PBKDF2 salted hashing based on PHP's * hash_pbkdf2() function. */ -class Pbkdf2Salt extends AbstractSalt implements SaltInterface +class Pbkdf2Salt extends AbstractComposedSalt { /** * Keeps a string for mapping an int to the corresponding @@ -88,7 +89,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $salt A salt to apply setting to * @return string Salt with setting */ - protected function applySettingsToSalt($salt) + protected function applySettingsToSalt(string $salt): string { $saltWithSettings = $salt; // salt without setting @@ -106,7 +107,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $saltedHashPW salted hash to compare plain-text password with * @return bool TRUE, if plain-text password matches the salted hash, otherwise FALSE */ - public function checkPassword($plainPW, $saltedHashPW) + public function checkPassword(string $plainPW, string $saltedHashPW): bool { return $this->isValidSalt($saltedHashPW) && \hash_equals($this->getHashedPassword($plainPW, $saltedHashPW), $saltedHashPW); } @@ -117,7 +118,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $setting Complete hash or a hash's setting string or to get log2 iteration count from * @return int|null Used hashcount for given hash string */ - protected function getIterationCount($setting) + protected function getIterationCount(string $setting) { $iterationCount = null; $setting = substr($setting, strlen($this->getSetting())); @@ -143,7 +144,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * * @return string A character string containing settings and a random salt */ - protected function getGeneratedSalt() + protected function getGeneratedSalt(): string { return GeneralUtility::makeInstance(Random::class)->generateRandomBytes($this->getSaltLength()); } @@ -155,7 +156,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $salt * @return string */ - protected function getStoredSalt($salt) + protected function getStoredSalt(string $salt): string { if (!strncmp('$', $salt, 1)) { if (!strncmp($this->getSetting(), $salt, strlen($this->getSetting()))) { @@ -171,7 +172,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * * @return string String for mapping an int to the corresponding base 64 character */ - protected function getItoa64() + protected function getItoa64(): string { return self::ITOA64; } @@ -183,7 +184,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $salt Optional custom salt with setting to use * @return string|null Salted hashed password */ - public function getHashedPassword($password, $salt = null) + public function getHashedPassword(string $password, string $salt = null) { $saltedPW = null; if ($password !== '') { @@ -207,7 +208,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @see $hashCount * @see setHashCount() */ - public function getHashCount() + public function getHashCount(): int { return isset(self::$hashCount) ? self::$hashCount : self::HASH_COUNT; } @@ -220,7 +221,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @see $maxHashCount * @see setMaxHashCount() */ - public function getMaxHashCount() + public function getMaxHashCount(): int { return isset(self::$maxHashCount) ? self::$maxHashCount : self::MAX_HASH_COUNT; } @@ -230,7 +231,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * * @return bool Method available */ - public function isAvailable() + public function isAvailable(): bool { return function_exists('hash_pbkdf2'); } @@ -243,7 +244,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @see $minHashCount * @see setMinHashCount() */ - public function getMinHashCount() + public function getMinHashCount(): int { return isset(self::$minHashCount) ? self::$minHashCount : self::MIN_HASH_COUNT; } @@ -256,7 +257,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * * @return int Length of a PBKDF2 salt in bytes */ - public function getSaltLength() + public function getSaltLength(): int { return self::$saltLengthPbkdf2; } @@ -269,7 +270,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * * @return string Setting string of PBKDF2 salted hashes */ - public function getSetting() + public function getSetting(): string { return self::$settingPbkdf2; } @@ -285,7 +286,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $saltedPW Salted hash to check if it needs an update * @return bool TRUE if salted hash needs an update, otherwise FALSE */ - public function isHashUpdateNeeded($saltedPW) + public function isHashUpdateNeeded(string $saltedPW): bool { // Check whether this was an updated password. if (strncmp($saltedPW, $this->getSetting(), strlen($this->getSetting())) || !$this->isValidSalt($saltedPW)) { @@ -305,7 +306,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $salt String to check * @return bool TRUE if it's valid salt, otherwise FALSE */ - public function isValidSalt($salt) + public function isValidSalt(string $salt): bool { $isValid = ($skip = false); $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -335,7 +336,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $saltedPW String to check * @return bool TRUE if it's valid salted hashed password, otherwise FALSE */ - public function isValidSaltedPW($saltedPW) + public function isValidSaltedPW(string $saltedPW): bool { $isValid = !strncmp($this->getSetting(), $saltedPW, strlen($this->getSetting())); if ($isValid) { @@ -352,9 +353,9 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @see $hashCount * @see getHashCount() */ - public function setHashCount($hashCount = null) + public function setHashCount(int $hashCount = null) { - self::$hashCount = !is_null($hashCount) && is_int($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT; + self::$hashCount = !is_null($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT; } /** @@ -365,9 +366,9 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @see $maxHashCount * @see getMaxHashCount() */ - public function setMaxHashCount($maxHashCount = null) + public function setMaxHashCount(int $maxHashCount = null) { - self::$maxHashCount = !is_null($maxHashCount) && is_int($maxHashCount) ? $maxHashCount : self::MAX_HASH_COUNT; + self::$maxHashCount = $maxHashCount ?? self::MAX_HASH_COUNT; } /** @@ -378,9 +379,9 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @see $minHashCount * @see getMinHashCount() */ - public function setMinHashCount($minHashCount = null) + public function setMinHashCount(int $minHashCount = null) { - self::$minHashCount = !is_null($minHashCount) && is_int($minHashCount) ? $minHashCount : self::MIN_HASH_COUNT; + self::$minHashCount = $minHashCount ?? self::MIN_HASH_COUNT; } /** @@ -391,7 +392,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param int $count The number of characters (bytes) to encode. * @return string Encoded string */ - public function base64Encode($input, $count) + public function base64Encode(string $input, int $count): string { $input = substr($input, 0, $count); return rtrim(str_replace('+', '.', base64_encode($input)), " =\r\n\t\0\x0B"); @@ -404,7 +405,7 @@ class Pbkdf2Salt extends AbstractSalt implements SaltInterface * @param string $value * @return string */ - public function base64Decode($value) + public function base64Decode(string $value): string { return base64_decode(str_replace('.', '+', $value)); } diff --git a/typo3/sysext/saltedpasswords/Classes/Salt/PhpassSalt.php b/typo3/sysext/saltedpasswords/Classes/Salt/PhpassSalt.php index 89d93cb16e2aab143cc2cdc996a092b069c13ac6..9dcf0846cb18c82ac36f4e83c26d0ea694777b0f 100644 --- a/typo3/sysext/saltedpasswords/Classes/Salt/PhpassSalt.php +++ b/typo3/sysext/saltedpasswords/Classes/Salt/PhpassSalt.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); namespace TYPO3\CMS\Saltedpasswords\Salt; /* @@ -28,7 +29,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; * @see http://drupal.org/node/29706/ * @see http://www.openwall.com/phpass/ */ -class PhpassSalt extends AbstractSalt implements SaltInterface +class PhpassSalt extends AbstractComposedSalt { /** * Keeps a string for mapping an int to the corresponding @@ -100,7 +101,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @param string $salt A salt to apply setting to * @return string Salt with setting */ - protected function applySettingsToSalt($salt) + protected function applySettingsToSalt(string $salt): string { $saltWithSettings = $salt; $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -122,7 +123,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @param string $saltedHashPW Salted hash to compare plain-text password with * @return bool TRUE, if plain-text password matches the salted hash, otherwise FALSE */ - public function checkPassword($plainPW, $saltedHashPW) + public function checkPassword(string $plainPW, string $saltedHashPW): bool { $hash = $this->cryptPassword($plainPW, $saltedHashPW); return $hash && \hash_equals($hash, $saltedHashPW); @@ -133,7 +134,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * * @return bool Method available */ - public function isAvailable() + public function isAvailable(): bool { return true; } @@ -150,7 +151,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @param string $setting An existing hash or the output of getGeneratedSalt() * @return mixed A string containing the hashed password (and salt) */ - protected function cryptPassword($password, $setting) + protected function cryptPassword(string $password, string $setting) { $saltedPW = null; $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -183,7 +184,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @param string $setting Complete hash or a hash's setting string or to get log2 iteration count from * @return int Used hashcount for given hash string */ - protected function getCountLog2($setting) + protected function getCountLog2(string $setting): int { return strpos($this->getItoa64(), $setting[strlen($this->getSetting())]); } @@ -199,7 +200,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * * @return string A character string containing settings and a random salt */ - protected function getGeneratedSalt() + protected function getGeneratedSalt(): string { $randomBytes = GeneralUtility::makeInstance(Random::class)->generateRandomBytes($this->getSaltLength()); return $this->base64Encode($randomBytes, $this->getSaltLength()); @@ -213,7 +214,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @see $hashCount * @see setHashCount() */ - public function getHashCount() + public function getHashCount(): int { return isset(self::$hashCount) ? self::$hashCount : self::HASH_COUNT; } @@ -223,9 +224,9 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * * @param string $password Plaintext password to create a salted hash from * @param string $salt Optional custom salt with setting to use - * @return string salted hashed password + * @return string|null salted hashed password */ - public function getHashedPassword($password, $salt = null) + public function getHashedPassword(string $password, string $salt = null) { $saltedPW = null; if (!empty($password)) { @@ -242,7 +243,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * * @return string String for mapping an int to the corresponding base 64 character */ - protected function getItoa64() + protected function getItoa64(): string { return self::ITOA64; } @@ -255,7 +256,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @see $maxHashCount * @see setMaxHashCount() */ - public function getMaxHashCount() + public function getMaxHashCount(): int { return isset(self::$maxHashCount) ? self::$maxHashCount : self::MAX_HASH_COUNT; } @@ -268,7 +269,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @see $minHashCount * @see setMinHashCount() */ - public function getMinHashCount() + public function getMinHashCount(): int { return isset(self::$minHashCount) ? self::$minHashCount : self::MIN_HASH_COUNT; } @@ -278,7 +279,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * * @return int Length of a Blowfish salt in bytes */ - public function getSaltLength() + public function getSaltLength(): int { return self::$saltLengthPhpass; } @@ -288,7 +289,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * * @return string Setting string of PHPass salted hashes */ - public function getSetting() + public function getSetting(): string { return self::$settingPhpass; } @@ -305,7 +306,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @param string $passString Salted hash to check if it needs an update * @return bool TRUE if salted hash needs an update, otherwise FALSE */ - public function isHashUpdateNeeded($passString) + public function isHashUpdateNeeded(string $passString): bool { // Check whether this was an updated password. if (strncmp($passString, '$P$', 3) || strlen($passString) != 34) { @@ -321,7 +322,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @param string $salt String to check * @return bool TRUE if it's valid salt, otherwise FALSE */ - public function isValidSalt($salt) + public function isValidSalt(string $salt): bool { $isValid = ($skip = false); $reqLenBase64 = $this->getLengthBase64FromBytes($this->getSaltLength()); @@ -351,7 +352,7 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @param string $saltedPW String to check * @return bool TRUE if it's valid salted hashed password, otherwise FALSE */ - public function isValidSaltedPW($saltedPW) + public function isValidSaltedPW(string $saltedPW): bool { $isValid = !strncmp($this->getSetting(), $saltedPW, strlen($this->getSetting())); if ($isValid) { @@ -368,9 +369,9 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @see $hashCount * @see getHashCount() */ - public function setHashCount($hashCount = null) + public function setHashCount(int $hashCount = null) { - self::$hashCount = !is_null($hashCount) && is_int($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT; + self::$hashCount = !is_null($hashCount) && $hashCount >= $this->getMinHashCount() && $hashCount <= $this->getMaxHashCount() ? $hashCount : self::HASH_COUNT; } /** @@ -381,9 +382,9 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @see $maxHashCount * @see getMaxHashCount() */ - public function setMaxHashCount($maxHashCount = null) + public function setMaxHashCount(int $maxHashCount = null) { - self::$maxHashCount = !is_null($maxHashCount) && is_int($maxHashCount) ? $maxHashCount : self::MAX_HASH_COUNT; + self::$maxHashCount = $maxHashCount ?? self::MAX_HASH_COUNT; } /** @@ -394,8 +395,8 @@ class PhpassSalt extends AbstractSalt implements SaltInterface * @see $minHashCount * @see getMinHashCount() */ - public function setMinHashCount($minHashCount = null) + public function setMinHashCount(int $minHashCount = null) { - self::$minHashCount = !is_null($minHashCount) && is_int($minHashCount) ? $minHashCount : self::MIN_HASH_COUNT; + self::$minHashCount = $minHashCount ?? self::MIN_HASH_COUNT; } } diff --git a/typo3/sysext/saltedpasswords/Classes/Salt/SaltFactory.php b/typo3/sysext/saltedpasswords/Classes/Salt/SaltFactory.php index c8888a33651fc068929cc41b080c2a86f26b017f..359bb2ee271f72af53385bfe3fb6fe1a46e928c1 100644 --- a/typo3/sysext/saltedpasswords/Classes/Salt/SaltFactory.php +++ b/typo3/sysext/saltedpasswords/Classes/Salt/SaltFactory.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); namespace TYPO3\CMS\Saltedpasswords\Salt; /* @@ -14,6 +15,9 @@ namespace TYPO3\CMS\Saltedpasswords\Salt; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility; + /** * Class that implements Blowfish salted hashing based on PHP's * crypt() function. @@ -24,7 +28,7 @@ class SaltFactory * An instance of the salted hashing method. * This member is set in the getSaltingInstance() function. * - * @var \TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt + * @var SaltInterface */ protected static $instance = null; @@ -34,7 +38,7 @@ class SaltFactory * * @return array */ - public static function getRegisteredSaltedHashingMethods() + public static function getRegisteredSaltedHashingMethods(): array { $saltMethods = static::getDefaultSaltMethods(); if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/saltedpasswords']['saltMethods'])) { @@ -58,13 +62,13 @@ class SaltFactory * * @return array */ - protected static function getDefaultSaltMethods() + protected static function getDefaultSaltMethods(): array { return [ - \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class => \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class, - \TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class => \TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class, - \TYPO3\CMS\Saltedpasswords\Salt\PhpassSalt::class => \TYPO3\CMS\Saltedpasswords\Salt\PhpassSalt::class, - \TYPO3\CMS\Saltedpasswords\Salt\Pbkdf2Salt::class => \TYPO3\CMS\Saltedpasswords\Salt\Pbkdf2Salt::class + Md5Salt::class => Md5Salt::class, + BlowfishSalt::class => BlowfishSalt::class, + PhpassSalt::class => PhpassSalt::class, + Pbkdf2Salt::class => Pbkdf2Salt::class ]; } @@ -78,7 +82,7 @@ class SaltFactory * * @param string|null $saltedHash Salted hashed password to determine the type of used method from or NULL to reset to the default type * @param string $mode The TYPO3 mode (FE or BE) saltedpasswords shall be used for - * @return SaltInterface An instance of salting hash method class + * @return SaltInterface|null An instance of salting hash method class or null if given hash is not supported */ public static function getSaltingInstance($saltedHash = '', $mode = TYPO3_MODE) { @@ -94,9 +98,9 @@ class SaltFactory self::$instance = null; } } else { - $classNameToUse = \TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility::getDefaultSaltingHashingMethod($mode); + $classNameToUse = SaltedPasswordsUtility::getDefaultSaltingHashingMethod($mode); $availableClasses = static::getRegisteredSaltedHashingMethods(); - self::$instance = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($availableClasses[$classNameToUse]); + self::$instance = GeneralUtility::makeInstance($availableClasses[$classNameToUse]); } } return self::$instance; @@ -111,17 +115,17 @@ class SaltFactory * @param string $mode (optional) The TYPO3 mode (FE or BE) saltedpasswords shall be used for * @return bool TRUE, if salting hashing method has been found, otherwise FALSE */ - public static function determineSaltingHashingMethod($saltedHash, $mode = TYPO3_MODE) + public static function determineSaltingHashingMethod(string $saltedHash, $mode = TYPO3_MODE): bool { $registeredMethods = static::getRegisteredSaltedHashingMethods(); - $defaultClassName = \TYPO3\CMS\Saltedpasswords\Utility\SaltedPasswordsUtility::getDefaultSaltingHashingMethod($mode); + $defaultClassName = SaltedPasswordsUtility::getDefaultSaltingHashingMethod($mode); $defaultReference = $registeredMethods[$defaultClassName]; unset($registeredMethods[$defaultClassName]); // place the default method first in the order $registeredMethods = [$defaultClassName => $defaultReference] + $registeredMethods; $methodFound = false; foreach ($registeredMethods as $method) { - $objectInstance = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($method); + $objectInstance = GeneralUtility::makeInstance($method); if ($objectInstance instanceof SaltInterface) { $methodFound = $objectInstance->isValidSaltedPW($saltedHash); if ($methodFound) { @@ -137,13 +141,13 @@ class SaltFactory * Method sets a custom salting hashing method class. * * @param string $resource Object resource to use (e.g. \TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class) - * @return \TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt An instance of salting hashing method object + * @return SaltInterface|null An instance of salting hashing method object or null */ - public static function setPreferredHashingMethod($resource) + public static function setPreferredHashingMethod(string $resource) { self::$instance = null; - $objectInstance = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($resource); - if (is_object($objectInstance) && is_subclass_of($objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt::class)) { + $objectInstance = GeneralUtility::makeInstance($resource); + if ($objectInstance instanceof SaltInterface) { self::$instance = $objectInstance; } return self::$instance; diff --git a/typo3/sysext/saltedpasswords/Classes/Salt/SaltInterface.php b/typo3/sysext/saltedpasswords/Classes/Salt/SaltInterface.php index 83022efaa26f7b59fa0a5f08eb68ade2b33bc499..fac7ea5fbf61b476cfce39f09c9273653d94ae26 100644 --- a/typo3/sysext/saltedpasswords/Classes/Salt/SaltInterface.php +++ b/typo3/sysext/saltedpasswords/Classes/Salt/SaltInterface.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); namespace TYPO3\CMS\Saltedpasswords\Salt; /* @@ -28,21 +29,14 @@ interface SaltInterface * @param string $saltedHashPW Salted hash to compare plain-text password with * @return bool TRUE, if plaintext password is correct, otherwise FALSE */ - public function checkPassword($plainPW, $saltedHashPW); - - /** - * Returns length of required salt. - * - * @return int Length of required salt - */ - public function getSaltLength(); + public function checkPassword(string $plainPW, string $saltedHashPW): bool; /** * Returns whether all prequesites for the hashing methods are matched * * @return bool Method available */ - public function isAvailable(); + public function isAvailable(): bool; /** * Method creates a salted hash for a given plaintext password @@ -51,7 +45,7 @@ interface SaltInterface * @param string $salt Optional custom salt to use * @return string Salted hashed password */ - public function getHashedPassword($password, $salt = null); + public function getHashedPassword(string $password, string $salt = null); /** * Checks whether a user's hashed password needs to be replaced with a new hash. @@ -65,15 +59,7 @@ interface SaltInterface * @param string $passString Salted hash to check if it needs an update * @return bool TRUE if salted hash needs an update, otherwise FALSE */ - public function isHashUpdateNeeded($passString); - - /** - * Method determines if a given string is a valid salt - * - * @param string $salt String to check - * @return bool TRUE if it's valid salt, otherwise FALSE - */ - public function isValidSalt($salt); + public function isHashUpdateNeeded(string $passString): bool; /** * Method determines if a given string is a valid salted hashed password. @@ -81,5 +67,5 @@ interface SaltInterface * @param string $saltedPW String to check * @return bool TRUE if it's valid salted hashed password, otherwise FALSE */ - public function isValidSaltedPW($saltedPW); + public function isValidSaltedPW(string $saltedPW): bool; } diff --git a/typo3/sysext/saltedpasswords/Classes/SaltedPasswordService.php b/typo3/sysext/saltedpasswords/Classes/SaltedPasswordService.php index 60f44fdaf04eade6fe6e986d417d6ac367930237..e8d1e49a316a1621ab07c110bd344c8134d9975d 100644 --- a/typo3/sysext/saltedpasswords/Classes/SaltedPasswordService.php +++ b/typo3/sysext/saltedpasswords/Classes/SaltedPasswordService.php @@ -50,7 +50,7 @@ class SaltedPasswordService extends AbstractAuthenticationService * An instance of the salted hashing method. * This member is set in the getSaltingInstance() function. * - * @var \TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt + * @var \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface */ protected $objInstanceSaltedPW = null; diff --git a/typo3/sysext/saltedpasswords/Documentation/DevelopersGuide/Index.rst b/typo3/sysext/saltedpasswords/Documentation/DevelopersGuide/Index.rst index b027deb086c14fba4eec64b8a397c47320a48682..6f46e4d481ee309ef5db8fcb3bb9c886594d76cf 100644 --- a/typo3/sysext/saltedpasswords/Documentation/DevelopersGuide/Index.rst +++ b/typo3/sysext/saltedpasswords/Documentation/DevelopersGuide/Index.rst @@ -93,8 +93,10 @@ such additional method available for this extension. Steps to be done: - create a new salting class that implements interface - :code:`\TYPO3\CMS\Saltedpasswords\Salt\SaltInterface` and abstract class - :code:`\TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt` (see class + :code:`\TYPO3\CMS\Saltedpasswords\Salt\SaltInterface` + + Optional: take advantage of abstract class + :code:`\TYPO3\CMS\Saltedpasswords\Salt\AbstractComposedSalt` (see class :code:`\TYPO3\CMS\Saltedpasswords\Salt\Md5Salt` for an example implementation) - register your salting method class diff --git a/typo3/sysext/saltedpasswords/Migrations/Code/ClassAliasMap.php b/typo3/sysext/saltedpasswords/Migrations/Code/ClassAliasMap.php new file mode 100644 index 0000000000000000000000000000000000000000..eff3a7a3c98e21885415b47e9ea46b35cc12712c --- /dev/null +++ b/typo3/sysext/saltedpasswords/Migrations/Code/ClassAliasMap.php @@ -0,0 +1,4 @@ +<?php +return [ + 'TYPO3\\CMS\\Saltedpasswords\\Salt\\AbstractSalt' => \TYPO3\CMS\Saltedpasswords\Salt\AbstractComposedSalt::class, +]; diff --git a/typo3/sysext/saltedpasswords/Tests/Unit/Salt/SaltFactoryTest.php b/typo3/sysext/saltedpasswords/Tests/Unit/Salt/SaltFactoryTest.php index d72c23e8eb5b2589d258deeb0891b12c78c75587..281b9fb77e1af8b27532606c225f2d81be437215 100644 --- a/typo3/sysext/saltedpasswords/Tests/Unit/Salt/SaltFactoryTest.php +++ b/typo3/sysext/saltedpasswords/Tests/Unit/Salt/SaltFactoryTest.php @@ -24,7 +24,7 @@ class SaltFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase /** * Keeps instance of object to test. * - * @var \TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt + * @var \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface */ protected $objectInstance = null; @@ -59,32 +59,23 @@ class SaltFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $this->assertNotNull($this->objectInstance); } - /** - * @test - */ - public function objectInstanceExtendsAbstractClass() - { - $this->assertTrue(is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\AbstractSalt::class)); - } - /** * @test */ public function objectInstanceImplementsInterface() { - $this->assertTrue(method_exists($this->objectInstance, 'checkPassword'), 'Missing method checkPassword() from interface ' . \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface::class . '.'); - $this->assertTrue(method_exists($this->objectInstance, 'isHashUpdateNeeded'), 'Missing method isHashUpdateNeeded() from interface ' . \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface::class . '.'); - $this->assertTrue(method_exists($this->objectInstance, 'isValidSalt'), 'Missing method isValidSalt() from interface ' . \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface::class . '.'); - $this->assertTrue(method_exists($this->objectInstance, 'isValidSaltedPW'), 'Missing method isValidSaltedPW() from interface ' . \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface::class . '.'); - $this->assertTrue(method_exists($this->objectInstance, 'getHashedPassword'), 'Missing method getHashedPassword() from interface ' . \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface::class . '.'); - $this->assertTrue(method_exists($this->objectInstance, 'getSaltLength'), 'Missing method getSaltLength() from interface ' . \TYPO3\CMS\Saltedpasswords\Salt\SaltInterface::class . '.'); + $this->assertInstanceOf(\TYPO3\CMS\Saltedpasswords\Salt\SaltInterface::class, $this->objectInstance); } /** * @test */ - public function base64EncodeReturnsProperLength() + public function abstractComposedSaltBase64EncodeReturnsProperLength() { + // set up an instance that extends AbstractComposedSalt first + $saltPbkdf2 = '$pbkdf2-sha256$6400$0ZrzXitFSGltTQnBWOsdAw$Y11AchqV4b0sUisdZd0Xr97KWoymNE0LNNrnEgY4H9M'; + $this->objectInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($saltPbkdf2); + // 3 Bytes should result in a 6 char length base64 encoded string // used for MD5 and PHPass salted hashing $byteLength = 3; @@ -107,6 +98,7 @@ class SaltFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $saltMD5 = '$1$rasmusle$rISCgZzpwk3UhDidwXvin0'; $this->objectInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($saltMD5); $this->assertTrue(get_class($this->objectInstance) == \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class || is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\Md5Salt::class)); + $this->assertInstanceOf(\TYPO3\CMS\Saltedpasswords\Salt\AbstractComposedSalt::class, $this->objectInstance); } /** @@ -117,6 +109,7 @@ class SaltFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $saltBlowfish = '$2a$07$abcdefghijklmnopqrstuuIdQV69PAxWYTgmnoGpe0Sk47GNS/9ZW'; $this->objectInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($saltBlowfish); $this->assertTrue(get_class($this->objectInstance) == \TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class || is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\BlowfishSalt::class)); + $this->assertInstanceOf(\TYPO3\CMS\Saltedpasswords\Salt\AbstractComposedSalt::class, $this->objectInstance); } /** @@ -127,6 +120,7 @@ class SaltFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $saltPhpass = '$P$CWF13LlG/0UcAQFUjnnS4LOqyRW43c.'; $this->objectInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($saltPhpass); $this->assertTrue(get_class($this->objectInstance) == \TYPO3\CMS\Saltedpasswords\Salt\PhpassSalt::class || is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\PhpassSalt::class)); + $this->assertInstanceOf(\TYPO3\CMS\Saltedpasswords\Salt\AbstractComposedSalt::class, $this->objectInstance); } /** @@ -137,6 +131,7 @@ class SaltFactoryTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $saltPbkdf2 = '$pbkdf2-sha256$6400$0ZrzXitFSGltTQnBWOsdAw$Y11AchqV4b0sUisdZd0Xr97KWoymNE0LNNrnEgY4H9M'; $this->objectInstance = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($saltPbkdf2); $this->assertTrue(get_class($this->objectInstance) == \TYPO3\CMS\Saltedpasswords\Salt\Pbkdf2Salt::class || is_subclass_of($this->objectInstance, \TYPO3\CMS\Saltedpasswords\Salt\Pbkdf2Salt::class)); + $this->assertInstanceOf(\TYPO3\CMS\Saltedpasswords\Salt\AbstractComposedSalt::class, $this->objectInstance); } /** diff --git a/typo3/sysext/saltedpasswords/composer.json b/typo3/sysext/saltedpasswords/composer.json index 9a1914cfaea12bdaf36ad35dc88fbbe378106730..21966ff90b221d0354d0013d8f74ce7130147612 100644 --- a/typo3/sysext/saltedpasswords/composer.json +++ b/typo3/sysext/saltedpasswords/composer.json @@ -30,6 +30,11 @@ "partOfMinimalUsableSystem": true }, "extension-key": "saltedpasswords" + }, + "typo3/class-alias-loader": { + "class-alias-maps": [ + "Migrations/Code/ClassAliasMap.php" + ] } }, "autoload": {