TOTP - 邮箱或手机号验证码生成与验证

TOTP

Time-based One-time Password algorithm, 是一种共享密钥和当前时间计算一次性密码的算法。

使用目的

利用时间戳和邮箱(或手机号)生成一段时间内唯一的验证码。验证用户输入的验证码和一段时间内生成的验证码集合对比,如果在此集合,则证明验证码有效。摆脱使用redis等方式存储和对比验证码。

CODE
class Totp {
    private $salt = 'salt';    // 盐
    private $refreshInterval = 30; //每隔30秒刷新验证码
    private $checkCount = 10;	//验证码集合数量 $refreshInterval x $checkCount 为验证码有效期
    private $codeLength  = 6;  //生成验证码长度

    public function generate(string $input) {
        return $this->trimTotp($this->genTotp($this->hashInput($input), time()));
    }

    public function check(string $input, string $code) {
        $hashedInput = $this->hashInput($input);
        $currentTime = time();
        for (
            $windowIndex = 0;
            $windowIndex <= $this->checkCount;
            $windowIndex++
        ) {
            if (
                $code === $this->trimTotp(
                    $this->genTotp(
                        $hashedInput, 
                        $currentTime - ($windowIndex * $this->refreshInterval)
                    )
                )
            ) {
                return TRUE;
            }
        }

        return FALSE;
    }
    
	private function hashInput (string $input) {
        $input = $input ? $input : $this->salt;
        return hash('sha256', md5($input) . md5($this->salt), FALSE);
    }
    
	private function genTotp (string $hashedInput, int $timestamp) {
        $sequence = floor($timestamp / 30);
        $code = hash_hmac("sha256", $hashedInput . md5($sequence), md5($sequence), TRUE);

        $finalValue = 0;
        $index = 0;

        do {
            $finalValue += ord($code[$index]);
            $finalValue = $finalValue << 2;
            $index++;
        } while (isset($code[$index]));

        return $finalValue;
    }
    
	private function trimTotp (int $sourceTotp) {
        $trimedTotp = $sourceTotp % pow(10, $this->codeLength);
        $format = "%'.0". $this->codeLength ."u";
        return sprintf($format, abs($trimedTotp));
    }
}

$email = 'xxxxxx@qq.com';
$totp = new Totp();
$code = $totp->generate($email);

echo $code;

if ($totp->check($email, $code)) {
	echo '验证通过';
} else {
	echo '验证失败';
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值