Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cc7cdf2

Browse filesBrowse files
minor symfony#49879 [Validator] Improve entropy estimation in PasswordStrengthValidator (nicolas-grekas)
This PR was merged into the 6.3 branch. Discussion ---------- [Validator] Improve entropy estimation in PasswordStrengthValidator | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Improves a bit the estimation of the entropy. /cc `@Spomky` Commits ------- 99c09ff [Validator] Improve entropy estimation in PasswordStrengthValidator
2 parents 4e3ac5e + 99c09ff commit cc7cdf2
Copy full SHA for cc7cdf2

File tree

Expand file treeCollapse file tree

3 files changed

+41
-8
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+41
-8
lines changed

‎src/Symfony/Component/Validator/Constraints/PasswordStrength.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/PasswordStrength.php
+9-5Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,16 @@ final class PasswordStrength extends Constraint
4040

4141
public int $minScore;
4242

43-
public function __construct(int $minScore = self::STRENGTH_REASONABLE, mixed $options = null, array $groups = null, mixed $payload = null)
43+
public function __construct(array $options = null, int $minScore = null, array $groups = null, mixed $payload = null)
4444
{
45-
if (isset($minScore) && (!\is_int($minScore) || $minScore < 1 || $minScore > 4)) {
46-
throw new ConstraintDefinitionException(sprintf('The parameter "minScore" of the "%s" constraint must be an integer between 1 and 4.', static::class));
47-
}
48-
$options['minScore'] = $minScore;
45+
$options['minScore'] ??= self::STRENGTH_REASONABLE;
46+
4947
parent::__construct($options, $groups, $payload);
48+
49+
$this->minScore = $minScore ?? $this->minScore;
50+
51+
if ($this->minScore < 1 || 4 < $this->minScore) {
52+
throw new ConstraintDefinitionException(sprintf('The parameter "minScore" of the "%s" constraint must be an integer between 1 and 4.', self::class));
53+
}
5054
}
5155
}

‎src/Symfony/Component/Validator/Constraints/PasswordStrengthValidator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Constraints/PasswordStrengthValidator.php
+20-1Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,26 @@ public function validate(#[\SensitiveParameter] mixed $value, Constraint $constr
5858
*/
5959
private static function estimateStrength(#[\SensitiveParameter] string $password): int
6060
{
61-
$entropy = log(\strlen(count_chars($password, 3)) ** \strlen($password), 2);
61+
if (!$length = \strlen($password)) {
62+
return PasswordStrength::STRENGTH_VERY_WEAK;
63+
}
64+
$password = count_chars($password, 1);
65+
$chars = \count($password);
66+
67+
$control = $digit = $upper = $lower = $symbol = $other = 0;
68+
foreach ($password as $chr => $count) {
69+
match (true) {
70+
$chr < 32 || 127 === $chr => $control = 33,
71+
48 <= $chr && $chr <= 57 => $digit = 10,
72+
65 <= $chr && $chr <= 90 => $upper = 26,
73+
97 <= $chr && $chr <= 122 => $lower = 26,
74+
128 <= $chr => $other = 128,
75+
default => $symbol = 33,
76+
};
77+
}
78+
79+
$pool = $lower + $upper + $digit + $symbol + $control + $other;
80+
$entropy = $chars * log($pool, 2) + ($length - $chars) * log($chars, 2);
6281

6382
return match (true) {
6483
$entropy >= 120 => PasswordStrength::STRENGTH_VERY_STRONG,

‎src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Tests/Constraints/PasswordStrengthValidatorTest.php
+12-2Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,22 @@ public function testValidValues(string $value, int $expectedStrength)
3030
$this->validator->validate($value, new PasswordStrength(minScore: $expectedStrength));
3131

3232
$this->assertNoViolation();
33+
34+
if (PasswordStrength::STRENGTH_VERY_STRONG === $expectedStrength) {
35+
return;
36+
}
37+
38+
$this->validator->validate($value, new PasswordStrength(minScore: $expectedStrength + 1));
39+
40+
$this->buildViolation('The password strength is too low. Please use a stronger password.')
41+
->setCode(PasswordStrength::PASSWORD_STRENGTH_ERROR)
42+
->assertRaised();
3343
}
3444

3545
public static function getValidValues(): iterable
3646
{
37-
yield ['How-is this 🤔?!', PasswordStrength::STRENGTH_WEAK];
38-
yield ['Reasonable-pwd-❤️', PasswordStrength::STRENGTH_REASONABLE];
47+
yield ['How-is-this', PasswordStrength::STRENGTH_WEAK];
48+
yield ['Reasonable-pwd', PasswordStrength::STRENGTH_REASONABLE];
3949
yield ['This 1s a very g00d Pa55word! ;-)', PasswordStrength::STRENGTH_VERY_STRONG];
4050
yield ['pudding-smack-👌🏼-fox-😎', PasswordStrength::STRENGTH_VERY_STRONG];
4151
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.