8000 [Security] add PasswordEncoderInterface::needsRehash() · symfony/symfony@7daff22 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7daff22

Browse files
[Security] add PasswordEncoderInterface::needsRehash()
1 parent c315767 commit 7daff22

11 files changed

+105
-0
lines changed

src/Symfony/Component/Security/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
4.4.0
5+
-----
6+
7+
* Added methods `PasswordEncoderInterface::needsRehash()` and `UserPasswordEncoderInterface::needsRehash()`
8+
49
4.3.0
510
-----
611

src/Symfony/Component/Security/Core/Encoder/BasePasswordEncoder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ abstract class BasePasswordEncoder implements PasswordEncoderInterface
2020
{
2121
const MAX_PASSWORD_LENGTH = 4096;
2222

23+
/**
24+
* {@inheritdoc}
25+
*/
26+
public function needsRehash(string $encoded): bool
27+
{
28+
return false;
29+
}
30+
2331
/**
2432
* Demerges a merge password and salt string.
2533
*

src/Symfony/Component/Security/Core/Encoder/NativePasswordEncoder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,12 @@ public function isPasswordValid($encoded, $raw, $salt)
8787

8888
return \strlen($raw) <= self::MAX_PASSWORD_LENGTH && password_verify($raw, $encoded);
8989
}
90+
91+
/**
92+
* {@inheritdoc}
93+
*/
94+
public function needsRehash(string $encoded): bool
95+
{
96+
return password_needs_rehash($encoded, $this->algo, $this->options);
97+
}
9098
}

src/Symfony/Component/Security/Cor 8000 e/Encoder/PasswordEncoderInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* PasswordEncoderInterface is the interface for all encoders.
1818
*
1919
* @author Fabien Potencier <fabien@symfony.com>
20+
*
21+
* @method bool needsRehash(string $encoded)
2022
*/
2123
interface PasswordEncoderInterface
2224
{

src/Symfony/Component/Security/Core/Encoder/SodiumPasswordEncoder.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,20 @@ public function isPasswordValid($encoded, $raw, $salt)
9494

9595
throw new LogicException('Libsodium is not available. You should either install the sodium extension, upgrade to PHP 7.2+ or use a different encoder.');
9696
}
97+
98+
/**
99+
* {@inheritdoc}
100+
*/
101+
public function needsRehash(string $encoded): bool
102+
{
103+
if (\function_exists('sodium_crypto_pwhash_str_needs_rehash')) {
104+
return \sodium_crypto_pwhash_str_needs_rehash($encoded, $this->opsLimit, $this->memLimit);
105+
}
106+
107+
if (\extension_loaded('libsodium')) {
108+
return \Sodium\crypto_pwhash_str_needs_rehash($encoded, $this->opsLimit, $this->memLimit);
109+
}
110+
111+
throw new LogicException('Libsodium is not available. You should either install the sodium extension, upgrade to PHP 7.2+ or use a different encoder.');
112+
}
97113
}

src/Symfony/Component/Security/Core/Encoder/UserPasswordEncoder.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,14 @@ public function isPasswordValid(UserInterface $user, $raw)
4646

4747
return $encoder->isPasswordValid($u 8000 ser->getPassword(), $raw, $user->getSalt());
4848
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
public function needsRehash(UserInterface $user, string $encoded): bool
54+
{
55+
$encoder = $this->encoderFactory->getEncoder($user);
56+
57+
return method_exists($encoder, 'needsRehash') && $encoder->needsRehash($encoded);
58+
}
4959
}

src/Symfony/Component/Security/Core/Encoder/UserPasswordEncoderInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* UserPasswordEncoderInterface is the interface for the password encoder service.
1818
*
1919
* @author Ariel Ferrandini <arielferrandini@gmail.com>
20+
*
21+
* @method bool needsRehash(UserInterface $user, string $encoded)
2022
*/
2123
interface UserPasswordEncoderInterface
2224
{

src/Symfony/Component/Security/Core/Tests/Encoder/BasePasswordEncoderTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ public function testIsPasswordTooLong()
6060
$this->assertFalse($this->invokeIsPasswordTooLong(str_repeat('a', 10)));
6161
}
6262

63+
public function testNeedsRehash()
64+
{
65+
$encoder = new PasswordEncoder();
66+
$this->assertFalse($encoder->needsRehash('foo'));
67+
}
68+
6369
protected function invokeDemergePasswordAndSalt($password)
6470
{
6571
$encoder = new PasswordEncoder();

src/Symfony/Component/Security/Core/Tests/Encoder/NativePasswordEncoderTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,17 @@ public function testCheckPasswordLength()
6767
$this->assertFalse($encoder->isPasswordValid($result, str_repeat('a', 73), 'salt'));
6868
$this->assertTrue($encoder->isPasswordValid($result, str_repeat('a', 72), 'salt'));
6969
}
70+
71+
public function testNeedsRehash()
72+
{
73+
$encoder = new NativePasswordEncoder(4, 11000, 4);
74+
75+
$this->assertTrue($encoder->needsRehash('dummyhash'));
76+
77+
$hash = $encoder->encodePassword('foo', 'salt');
78+
$this->assertFalse($encoder->needsRehash($hash));
79+
80+
$encoder = new NativePasswordEncoder(5, 11000, 5);
81+
$this->assertTrue($encoder->needsRehash($hash));
82+
}
7083
}

src/Symfony/Component/Security/Core/Tests/Encoder/SodiumPasswordEncoderTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,17 @@ public function testUserProvidedSaltIsNotUsed()
5454
$result = $encoder->encodePassword('password', 'salt');
5555
$this->assertTrue($encoder->isPasswordValid($result, 'password', 'anotherSalt'));
5656
}
57+
58+
public function testNeedsRehash()
59+
{
60+
$encoder = new SodiumPasswordEncoder(4, 11000);
61+
62+
$this->assertTrue($encoder->needsRehash('dummyhash'));
63+
64+
$hash = $encoder->encodePassword('foo', 'salt');
65+
$this->assertFalse($encoder->needsRehash($hash));
66+
67+
$encoder = new SodiumPasswordEncoder(5, 11000);
68+
$this->assertTrue($encoder->needsRehash($hash));
69+
}
5770
}

0 commit comments

Comments
 (0)
0