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 dc95a6f

Browse filesBrowse files
author
Robin Chalas
committed
[Security] Fix argon2 availability checks
1 parent d935f40 commit dc95a6f
Copy full SHA for dc95a6f

File tree

5 files changed

+60
-26
lines changed
Filter options

5 files changed

+60
-26
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ private function createEncoder($config, ContainerBuilder $container)
571571
}
572572

573573
throw new InvalidConfigurationException('Argon2i algorithm is not supported. Install the libsodium extension or use BCrypt instead.');
574-
} elseif (\defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
574+
} elseif (!\defined('PASSWORD_ARGON2I') && Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
575575
@trigger_error('Configuring an encoder based on the "argon2i" algorithm while only "argon2id" is supported is deprecated since Symfony 4.3, use "argon2id" instead.', E_USER_DEPRECATED);
576576
}
577577

‎src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function testEncodePasswordBcrypt()
7373

7474
public function testEncodePasswordArgon2i()
7575
{
76-
if (!Argon2iPasswordEncoder::isSupported() || \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
76+
if (!Argon2iPasswordEncoder::isSupported() || !\defined('PASSWORD_ARGON2I') && Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
7777
$this->markTestSkipped('Argon2i algorithm not available.');
7878
}
7979
$this->setupArgon2i();
@@ -95,7 +95,7 @@ public function testEncodePasswordArgon2i()
9595
public function testEncodePasswordArgon2id()
9696
{
9797
if (!Argon2idPasswordEncoder::isSupported()) {
98-
$this->markTestSkipped('Argon2i algorithm not available.');
98+
$this->markTestSkipped('Argon2id algorithm not available.');
9999
}
100100
$this->setupArgon2id();
101101
$this->passwordEncoderCommandTester->execute([
@@ -107,7 +107,7 @@ public function testEncodePasswordArgon2id()
107107
$output = $this->passwordEncoderCommandTester->getDisplay();
108108
$this->assertContains('Password encoding succeeded', $output);
109109

110-
$encoder = new Argon2iPasswordEncoder();
110+
$encoder = new Argon2idPasswordEncoder();
111111
preg_match('# Encoded password\s+(\$argon2id?\$[\w,=\$+\/]+={0,2})\s+#', $output, $matches);
112112
$hash = $matches[1];
113113
$this->assertTrue($encoder->isPasswordValid($hash, 'password', null));
@@ -175,7 +175,7 @@ public function testEncodePasswordBcryptOutput()
175175

176176
public function testEncodePasswordArgon2iOutput()
177177
{
178-
if (!Argon2iPasswordEncoder::isSupported() || \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
178+
if (!Argon2iPasswordEncoder::isSupported() || !\defined('PASSWORD_ARGON2I') && Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
179179
$this->markTestSkipped('Argon2id algorithm not available.');
180180
}
181181

‎src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php
+7-7Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ public function encodePassword($raw, $salt)
4848
if (\PHP_VERSION_ID >= 70200 && \defined('PASSWORD_ARGON2I')) {
4949
return $this->encodePasswordNative($raw, \PASSWORD_ARGON2I);
5050
} elseif (\function_exists('sodium_crypto_pwhash_str')) {
51-
if (0 === strpos($hash = $this->encodePasswordSodiumFunction($raw), Argon2idPasswordEncoder::HASH_PREFIX)) {
51+
if (Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
5252
@trigger_error(sprintf('Using "%s" while only the "argon2id" algorithm is supported is deprecated since Symfony 4.3, use "%s" instead.', __CLASS__, Argon2idPasswordEncoder::class), E_USER_DEPRECATED);
5353
}
5454

55-
return $hash;
55+
return $this->encodePasswordSodiumFunction($raw);
5656
}
5757
if (\extension_loaded('libsodium')) {
5858
return $this->encodePasswordSodiumExtension($raw);
@@ -70,12 +70,12 @@ public function isPasswordValid($encoded, $raw, $salt)
7070
return false;
7171
}
7272

73-
if (\PHP_VERSION_ID >= 70200 && \defined('PASSWORD_ARGON2I')) {
74-
// If $encoded was created via "sodium_crypto_pwhash_str()", the hashing algorithm may be "argon2id" instead of "argon2i"
75-
if ($isArgon2id = (0 === strpos($encoded, Argon2idPasswordEncoder::HASH_PREFIX))) {
76-
@trigger_error(sprintf('Calling "%s()" with a password hashed using argon2id is deprecated since Symfony 4.3, use "%s" instead.', __METHOD__, Argon2idPasswordEncoder::class), E_USER_DEPRECATED);
77-
}
73+
// If $encoded was created via "sodium_crypto_pwhash_str()", the hashing algorithm may be "argon2id" instead of "argon2i"
74+
if ($isArgon2id = (0 === strpos($encoded, Argon2idPasswordEncoder::HASH_PREFIX))) {
75+
@trigger_error(sprintf('Calling "%s()" with a password hashed using argon2id is deprecated since Symfony 4.3, use "%s" instead.', __METHOD__, Argon2idPasswordEncoder::class), E_USER_DEPRECATED);
76+
}
7877

78+
if (\PHP_VERSION_ID >= 70200 && \defined('PASSWORD_ARGON2I')) {
7979
// Remove the right part of the OR in 5.0
8080
if (\defined('PASSWORD_ARGON2I') || $isArgon2id && \defined('PASSWORD_ARGON2ID')) {
8181
return password_verify($raw, $encoded);

‎src/Symfony/Component/Security/Core/Encoder/Argon2idPasswordEncoder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Core/Encoder/Argon2idPasswordEncoder.php
+12-9Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,11 @@ public function encodePassword($raw, $salt)
4646
if (\defined('PASSWORD_ARGON2ID')) {
4747
return $this->encodePasswordNative($raw, \PASSWORD_ARGON2ID);
4848
}
49-
if (!\defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
49+
if (!self::isDefaultSodiumAlgorithm()) {
5050
throw new LogicException('Algorithm "argon2id" is not supported. Please install the libsodium extension or upgrade to PHP 7.3+.');
5151
}
5252

53-
$hash = \sodium_crypto_pwhash_str(
54-
$raw,
55-
\SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
56-
\SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
57-
);
58-
\sodium_memzero($raw);
59-
60-
return $hash;
53+
return $this->encodePasswordSodiumFunction($raw);
6154
}
6255

6356
/**
@@ -82,4 +75,14 @@ public function isPasswordValid($encoded, $raw, $salt)
8275

8376
throw new LogicException('Algorithm "argon2id" is not supported. Please install the libsodium extension or upgrade to PHP 7.3+.');
8477
}
78+
79+
/**
80+
* @internal
81+
*/
82+
public static function isDefaultSodiumAlgorithm()
83+
{
84+
return \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')
85+
&& \defined('SODIUM_CRYPTO_PWHASH_ALG_DEFAULT')
86+
&& \SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 === \SODIUM_CRYPTO_PWHASH_ALG_DEFAULT;
87+
}
8588
}

‎src/Symfony/Component/Security/Core/Tests/Encoder/Argon2iPasswordEncoderTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Core/Tests/Encoder/Argon2iPasswordEncoderTest.php
+36-5Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Security\Core\Tests\Encoder;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Security\Core\Encoder\Argon2idPasswordEncoder;
1516
use Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder;
1617

1718
/**
@@ -21,15 +22,12 @@ class Argon2iPasswordEncoderTest extends TestCase
2122
{
2223
const PASSWORD = 'password';
2324

24-
protected function setUp()
25+
public function testValidationWithConfig()
2526
{
26-
if (!Argon2iPasswordEncoder::isSupported() || \defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13')) {
27+
if (!Argon2iPasswordEncoder::isSupported() || Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
2728
$this->markTestSkipped('Argon2i algorithm is not supported.');
2829
}
29-
}
3030

31-
public function testValidationWithConfig()
32-
{
3331
$encoder = new Argon2iPasswordEncoder(8, 4, 1);
3432
$result = $encoder->encodePassword(self::PASSWORD, null);
3533
$this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null));
@@ -38,6 +36,10 @@ public function testValidationWithConfig()
3836

3937
public function testValidation()
4038
{
39+
if (!Argon2iPasswordEncoder::isSupported() || Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
40+
$this->markTestSkipped('Argon2i algorithm is not supported.');
41+
}
42+
4143
$encoder = new Argon2iPasswordEncoder();
4244
$result = $encoder->encodePassword(self::PASSWORD, null);
4345
$this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null));
@@ -49,12 +51,20 @@ public function testValidation()
4951
*/
5052
public function testEncodePasswordLength()
5153
{
54+
if (!Argon2iPasswordEncoder::isSupported() || Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
55+
$this->markTestSkipped('Argon2i algorithm is not supported.');
56+
}
57+
5258
$encoder = new Argon2iPasswordEncoder();
5359
$encoder->encodePassword(str_repeat('a', 4097), 'salt');
5460
}
5561

5662
public function testCheckPasswordLength()
5763
{
64+
if (!Argon2iPasswordEncoder::isSupported() || Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
65+
$this->markTestSkipped('Argon2i algorithm is not supported.');
66+
}
67+
5868
$encoder = new Argon2iPasswordEncoder();
5969
$result = $encoder->encodePassword(str_repeat('a', 4096), null);
6070
$this->assertFalse($encoder->isPasswordValid($result, str_repeat('a', 4097), null));
@@ -63,8 +73,29 @@ public function testCheckPasswordLength()
6373

6474
public function testUserProvidedSaltIsNotUsed()
6575
{
76+
if (!Argon2iPasswordEncoder::isSupported() || Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
77+
$this->markTestSkipped('Argon2i algorithm is not supported.');
78+
}
79+
6680
$encoder = new Argon2iPasswordEncoder();
6781
$result = $encoder->encodePassword(self::PASSWORD, 'salt');
6882
$this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, 'anotherSalt'));
6983
}
84+
85+
/**
86+
* @group legacy
87+
* @exectedDeprecation Using "Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder" while only the "argon2id" algorithm is supported is deprecated since Symfony 4.3, use "Symfony\Component\Security\Core\Encoder\Argon2idPasswordEncoder" instead.
88+
* @exectedDeprecation Calling "Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder::isPasswordValid()" with a password hashed using argon2id is deprecated since Symfony 4.3, use "Symfony\Component\Security\Core\Encoder\Argon2idPasswordEncoder" instead.
89+
*/
90+
public function testEncodeWithArgon2idSupportOnly()
91+
{
92+
if (!Argon2iPasswordEncoder::isSupported() || !Argon2idPasswordEncoder::isDefaultSodiumAlgorithm()) {
93+
$this->markTestSkipped('Argon2id algorithm not available.');
94+
}
95+
96+
$encoder = new Argon2iPasswordEncoder();
97+
$result = $encoder->encodePassword(self::PASSWORD, null);
98+
$this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null));
99+
$this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null));
100+
}
70101
}

0 commit comments

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