Как стать автором
Обновить

Менеджер паролей без хранения

Время на прочтение3 мин
Количество просмотров16K

Всем привет!

Хочу поделиться с народом своей идеей по поводу безопасного хранения паролей. Сторонние менеджеры паролей мне всегда не нравились. Хранение сокровенного у чужого дяди – идея ну очень так себе. Можно сколько угодно клясться, что все надежно, что утечки маловероятны и т.д. Но одна утечка – и все что нажито непосильным трудом погибнет.

Поэтому, я, руководствуясь принципом «хочешь, чтобы было сделано хорошо – сделай сам», решил создать свое решение этой проблемы.

Задачи стояли следующие:

  1. Я программист не настоящий, так что алгоритм должен быть простым в реализации.

  2. Он должен быть кроссплатформенным: Android/Linux/Windows.

  3. Пароли в принципе не должны храниться нигде и ни в каком виде – это и есть изюминка моей идеи.

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

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

Алгоритм заворачивается в скрипт на питоне. Интерпретаторов под Android/Linux/Windows – вагон и маленькая тележка. Далее привожу код с пояснениями.

Импортируем нужные библиотеки:

import hashlib
from textwrap import wrap
import random

Подключаем список алгоритмов хэширования. Длина хэша у них разная, сделано это для сайтов с ограничением сверху по длине пароля.

algs = ['md5', 'sha1', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512']

Алфавит разбиваем на три куска. Отдельно цифробуквенный, отдельно знаки препинания,  и отдельно пробел, решетка звездочка и обратный слэш. Третий блок почему-то кое-где запрещен в паролях, например на госуслугах.

abc_blocks = ['0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '!"$%&\'()+,-./:;<=>?@[]^_{|}~`', ' #*\\'] 
abc = ''

Принимаем на входе количество блоков. По умолчанию берем все три блока.

И задаем зерно для рандома. Это вышеупомянутое число из мнемонического идентификатора.

abc_colvo = int(input("Количество блоков (3): ") or 3)
s = int(input("Зерно для рандома: "))

 Склеиваем блоки алфавита и перемешиваем его.

for i in range(abc_colvo):
    abc += abc_blocks[i] 

abc = list(abc)
random.seed(s)
random.shuffle(abc)
abc = ''.join(abc)

Далее вводим фразу.

memory_phrase = input('Ключевая фраза: ')
memory_phrase = bytes(memory_phrase, encoding = 'utf-8')

Запускается вычисление паролей.

print()
print('-----------------------------')

for alg in algs:
    hash_key = getattr(hashlib, alg)(memory_phrase).hexdigest()
    password = [hash_key[x:x+2] for x in range(0, len(hash_key), 2)]
    password = list(map(lambda x: int(x, 16) % len(abc), password))
    password = list(abc[x] for x in password)
    password = ''.join(password)
    print(alg + ':', len(password), 'chars')
    print()
    print(password)
    print()

     for block in wrap(''.join(password), 4):
        print(block + '  ', end = '')

    print()
    print('-----------------------------')

И вуаля – вот ваши возможные пароли для сайта.

Ваши пароли
Ваши пароли

Разбивка по 4 символа нужна на тот редкий случай, если придется вводить все это с клавиатуры. Так визуально проще его читать.

Теги:
Хабы:
Всего голосов 14: ↑1 и ↓13-12
Комментарии90

Публикации