Skip to content

Commit eae871b

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

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/Core/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($user->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);
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);
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy