帐户激活链接是HMAC的用例?

时间:2015-08-19 20:56:25

标签: php security

我使用PHP并需要设计激活器链接

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

因此,会向用户发送以下网址

hostname/account/confirm/7c7b0f24eff74902cb07e900b07a0cafc8fccfa5d2704fb92aaf3b91e9774f98

这种方式好主意?

如果为true,sha256hash_hmac()在这种情况下的最佳选择?特别是,我希望有一个length <= 24

的字符串

1 个答案:

答案 0 :(得分:2)

TL; DR::此用例无需使用hash_hmac()。您可以直接使用令牌。

如果$user->token是安全生成的(由于collisions in OpenSSL's random number generator,您想要random_bytes()而不是openssl_random_pseudo_bytes()是nb),那么它是一个安全的随机值,攻击者无法无需破解表就知道它。

您要在哪里使用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

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