* @copyright 2023 smiley * @license MIT */ declare(strict_types=1); namespace chillerlan\Authenticator\Authenticators; use SensitiveParameter; use function floor; use function hash_equals; use function time; /** * @link https://tools.ietf.org/html/rfc6238 */ class TOTP extends HOTP{ /** * @inheritDoc */ public function getCounter(int|null $data = null):int{ $data ??= time(); if($this->options->useLocalTime === false){ $data = $this->getServerTime(); } return (int)floor(($data + $this->options->time_offset) / $this->options->period); } /** * @inheritDoc */ public function verify(#[SensitiveParameter] string $otp, int|null $data = null):bool{ $limit = $this->options->adjacent; if($limit === 0){ return parent::verify($otp, $data); // @codeCoverageIgnore } $timeslice = $this->getCounter($data); // phpcs:ignore for($i = -$limit; $i <= $limit; $i++){ $hash = $this->getHMAC($timeslice + $i); $code = $this->getOTP($this->getCode($hash)); if(hash_equals($code, $otp)){ return true; } } return false; } }