Рейтинг@Mail.ru

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 можно самому сгенерировать такую последовательность; пользователя придётся инициировать заново после того, как он «израсходует» все свои ключи.

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

from md5 import md5 import sys, os def skey_register():     name = raw_input("Enter your name: ")     if os.path.exists(name):         print "Error, user always exists."         sys.exit(-1)     r = raw_input("Enter random sequence R: ")     for i in range(100):             r = md5(r).hexdigest()             print i, r     key = md5(r).hexdigest()     try:         f = open(name, "w")     except:         print "Error, can't open file %s for write!" % name         sys.exit(-1)     f.write(key)     f.close() def skey_login():     name = raw_input("Enter your name: ")     try:         f = open(name, "r")     except:         print "Error, can't open file %s!" % name         sys.exit(-1)     passwd = f.read()     f.close()     upasswd = raw_input("Enter password: ")     new_upasswd = md5(upasswd).hexdigest()     if new_upasswd != passwd:         print "Invalid password!"     else:         print "Login successful!"         f = open(name, "w")         f.write(upasswd)         f.close() if __name__ == "__main__":     while True:         action = raw_input("Enter action ((r)egister, (l)ogin or (q)uit): ")         if action == "r":             skey_register()         elif action == "l":             skey_login()         elif action == "q":             sys.exit(0)

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

Ссылки к статье:
http://en.wikipedia.org/wiki/Skey — Skey на английской википедии.

криптография, Программирование ,

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1 звезда2 звезды3 звезды4 звезды5 звёзд (1 голосов, средний: 5,00 из 5)
Loading ... Loading ...

  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.
*