我应该在 HMAC 中使用密码哈希作为密钥吗?


Should I use password hash as secret key in HMAC?

我正在尝试建立一个密码重置/忘记密码链接。该链接将通过电子邮件发送给用户。到目前为止,我正在采用这种方法:

  1. 使用bin2hex(openssl_random_pseudo_bytes(16));生成令牌

  2. 将此令牌的哈希存储在数据库表中

  3. 为其存储到期时间。

网址将被/reset-password/{$email address}/{$token}

我想在网址中添加一个 HMAC。如果我这样做,我可以安全地使用该用户的密码哈希(编辑:- 使用 PHP5.5 中的password_hash()创建的哈希)作为密钥吗?例如

$hmac = hash_hmac('sha256', $url_without_hmac, $password_hash);

所以新的网址将是/reset-password/{$email_address}/{$token}/{$hmac}

HMAC将使我们能够验证URL是否真实,而无需全局存储的密钥。这似乎是一种安全的方法,尽管使用电子邮件发送链接?

不,你不应该这样做。

HMAC 密钥与加密密钥相同,这意味着它必须是完全随机且不可预测的。密码哈希没有该属性,也可能长度不足。

更糟糕的是,如果您这样做,您将暴露第二个(可能更容易利用)攻击媒介以获取用户的密码 - 攻击者将能够通过蛮力确定用户的密码哈希,允许他们稍后在本地对密码本身执行相同的攻击。

最后,即使这些缺陷不存在,你也不会用这个想法添加任何有意义的保护措施。你只是过度设计它。

我不建议这样做,其他人可能不同意,但是,我认为这是违反安全性的;哈希不是100%安全的,因此可能不必要地给出用户密码将是危险的。单独设置临时令牌并将其存储在具有到期时间的数据库中将是一个更安全的选择(实际上没有那么多工作)