public static function needsRehash(string $stored, EncryptionKey $secretKey, string $level = KeyFactory::INTERACTIVE) : bool
{
$config = self::getConfig($stored);
if (Util::safeStrlen($stored) < $config->SHORTEST_CIPHERTEXT_LENGTH * 4 / 3) {
throw new InvalidMessage('Encrypted password hash is too short.');
}
// First let's decrypt the hash
$hash_str = Crypto::decrypt($stored, $secretKey, $config->ENCODING)->getString();
// Upon successful decryption, verify that we're using Argon2i
if (!\hash_equals(Util::safeSubstr($hash_str, 0, 9), \Sodium\CRYPTO_PWHASH_STRPREFIX)) {
return true;
}
// Parse the cost parameters:
switch ($level) {
case KeyFactory::INTERACTIVE:
return !\hash_equals('$argon2i$v=19$m=32768,t=4,p=1$', Util::safeSubstr($hash_str, 0, 30));
case KeyFactory::MODERATE:
return !\hash_equals('$argon2i$v=19$m=131072,t=6,p=1$', Util::safeSubstr($hash_str, 0, 31));
case KeyFactory::SENSITIVE:
return !\hash_equals('$argon2i$v=19$m=524288,t=8,p=1$', Util::safeSubstr($hash_str, 0, 31));
default:
return true;
}
}