Как работают мобильные аутентификаторы - PullRequest
4 голосов
/ 21 июня 2011

Мне было интересно, как работают мобильные аутентификаторы (например, Battle.net , rift , в некоторых банках есть один и т. Д.), Поэтому я могу сделать один для своего сайта (просто в шутку).

Я понимаю основы: аутентификатор имеет код, связанный с телефоном, и код, связанный с веб-сайтом. Пользователь вводит телефонный код на сайте. Затем можно сгенерировать связанный токен (используя телефон и код веб-сайта).

Мне просто интересно как создаются токены. Есть ли стандартный алгоритм для этого? Как работает алгоритм? Какие-нибудь существующие библиотеки PHP, которые могут делать что-то подобное (в качестве примера)?

Ответы [ 4 ]

6 голосов
/ 24 июня 2011

Посмотрите на Google Authenticator . Для этого уже есть приложения для iPhone, Android и Blackberry, и это уже установленный протокол.

Они реализовали его как модуль PAM с открытым исходным кодом , который вы можете использовать с пакетом PECL PAM .

Существует чистая версия PHP , но я не использовал ее, поэтому не могу ручаться за нее.

spec не является таким сложным , чтобы вы могли реализовать его самостоятельно, особенно если вы конвертировали модуль C. Связанная там спецификация объясняет его работу в деталях.

Редактировать: Я предполагаю ответить на оригинальный вопрос, это RFC, так что он несколько стандартизирован, и это полностью открытая спецификация, а инструменты для ее использования полностью открыты. Протоколы известны как HOTP и TOTP. Первый - это HMAC на основе счетчика (поэтому используется n-й пароль), а второй - на основе времени (поэтому пароль циклически повторяется каждые 30 секунд).

1 голос
/ 13 февраля 2012

Что касается аутентификатора Blizzad Battle.Net, вы можете найти реализацию с открытым исходным кодом в PHP: https://github.com/krtek4/php-bma

Реализация используется для предоставления службы онлайн-аутентификации для Battle.Net: https://authenticator.me

Если вы хотите сделать что-то подобное для своего сайта, это довольно просто.Единственная вещь, которую нужно разделить между серверной и клиентской частью, - это секрет, сгенерированный сервером.Поэтому, когда клиент запрашивает новый секрет, просто сохраните его, и вы сможете в любой момент вычислить код для сравнения с тем, что вам отправлено.

0 голосов
/ 23 июня 2011

Если бы это был я, я бы сгенерировал хеш на основе ранее использованного хеша и обычного одноразового номера, хитрый бит поддерживал бы синхронизацию двух систем. например,

<?php

class otp {
   var $salt;
   var $previous_hash;
   var $user_id;

   function __construct($user_id)
   {
      $this->user_id=$user_id;
      list($this->$salt, $this->$previous_hash)
          =unserialize(file_get_contents(BASE_PATH . $user_id));
   }
   function authenticate($submitted_otp)
   {
      if (!$this->salt) {
          // user does not exist
          return false;
      }
      $new_hash=$this->previous_hash;
      // allow for the sequence to get out of sync by 5 steps....
      for ($x=0; $x<5; $x++) {
          $new_hash=md5($this->salt, $new_hash);
          if ($new_hash===$submitted_otp) {
              $this->update_token($new_hash);
              return true;
          }
      }
      // none of the next N iterations of the local password match
      return false;
   }
   function create_user($user_id, $salt, $init_hash)
   {
      return file_put_contents(BASE_PATH . $user_id, array($salt, $init_hash));
   }
   function update_token($new_hash)
   {
       file_put_contents(BASE_PATH . $user_id, array($this->salt, $new_hash));
   }
}

Конечно, на практике вы, вероятно, не захотите использовать весь хэш md5 из 32 символов (скажем, только первые 6 символов и применить очистку, например, изменить 'S' на '5' и т. Д.).

0 голосов
/ 21 июня 2011

Я реализовал это один раз. Я использую 4-значный ключ с подмножеством символов (обратите внимание, что потенциально сбивающие с толку символы, такие как 0oO и l1L, удалены. Я использовал 4 символа, потому что потенциальный пробел из 4 цифр из набора символов был больше, чем 6 цифр ключа RSA.

В любом случае, я позволил пользователю войти в систему со своим именем пользователя и паролем. Если это правильно, сгенерируйте ключ и отправьте его на телефон, сохраните в сеансе и покажите пользователю следующую страницу, для которой требуется ввести ключ. Пользователь получает 4-значный ключ со своего телефона и вводит его на страницу. Затем проверьте, что они ввели против сохраненного в сеансе ключа, и все.

Некоторые удобные функции: срок действия ключа истекает через несколько минут, но достаточно долго, чтобы задержки при отправке текстовых сообщений не делали его невозможным. Заставьте его истечь после нескольких неудачных попыток. Дайте пользователям ссылку для повторной отправки ключа или для отправки нового ключа.

//pick a random 4 digit string
$chars = "abcdefghjkrstwxyzABCDEFGHJKRSTWXYZ23456789";
$key = "";
for($i=0;$i<4;$i++){
    //here, rand is used, but any generator could be used
    //to choose the characters.
    $key .= $chars[rand(0,strlen($chars)-1)];
}
//save it to the session
$_SESSION['test']['KEY'] = $key;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...