Pull to refresh

Консольное приложение PassKeep

Reading time 3 min
Views 7.7K
Здравствуйте, Хабражители!

А как Вы храните свои пароли? Или у Вас один пароль на все случаи жизни? Раньше у меня было именно так! Ну то есть почти так. У меня их было два — идентификационный код и хитро мудрая анаграмма, составленная из моего мобильного телефона.

Если Вы один из таких как я, то прошу под кат.

У меня уже давно созревала идея написать что-нибудь подобное. И вот, наконец-то, у меня выдался свободный день и я решил реализовать это дело.

План действий

Итак, что бы мы хотели видеть:
  1. Программа должна сама генерировать пароль на основе url ресурса, на котором мы регистрируемся например;
  2. Пароль должен быть достаточно стойким к брутафорсу, то есть содержать буквы и цифры;
  3. Пароль не должен храниться где-либо, а генерироваться на лету;
  4. Пароль должен быть восстановимым.


Я представляю себе так:
  1. После запуска программы, требуется ввести пароль(он может быть простым, допустим 45678);
  2. Требуется ввести url, например www.twitter.com ;
  3. Получаем 10-значный пароль, который и используем для регистрации.


Как это работает?

После ввода пароля и url, мы получаем их md5-суммы, выполняем конкатенацию строк и получаем строку длинной 64 символа. Далее получаем md5-сумму этой строки и берем первые 10 символов — это и будет наш пароль. Довольно таки просто.

Реализация

Мне очень нравиться Python и JavaScript, но так, как мы хотим получить консольное приложение, а как запустить в консоли программу на JavaScripte я не знаю, то будем писать на Pythone. Начнем:

import hashlib, sys, re

class PassKeep:   #Да, это ООП, детка!
	__password = ""                    
	__length = 10   #Длина генерируемого пароля будет 10 символов.
	url = ""

	def getMd5(self, string):   #Функция для получения md5 из строки.
		string = str(string)
		md5 = hashlib.md5()
		md5.update(string)
		return md5.hexdigest()

	def __init__(self):   #Ага, даже конструктор есть.  На всякий пожарный. Вдруг я поставлю пароль по умолчанию.
		self.__password = self.getMd5(self.__password)
		self.time = self.getMd5(time.time())

	def setUrl(self, url):   #Задаем url.
		self.url = self.getMd5(url)
		return self.url

	def setPasswd(self, passwd):   #И пароль.
		self.__password = self.getMd5(passwd)
		return self.__password

	def decrypt(self):   #Главная функция, она все декрупирует.
		password = self.__password               #Получаем пароль и url,
		url = self.url   #что бы удобнее было работать.
		result = self.getMd5(password + url)   #И получаем md5 от результата конкатенации строк.
		passwd_candidate = result[:self.__length]     #От результата откусываем нужные нам 10 символов.
                #А вот теперь начинаются извращения! После некоторого использования, 
                #я понял, что есть вероятность того, что первые n(10) символов могут быть цифрами.
                #А пароль из одних цифр - это плохой пароль, поэтому надо проверять и что-то с этим делать!
		if (len(re.findall(r'([0-9]+)', passwd_candidate)[0]) + 3 < len(passwd_candidate)): #Не менее трёх букв
			return passwd_candidate
		else:   #А если менее, то будем исправлять.
			result = ""
			count = 0
			sum = 1
			for symbol in passwd_candidate:   #Получаем по одному символы и проверяем.
				if (sum < 4):   #Если мы уже замени три цифры на буквы, то остальное просто добавляем. 
					try:   #Если символ не приводиться к int, то он str (кэп).
						int_symbol = int(symbol)
						if (count%2 != 0):   #Будем преобразовывать только нечётные по счету цифры.
							print int_symbol
							result += chr(122 - int_symbol) #Заменим цифру на букву, которая находиться под тем же порядковым номером с конца алфавита, что б никто не догадался! 
							sum += 1
							count += 1
						else:   #Если четная, то пусть не меняется.
							result += symbol
							count += 1
					except:   #Если он str то мы его просто добавляем к результату.
						result += symbol
						count += 1
				else:
					result += symbol
					count += 1
			return result


p = PassKeep()   #Создаем объект.
passwd = raw_input("Enter passwd \n")    #У нас же консольное приложение как ни как!
p.setPasswd(passwd)
url = raw_input("Enter url, like www.example.com \n") 
p.setUrl(url)
print p.decrypt()   #Выводим все это безобразие на экран
sys.exit(0)   #и выходим.


Запуск

Запустить это довольно просто — сохраняем все это дело в файл passkeep.py и запускаем:
python passkeep.py


Заключение

Вот этой вещью я пользуюсь уже почти 12 часов. Зарегистрировался на 5 ресурсах и на 2 поменял пароль. Изначально, пароли генировал на 64 разрядном процессоре, теперь попробовал на 86 разрядном, вроде бы пароли совпадают. Ну это я так, на всякий случай.

Ах, да. Я еще это дело залил на Github: клац.

Хочу еще немного по-тестировать все это дело и, если проблем не будет, портировать на iOS/Android/Chrome Extensions.

Буду очень рад конструктивным замечаниям по реализации.

Спасибо за внимание.

UPD:
Спасибо хабраюзеру Dark_MX за его дополнения и спасибо Romansl за то, что нашел расширение для хрома.
Tags:
Hubs:
-5
Comments 20
Comments Comments 20

Articles