当前位置: 首页 > 工具软件 > TOTP-Miniapp > 使用案例 >

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

颛孙正谊
2023-12-01

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 '验证失败';
}
 类似资料: