Пароли, читаемые человеком


Введение

Для приложения Django мне нужно было создать пароли для пользователей, регистрирующихся на сайте. Генерировать пароли может быть относительно просто.

Взгляните на эту функцию.

def generate_password(length=10):
 return "".join(
        random.choice(string.ascii_letters + string.digits) for _ in range(length)
    )
Вход в полноэкранный режим Выход из полноэкранного режима

Вот результат

>>> print(generate_raw_password())
>>> B61CbF9GdW
Вход в полноэкранный режим Выйти из полноэкранного режима

Это безопасно, но трудно запомнить.

Чтобы сделать их более удобными для пользователя, я решил создать функцию, вдохновленную сайтом https://xkpasswd.net/s/. Этот веб-сайт создает человекочитаемые пароли, которые являются безопасными. Например, 3~shoes~FOUND@, и это гораздо более человекочитаемый пароль, чем предыдущий метод.

Подробности

Как я создавал человекочитаемые пароли?

Список слов

Я должен был начать со списка слов. С учетом популярности Wordle найти список слов из 5 букв не так уж сложно. Существует множество клонов Worlde, а на GitHub есть целая куча клонов Wordle с подобным списком. Но если честно, почему бы не обратиться к источнику оригинального Wordle и не посмотреть, сможете ли вы получить их список.

NY Times Wordle

NY Times купила оригинальный Wordle, и источник больше не доступен. Вы все еще можете получить список с помощью небольшого взлома.
Откройте эту ссылку: https://www.nytimes.com/games/wordle/main.bd4cb59c.js. Найдите ,Oa= и вот вам начало списка. В этом списке около 10 тысяч слов. Когда я проверял список, я нашел несколько слов, которые люди могут счесть слегка неуместными, d*cks и это не птица, b**by.

На вашем компьютере

Я нашел другой способ создания списка 5-буквенных слов. Большинство компьютеров на базе Linux и Mac имеют список слов в системе, /usr/share/dict/words. Чтобы извлечь все 5-буквенные слова, мы можем написать простую однострочную строку на языке Perl.

perl -nle 'print if /^[a-z]{5}$/' /usr/share/dict/words > words5.txt
Войти в полноэкранный режим Выйти из полноэкранного режима

И вот у нас есть список. К сожалению, полный список содержит слова 1934 года, и я нашел в нем несколько слов, которые мы больше не используем.

Стэнфордская база данных GraphBase

Дональд Кнут создал список пятибуквенных слов. Этот список используется для проведения различных комбинаторных экспериментов, графовых алгоритмов и других алгоритмов для изучения взаимосвязей между этими словами. Список находится в открытом доступе и содержит 5757 слов.

Именно этот список я использую сейчас для создания человекочитаемого пароля.

Использование списка

Вместо того чтобы поместить список слов в список Python, я решил поместить список в БД. Это облегчает добавление дополнительных слов позже, если это будет предпочтительнее.

Модель очень проста.

# code/word_model.py

class Word(models.Model):
    word = models.CharField(max_length=10, unique=True)

    def __str__(self):
        return self.word

Войдите в полноэкранный режим Выход из полноэкранного режима

Я оставлю на ваше усмотрение, как наполнить модель.

Требования

Пароль должен отвечать следующим требованиям

  • В начале и в конце пароля должно быть не менее 1 цифры и не более 2 цифр.
  • Разделяйте каждое слово специальным символом.
  • Каждое слово будет преобразовано в нижний регистр, верхний регистр или заглавную букву.
  • Не повторяйте слова в пароле.

Я также хочу иметь возможность использовать столько слов, сколько захочу, по умолчанию я использую 3 и не допускаю менее двух слов.

Код

# code/password.py

import random

from models import Word


def create_password(words=3):
    """
    Generate a password

    Parameters
    ----------
    words: int

    Returns
    -------
    str
    """
    if words < 2:
        raise ValueError
    numbers = random.sample(range(1, 99), 2)
    special_character = "!@$%^&*-_+=:|~?/.;"
    separator = random.sample(special_character, words - 1)
    selected_words = get_random_words(words)
    password = str(numbers[0])
    for step in range(words - 1):
        password = password + transform_word(selected_words[step]) + separator[step]
    password = password + transform_word(selected_words[words - 1]) + str(numbers[1])
    return password


def get_random_words(amount):
    """
    Get a list of unique words

    Parameters
    ----------
    amount: int

    Returns
    -------
    list of str

    """
    total_word_count = Word.objects.all().count()
    ids = random.sample(range(1, total_word_count), amount)
    selected_words = list(
        Word.objects.filter(id__in=ids).values_list("word", flat=True)
    )
    while len(selected_words) < amount:
        id = random.randint(1, total_word_count)
        if id in ids:
            continue
        selected_word = Word.objects.get(id=id)
        if selected_word:
            selected_words.append(selected_word.word)
    return selected_words


def transform_word(word):
    """
    Transform a string

    Parameters
    ----------
    word: str

    Returns
    -------
    str
    """
    transform = random.randint(1, 3)
    if transform == 1:
        transformed_word = word.capitalize()
    elif transform == 2:
        transformed_word = word.lower()
    elif transform == 3:
        transformed_word = word.upper()
    return transformed_word

Войти в полноэкранный режим Выйти из полноэкранного режима

Некоторые примеры паролей, сгенерированных этой функцией:

73PYGMY|Glens~Naiad33
29radar|bylaw%SWATH19
5plant.Cages+Dizzy54
72DOUGH!Yolks-hooch28
92FLESH^churl%genet69
Вход в полноэкранный режим Выход из полноэкранного режима

Заключение

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

Примечания

  • Я использую свой выбор специальных символов вместо string.punctuation. Мне не нужны были некоторые символы из этого списка, например, кавычки.

Ссылки

  • NY Times Wordle: https://www.nytimes.com/games/wordle/index.html
  • Стэнфордская база данных GraphBase: https://www-cs-faculty.stanford.edu/~knuth/sgb.html

Нашли опечатку?

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


Фото Колина Ллойда — https://unsplash.com/photos/62OEfKjU1Vs

Оцените статью
Procodings.ru
Добавить комментарий