encryptor = clone $encryptor; parent::__construct($context, $connectionName); $this->directory = $filesystem->getDirectoryWrite(DirectoryList::CONFIG); $this->structure = $structure; $this->writer = $writer; $this->random = $random; } /** * Initialize * * @return void */ protected function _construct() { $this->_init('core_config_data', 'config_id'); } /** * Change encryption key * * @param string|null $key * @return null|string * @throws \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.')); } if (null === $key) { $key = md5($this->random->getRandomString(ConfigOptionsListConstants::STORE_KEY_RANDOM_STRING_SIZE)); } $this->encryptor->setNewKey($key); $encryptSegment = new ConfigData(ConfigFilePool::APP_ENV); $encryptSegment->set(ConfigOptionsListConstants::CONFIG_PATH_CRYPT_KEY, $this->encryptor->exportKeys()); $configData = [$encryptSegment->getFileKey() => $encryptSegment->getData()]; // update database and config.php $this->beginTransaction(); try { $this->_reEncryptSystemConfigurationValues(); $this->_reEncryptCreditCardNumbers(); $this->writer->saveConfig($configData); $this->commit(); return $key; } catch (\Exception $e) { $this->rollBack(); throw $e; } } /** * Gather all encrypted system config values and re-encrypt them * * @return void */ protected function _reEncryptSystemConfigurationValues() { // look for encrypted node entries in all system.xml files /** @var \Magento\Config\Model\Config\Structure $configStructure */ $configStructure = $this->structure; $paths = $configStructure->getFieldPathsByAttribute( 'backend_model', 'Magento\Config\Model\Config\Backend\Encrypted' ); // walk through found data and re-encrypt it if ($paths) { $table = $this->getTable('core_config_data'); $values = $this->getConnection()->fetchPairs( $this->getConnection() ->select() ->from($table, ['config_id', 'value']) ->where('path IN (?)', $paths) ->where('value NOT LIKE ?', '') ); foreach ($values as $configId => $value) { $this->getConnection()->update( $table, ['value' => $this->encryptor->encrypt($this->encryptor->decrypt($value))], ['config_id = ?' => (int)$configId] ); } } } /** * Gather saved credit card numbers from sales order payments and re-encrypt them * * @return void */ protected function _reEncryptCreditCardNumbers() { $table = $this->getTable('sales_order_payment'); $select = $this->getConnection()->select()->from($table, ['entity_id', 'cc_number_enc']); $attributeValues = $this->getConnection()->fetchPairs($select); // save new values foreach ($attributeValues as $valueId => $value) { $this->getConnection()->update( $table, ['cc_number_enc' => $this->encryptor->encrypt($this->encryptor->decrypt($value))], ['entity_id = ?' => (int)$valueId] ); } } }