密码散列

目前,Commerce基于不同的本机PHP哈希算法,采用自己的密码哈希处理策略。 Commerce支持多种算法,如MD5SHA256Argon 2ID13。 如果安装了Na扩展(默认安装在PHP 7.3中),则选择Argon 2ID13作为默认散列算法。 否则,SHA256为默认值。 Commerce可以使用支持Argon 2i算法的本机PHP password_hash函数。

为避免损害已使用过时算法(如MD5)进行哈希处理的旧密码,当前实现提供了升级哈希而不更改原始密码的方法。 通常,密码哈希的格式如下:

password_hash:salt:version<n>:version<n>

其中version<n>version<n>表示密码上使用的所有哈希算法版本。 而且,Salt始终与密码哈希一起存储,因此我们可以还原整个算法链。 示例如下所示:

a853b06f077b686f8a3af80c98acfca763cf10c0e03597c67e756f1c782d1ab0:8qnyO4H1OYIfGCUb:1:2

第一部分代表密码散列。 第二种8qnyO4H1OYIfGCUb是盐。 最后两个是不同的哈希算法: 1是SHA256,2是Argon 2ID13。 这意味着客户的密码最初是使用SHA256进行哈希处理,此后,算法更新为Argon 2ID13,哈希使用氩重新进行哈希处理。

升级哈希策略

请考虑哈希升级机制是什么样的。 假设最初使用MD5对密码进行了哈希处理,然后使用Argon 2ID13多次更新算法。 下图显示了哈希升级流程。

哈希升级工作流

每个哈希算法都使用上一个密码哈希来生成一个新的哈希。 Commerce不会存储原始原始密码。

哈希升级策略

如上所述,密码哈希可能具有多个应用于原始密码的哈希版本。
下面是密码验证机制在客户身份验证期间的工作方式。

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)

由于Commerce将所有使用的密码哈希版本与密码哈希一起存储,因此可以在密码验证期间还原整个哈希链。 散列验证机制类似于散列升级策略:根据与口令散列一起存储的版本,算法从提供的口令生成散列,并返回散列口令与数据库存储的散列的比较结果。

实现

\Magento\Framework\Encryption\Encryptor类负责密码哈希生成和验证。 bin/magento customer:hash:upgrade命令将客户密码哈希升级为最新的哈希算法。

recommendation-more-help
386822bd-e32c-40a8-81c2-ed90ad1e198c