Я пытаюсь реализовать TOTP в PHP, и я получаю код на шесть ди git, но он никогда не совпадает с кодом в моем приложении Authenticator. Я смог сосредоточиться на проблеме, которая, скорее всего, связана с выводом hash_hma c, так как я протестировал все сдвиги битов, возникающие после того, как ha sh сгенерировано на примере в документе RF C, и это произвел ожидаемый результат. Мой вопрос сейчас: что я делаю не так? Я передаю неправильно отформатированный ввод в hash_hma c? Я действительно в растерянности.
<?php
class TOTP
{
function __construct ($d, $k)
{
$this->digits = $d;
$this->secret = $k;
$this->ival = 30;
}
private function int2bytes ($n)
{
$bytes = array();
for ($i = 7; $i >= 0; $i--) {
$bytes[] = ($n >> ($i * 8)) & 0xff;
}
return pack("C*", ...$bytes);
}
function hotp ($d, $k, $c)
{
// @$d the number of digits
// @$k the shared secret
// @$c an integer counter
$hmac = hash_hmac("sha1", $this->int2bytes($c), $k);
$hex = str_split($hmac, 2);
$bytes = array();
for ($i = 0; $i < count($hex); $i++) {
$bytes[] = hexdec($hex[$i]);
}
$offset = $bytes[19] & 0xf;
$bincode =
($bytes[$offset] & 0x7f) << 24 |
($bytes[$offset + 1] & 0xff) << 16|
($bytes[$offset + 2] & 0xff) << 8 |
$bytes[$offset + 3] & 0xff;
$hotp = strval($bincode % pow(10, $d));
while (strlen($hotp) < $d) {
$hotp = "0$hotp";
}
return $hotp;
}
public function get ()
{
$counter = floor(time() / $this->ival);
return $this->hotp($this->digits, $this->secret, $counter);
}
}
?>
Некоторые примеры ввода и вывода для TOTP :: get (), где $ this-> secret всегда "secret", а цифры всегда 6:
unix time: 1584041829
output: 79 06 09
expected: 91 97 63
unix time: 1584041867
output: 76 89 74
expected: 70 54 64
unix time: 1584041918
output: 46 57 96
expected: 52 96 15