Upgrade hash strategy

Consider what the hash upgrade mechanism looks like. Assume that originally, a password was hashed with MD5 and then the algorithm was updated multiple times with Argon 2ID13. The following diagram shows the hash upgrade flow.

Hash upgrade workflow

Each hash algorithm uses the previous password hash to generate a new hash. Commerce does not store the original, raw password.

Hash upgrade strategy

As discussed above, the password hash might have multiple hash versions applied to the original password.
Here is how the password verification mechanism works during a customer authentication.

def verify(password, hash):
    restored = password

    hash_map = extract(hash)
    # iterate through all versions specified in the received hash [md5, sha256, argon2id13]
    for version in hash_map.get_versions():
        # generate new hash based on password/previous hash, salt and version
        restored = hash_func(salt . restored, version)

    # extract only password hash from the hash:salt:version chain
    hash = hash_map.get_hash()

    return compare(restored, hash)

Since Commerce stores all used password hashes versions together with the password hash, we can restore the whole hash chain during the password verification. The hash verification mechanism is similar to the hash upgrade strategy: based on versions stored together with the password hash, the algorithm generates hashes from the provided password and returns the comparison result between hashed password and the database-stored hash.

Implementation

The \Magento\Framework\Encryption\Encryptor class is responsible for password hash generation and verification. The bin/magento customer:hash:upgrade command upgrades a customer password hash to the latest hash algorithm.

Previous pageSecurity overview
Next pageCache poisoning

Commerce