From 77fd99d2a38c864466986465514e991ad255dee8 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 29 Mar 2023 17:18:02 +0530 Subject: [PATCH 01/20] AC-8017 system settings improvement --- .../Model/ResourceModel/Key/Change.php | 68 +++++++++++-------- .../Model/ResourceModel/Key/ChangeTest.php | 6 +- .../Config/ConfigOptionsListConstants.php | 5 ++ .../Framework/Encryption/Encryptor.php | 27 ++++++-- .../Framework/Encryption/KeyValidator.php | 9 ++- .../Magento/Framework/Math/Random.php | 20 +++++- .../Magento/Setup/Model/CryptKeyGenerator.php | 5 +- .../Test/Unit/Model/CryptKeyGeneratorTest.php | 13 ---- .../Test/Unit/Module/ConfigGeneratorTest.php | 2 +- 9 files changed, 97 insertions(+), 58 deletions(-) diff --git a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php index e687817be7431..1b3e018b2ddc2 100644 --- a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php +++ b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php @@ -5,10 +5,22 @@ */ namespace Magento\EncryptionKey\Model\ResourceModel\Key; +use \Exception; +use Magento\Config\Model\Config\Backend\Encrypted; +use Magento\Config\Model\Config\Structure; +use Magento\Framework\App\DeploymentConfig\Writer; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\Config\Data\ConfigData; use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\Math\Random; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Context; /** * Encryption key changer resource model @@ -19,60 +31,60 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ -class Change extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb +class Change extends AbstractDb { /** * Encryptor interface * - * @var \Magento\Framework\Encryption\EncryptorInterface + * @var EncryptorInterface */ protected $encryptor; /** * Filesystem directory write interface * - * @var \Magento\Framework\Filesystem\Directory\WriteInterface + * @var WriteInterface */ protected $directory; /** * System configuration structure * - * @var \Magento\Config\Model\Config\Structure + * @var Structure */ protected $structure; /** * Configuration writer * - * @var \Magento\Framework\App\DeploymentConfig\Writer + * @var Writer */ protected $writer; /** - * Random + * Random string generator * - * @var \Magento\Framework\Math\Random + * @var Random * @since 100.0.4 */ protected $random; /** - * @param \Magento\Framework\Model\ResourceModel\Db\Context $context - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\Config\Model\Config\Structure $structure - * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor - * @param \Magento\Framework\App\DeploymentConfig\Writer $writer - * @param \Magento\Framework\Math\Random $random + * @param Context $context + * @param Filesystem $filesystem + * @param Structure $structure + * @param EncryptorInterface $encryptor + * @param Writer $writer + * @param Random $random * @param string $connectionName */ public function __construct( - \Magento\Framework\Model\ResourceModel\Db\Context $context, - \Magento\Framework\Filesystem $filesystem, - \Magento\Config\Model\Config\Structure $structure, - \Magento\Framework\Encryption\EncryptorInterface $encryptor, - \Magento\Framework\App\DeploymentConfig\Writer $writer, - \Magento\Framework\Math\Random $random, + Context $context, + Filesystem $filesystem, + Structure $structure, + EncryptorInterface $encryptor, + Writer $writer, + Random $random, $connectionName = null ) { $this->encryptor = clone $encryptor; @@ -98,20 +110,20 @@ protected function _construct() * * @param string|null $key * @return null|string - * @throws \Exception + * @throws FileSystemException|LocalizedException|Exception */ public function changeEncryptionKey($key = null) { // prepare new key, encryptor and new configuration segment if (!$this->writer->checkIfWritable()) { - throw new \Exception(__('Deployment configuration file is not writable.')); + throw new FileSystemException(__('Deployment configuration file is not writable.')); } if (null === $key) { - // md5() here is not for cryptographic use. It used for generate encryption key itself - // and do not encrypt any passwords - // phpcs:ignore Magento2.Security.InsecureFunction - $key = md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE)); + $key = $this->random->getRandomBytes( + ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE, + ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX + ); } $this->encryptor->setNewKey($key); @@ -128,7 +140,7 @@ public function changeEncryptionKey($key = null) $this->writer->saveConfig($configData); $this->commit(); return $key; - } catch (\Exception $e) { + } catch (LocalizedException $e) { $this->rollBack(); throw $e; } @@ -142,11 +154,11 @@ public function changeEncryptionKey($key = null) protected function _reEncryptSystemConfigurationValues() { // look for encrypted node entries in all system.xml files - /** @var \Magento\Config\Model\Config\Structure $configStructure */ + /** @var Structure $configStructure */ $configStructure = $this->structure; $paths = $configStructure->getFieldPathsByAttribute( 'backend_model', - \Magento\Config\Model\Config\Backend\Encrypted::class + Encrypted::class ); // walk through found data and re-encrypt it diff --git a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php index 892738b450f21..068f6d6c0a7c2 100644 --- a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php +++ b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php @@ -148,7 +148,7 @@ private function setUpChangeEncryptionKey() public function testChangeEncryptionKey() { $this->setUpChangeEncryptionKey(); - $this->randomMock->expects($this->never())->method('getRandomString'); + $this->randomMock->expects($this->never())->method('getRandomBytes'); $key = 'key'; $this->assertEquals($key, $this->model->changeEncryptionKey($key)); } @@ -156,8 +156,8 @@ public function testChangeEncryptionKey() public function testChangeEncryptionKeyAutogenerate() { $this->setUpChangeEncryptionKey(); - $this->randomMock->expects($this->once())->method('getRandomString')->willReturn('abc'); - $this->assertEquals(hash('md5', 'abc'), $this->model->changeEncryptionKey()); + $this->randomMock->expects($this->once())->method('getRandomBytes')->willReturn('abc'); + $this->assertEquals('abc', $this->model->changeEncryptionKey()); } public function testChangeEncryptionKeyThrowsException() diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php index 670c74dd197bc..667d78ca7d361 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php @@ -167,4 +167,9 @@ class ConfigOptionsListConstants */ public const STORE_KEY_RANDOM_STRING_SIZE = SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES; //phpcs:enable + + /** + * Prefix of encoded random string + */ + public const STORE_KEY_ENCODED_RANDOM_STRING_PREFIX = 'base64'; } diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 06fbf6c83fa21..de0571ac831dc 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -10,6 +10,7 @@ use Magento\Framework\App\DeploymentConfig; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\Encryption\Adapter\EncryptionAdapterInterface; use Magento\Framework\Encryption\Adapter\Mcrypt; use Magento\Framework\Encryption\Adapter\SodiumChachaIetf; @@ -265,7 +266,12 @@ public function hash($data, $version = self::HASH_VERSION_SHA256) throw new \InvalidArgumentException('Unknown hashing algorithm'); } - return hash_hmac($this->hashVersionMap[$version], (string)$data, $this->keys[$this->keyVersion], false); + return hash_hmac( + $this->hashVersionMap[$version], + (string)$data, + $this->decodeKey($this->keys[$this->keyVersion]), + false + ); } /** @@ -375,7 +381,7 @@ private function explodePasswordHash($hash) */ public function encrypt($data) { - $crypt = new SodiumChachaIetf($this->keys[$this->keyVersion]); + $crypt = new SodiumChachaIetf($this->decodeKey($this->keys[$this->keyVersion])); return $this->keyVersion . ':' . self::CIPHER_AEAD_CHACHA20POLY1305 . @@ -445,7 +451,7 @@ public function decrypt($data) if (!isset($this->keys[$keyVersion])) { return ''; } - $crypt = $this->getCrypt($this->keys[$keyVersion], $cryptVersion, $initVector); + $crypt = $this->getCrypt($this->decodeKey($this->keys[$keyVersion]), $cryptVersion, $initVector); if (null === $crypt) { return ''; } @@ -520,7 +526,7 @@ private function getCrypt( } if (null === $key) { - $key = $this->keys[$this->keyVersion]; + $key = $this->decodeKey($this->keys[$this->keyVersion]); } if (!$key) { @@ -596,4 +602,17 @@ private function getArgonHash( ) ); } + + /** + * Find out actual decode key + * + * @param string $key + * @return false|string + */ + private function decodeKey(string $key) + { + return (strpos($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) ? + base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : + $key; + } } diff --git a/lib/internal/Magento/Framework/Encryption/KeyValidator.php b/lib/internal/Magento/Framework/Encryption/KeyValidator.php index c60ce0c5d5339..4cfd6948b6a4f 100644 --- a/lib/internal/Magento/Framework/Encryption/KeyValidator.php +++ b/lib/internal/Magento/Framework/Encryption/KeyValidator.php @@ -25,7 +25,12 @@ class KeyValidator */ public function isValid($value) : bool { - return $value && strlen($value) === ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE - && preg_match('/^\S+$/', $value); + if (strpos($value, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) { + return (bool)$value; + } else { + return $value + && strlen($value) === ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE + && preg_match('/^\S+$/', $value); + } } } diff --git a/lib/internal/Magento/Framework/Math/Random.php b/lib/internal/Magento/Framework/Math/Random.php index 8adb602e00479..00ccf7dc12d2b 100644 --- a/lib/internal/Magento/Framework/Math/Random.php +++ b/lib/internal/Magento/Framework/Math/Random.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Math; +use \Exception; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; @@ -19,11 +20,11 @@ class Random /**#@+ * Frequently used character classes */ - const CHARS_LOWERS = 'abcdefghijklmnopqrstuvwxyz'; + public const CHARS_LOWERS = 'abcdefghijklmnopqrstuvwxyz'; - const CHARS_UPPERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + public const CHARS_UPPERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - const CHARS_DIGITS = '0123456789'; + public const CHARS_DIGITS = '0123456789'; /**#@-*/ @@ -83,4 +84,17 @@ public function getUniqueHash($prefix = '') { return $prefix . $this->getRandomString(32); } + + /** + * Generate a base64 encoded binary string. + * + * @param int $length + * @param string $prefix + * @return string + * @throws Exception + */ + public function getRandomBytes($length, $prefix = '') + { + return $prefix . base64_encode(random_bytes($length)); + } } diff --git a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php index 5bd764673a45e..da5cb8b4d918a 100644 --- a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php +++ b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php @@ -37,10 +37,7 @@ public function __construct(Random $random) */ public function generate() { - // md5() here is not for cryptographic use. It used for generate encryption key itself - // and do not encrypt any passwords - // phpcs:ignore Magento2.Security.InsecureFunction - return md5($this->getRandomString()); + return $this->getRandomString(); } /** diff --git a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php index 2511c08668198..a753911b99af6 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php @@ -45,17 +45,4 @@ public function testStringForHashingIsReadFromRandom() $this->cryptKeyGenerator->generate(); } - - public function testReturnsMd5OfRandomString() - { - $expected = 'fdb7594e77f1ad5fbb8e6c917b6012ce'; // == 'magento2' - - $this->randomMock - ->method('getRandomString') - ->willReturn('magento2'); - - $actual = $this->cryptKeyGenerator->generate(); - - $this->assertEquals($expected, $actual); - } } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index 8e37e295d6fba..8ea46c042d2fc 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -78,7 +78,7 @@ public function testCreateCryptConfigWithoutInput() $returnValue = $this->configGeneratorObject->createCryptConfig([]); $this->assertEquals(ConfigFilePool::APP_ENV, $returnValue->getFileKey()); // phpcs:ignore Magento2.Security.InsecureFunction - $this->assertEquals(['crypt' => ['key' => md5('key')]], $returnValue->getData()); + $this->assertEquals(['crypt' => ['key' => 'key']], $returnValue->getData()); } public function testCreateSessionConfigWithInput() From 80693477a6794ad4d0d7a5f75a00790943f60769 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Thu, 30 Mar 2023 17:17:16 +0530 Subject: [PATCH 02/20] AC-8017 system settings improvement --- .../EncryptionKey/Model/ResourceModel/Key/Change.php | 6 ++---- lib/internal/Magento/Framework/Encryption/Encryptor.php | 2 +- lib/internal/Magento/Framework/Encryption/KeyValidator.php | 5 +++-- lib/internal/Magento/Framework/Math/Random.php | 5 ++--- setup/src/Magento/Setup/Model/CryptKeyGenerator.php | 3 ++- .../Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php index 1b3e018b2ddc2..5bb2b28c3e3ae 100644 --- a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php +++ b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php @@ -120,10 +120,8 @@ public function changeEncryptionKey($key = null) } if (null === $key) { - $key = $this->random->getRandomBytes( - ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE, - ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX - ); + $key = ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . + $this->random->getRandomBytes(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE); } $this->encryptor->setNewKey($key); diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index de0571ac831dc..19d98beea4dba 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -611,7 +611,7 @@ private function getArgonHash( */ private function decodeKey(string $key) { - return (strpos($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) ? + return (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : $key; } diff --git a/lib/internal/Magento/Framework/Encryption/KeyValidator.php b/lib/internal/Magento/Framework/Encryption/KeyValidator.php index 4cfd6948b6a4f..77dd9db277a21 100644 --- a/lib/internal/Magento/Framework/Encryption/KeyValidator.php +++ b/lib/internal/Magento/Framework/Encryption/KeyValidator.php @@ -25,8 +25,9 @@ class KeyValidator */ public function isValid($value) : bool { - if (strpos($value, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) { - return (bool)$value; + if (str_starts_with($value, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) { + return (bool)$value + && preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $value); } else { return $value && strlen($value) === ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE diff --git a/lib/internal/Magento/Framework/Math/Random.php b/lib/internal/Magento/Framework/Math/Random.php index 00ccf7dc12d2b..6160b7d8f665c 100644 --- a/lib/internal/Magento/Framework/Math/Random.php +++ b/lib/internal/Magento/Framework/Math/Random.php @@ -89,12 +89,11 @@ public function getUniqueHash($prefix = '') * Generate a base64 encoded binary string. * * @param int $length - * @param string $prefix * @return string * @throws Exception */ - public function getRandomBytes($length, $prefix = '') + public function getRandomBytes($length) { - return $prefix . base64_encode(random_bytes($length)); + return base64_encode(random_bytes($length)); } } diff --git a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php index da5cb8b4d918a..c85169487131c 100644 --- a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php +++ b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php @@ -48,6 +48,7 @@ public function generate() */ private function getRandomString() { - return $this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE); + return ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . + $this->random->getRandomBytes(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE); } } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php index a753911b99af6..dff5a5b9d68ae 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php @@ -40,7 +40,7 @@ public function testStringForHashingIsReadFromRandom() { $this->randomMock ->expects($this->once()) - ->method('getRandomString') + ->method('getRandomBytes') ->willReturn(''); $this->cryptKeyGenerator->generate(); From 9ba2afc1fb766d490d1c7ecc2f0c242191a43546 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Thu, 30 Mar 2023 19:06:44 +0530 Subject: [PATCH 03/20] AC-8017 system settings improvement --- .../Test/Unit/Model/ResourceModel/Key/ChangeTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php index 068f6d6c0a7c2..73a292b22a707 100644 --- a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php +++ b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php @@ -11,6 +11,7 @@ use Magento\EncryptionKey\Model\ResourceModel\Key\Change; use Magento\Framework\App\DeploymentConfig\Writer; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; use Magento\Framework\Encryption\EncryptorInterface; @@ -157,7 +158,7 @@ public function testChangeEncryptionKeyAutogenerate() { $this->setUpChangeEncryptionKey(); $this->randomMock->expects($this->once())->method('getRandomBytes')->willReturn('abc'); - $this->assertEquals('abc', $this->model->changeEncryptionKey()); + $this->assertEquals(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'abc', $this->model->changeEncryptionKey()); } public function testChangeEncryptionKeyThrowsException() From e81b0518dea747dc2df5c3a5923d4111c0a47f90 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Tue, 11 Apr 2023 14:42:10 +0530 Subject: [PATCH 04/20] AC-8017 system settings improvement --- .../Test/Unit/Model/ResourceModel/Key/ChangeTest.php | 5 ++++- .../Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php index 73a292b22a707..705e3a66ddeea 100644 --- a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php +++ b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php @@ -158,7 +158,10 @@ public function testChangeEncryptionKeyAutogenerate() { $this->setUpChangeEncryptionKey(); $this->randomMock->expects($this->once())->method('getRandomBytes')->willReturn('abc'); - $this->assertEquals(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'abc', $this->model->changeEncryptionKey()); + $this->assertEquals( + ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'abc', + $this->model->changeEncryptionKey() + ); } public function testChangeEncryptionKeyThrowsException() diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index 8ea46c042d2fc..74c74ee0db4fb 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -39,6 +39,7 @@ protected function setUp(): void /** @var Random|MockObject $randomMock */ $randomMock = $this->createMock(Random::class); $randomMock->expects($this->any())->method('getRandomString')->willReturn('key'); + $randomMock->expects($this->any())->method('getRandomBytes')->willReturn('randombytes'); $cryptKeyGenerator = new CryptKeyGenerator($randomMock); @@ -78,7 +79,11 @@ public function testCreateCryptConfigWithoutInput() $returnValue = $this->configGeneratorObject->createCryptConfig([]); $this->assertEquals(ConfigFilePool::APP_ENV, $returnValue->getFileKey()); // phpcs:ignore Magento2.Security.InsecureFunction - $this->assertEquals(['crypt' => ['key' => 'key']], $returnValue->getData()); + $this->assertEquals([ + 'crypt' => [ + 'key' => ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'randombytes' + ] + ], $returnValue->getData()); } public function testCreateSessionConfigWithInput() From ee8360920cd90111a63c4f041517c01b0e934c5c Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 12 Apr 2023 10:21:04 +0530 Subject: [PATCH 05/20] AC-8017 system settings improvement --- .../Setup/Patch/Data/SodiumChachaPatchTest.php | 11 ++++++++++- .../testsuite/Magento/Sales/_files/payment_enc_cc.php | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 0c83a0bc6d602..80655d0eda43c 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -8,6 +8,7 @@ namespace Magento\EncryptionKey\Setup\Patch\Data; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Encryption\Encryptor; @@ -88,7 +89,7 @@ private function legacyEncrypt(string $data): string $handle = @mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, ''); $initVectorSize = @mcrypt_enc_get_iv_size($handle); $initVector = str_repeat("\0", $initVectorSize); - @mcrypt_generic_init($handle, $this->deployConfig->get(static::PATH_KEY), $initVector); + @mcrypt_generic_init($handle, $this->getEncryptionKey(), $initVector); $encrpted = @mcrypt_generic($handle, $data); @@ -98,4 +99,12 @@ private function legacyEncrypt(string $data): string return '0:' . Encryptor::CIPHER_RIJNDAEL_256 . ':' . base64_encode($encrpted); } + + private function getEncryptionKey(): string + { + $key = $this->deployConfig->get(static::PATH_KEY); + return (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? + base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : + $key; + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php b/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php index a5fa4e402197a..a6f13c0733939 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php @@ -8,6 +8,7 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SearchCriteria; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\ResourceModel\Order\Payment\EncryptionUpdateTest; use Magento\Framework\App\DeploymentConfig; @@ -30,7 +31,14 @@ $handle = @mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, ''); $initVectorSize = @mcrypt_enc_get_iv_size($handle); $initVector = str_repeat("\0", $initVectorSize); -@mcrypt_generic_init($handle, $deployConfig->get('crypt/key'), $initVector); + +// Key is also encrypted to support 256-key +$key = $deployConfig->get('crypt/key'); +$originalKey = (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? + base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : + $key; + +@mcrypt_generic_init($handle, $originalKey, $initVector); $encCcNumber = @mcrypt_generic($handle, EncryptionUpdateTest::TEST_CC_NUMBER); From 2eb929469b73d50e959a18b3a93ada2508763a36 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 12 Apr 2023 18:12:57 +0530 Subject: [PATCH 06/20] AC-8017 system settings improvement --- .../EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php | 2 +- lib/internal/Magento/Framework/Math/Random.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 80655d0eda43c..53167f4e31ec0 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -15,7 +15,7 @@ class SodiumChachaPatchTest extends \PHPUnit\Framework\TestCase { - const PATH_KEY = 'crypt/key'; + private const PATH_KEY = 'crypt/key'; /** * @var ObjectManagerInterface diff --git a/lib/internal/Magento/Framework/Math/Random.php b/lib/internal/Magento/Framework/Math/Random.php index 6160b7d8f665c..5fb78ac51d7fb 100644 --- a/lib/internal/Magento/Framework/Math/Random.php +++ b/lib/internal/Magento/Framework/Math/Random.php @@ -92,7 +92,7 @@ public function getUniqueHash($prefix = '') * @return string * @throws Exception */ - public function getRandomBytes($length) + public function getRandomBytes(int $length) : string { return base64_encode(random_bytes($length)); } From c77ce0072e6b60f41b1650025e8d6361c6545d5e Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Fri, 14 Apr 2023 17:09:12 +0530 Subject: [PATCH 07/20] AC-8017 system settings improvement --- .../EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 53167f4e31ec0..561cc77ce9282 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -38,7 +38,10 @@ public function testChangeEncryptionKey() $testPath = 'test/config'; $testValue = 'test'; - $structureMock = $this->createMock(\Magento\Config\Model\Config\Structure\Proxy::class); + $structureMock = $this->createMock( + // phpstan:ignore "Class Magento\Config\Model\Config\Structure\Proxy not found." + \Magento\Config\Model\Config\Structure\Proxy::class + ); $structureMock->expects($this->once()) ->method('getFieldPathsByAttribute') ->willReturn([$testPath]); From bc7ab9653415515bb62e96453b0d9758d96f7825 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Fri, 19 May 2023 11:34:49 +0530 Subject: [PATCH 08/20] AC-8017 system settings improvement --- lib/internal/Magento/Framework/Encryption/Encryptor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 19d98beea4dba..a7f3ec7692f1e 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -609,7 +609,7 @@ private function getArgonHash( * @param string $key * @return false|string */ - private function decodeKey(string $key) + private function decodeKey(string $key) : string|bool { return (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : From 58128894fa85ec422ca9d7ba59a770bb48dae9b7 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 24 May 2023 18:36:16 +0530 Subject: [PATCH 09/20] AC-8017 system settings improvement --- .../Setup/Patch/Data/SodiumChachaPatchTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 561cc77ce9282..c5cfa5c37307b 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -13,6 +13,9 @@ use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Encryption\Encryptor; +/** + * Class SodiumChachaPatch library test + */ class SodiumChachaPatchTest extends \PHPUnit\Framework\TestCase { private const PATH_KEY = 'crypt/key'; @@ -103,6 +106,13 @@ private function legacyEncrypt(string $data): string return '0:' . Encryptor::CIPHER_RIJNDAEL_256 . ':' . base64_encode($encrpted); } + /** + * Get Encryption key + * + * @return string + * @throws \Magento\Framework\Exception\FileSystemException + * @throws \Magento\Framework\Exception\RuntimeException + */ private function getEncryptionKey(): string { $key = $this->deployConfig->get(static::PATH_KEY); From 328bde8add66e2dcdc67482ac375ee64c37b2c24 Mon Sep 17 00:00:00 2001 From: "Pawan.kumar" Date: Tue, 27 Jun 2023 11:16:25 +0530 Subject: [PATCH 10/20] AC-8490: Fix Customer Issue --- .../Controller/Rest/ValidateCustomerData.php | 6 ++-- .../Rest/ValidateCustomerDataTest.php | 34 ++++++++++++------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Customer/Plugin/Webapi/Controller/Rest/ValidateCustomerData.php b/app/code/Magento/Customer/Plugin/Webapi/Controller/Rest/ValidateCustomerData.php index ad2d8ed1cf974..63551ff5a7576 100644 --- a/app/code/Magento/Customer/Plugin/Webapi/Controller/Rest/ValidateCustomerData.php +++ b/app/code/Magento/Customer/Plugin/Webapi/Controller/Rest/ValidateCustomerData.php @@ -28,8 +28,8 @@ class ValidateCustomerData */ public function beforeOverride(ParamsOverrider $subject, array $inputData, array $parameters): array { - if (isset($inputData[self:: CUSTOMER_KEY])) { - $inputData[self:: CUSTOMER_KEY] = $this->validateInputData($inputData[self:: CUSTOMER_KEY]); + if (isset($inputData[self::CUSTOMER_KEY])) { + $inputData[self::CUSTOMER_KEY] = $this->validateInputData($inputData[self::CUSTOMER_KEY]); } return [$inputData, $parameters]; } @@ -45,7 +45,7 @@ private function validateInputData(array $inputData): array $result = []; $data = array_filter($inputData, function ($k) use (&$result) { - $key = is_string($k) ? strtolower($k) : $k; + $key = is_string($k) ? strtolower(str_replace('_', "", $k)) : $k; return !isset($result[$key]) && ($result[$key] = true); }, ARRAY_FILTER_USE_KEY); diff --git a/app/code/Magento/Customer/Test/Unit/Plugin/Webapi/Controller/Rest/ValidateCustomerDataTest.php b/app/code/Magento/Customer/Test/Unit/Plugin/Webapi/Controller/Rest/ValidateCustomerDataTest.php index cda66041ab3c5..72d5f36e2266f 100644 --- a/app/code/Magento/Customer/Test/Unit/Plugin/Webapi/Controller/Rest/ValidateCustomerDataTest.php +++ b/app/code/Magento/Customer/Test/Unit/Plugin/Webapi/Controller/Rest/ValidateCustomerDataTest.php @@ -8,8 +8,8 @@ namespace Magento\Customer\Test\Unit\Plugin\Webapi\Controller\Rest; use Exception; -use Magento\Framework\App\ObjectManager; use Magento\Customer\Plugin\Webapi\Controller\Rest\ValidateCustomerData; +use Magento\Framework\App\ObjectManager; use PHPUnit\Framework\TestCase; use ReflectionClass; @@ -75,40 +75,48 @@ public function dataProviderInputData(): array { return [ [ - ['customer' => - [ + ['customer' => [ 'id' => -1, 'Id' => 1, - 'name' => - [ + 'name' => [ 'firstName' => 'Test', 'LastName' => 'user' ], 'isHavingOwnHouse' => 1, - 'address' => - [ + 'address' => [ 'street' => '1st Street', 'Street' => '3rd Street', 'city' => 'London' ], ] ], - ['customer' => - [ + ['customer' => [ 'id' => -1, - 'name' => - [ + 'name' => [ 'firstName' => 'Test', 'LastName' => 'user' ], 'isHavingOwnHouse' => 1, - 'address' => - [ + 'address' => [ 'street' => '1st Street', 'city' => 'London' ], ] ], + ['customer' => [ + 'id' => -1, + '_Id' => 1, + 'name' => [ + 'firstName' => 'Test', + 'LastName' => 'user' + ], + 'isHavingOwnHouse' => 1, + 'address' => [ + 'street' => '1st Street', + 'city' => 'London' + ], + ] + ], ] ]; } From ec567383ffc4c5e647943669de602f6021015967 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 29 Mar 2023 17:18:02 +0530 Subject: [PATCH 11/20] AC-8017 system settings improvement --- .../Model/ResourceModel/Key/Change.php | 68 +++++++++++-------- .../Model/ResourceModel/Key/ChangeTest.php | 6 +- .../Config/ConfigOptionsListConstants.php | 5 ++ .../Framework/Encryption/Encryptor.php | 27 ++++++-- .../Framework/Encryption/KeyValidator.php | 9 ++- .../Magento/Framework/Math/Random.php | 20 +++++- .../Magento/Setup/Model/CryptKeyGenerator.php | 5 +- .../Test/Unit/Model/CryptKeyGeneratorTest.php | 13 ---- .../Test/Unit/Module/ConfigGeneratorTest.php | 2 +- 9 files changed, 97 insertions(+), 58 deletions(-) diff --git a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php index e687817be7431..1b3e018b2ddc2 100644 --- a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php +++ b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php @@ -5,10 +5,22 @@ */ namespace Magento\EncryptionKey\Model\ResourceModel\Key; +use \Exception; +use Magento\Config\Model\Config\Backend\Encrypted; +use Magento\Config\Model\Config\Structure; +use Magento\Framework\App\DeploymentConfig\Writer; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\Config\Data\ConfigData; use Magento\Framework\Config\File\ConfigFilePool; +use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; +use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\Math\Random; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Model\ResourceModel\Db\Context; /** * Encryption key changer resource model @@ -19,60 +31,60 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ -class Change extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb +class Change extends AbstractDb { /** * Encryptor interface * - * @var \Magento\Framework\Encryption\EncryptorInterface + * @var EncryptorInterface */ protected $encryptor; /** * Filesystem directory write interface * - * @var \Magento\Framework\Filesystem\Directory\WriteInterface + * @var WriteInterface */ protected $directory; /** * System configuration structure * - * @var \Magento\Config\Model\Config\Structure + * @var Structure */ protected $structure; /** * Configuration writer * - * @var \Magento\Framework\App\DeploymentConfig\Writer + * @var Writer */ protected $writer; /** - * Random + * Random string generator * - * @var \Magento\Framework\Math\Random + * @var Random * @since 100.0.4 */ protected $random; /** - * @param \Magento\Framework\Model\ResourceModel\Db\Context $context - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\Config\Model\Config\Structure $structure - * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor - * @param \Magento\Framework\App\DeploymentConfig\Writer $writer - * @param \Magento\Framework\Math\Random $random + * @param Context $context + * @param Filesystem $filesystem + * @param Structure $structure + * @param EncryptorInterface $encryptor + * @param Writer $writer + * @param Random $random * @param string $connectionName */ public function __construct( - \Magento\Framework\Model\ResourceModel\Db\Context $context, - \Magento\Framework\Filesystem $filesystem, - \Magento\Config\Model\Config\Structure $structure, - \Magento\Framework\Encryption\EncryptorInterface $encryptor, - \Magento\Framework\App\DeploymentConfig\Writer $writer, - \Magento\Framework\Math\Random $random, + Context $context, + Filesystem $filesystem, + Structure $structure, + EncryptorInterface $encryptor, + Writer $writer, + Random $random, $connectionName = null ) { $this->encryptor = clone $encryptor; @@ -98,20 +110,20 @@ protected function _construct() * * @param string|null $key * @return null|string - * @throws \Exception + * @throws FileSystemException|LocalizedException|Exception */ public function changeEncryptionKey($key = null) { // prepare new key, encryptor and new configuration segment if (!$this->writer->checkIfWritable()) { - throw new \Exception(__('Deployment configuration file is not writable.')); + throw new FileSystemException(__('Deployment configuration file is not writable.')); } if (null === $key) { - // md5() here is not for cryptographic use. It used for generate encryption key itself - // and do not encrypt any passwords - // phpcs:ignore Magento2.Security.InsecureFunction - $key = md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE)); + $key = $this->random->getRandomBytes( + ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE, + ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX + ); } $this->encryptor->setNewKey($key); @@ -128,7 +140,7 @@ public function changeEncryptionKey($key = null) $this->writer->saveConfig($configData); $this->commit(); return $key; - } catch (\Exception $e) { + } catch (LocalizedException $e) { $this->rollBack(); throw $e; } @@ -142,11 +154,11 @@ public function changeEncryptionKey($key = null) protected function _reEncryptSystemConfigurationValues() { // look for encrypted node entries in all system.xml files - /** @var \Magento\Config\Model\Config\Structure $configStructure */ + /** @var Structure $configStructure */ $configStructure = $this->structure; $paths = $configStructure->getFieldPathsByAttribute( 'backend_model', - \Magento\Config\Model\Config\Backend\Encrypted::class + Encrypted::class ); // walk through found data and re-encrypt it diff --git a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php index 892738b450f21..068f6d6c0a7c2 100644 --- a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php +++ b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php @@ -148,7 +148,7 @@ private function setUpChangeEncryptionKey() public function testChangeEncryptionKey() { $this->setUpChangeEncryptionKey(); - $this->randomMock->expects($this->never())->method('getRandomString'); + $this->randomMock->expects($this->never())->method('getRandomBytes'); $key = 'key'; $this->assertEquals($key, $this->model->changeEncryptionKey($key)); } @@ -156,8 +156,8 @@ public function testChangeEncryptionKey() public function testChangeEncryptionKeyAutogenerate() { $this->setUpChangeEncryptionKey(); - $this->randomMock->expects($this->once())->method('getRandomString')->willReturn('abc'); - $this->assertEquals(hash('md5', 'abc'), $this->model->changeEncryptionKey()); + $this->randomMock->expects($this->once())->method('getRandomBytes')->willReturn('abc'); + $this->assertEquals('abc', $this->model->changeEncryptionKey()); } public function testChangeEncryptionKeyThrowsException() diff --git a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php index 670c74dd197bc..667d78ca7d361 100644 --- a/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php +++ b/lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php @@ -167,4 +167,9 @@ class ConfigOptionsListConstants */ public const STORE_KEY_RANDOM_STRING_SIZE = SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES; //phpcs:enable + + /** + * Prefix of encoded random string + */ + public const STORE_KEY_ENCODED_RANDOM_STRING_PREFIX = 'base64'; } diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 06fbf6c83fa21..de0571ac831dc 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -10,6 +10,7 @@ use Magento\Framework\App\DeploymentConfig; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\Encryption\Adapter\EncryptionAdapterInterface; use Magento\Framework\Encryption\Adapter\Mcrypt; use Magento\Framework\Encryption\Adapter\SodiumChachaIetf; @@ -265,7 +266,12 @@ public function hash($data, $version = self::HASH_VERSION_SHA256) throw new \InvalidArgumentException('Unknown hashing algorithm'); } - return hash_hmac($this->hashVersionMap[$version], (string)$data, $this->keys[$this->keyVersion], false); + return hash_hmac( + $this->hashVersionMap[$version], + (string)$data, + $this->decodeKey($this->keys[$this->keyVersion]), + false + ); } /** @@ -375,7 +381,7 @@ private function explodePasswordHash($hash) */ public function encrypt($data) { - $crypt = new SodiumChachaIetf($this->keys[$this->keyVersion]); + $crypt = new SodiumChachaIetf($this->decodeKey($this->keys[$this->keyVersion])); return $this->keyVersion . ':' . self::CIPHER_AEAD_CHACHA20POLY1305 . @@ -445,7 +451,7 @@ public function decrypt($data) if (!isset($this->keys[$keyVersion])) { return ''; } - $crypt = $this->getCrypt($this->keys[$keyVersion], $cryptVersion, $initVector); + $crypt = $this->getCrypt($this->decodeKey($this->keys[$keyVersion]), $cryptVersion, $initVector); if (null === $crypt) { return ''; } @@ -520,7 +526,7 @@ private function getCrypt( } if (null === $key) { - $key = $this->keys[$this->keyVersion]; + $key = $this->decodeKey($this->keys[$this->keyVersion]); } if (!$key) { @@ -596,4 +602,17 @@ private function getArgonHash( ) ); } + + /** + * Find out actual decode key + * + * @param string $key + * @return false|string + */ + private function decodeKey(string $key) + { + return (strpos($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) ? + base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : + $key; + } } diff --git a/lib/internal/Magento/Framework/Encryption/KeyValidator.php b/lib/internal/Magento/Framework/Encryption/KeyValidator.php index c60ce0c5d5339..4cfd6948b6a4f 100644 --- a/lib/internal/Magento/Framework/Encryption/KeyValidator.php +++ b/lib/internal/Magento/Framework/Encryption/KeyValidator.php @@ -25,7 +25,12 @@ class KeyValidator */ public function isValid($value) : bool { - return $value && strlen($value) === ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE - && preg_match('/^\S+$/', $value); + if (strpos($value, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) { + return (bool)$value; + } else { + return $value + && strlen($value) === ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE + && preg_match('/^\S+$/', $value); + } } } diff --git a/lib/internal/Magento/Framework/Math/Random.php b/lib/internal/Magento/Framework/Math/Random.php index 8adb602e00479..00ccf7dc12d2b 100644 --- a/lib/internal/Magento/Framework/Math/Random.php +++ b/lib/internal/Magento/Framework/Math/Random.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Math; +use \Exception; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; @@ -19,11 +20,11 @@ class Random /**#@+ * Frequently used character classes */ - const CHARS_LOWERS = 'abcdefghijklmnopqrstuvwxyz'; + public const CHARS_LOWERS = 'abcdefghijklmnopqrstuvwxyz'; - const CHARS_UPPERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + public const CHARS_UPPERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - const CHARS_DIGITS = '0123456789'; + public const CHARS_DIGITS = '0123456789'; /**#@-*/ @@ -83,4 +84,17 @@ public function getUniqueHash($prefix = '') { return $prefix . $this->getRandomString(32); } + + /** + * Generate a base64 encoded binary string. + * + * @param int $length + * @param string $prefix + * @return string + * @throws Exception + */ + public function getRandomBytes($length, $prefix = '') + { + return $prefix . base64_encode(random_bytes($length)); + } } diff --git a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php index 5bd764673a45e..da5cb8b4d918a 100644 --- a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php +++ b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php @@ -37,10 +37,7 @@ public function __construct(Random $random) */ public function generate() { - // md5() here is not for cryptographic use. It used for generate encryption key itself - // and do not encrypt any passwords - // phpcs:ignore Magento2.Security.InsecureFunction - return md5($this->getRandomString()); + return $this->getRandomString(); } /** diff --git a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php index 2511c08668198..a753911b99af6 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php @@ -45,17 +45,4 @@ public function testStringForHashingIsReadFromRandom() $this->cryptKeyGenerator->generate(); } - - public function testReturnsMd5OfRandomString() - { - $expected = 'fdb7594e77f1ad5fbb8e6c917b6012ce'; // == 'magento2' - - $this->randomMock - ->method('getRandomString') - ->willReturn('magento2'); - - $actual = $this->cryptKeyGenerator->generate(); - - $this->assertEquals($expected, $actual); - } } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index 8e37e295d6fba..8ea46c042d2fc 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -78,7 +78,7 @@ public function testCreateCryptConfigWithoutInput() $returnValue = $this->configGeneratorObject->createCryptConfig([]); $this->assertEquals(ConfigFilePool::APP_ENV, $returnValue->getFileKey()); // phpcs:ignore Magento2.Security.InsecureFunction - $this->assertEquals(['crypt' => ['key' => md5('key')]], $returnValue->getData()); + $this->assertEquals(['crypt' => ['key' => 'key']], $returnValue->getData()); } public function testCreateSessionConfigWithInput() From 66a429568c005b6f04a5dbec330b3d04b2a4eae8 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Thu, 30 Mar 2023 17:17:16 +0530 Subject: [PATCH 12/20] AC-8017 system settings improvement --- .../EncryptionKey/Model/ResourceModel/Key/Change.php | 6 ++---- lib/internal/Magento/Framework/Encryption/Encryptor.php | 2 +- lib/internal/Magento/Framework/Encryption/KeyValidator.php | 5 +++-- lib/internal/Magento/Framework/Math/Random.php | 5 ++--- setup/src/Magento/Setup/Model/CryptKeyGenerator.php | 3 ++- .../Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php index 1b3e018b2ddc2..5bb2b28c3e3ae 100644 --- a/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php +++ b/app/code/Magento/EncryptionKey/Model/ResourceModel/Key/Change.php @@ -120,10 +120,8 @@ public function changeEncryptionKey($key = null) } if (null === $key) { - $key = $this->random->getRandomBytes( - ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE, - ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX - ); + $key = ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . + $this->random->getRandomBytes(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE); } $this->encryptor->setNewKey($key); diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index de0571ac831dc..19d98beea4dba 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -611,7 +611,7 @@ private function getArgonHash( */ private function decodeKey(string $key) { - return (strpos($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) ? + return (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : $key; } diff --git a/lib/internal/Magento/Framework/Encryption/KeyValidator.php b/lib/internal/Magento/Framework/Encryption/KeyValidator.php index 4cfd6948b6a4f..77dd9db277a21 100644 --- a/lib/internal/Magento/Framework/Encryption/KeyValidator.php +++ b/lib/internal/Magento/Framework/Encryption/KeyValidator.php @@ -25,8 +25,9 @@ class KeyValidator */ public function isValid($value) : bool { - if (strpos($value, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX) === 0) { - return (bool)$value; + if (str_starts_with($value, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) { + return (bool)$value + && preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $value); } else { return $value && strlen($value) === ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE diff --git a/lib/internal/Magento/Framework/Math/Random.php b/lib/internal/Magento/Framework/Math/Random.php index 00ccf7dc12d2b..6160b7d8f665c 100644 --- a/lib/internal/Magento/Framework/Math/Random.php +++ b/lib/internal/Magento/Framework/Math/Random.php @@ -89,12 +89,11 @@ public function getUniqueHash($prefix = '') * Generate a base64 encoded binary string. * * @param int $length - * @param string $prefix * @return string * @throws Exception */ - public function getRandomBytes($length, $prefix = '') + public function getRandomBytes($length) { - return $prefix . base64_encode(random_bytes($length)); + return base64_encode(random_bytes($length)); } } diff --git a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php index da5cb8b4d918a..c85169487131c 100644 --- a/setup/src/Magento/Setup/Model/CryptKeyGenerator.php +++ b/setup/src/Magento/Setup/Model/CryptKeyGenerator.php @@ -48,6 +48,7 @@ public function generate() */ private function getRandomString() { - return $this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE); + return ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . + $this->random->getRandomBytes(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE); } } diff --git a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php index a753911b99af6..dff5a5b9d68ae 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/CryptKeyGeneratorTest.php @@ -40,7 +40,7 @@ public function testStringForHashingIsReadFromRandom() { $this->randomMock ->expects($this->once()) - ->method('getRandomString') + ->method('getRandomBytes') ->willReturn(''); $this->cryptKeyGenerator->generate(); From eaf9fca0eaa4ff994570fb41a851b2047e2711ea Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Thu, 30 Mar 2023 19:06:44 +0530 Subject: [PATCH 13/20] AC-8017 system settings improvement --- .../Test/Unit/Model/ResourceModel/Key/ChangeTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php index 068f6d6c0a7c2..73a292b22a707 100644 --- a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php +++ b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php @@ -11,6 +11,7 @@ use Magento\EncryptionKey\Model\ResourceModel\Key\Change; use Magento\Framework\App\DeploymentConfig\Writer; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; use Magento\Framework\Encryption\EncryptorInterface; @@ -157,7 +158,7 @@ public function testChangeEncryptionKeyAutogenerate() { $this->setUpChangeEncryptionKey(); $this->randomMock->expects($this->once())->method('getRandomBytes')->willReturn('abc'); - $this->assertEquals('abc', $this->model->changeEncryptionKey()); + $this->assertEquals(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'abc', $this->model->changeEncryptionKey()); } public function testChangeEncryptionKeyThrowsException() From e5ffa96eae2e36274abdc1011e248e4689fc6117 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Tue, 11 Apr 2023 14:42:10 +0530 Subject: [PATCH 14/20] AC-8017 system settings improvement --- .../Test/Unit/Model/ResourceModel/Key/ChangeTest.php | 5 ++++- .../Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php index 73a292b22a707..705e3a66ddeea 100644 --- a/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php +++ b/app/code/Magento/EncryptionKey/Test/Unit/Model/ResourceModel/Key/ChangeTest.php @@ -158,7 +158,10 @@ public function testChangeEncryptionKeyAutogenerate() { $this->setUpChangeEncryptionKey(); $this->randomMock->expects($this->once())->method('getRandomBytes')->willReturn('abc'); - $this->assertEquals(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'abc', $this->model->changeEncryptionKey()); + $this->assertEquals( + ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'abc', + $this->model->changeEncryptionKey() + ); } public function testChangeEncryptionKeyThrowsException() diff --git a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php index 8ea46c042d2fc..74c74ee0db4fb 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/ConfigGeneratorTest.php @@ -39,6 +39,7 @@ protected function setUp(): void /** @var Random|MockObject $randomMock */ $randomMock = $this->createMock(Random::class); $randomMock->expects($this->any())->method('getRandomString')->willReturn('key'); + $randomMock->expects($this->any())->method('getRandomBytes')->willReturn('randombytes'); $cryptKeyGenerator = new CryptKeyGenerator($randomMock); @@ -78,7 +79,11 @@ public function testCreateCryptConfigWithoutInput() $returnValue = $this->configGeneratorObject->createCryptConfig([]); $this->assertEquals(ConfigFilePool::APP_ENV, $returnValue->getFileKey()); // phpcs:ignore Magento2.Security.InsecureFunction - $this->assertEquals(['crypt' => ['key' => 'key']], $returnValue->getData()); + $this->assertEquals([ + 'crypt' => [ + 'key' => ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX . 'randombytes' + ] + ], $returnValue->getData()); } public function testCreateSessionConfigWithInput() From 74a0c37a48d1a0e951cb9798a23442fef98c04b0 Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 12 Apr 2023 10:21:04 +0530 Subject: [PATCH 15/20] AC-8017 system settings improvement --- .../Setup/Patch/Data/SodiumChachaPatchTest.php | 11 ++++++++++- .../testsuite/Magento/Sales/_files/payment_enc_cc.php | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 0c83a0bc6d602..80655d0eda43c 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -8,6 +8,7 @@ namespace Magento\EncryptionKey\Setup\Patch\Data; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Encryption\Encryptor; @@ -88,7 +89,7 @@ private function legacyEncrypt(string $data): string $handle = @mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, ''); $initVectorSize = @mcrypt_enc_get_iv_size($handle); $initVector = str_repeat("\0", $initVectorSize); - @mcrypt_generic_init($handle, $this->deployConfig->get(static::PATH_KEY), $initVector); + @mcrypt_generic_init($handle, $this->getEncryptionKey(), $initVector); $encrpted = @mcrypt_generic($handle, $data); @@ -98,4 +99,12 @@ private function legacyEncrypt(string $data): string return '0:' . Encryptor::CIPHER_RIJNDAEL_256 . ':' . base64_encode($encrpted); } + + private function getEncryptionKey(): string + { + $key = $this->deployConfig->get(static::PATH_KEY); + return (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? + base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : + $key; + } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php b/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php index a5fa4e402197a..a6f13c0733939 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/payment_enc_cc.php @@ -8,6 +8,7 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SearchCriteria; +use Magento\Framework\Config\ConfigOptionsListConstants; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\ResourceModel\Order\Payment\EncryptionUpdateTest; use Magento\Framework\App\DeploymentConfig; @@ -30,7 +31,14 @@ $handle = @mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, ''); $initVectorSize = @mcrypt_enc_get_iv_size($handle); $initVector = str_repeat("\0", $initVectorSize); -@mcrypt_generic_init($handle, $deployConfig->get('crypt/key'), $initVector); + +// Key is also encrypted to support 256-key +$key = $deployConfig->get('crypt/key'); +$originalKey = (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? + base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : + $key; + +@mcrypt_generic_init($handle, $originalKey, $initVector); $encCcNumber = @mcrypt_generic($handle, EncryptionUpdateTest::TEST_CC_NUMBER); From cff1b9cb3f21f86682aba637c59e62383d10d8bb Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 12 Apr 2023 18:12:57 +0530 Subject: [PATCH 16/20] AC-8017 system settings improvement --- .../EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php | 2 +- lib/internal/Magento/Framework/Math/Random.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 80655d0eda43c..53167f4e31ec0 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -15,7 +15,7 @@ class SodiumChachaPatchTest extends \PHPUnit\Framework\TestCase { - const PATH_KEY = 'crypt/key'; + private const PATH_KEY = 'crypt/key'; /** * @var ObjectManagerInterface diff --git a/lib/internal/Magento/Framework/Math/Random.php b/lib/internal/Magento/Framework/Math/Random.php index 6160b7d8f665c..5fb78ac51d7fb 100644 --- a/lib/internal/Magento/Framework/Math/Random.php +++ b/lib/internal/Magento/Framework/Math/Random.php @@ -92,7 +92,7 @@ public function getUniqueHash($prefix = '') * @return string * @throws Exception */ - public function getRandomBytes($length) + public function getRandomBytes(int $length) : string { return base64_encode(random_bytes($length)); } From 6dcd54b433557659a6e8b4351d31aed456cd2cef Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Fri, 14 Apr 2023 17:09:12 +0530 Subject: [PATCH 17/20] AC-8017 system settings improvement --- .../EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 53167f4e31ec0..561cc77ce9282 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -38,7 +38,10 @@ public function testChangeEncryptionKey() $testPath = 'test/config'; $testValue = 'test'; - $structureMock = $this->createMock(\Magento\Config\Model\Config\Structure\Proxy::class); + $structureMock = $this->createMock( + // phpstan:ignore "Class Magento\Config\Model\Config\Structure\Proxy not found." + \Magento\Config\Model\Config\Structure\Proxy::class + ); $structureMock->expects($this->once()) ->method('getFieldPathsByAttribute') ->willReturn([$testPath]); From 9be4ba48c300f4b74aba9a99c95916356f0ae34a Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Fri, 19 May 2023 11:34:49 +0530 Subject: [PATCH 18/20] AC-8017 system settings improvement --- lib/internal/Magento/Framework/Encryption/Encryptor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Encryption/Encryptor.php b/lib/internal/Magento/Framework/Encryption/Encryptor.php index 19d98beea4dba..a7f3ec7692f1e 100644 --- a/lib/internal/Magento/Framework/Encryption/Encryptor.php +++ b/lib/internal/Magento/Framework/Encryption/Encryptor.php @@ -609,7 +609,7 @@ private function getArgonHash( * @param string $key * @return false|string */ - private function decodeKey(string $key) + private function decodeKey(string $key) : string|bool { return (str_starts_with($key, ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX)) ? base64_decode(substr($key, strlen(ConfigOptionsListConstants::STORE_KEY_ENCODED_RANDOM_STRING_PREFIX))) : From 79a9e2e4c2e70a6e5591291fc4662bad23fc0dfe Mon Sep 17 00:00:00 2001 From: Sreeni A Date: Wed, 24 May 2023 18:36:16 +0530 Subject: [PATCH 19/20] AC-8017 system settings improvement --- .../Setup/Patch/Data/SodiumChachaPatchTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php index 561cc77ce9282..c5cfa5c37307b 100644 --- a/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php +++ b/dev/tests/integration/testsuite/Magento/EncryptionKey/Setup/Patch/Data/SodiumChachaPatchTest.php @@ -13,6 +13,9 @@ use Magento\Framework\App\DeploymentConfig; use Magento\Framework\Encryption\Encryptor; +/** + * Class SodiumChachaPatch library test + */ class SodiumChachaPatchTest extends \PHPUnit\Framework\TestCase { private const PATH_KEY = 'crypt/key'; @@ -103,6 +106,13 @@ private function legacyEncrypt(string $data): string return '0:' . Encryptor::CIPHER_RIJNDAEL_256 . ':' . base64_encode($encrpted); } + /** + * Get Encryption key + * + * @return string + * @throws \Magento\Framework\Exception\FileSystemException + * @throws \Magento\Framework\Exception\RuntimeException + */ private function getEncryptionKey(): string { $key = $this->deployConfig->get(static::PATH_KEY); From 511ade5aadd8ee79046aba865aad1a1651ba28b2 Mon Sep 17 00:00:00 2001 From: Rizwan Khan Date: Thu, 20 Jul 2023 15:35:03 +0530 Subject: [PATCH 20/20] AC-8425: Import file enhancements --- .../Framework/Url/Test/Unit/ValidatorTest.php | 12 ++++++++++++ lib/internal/Magento/Framework/Url/Validator.php | 11 +++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Url/Test/Unit/ValidatorTest.php b/lib/internal/Magento/Framework/Url/Test/Unit/ValidatorTest.php index 32c90cb1b8030..5cd86de6911f3 100644 --- a/lib/internal/Magento/Framework/Url/Test/Unit/ValidatorTest.php +++ b/lib/internal/Magento/Framework/Url/Test/Unit/ValidatorTest.php @@ -23,6 +23,9 @@ class ValidatorTest extends TestCase /** @var string[] */ protected $expectedValidationMessages = [Uri::INVALID => "Invalid URL '%value%'."]; + /** @var string[] */ + protected $invalidURL = [Uri::INVALID => "Invalid URL 'php://filter'."]; + protected function setUp(): void { $objectManager = new ObjectManager($this); @@ -59,4 +62,13 @@ public function testIsValidWhenInvalid() $this->assertFalse($this->object->isValid('%value%')); $this->assertEquals($this->expectedValidationMessages, $this->object->getMessages()); } + + public function testIsValidWhenInvalidURL() + { + $this->laminasValidator + ->method('isValid') + ->with('php://filter'); + $this->assertFalse($this->object->isValid('php://filter')); + $this->assertEquals($this->invalidURL, $this->object->getMessages()); + } } diff --git a/lib/internal/Magento/Framework/Url/Validator.php b/lib/internal/Magento/Framework/Url/Validator.php index 44fcf028d98c0..f2d3158029c8f 100644 --- a/lib/internal/Magento/Framework/Url/Validator.php +++ b/lib/internal/Magento/Framework/Url/Validator.php @@ -55,11 +55,14 @@ public function isValid($value) $this->setValue($value); $valid = $this->validator->isValid($value); - - if (!$valid) { - $this->error(Uri::INVALID); + // phpcs:ignore Magento2.Functions.DiscouragedFunction + $protocol = parse_url($value ? $value : '', PHP_URL_SCHEME); + if ($valid && ($protocol === 'https' || $protocol === 'http')) { + return true; } - return $valid; + $this->error(Uri::INVALID); + + return false; } }