Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 89ec311

Browse files
author
Robin Chalas
committed
feature #31140 [Security] Add NativePasswordEncoder (nicolas-grekas)
This PR was merged into the 4.3-dev branch. Discussion ---------- [Security] Add NativePasswordEncoder | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - This PR adds a new `NativePasswordEncoder` that defaults to the best available hashing algo to `password_hash()`. Best is determined by "us" or "php", the goal being that this will change in the future as new algos are published. This provides a native encoder that we should recommend using by default. Commits ------- 28f7961 [Security] Add NativePasswordEncoder
2 parents a59fe66 + 28f7961 commit 89ec311

16 files changed

+314
-39
lines changed

UPGRADE-4.3.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Security
174174
SecurityBundle
175175
--------------
176176

177-
* Configuring encoders using `argon2i` as algorithm has been deprecated, use `sodium` instead.
177+
* Configuring encoders using `argon2i` as algorithm has been deprecated, use `auto` instead.
178178

179179
TwigBridge
180180
----------

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ CHANGELOG
44
4.3.0
55
-----
66

7+
* Added new encoder types: `auto` (recommended), `native` and `sodium`
78
* The normalization of the cookie names configured in the `logout.delete_cookies`
89
option is deprecated and will be disabled in Symfony 5.0. This affects to cookies
910
with dashes in their names. For example, starting from Symfony 5.0, the `my-cookie`
1011
name will delete `my-cookie` (with a dash) instead of `my_cookie` (with an underscore).
11-
* Deprecated configuring encoders using `argon2i` as algorithm, use `sodium` instead
12+
* Deprecated configuring encoders using `argon2i` as algorithm, use `auto` instead
1213

1314
4.2.0
1415
-----

src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,10 @@ private function addEncodersSection(ArrayNodeDefinition $rootNode)
394394
->children()
395395
->arrayNode('encoders')
396396
->example([
397-
'App\Entity\User1' => 'bcrypt',
397+
'App\Entity\User1' => 'auto',
398398
'App\Entity\User2' => [
399-
'algorithm' => 'bcrypt',
399+
'algorithm' => 'auto',
400+
'time_cost' => 8,
400401
'cost' => 13,
401402
],
402403
])
@@ -416,11 +417,14 @@ private function addEncodersSection(ArrayNodeDefinition $rootNode)
416417
->integerNode('cost')
417418
->min(4)
418419
->max(31)
419-
->defaultValue(13)
420+
->defaultNull()
420421
->end()
421422
->scalarNode('memory_cost')->defaultNull()->end()
422423
->scalarNode('time_cost')->defaultNull()->end()
423-
->scalarNode('threads')->defaultNull()->end()
424+
->scalarNode('threads')
425+
->defaultNull()
426+
->setDeprecated('The "%path%.%node%" configuration key has no effect since Symfony 4.3 and will be removed in 5.0.')
427+
->end()
424428
->scalarNode('id')->end()
425429
->end()
426430
->end()

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
3131
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
3232
use Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder;
33+
use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder;
3334
use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder;
3435
use Symfony\Component\Security\Core\User\UserProviderInterface;
3536
use Symfony\Component\Security\Http\Controller\UserValueResolver;
@@ -559,20 +560,20 @@ private function createEncoder($config, ContainerBuilder $container)
559560
if ('bcrypt' === $config['algorithm']) {
560561
return [
561562
'class' => 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder',
562-
'arguments' => [$config['cost']],
563+
'arguments' => [$config['cost'] ?? 13],
563564
];
564565
}
565566

566567
// Argon2i encoder
567568
if ('argon2i' === $config['algorithm']) {
568-
@trigger_error('Configuring an encoder with "argon2i" as algorithm is deprecated since Symfony 4.3, use "sodium" instead.', E_USER_DEPRECATED);
569+
@trigger_error('Configuring an encoder with "argon2i" as algorithm is deprecated since Symfony 4.3, use "auto" instead.', E_USER_DEPRECATED);
569570

570571
if (!Argon2iPasswordEncoder::isSupported()) {
571572
if (\extension_loaded('sodium') && !\defined('SODIUM_CRYPTO_PWHASH_SALTBYTES')) {
572-
throw new InvalidConfigurationException('The installed libsodium version does not have support for Argon2i. Use Bcrypt instead.');
573+
throw new InvalidConfigurationException('The installed libsodium version does not have support for Argon2i. Use "auto" instead.');
573574
}
574575

575-
throw new InvalidConfigurationException('Argon2i algorithm is not supported. Install the libsodium extension or use BCrypt instead.');
576+
throw new InvalidConfigurationException('Argon2i algorithm is not supported. Install the libsodium extension or use "auto" instead.');
576577
}
577578

578579
return [
@@ -585,14 +586,28 @@ private function createEncoder($config, ContainerBuilder $container)
585586
];
586587
}
587588

589+
if ('native' === $config['algorithm']) {
590+
return [
591+
'class' => NativePasswordEncoder::class,
592+
'arguments' => [
593+
$config['time_cost'],
594+
(($config['memory_cost'] ?? 0) << 10) ?: null,
595+
$config['cost'],
596+
],
597+
];
598+
}
599+
588600
if ('sodium' === $config['algorithm']) {
589601
if (!SodiumPasswordEncoder::isSupported()) {
590-
throw new InvalidConfigurationException('Libsodium is not available. Install the sodium extension or use BCrypt instead.');
602+
throw new InvalidConfigurationException('Libsodium is not available. Install the sodium extension or use "auto" instead.');
591603
}
592604

593605
return [
594606
'class' => SodiumPasswordEncoder::class,
595-
'arguments' => [],
607+
'arguments' => [
608+
$config['time_cost'],
609+
(($config['memory_cost'] ?? 0) << 10) ?: null,
610+
],
596611
];
597612
}
598613

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ public function testEncoders()
283283
'hash_algorithm' => 'sha512',
284284
'key_length' => 40,
285285
'ignore_case' => false,
286-
'cost' => 13,
286+
'cost' => null,
287287
'memory_cost' => null,
288288
'time_cost' => null,
289289
'threads' => null,
@@ -295,7 +295,7 @@ public function testEncoders()
295295
'ignore_case' => false,
296296
'encode_as_base64' => true,
297297
'iterations' => 5000,
298-
'cost' => 13,
298+
'cost' => null,
299299
'memory_cost' => null,
300300
'time_cost' => null,
301301
'threads' => null,
@@ -309,6 +309,22 @@ public function testEncoders()
309309
'class' => 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder',
310310
'arguments' => [15],
311311
],
312+
'JMS\FooBundle\Entity\User7' => [
313+
'class' => 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder',
314+
'arguments' => [8, 102400, 15],
315+
],
316+
'JMS\FooBundle\Entity\User8' => [
317+
'algorithm' => 'auto',
318+
'hash_algorithm' => 'sha512',
319+
'key_length' => 40,
320+
'ignore_case' => false,
321+
'encode_as_base64' => true,
322+
'iterations' => 5000,
323+
'cost' => null,
324+
'memory_cost' => null,
325+
'time_cost' => null,
326+
'threads' => null,
327+
],
312328
]], $container->getDefinition('security.encoder_factory.generic')->getArguments());
313329
}
314330

@@ -332,7 +348,7 @@ public function testEncodersWithLibsodium()
332348
'hash_algorithm' => 'sha512',
333349
'key_length' => 40,
334350
'ignore_case' => false,
335-
'cost' => 13,
351+
'cost' => null,
336352
'memory_cost' => null,
337353
'time_cost' => null,
338354
'threads' => null,
@@ -344,7 +360,7 @@ public function testEncodersWithLibsodium()
344360
'ignore_case' => false,
345361
'encode_as_base64' => true,
346362
'iterations' => 5000,
347-
'cost' => 13,
363+
'cost' => null,
348364
'memory_cost' => null,
349365
'time_cost' => null,
350366
'threads' => null,
@@ -360,15 +376,27 @@ public function testEncodersWithLibsodium()
360376
],
361377
'JMS\FooBundle\Entity\User7' => [
362378
'class' => 'Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder',
363-
'arguments' => [],
379+
'arguments' => [8, 128 * 1024 * 1024],
380+
],
381+
'JMS\FooBundle\Entity\User8' => [
382+
'algorithm' => 'auto',
383+
'hash_algorithm' => 'sha512',
384+
'key_length' => 40,
385+
'ignore_case' => false,
386+
'encode_as_base64' => true,
387+
'iterations' => 5000,
388+
'cost' => null,
389+
'memory_cost' => null,
390+
'time_cost' => null,
391+
'threads' => null,
364392
],
365393
]], $container->getDefinition('security.encoder_factory.generic')->getArguments());
366394
}
367395

368396
/**
369397
* @group legacy
370398
*
371-
* @expectedDeprecation Configuring an encoder with "argon2i" as algorithm is deprecated since Symfony 4.3, use "sodium" instead.
399+
* @expectedDeprecation Configuring an encoder with "argon2i" as algorithm is deprecated since Symfony 4.3, use "auto" instead.
372400
*/
373401
public function testEncodersWithArgon2i()
374402
{
@@ -390,7 +418,7 @@ public function testEncodersWithArgon2i()
390418
'hash_algorithm' => 'sha512',
391419
'key_length' => 40,
392420
'ignore_case' => false,
393-
'cost' => 13,
421+
'cost' => null,
394422
'memory_cost' => null,
395423
'time_cost' => null,
396424
'threads' => null,
@@ -402,7 +430,7 @@ public function testEncodersWithArgon2i()
402430
'ignore_case' => false,
403431
'encode_as_base64' => true,
404432
'iterations' => 5000,
405-
'cost' => 13,
433+
'cost' => null,
406434
'memory_cost' => null,
407435
'time_cost' => null,
408436
'threads' => null,
@@ -420,6 +448,18 @@ public function testEncodersWithArgon2i()
420448
'class' => 'Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder',
421449
'arguments' => [256, 1, 2],
422450
],
451+
'JMS\FooBundle\Entity\User8' => [
452+
'algorithm' => 'auto',
453+
'hash_algorithm' => 'sha512',
454+
'key_length' => 40,
455+
'ignore_case' => false,
456+
'encode_as_base64' => true,
457+
'iterations' => 5000,
458+
'cost' => null,
459+
'memory_cost' => null,
460+
'time_cost' => null,
461+
'threads' => null,
462+
],
423463
]], $container->getDefinition('security.encoder_factory.generic')->getArguments());
424464
}
425465

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@
2525
'algorithm' => 'bcrypt',
2626
'cost' => 15,
2727
],
28+
'JMS\FooBundle\Entity\User7' => [
29+
'algorithm' => 'native',
30+
'time_cost' => 8,
31+
'memory_cost' => 100,
32+
'cost' => 15,
33+
],
34+
'JMS\FooBundle\Entity\User8' => [
35+
'algorithm' => 'auto',
36+
],
2837
],
2938
'providers' => [
3039
'default' => [

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/sodium_encoder.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
'encoders' => [
77
'JMS\FooBundle\Entity\User7' => [
88
'algorithm' => 'sodium',
9+
'time_cost' => 8,
10+
'memory_cost' => 128 * 1024,
911
],
1012
],
1113
]);

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818

1919
<encoder class="JMS\FooBundle\Entity\User6" algorithm="bcrypt" cost="15" />
2020

21+
<encoder class="JMS\FooBundle\Entity\User7" algorithm="native" time-cost="8" memory-cost="100" cost="15" />
22+
23+
<encoder class="JMS\FooBundle\Entity\User8" algorithm="auto" />
24+
2125
<provider name="default">
2226
<memory>
2327
<user name="foo" password="foo" roles="ROLE_USER" />

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/sodium_encoder.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</imports>
1111

1212
<sec:config>
13-
<sec:encoder class="JMS\FooBundle\Entity\User7" algorithm="sodium" />
13+
<sec:encoder class="JMS\FooBundle\Entity\User7" algorithm="sodium" time-cost="8" memory-cost="131072" />
1414
</sec:config>
1515

1616
</container>

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ security:
1818
JMS\FooBundle\Entity\User6:
1919
algorithm: bcrypt
2020
cost: 15
21+
JMS\FooBundle\Entity\User7:
22+
algorithm: native
23+
time_cost: 8
24+
memory_cost: 100
25+
cost: 15
26+
JMS\FooBundle\Entity\User8:
27+
algorithm: auto
2128

2229
providers:
2330
default:

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/sodium_encoder.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ security:
55
encoders:
66
JMS\FooBundle\Entity\User7:
77
algorithm: sodium
8+
time_cost: 8
9+
memory_cost: 131072

src/Symfony/Component/Security/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ CHANGELOG
44
4.3.0
55
-----
66

7+
* Added methods `__serialize` and `__unserialize` to the `TokenInterface`
8+
* Added `SodiumPasswordEncoder` and `NativePasswordEncoder`
79
* The `Role` and `SwitchUserRole` classes are deprecated and will be removed in 5.0. Use strings for roles
810
instead.
911
* The `getReachableRoles()` method of the `RoleHierarchyInterface` is deprecated and will be removed in 5.0.
@@ -19,8 +21,7 @@ CHANGELOG
1921
* Dispatch `AuthenticationFailureEvent` on `security.authentication.failure`
2022
* Dispatch `InteractiveLoginEvent` on `security.interactive_login`
2123
* Dispatch `SwitchUserEvent` on `security.switch_user`
22-
* deprecated `Argon2iPasswordEncoder`, use `SodiumPasswordEncoder` instead
23-
* Added methods `__serialize` and `__unserialize` to the `TokenInterface`
24+
* Deprecated `Argon2iPasswordEncoder`, use `SodiumPasswordEncoder`
2425

2526
4.2.0
2627
-----

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ private function createEncoder(array $config)
8484

8585
private function getEncoderConfigFromAlgorithm($config)
8686
{
87+
if ('auto' === $config['algorithm']) {
88+
$config['algorithm'] = SodiumPasswordEncoder::isSupported() ? 'sodium' : 'native';
89+
}
90+
8791
switch ($config['algorithm']) {
8892
case 'plaintext':
8993
return [
@@ -108,10 +112,23 @@ private function getEncoderConfigFromAlgorithm($config)
108112
'arguments' => [$config['cost']],
109113
];
110114

115+
case 'native':
116+
return [
117+
'class' => NativePasswordEncoder::class,
118+
'arguments' => [
119+
$config['time_cost'] ?? null,
120+
(($config['memory_cost'] ?? 0) << 10) ?: null,
121+
$config['cost'] ?? null,
122+
],
123+
];
124+
111125
case 'sodium':
112126
return [
113127
'class' => SodiumPasswordEncoder::class,
114-
'arguments' => [],
128+
'arguments' => [
129+
$config['time_cost'] ?? null,
130+
(($config['memory_cost'] ?? 0) << 10) ?: null,
131+
],
115132
];
116133

117134
/* @deprecated since Symfony 4.3 */

0 commit comments

Comments
 (0)