帐户激活器链接是HMAC的一个用例


Account activator link is a use case for HMAC?

我正在使用PHP,需要设计激活器链接

$data = $user->email; 
$key = $user->token; // bin2hex(openssl_random_pseud_bytes(16));
$hmac = hash_hmac( 'sha256', $data, $key );

那么,会向用户发送以下url

hostname/account/confirm/7c7b0f24eff74902cb07e900b07a0cafc8fccfa5d2704fb92aaf3b91e9774f98

这样好吗?

如果成立,在这种情况下,sha256hash_hmac()的最佳选择?特别是,我会欣赏length <= 24

的字符串。

TL;DR:对于这个用例,您不需要使用hash_hmac()。您可以直接使用令牌

如果$user->token是安全生成的(注意,你想要random_bytes(),而不是openssl_random_pseudo_bytes(),由于OpenSSL的随机数生成器中的冲突),那么它是一个安全的随机值,攻击者没有办法知道它,除非入侵表。

想要使用HMAC

的地方

如果你想验证一些发送到用户电子邮件地址的明文数据,你可以使用HMAC来实现这个目的。

例如:在注册时,如果您需要向用户提供一个选项(例如GDPR同意),您可以创建以下两个绑定到相同令牌的url,如下所示:

$hmacYes = hash_hmac('sha256', 'yes', $user->token);
$hmacNo = hash_hmac('sha256', 'no', $user->token);

那么你可以为每个选项设置两个链接,并像这样发送链接:

* `hostname/account/confirm/yes${hmacYes}`
* `hostname/account/confirm/no${hmacNo}`

然后你可以解析HMAC值:

if (!preg_match('/^(yes|no)(.*)$/', $urlParam, $matches) {
    throw new SecurityException('bad url');
}
$choice = $matches[1];
$hmac =   $matches[2];
$recalc = hash_hmac('sha256', $choice, $user->token);
if (!hash_equals($recalc, $mac)) {
    throw new SecurityException('bad url');
}
// Now you know $choice is from a genuine user email

但是,如果您只需要质询-响应身份验证,那么一个安全随机令牌就足够了。