БэкендPython

Как сделать генератор паролей на Python: длина, символы и кнопка копирования

Пишем безопасный генератор паролей на Python с модулем secrets и интерфейсом Tkinter: выбор длины, включение символов, новый пароль и копирование в буфер.

Кодик

Автор

6 мин чтения

Для генератора паролей используйте модуль secrets, а не random. Он получает случайность из источника операционной системы, предназначенного для секретов. Наша программа создаст пароль заданной длины, гарантирует буквы и цифру, по желанию добавит специальные символы и скопирует результат в буфер обмена. Интерфейс соберём на встроенном Tkinter.

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

1Выбираем

Собираем допустимые группы: строчные, заглавные, цифры и символы.

2Генерируем

Берём минимум по одному знаку из каждой группы и заполняем остаток через secrets.

3Копируем

Tkinter показывает результат и переносит его в системный буфер обмена.

Почему secrets подходит, а random нет

Модуль random полезен для моделирования, игр и случайного порядка, но его генератор не предназначен для криптографических секретов. Официальная документация Python прямо рекомендует secrets для паролей, токенов и ссылок сброса. Мы используем secrets.choice() для выбора символов и SystemRandom().shuffle() для перемешивания обязательных знаков с остальными.

ИнструментПодходит для пароляПример задачи
random.choiceНетИгра, симуляция, учебная выборка
secrets.choiceДаВыбор непредсказуемого символа
secrets.token_urlsafeДа, для токенаСсылка подтверждения или API-токен
Собственный алгоритм от времениНетЛегко предсказать и повторить

Схема генератора паролей на Python от настроек до результата
Настройки формируют группы символов, secrets выбирает значения, а перемешивание скрывает обязательные позиции.

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

Пишем функцию и окно Tkinter

Создайте файл password_generator.py. Чистая функция принимает длину и флаг символов, формирует список групп и сначала берёт по одному знаку из каждой. Затем она заполняет остаток общим алфавитом и перемешивает список. Интерфейс только читает настройки, вызывает функцию и работает с буфером обмена.

import secrets
import string
import tkinter as tk
from tkinter import messagebox, ttk

SYMBOLS = "!@#$%^&*_-+="


def generate_password(length: int, use_symbols: bool = True) -> str:
    pools = [string.ascii_lowercase, string.ascii_uppercase, string.digits]
    if use_symbols:
        pools.append(SYMBOLS)

    if length < max(8, len(pools)):
        raise ValueError("Длина должна быть не меньше 8")

    chars = [secrets.choice(pool) for pool in pools]
    alphabet = "".join(pools)
    chars.extend(secrets.choice(alphabet) for _ in range(length - len(chars)))
    secrets.SystemRandom().shuffle(chars)
    return "".join(chars)


def build_app() -> tk.Tk:
    root = tk.Tk()
    root.title("Генератор паролей")
    root.resizable(False, False)

    length = tk.IntVar(value=16)
    use_symbols = tk.BooleanVar(value=True)
    password = tk.StringVar()
    status = tk.StringVar(value="Выберите параметры и нажмите «Создать»")

    frame = ttk.Frame(root, padding=20)
    frame.grid()
    ttk.Label(frame, text="Длина").grid(row=0, column=0, sticky="w")
    ttk.Spinbox(frame, from_=8, to=64, textvariable=length, width=7).grid(row=0, column=1)
    ttk.Checkbutton(frame, text="Добавить символы", variable=use_symbols).grid(
        row=1, column=0, columnspan=2, sticky="w", pady=10
    )
    ttk.Entry(frame, textvariable=password, width=34, state="readonly").grid(
        row=2, column=0, columnspan=2, pady=8
    )

    def refresh() -> None:
        try:
            password.set(generate_password(length.get(), use_symbols.get()))
            status.set(f"Создан пароль длиной {length.get()} символов")
        except (ValueError, tk.TclError) as error:
            messagebox.showerror("Проверьте длину", str(error))

    def copy_password() -> None:
        if not password.get():
            status.set("Сначала создайте пароль")
            return
        root.clipboard_clear()
        root.clipboard_append(password.get())
        root.update()
        status.set("Пароль скопирован")

    ttk.Button(frame, text="Создать", command=refresh).grid(row=3, column=0, sticky="ew")
    ttk.Button(frame, text="Копировать", command=copy_password).grid(row=3, column=1, sticky="ew")
    ttk.Label(frame, textvariable=status).grid(row=4, column=0, columnspan=2, pady=(12, 0))
    return root


if __name__ == "__main__":
    app = build_app()
    app.mainloop()
Какие свойства гарантирует функция
  • Результат имеет ровно ту длину, которую передали в length.
  • В нём есть хотя бы одна строчная буква, одна заглавная и одна цифра.
  • При включённом флаге присутствует хотя бы один символ из безопасно заданного набора.
  • Обязательные знаки перемешаны и не стоят постоянно в начале в одном порядке.

Сравнение модулей random и secrets для генерации паролей
Оба модуля выбирают элементы, но только secrets предназначен для данных, которые должны быть непредсказуемыми.

Как устроены длина, группы и копирование

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

ЭлементЗначение в примереЧто меняет
Длина8-64, по умолчанию 16Количество позиций в результате
Строчные буквыВсегда включеныХотя бы один знак a-z
Заглавные буквыВсегда включеныХотя бы один знак A-Z
ЦифрыВсегда включеныХотя бы один знак 0-9
СпецсимволыПереключательДобавляет заданный набор
Буфер обменаКнопка КопироватьПередаёт строку другому приложению
Буфер обмена не является сейфом. Скопированное значение может увидеть другое приложение с соответствующим доступом или история буфера системы. Вставьте пароль в нужное поле и очистите историю, если устройство общее.

Практика: проверяем генератор, а не одну удачную строку

Случайный результат нельзя проверять точным сравнением. Проверяйте свойства: длину, наличие групп и разнообразие серии. Временно добавьте небольшой тестовый фрагмент под защитой if __name__ == "__main__" или вынесите его в отдельный файл. Не печатайте реальные пароли пользователя в журналы и не сохраняйте их автоматически.

Шесть проверок функции и интерфейса
  1. Запустите python password_generator.py и создайте пароль длиной 16 с символами.
  2. Посчитайте символы вручную или через len(): результат должен иметь длину 16.
  3. Повторите генерацию десять раз. Строки должны различаться, а окно не должно зависать.
  4. Выключите символы и убедитесь, что результат состоит только из букв и цифр.
  5. Введите значение меньше восьми. Программа должна показать понятное окно ошибки, а не traceback.
  6. Нажмите «Копировать», вставьте результат во временное поле и сравните строки.
  7. Импортируйте функцию из другого файла: окно не должно открываться благодаря проверке __name__.
Что считать готовой программой
  • Каждый запуск функции возвращает строку нужной длины с обязательными группами символов.
  • Некорректная длина обрабатывается внутри интерфейса и объясняется пользователю.
  • Кнопки создания и копирования работают несколько раз подряд.
  • Генератор не записывает созданные значения в файл, консоль или историю приложения.

Матрица проверки длины состава интерфейса и хранения пароля
Случайную строку проверяют не на точное значение, а на свойства и безопасное обращение.

Какие ошибки делают генератор небезопасным или неудобным

Красивое окно не исправляет слабый источник случайности. Сначала проверьте модуль и алгоритм, затем интерфейс. Второй частый перекос состоит в попытке гарантировать группы повторной генерацией всей строки: такой цикл сложнее читать и может скрывать проблему с короткой длиной. Явно добавленные обязательные символы делают правило видимым, а перемешивание убирает постоянные позиции.

Использован random

Он предназначен для моделирования, а не секретов. Замените выбор на функции модуля secrets.

Пароль строится только из цифр

Алфавит слишком мал для той же длины. Включите несколько групп и проверяйте ограничения конкретного сервиса.

Обязательные символы всегда первые

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

Значение печатается в консоль

Журналы и история терминала не должны становиться вторым хранилищем секретов.

Окно создаётся при импорте

Поместите запуск GUI под if __name__ == "__main__", чтобы функцию можно было тестировать отдельно.

Генератор не заменяет менеджер паролей. Программа создаёт строку, но не решает безопасное хранение, уникальность для разных сервисов и восстановление. Для реальных аккаунтов используйте проверенный менеджер и многофакторную защиту. Технические детали сверены с официальной документацией Python по secrets.
Короткие ответы
Почему нельзя использовать random?

Его генератор не предназначен для криптографических секретов. Для паролей Python рекомендует secrets.

Как гарантировать наличие цифры?

Сначала явно выбрать один символ из string.digits, затем добавить остальное и перемешать список.

Зачем нужен shuffle?

Без перемешивания обязательные буква, цифра и символ всегда занимали бы известные позиции.

Почему окно не создают на уровне импорта?

Защита if __name__ == "__main__" позволяет импортировать и тестировать функцию без запуска GUI.

Безопасно ли хранить пароль в буфере?

Буфер удобен, но не является защищённым долговременным хранилищем. После вставки учитывайте историю буфера устройства.

Разделите проект на функцию, тесты и интерфейс

Функции, списки, исключения и модули можно закрепить в курсе Python. Если программа падает на вводе, откройте разбор строк и чисел, а окружение для проекта настройте по гайду виртуальных окружений.

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