Аутентификация с одноразовым паролем (eToken PASS)


Довольно удобная вещь для повышения безопасности.
eToken PASS – автономный генератор одноразовых паролей. Устройство не требует подключения к компьютеру и установки дополнительного ПО, и поэтому может спокойно использоваться на web-ресурсах.
Реализацию подсмотрел на habrahabr.ru (перепостил частично себе на память).


В первую очередь нам необходимо получить значение счетчика в токене.

Для этого нажимаем кнопку на токене и удерживаем ее ~5 секунд. На экране начнет моргать «888888», жмем еще 4 раза на кнопку и увидим «F00055» – 55 это и будет значение счетчика. Каждый раз, когда токен генерирует пароль, счетчик увеличивается.

Чтобы провести аутентификацию, в функцию authOTP передаем:
•    $secret — секретный ключ (находится в файле прилагаемый к токену);
•    $pass — пароль сгенерированный токеном;
•    $cnt — текущее значение счетчика;
•    $window – разрешенное окно т.е. интервал возможных значение счетчика, в нашем случае будет от 55 до 65. В процессе эксплуатации токена, при случайном нажатии счетчик будет увеличен, а информация в базе останется прежней и для того чтобы пароль был принят мы в цикле перебираем возможные значения.


В случае успешной аутентификации функция authOTP возвращает текущее значение счетчика, сохраняем его в БД или куда-либо еще для следующих попыток входа.

public function authOTP($secret, $pass, $cnt, $window = 10)
{
  if(preg_match("/(\\d{6})$/", $pass)) {
    $cnt = intval($cnt)+1;
    $i = 0;
    while($i < $window) {
      if($this->hotp($secret, $cnt) == $pass) {
        return $cnt;
      }
      $cnt++;
      $i++;
    }
  }
}
  
public function hmac_sha1($data, $key)
{
  if(function_exists('hash_hmac')) {
    return hash_hmac('sha1', $data, $key);
  }

  if(strlen($key) > 64) {
    $key = pack('H*', sha1($key));
  }

  $key = str_pad($key, 64, chr(0x00));
  $ipad = str_repeat(chr(0x36), 64);
  $opad = str_repeat(chr(0x5c), 64);
  $hmac = pack('H*',sha1(($key^$opad).pack('H*',sha1(($key^$ipad).$data))));
  return bin2hex($hmac);
}

public function hotp($secret, $cnt, $digits = 6)
{
  $secret  = pack('H*', $secret);
  $sha1_hash = $this->hmac_sha1(pack("NN", 0, $cnt), $secret);
  $dwOffset = hexdec(substr($sha1_hash, -1, 1));
  $dbc1   = hexdec(substr($sha1_hash, $dwOffset * 2, 8 ));
  $dbc2   = $dbc1 & 0x7fffffff;
  $hotp   = $dbc2 % pow(10, $digits);
  return $hotp;
}

Ключи покупал на softkey.ru

#php

Copyright © 2019