base32_decode($this->secret); $binaryTime = pack('N*', 0) . pack('N*', $time); $hash = hash_hmac('sha1', $binaryTime, $secretKey, true); $offset = ord($hash[strlen($hash) - 1]) & 0x0F; $otp = ( ((ord($hash[$offset]) & 0x7F) << 24) | ((ord($hash[$offset + 1]) & 0xFF) << 16) | ((ord($hash[$offset + 2]) & 0xFF) << 8) | (ord($hash[$offset + 3]) & 0xFF) ) % 10 ** $digits; return str_pad((string)$otp, $digits, '0', STR_PAD_LEFT); } private function base32_decode(string $input): string { $base32charsFlipped = array_flip(str_split(self::BASE32CHARS)); $output = ''; $v = 0; $vbits = 0; for ($i = 0, $j = strlen($input); $i < $j; $i++) { $v <<= 5; if ($input[$i] == '=') continue; $v += $base32charsFlipped[$input[$i]]; $vbits += 5; if ($vbits >= 8) { $vbits -= 8; $output .= chr(($v & (0xFF << $vbits)) >> $vbits); } } return $output; } }