Python: Аутентификация с помощью протокола S/KEY

Смотрю, тут многие интересуются безопасностью, поэтому решил выложить с описанием свою реализацию протокола S/KEY. В общем то задача тривиальная, на мой взгляд, но может кому-то понадобится, если зададут в универе.

S/KEY был разработан для аутентификации на на unix-подобных ОС, в частности, на «глупых» терминалах или на публичных компьютерах с низким уровнем доверия, где использовать долгосрочные пароли нецелесообразно.

Начнём с описания протокола. Сам протокол предназначен для аутентификации пользователей с использованием одноразовых паролей. Распишем всё по шагам:

  1. Для инициализации программы надо взять случайное число w, которое может быть задано как пользователем, так и компьютером. Если это число станет известным злоумышленнику, то протокол будет скомпрометирован.
  2. H — односторонняя функция, но т.к. односторонних функций не существует (по крайней мере, обычные смертные о них точно не знают), то возьмём какую-нибудь функцию, которая претендует на роль односторонней. Говоря простым языком, H — хеш-функция. Возьмём и применим её n раз. Сначала к w, потом к H(w), H(H(w)), …, H(…H(w)…).
  3. Начальное секретное число w уничтожается, дабы не досталось вражине.
  4. Выводим пользователю сгенерированные n-1 хешей, пользователь запоминает, или, если он не мнемоник, сохраняет их у себя в укромном месте.
  5. Сохраняем на сервере ключ под номером n для данного пользователя, все остальные уничтожаем.

Теперь при попытки войти пользователь передаёт своё имя и в качестве пароля последний ключ из своего списка (ключ, который был сгенерирован на шаге n-1). Сервер получает этот ключ, находит запись о ключе для данного имени пользователя, и сравнивает результат хеширования полученного пароля с найденым у себя в базе ключом, если результат операции совпадает с введённым паролем, то допускает пользователя к своему сверхсекретному сервису (для условности, обозначим его xxx). Но это ещё не всё, ведь протокол использует одноразовые пароли, поэтому на сервере при удачной попытке входа хранящееся значение ключа заменяется на полученное в начале от пользователя (т.е. праобраз хеша), а пользователь вычёркивает из своего списка последний ключ. Т.о., при первом входе пользователь передают ключ с номером n — 1, на сервере хранится ключ с номером n, при втором n — 2 и n — 1 соответственно, и т.д..

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

Недостатки: при перехвате начального секретного ключа w можно самому сгенерировать такую последовательность; пользователя придётся инициировать заново после того, как он «израсходует» все свои ключи.

А вот и обещанная реализация:

На мой взгляд, код достаточно примитивен, поэтому комментировать не буду, если у кого вопросы — в комментарии. В качестве хеш-функции была выбрана md5.

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: