0

I am trying to run a password hash to change user passwords from MD5 to SHA256 following a migration from Magento 1 to Magento 2.

The problem is, I have around 8 million customer records. I have ensured that the hardware is scaled right up, currently using 8 cores and 60gb RAM which is about the limit I can do.

The process starts off ok running about 1000 records in 10 seconds but over time it grinds down to about 1 min per 1000 records.

Based on rough calculations it will take weeks to run which isn't viable for us.

I have also tried to add some filters to the collection so that it runs in batches and checks the hash version before hashing so it doesn't redo previously hashed items.

I was wondering if there are any tips for optimising this core method to ensure it can run in a decent time?

See below for the modified method that I am using:

protected function configure()
{
    $this->setName('customer:hash:upgrade')
        ->setDescription('Upgrade customer\'s hash according to the latest algorithm');

protected function execute(InputInterface $input, OutputInterface $output)
{
    $this->collection = $this->customerCollectionFactory->create();
    $this->collection->addAttributeToSelect('password_hash');
    $this->collection->addAttributeToSelect('entity_id');
    $this->collection->setPageSize(1000);
    $this->collection->getSelect()->where('password_hash NOT LIKE "%0:1"');
    $pages = $this->collection->getLastPageNumber();
    $currentPage = 1;


    echo $this->collection->getPasswordHash();

    do {
        $output->writeln("starting batch of 1000 customers");
        $time_start = microtime(true);
        $this->collection->setCurPage($currentPage);
        $this->collection->load();
        $this->collection->getSelect()->where('password_hash NOT LIKE "%0:1"');
        $customerCollection = $this->collection->getItems();

        /** @var $customer Customer */
         foreach ($customerCollection as $customer) {
            $customer->load($customer->getId());
           if (!$this->encryptor->validateHashVersion($customer->getPasswordHash())) {
                list($hash, $salt, $version) = explode(Encryptor::DELIMITER, $customer->getPasswordHash(), 3);
                if ($version !== '0') {
                    $version .= Encryptor::DELIMITER . Encryptor::HASH_VERSION_LATEST;
                    $customer->setPasswordHash($this->encryptor->getHash($hash, $salt, $version));
                    $customer->save();
                    $output->write(".");
                }
            }
        } 
        $output->writeln('last id: '.$customer->getId(). "");
        $currentPage++;
        //clear collection and free memory
        $this->collection->clear();
        $time_end = microtime(true);
        //dividing with 60 will give the execution time in minutes otherwise seconds
        $execution_time = ($time_end - $time_start) / 60;
        $output->writeln("1000 customers comepleted in " . $execution_time . " min");
    } 
while ($currentPage <= $pages && ((1000*$currentPage) > $stopLimit || $stopLimit));
    $output->writeln(".");
    $output->writeln("<info>Finished</info>");
}

}

2
  • This seems to be based on a faulty premise, that you can just rehash an existing hash and have it work. Hashes do not work this way. Have you even tried this on one single migrated customer account for which you know the password and shown that it will work in the way you expect? Commented Oct 14, 2019 at 16:33
  • Thanks for the reply. I haven't as unfortunately the only passwords I know are deep into the records so haven't managed to get that far. However, I am not sure what the password hash cli tool does if it doesn't work this way as no unhashed passwords are stored in the DB so what would it be hashing from the CLI?
    – apt_dev
    Commented Oct 15, 2019 at 16:51

1 Answer 1

0

Looks like you need to hash user password, not the hash of user password.

So, you can do it only when user is login and provide password for you

2
  • This is the correct answer. One will have to require the customer to reset their password when they login post-migration for the first time. Commented Oct 14, 2019 at 16:34
  • magento.stackexchange.com/questions/173578/… See here, It seems this is the purpose of this command...
    – apt_dev
    Commented Oct 16, 2019 at 9:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.