Reputation: 117
I'm importing 15000 users from virtuemart into magento but have been unable to get the passwords to import correctly.
My problem is that the passwords are hashed differently.
Virtuemart HASH = md5($password.$salt);
Magento HASH = md5($salt.$password);
An example password looks like:
c957d358c8a79e66af10086b53b5a069:AuHg2mCXUhViqKYCLtFco22rmUCDwIFI
An answer has been provided below which partially solves my problem. Applying this allows my virtuemart customers to login but causes issues with the admin login and forces new users to use the virtuemart password hash format.
I now need to modify this in such a way that it checks the core hashing method, and if that fails it checks the virtuemart hashing method allowing both password formats to login.
I was thinking something along the lines of
public function getHash($password, $salt = false)
{
if (is_integer($salt)) {
$salt = $this->_helper->getRandomString($salt);
}
return $salt === false ? $this->hash($password) : $this->hash($password . $salt) . ':' . $salt : $this->hash($salt . $password) . ':' . $salt;
}
.
public function validateHash($password, $hash)
{
$hashArr = explode(':', $hash);
switch (count($hashArr)) {
case 1:
// no hash
return $this->hash($password) === $hash;
case 2:
// magento default hash
return $this->hash($hashArr[1] . $password) === $hashArr[0];
case 3:
// virtuemart hash
return $this->hash($password . $hashArr[1]) === $hashArr[0]; }
Mage::throwException('Invalid hash.');
}
but as you can probably tell this doesnt work as i have no way to check the hash type method.
How would i go about this please ?
UPDATE - Heres my latest attempt.
public function validateHash($password, $hash)
{
$hashArr = explode(':', $hash);
if(admin_login_handling_and_api_user_accounts){
switch (count($hashArr)) {
case 1:
return $this->hash($password) === $hash;
case 2:
return $this->hash($hashArr[1] . $password) === $hashArr[0];
}
} else if(Magento_customer_handling){
switch (count($hashArr)) {
case 1:
return $this->hash($password) === $hash;
case 2:
return $this->hash($password . $hashArr[1]) === $hashArr[0];
}
} else if(soap_Api_customer_handling){
switch (count($hashArr)) {
case 1:
return $this->hash($password) === $hash;
case 2:
return $this->hash($hashArr[1] . $password) === $hashArr[0];
}
}
}
I've changed the validatehash function to include if statements but this doesnt seem to be recognised. My php skills are on the very basic side so if someone could please explain where im going wrong with this or if theres a better way to go about it.
Thanks.
Upvotes: 1
Views: 6421
Reputation: 6186
It all depends how the algorithm works in virtuemart. After a quick google it seems like it takes the password provided by the user and appends the salt (the part after the semi-colon) to the end, then md5's the value, which it compares to the password hash (the part before the semi-colon in the database).
In contrast to that Magento prepends the salt to the start of the password before md5 hashing it, rather than the end.
Long story short, the quick win should be attainable by editing Mage_Core_Model_Encryption::validateHash
so that if $hashArr
has a count of two it will append the hash, rather than prepend.
// replace
return $this->hash($hashArr[1] . $password) === $hashArr[0];
// with
return $this->hash($password . $hashArr[1]) === $hashArr[0];
Upvotes: 1