18
18
19
19
final class PasswordStrengthValidator extends ConstraintValidator
20
20
{
21
+ /**
22
+ * @param (\Closure(string):PasswordStrength::STRENGTH_*)|null $passwordStrengthEstimator
23
+ */
21
24
public function __construct (
22
25
private readonly ?\Closure $ passwordStrengthEstimator = null ,
23
26
) {
@@ -36,7 +39,7 @@ public function validate(#[\SensitiveParameter] mixed $value, Constraint $constr
36
39
if (!\is_string ($ value )) {
37
40
throw new UnexpectedValueException ($ value , 'string ' );
38
41
}
39
- $ passwordStrengthEstimator = $ this ->passwordStrengthEstimator ?? $ this -> estimate (...);
42
+ $ passwordStrengthEstimator = $ this ->passwordStrengthEstimator ?? self :: estimateStrength (...);
40
43
$ strength = $ passwordStrengthEstimator ($ value );
41
44
42
45
if ($ strength < $ constraint ->minScore ) {
@@ -47,26 +50,22 @@ public function validate(#[\SensitiveParameter] mixed $value, Constraint $constr
47
50
}
48
51
49
52
/**
50
- * Returns the estimated strength of a password between 0 and 4 .
53
+ * Returns the estimated strength of a password.
51
54
* The higher the value, the stronger the password.
52
55
*
53
- * @return int<0, 4>
56
+ * @return PasswordStrength::STRENGTH_*
54
57
*/
55
- private static function estimate (#[\SensitiveParameter] string $ password ): int
58
+ private static function estimateStrength (#[\SensitiveParameter] string $ password ): int
56
59
{
57
- $ criteria = [
58
- ['score ' => PasswordStrength::STRENGTH_VERY_STRONG , 'minEntropy ' => 120 ],
59
- ['score ' => PasswordStrength::STRENGTH_STRONG , 'minEntropy ' => 100 ],
60
- ['score ' => PasswordStrength::STRENGTH_REASONABLE , 'minEntropy ' => 80 ],
61
- ['score ' => PasswordStrength::STRENGTH_WEAK , 'minEntropy ' => 60 ],
62
- ['score ' => PasswordStrength::STRENGTH_VERY_WEAK , 'minEntropy ' => 0 ],
63
- ];
64
60
$ uniqueChars = array_unique (str_split ($ password ));
65
61
$ entropy = log (\count ($ uniqueChars ) ** \strlen ($ password ), 2 );
66
- $ fulfilledCriteria = array_filter ($ criteria , function (array $ option ) use ($ entropy ) {
67
- return $ entropy >= $ option ['minEntropy ' ];
68
- });
69
62
70
- return current ($ fulfilledCriteria )['score ' ] ?? PasswordStrength::STRENGTH_VERY_WEAK ;
63
+ return match (true ) {
64
+ $ entropy >= 120 => PasswordStrength::STRENGTH_VERY_STRONG ,
65
+ $ entropy >= 100 => PasswordStrength::STRENGTH_STRONG ,
66
+ $ entropy >= 80 => PasswordStrength::STRENGTH_REASONABLE ,
67
+ $ entropy >= 60 => PasswordStrength::STRENGTH_WEAK ,
68
+ default => PasswordStrength::STRENGTH_VERY_WEAK ,
69
+ };
71
70
}
72
71
}
0 commit comments