Статья Пишем простой генератор сложных паролей

Тема не новая, генераторов существует множество, однако такой простой код и глазу приятен, и место не занимает.

Для начала вставим в шапку кодировку и версию питона. Импортируем модуль random для генерации случайной последовательности. Зададим переменную chars и вобьём буквы в разном регистре, цифры и какие-нибудь спецсимволы для получения максимально взломостойкого пароля.
Python:
# -*- coding:utf -8 -*-
#!/usr/bin/python3

import random

chars = '+-/*!&$#?=@<>abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
Чтобы программа тупо не генерила один пароль или строго заданное количество, разрешим пользователю самому решать сколько паролей он хочет сгенерировать. Кроме этого дадим возможность определять и длину пароля.
Python:
number = input('количество паролей?'+ "\n")
length = input('длина пароля?'+ "\n")
number = int(number)
length = int(length)
Осталось добавить самое главное - цикл случайной генерации символов, букв и цифр из нашей переменной, согласно параметрам введённым пользователем.
Python:
for n in range(number):
    password =''
    for i in range(length):
        password += random.choice(chars)
    print(password)
Вот собственно и всё - простой генератор сложных паролей готов.
Код полностью:

Python:
# -*- coding:utf -8 -*-
#!/usr/bin/python3

import random

chars = '+-/*!&$#?=@<>abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
number = input('количество паролей?'+ "\n")
length = input('длина пароля?'+ "\n")
number = int(number)
length = int(length)
for n in range(number):
    password =''
    for i in range(length):
        password += random.choice(chars)
    print(password)
Результат работы:
pas.png


Не нужно искать сложных путей, если есть простые решения :)
 

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
strings = string.ascii_letters + string.digits + string.punctuation
Можно обойтись без конкатенации, немного попроще. Функция chr() возвращает символ из таблицы Unicode.

Python:
import secrets

number = int(input('количество паролей?' + "\n"))
length = int(input('длина пароля?' + "\n"))


def symbol():
    symbols = ([chr(s) for s in range(33, 127)])  # магия здесь
    return symbols


symbol()

for n in range(number):
    password = ''
    for i in range(length):
        password += secrets.choice(symbol())
    print(password)
 

f22

Codeby Academy
Gold Team
05.05.2019
1 929
226
BIT
1 704
Можно обойтись без конкатенации, немного попроще. Функция chr() возвращает символ из таблицы Unicode.

Python:
import secrets

number = int(input('количество паролей?' + "\n"))
length = int(input('длина пароля?' + "\n"))


def symbol():
    symbols = ([chr(s) for s in range(33, 127)])  # магия здесь
    return symbols


symbol()

for n in range(number):
    password = ''
    for i in range(length):
        password += secrets.choice(symbol())
    print(password)
Определённо, этот код будет выполняться быстрее,
но вряд ли он выглядит проще, чем указание конкретных диапазонов.
Изменить его будет проблематично.
А в gui для выбора диапазона, используя string, легче будет добавить что-то вроде radio button или флажков.
 

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
Изменить его будет проблематично.
А в gui для выбора диапазона, используя string, легче будет добавить что-то вроде radio button или флажков.
С этим не могу согласиться. Диапазоны любые можно для баттонов задать, символы ASCII идут подряд, а не вперемешку, например большие буквы будут под номерами 65-90. Поэтому разницы никакой не будет, как задать диапазоны. Просто вариации одного и того же по сути.

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

f22

Codeby Academy
Gold Team
05.05.2019
1 929
226
BIT
1 704
символы ASCII идут подряд, а не вперемешку,
Да нет же, ты что-то путаешь
putty_CvB5UDbAoX.png
Хотя, может у меня не та версия Python... )

С этим не могу согласиться.
Для кого-то, действительно, может проще работать с цифрами,
но я бы для себя выбрал такой вариант:

Code_YG73x41HB4.png
нежели использовать какие-то безликие диапазоны
symbols = ([chr(s) for s in range(33, 65)])
в которых к тому же легко ошибиться, а уж потратить время
на то, чтобы искать нужные символы пунктуации - это та ещё затея.
 

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
Да нет же, ты что-то путаешь
Посмотреть вложение 34557
Хотя, может у меня не та версия Python... )

Уважаемый, я не путаю, есть в которой наглядно видна последовательность символов. Очень широко применяется, в пентесте в том числе, для обхода WAF.

1.png
 

f22

Codeby Academy
Gold Team
05.05.2019
1 929
226
BIT
1 704
Уважаемый, я не путаю, есть в которой наглядно видна последовательность символов. Очень широко применяется, в пентесте в том числе, для обхода WAF.
И чем эта таблица отличается от той, что я тебе показал?
putty_CvB5UDbAoX.png
Я же твой код использовал или ты думаешь я в Python вставил другую таблицу? )

А если пролистать ниже , то ты увидишь такой же фарш из символов пунктуации,
которые разбиты на ЧЕТЫРЕ диапазона (выделил зелёной рамкой).
chrome_2019-11-01_17-17-58.png chrome_2019-11-01_17-26-47.png chrome_2019-11-01_17-26-57.png
Ты утверждаешь, что
символы ASCII идут подряд
Поэтому разницы никакой не будет, как задать диапазоны.

Вопрос-то простой, как ты из этой таблицы хоть с сайта, хоть из Python'a
получишь только знаки пунктуации? Можешь привести код?
Будет ли этот код проще, чем этот?
Python:
import string

symbols = string.punctuation
 

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
Можешь привести код?
Будет ли этот код проще, чем этот?
Python:
import string

symbols = string.punctuation

Буквы большие, буквы маленькие, и номера идут подряд. Что касается именно спецсимволов, то здесь ты прав, да они разбиты на 4 части. И это неудобно, если делать например прогу с возможностью выбора буквы/номера/спецсимволы. Придётся функцию для спецсимволов конкатенировать, например так:


Python:
def special_symbol():
    special_symbols1 = ([chr(s) for s in range(33, 47)]) 
    special_symbols2 = ([chr(s) for s in range(58, 64)])
    special_symbols3 = ([chr(s) for s in range(91, 96)])
    special_symbols4 = ([chr(s) for s in range(123, 126)])
    res = special_symbols1 + special_symbols2 + special_symbols3 + special_symbols4
    return res
 
  • Нравится
Реакции: f22

Citizen0

Green Team
07.02.2017
203
228
BIT
0
Можно обойтись без конкатенации, немного попроще. Функция chr() возвращает символ из таблицы Unicode.

Python:
import secrets

number = int(input('количество паролей?' + "\n"))
length = int(input('длина пароля?' + "\n"))


def symbol():
    symbols = ([chr(s) for s in range(33, 127)])  # магия здесь
    return symbols


symbol()

for n in range(number):
    password = ''
    for i in range(length):
        password += secrets.choice(symbol())
    print(password)
Python:
symbol()

for n in range(number):
Зачем Вы здесь вызываете функцию?

Python:
        password += secrets.choice(symbol())
Здесь тоже не понятно, для чего.
100000 паролей длиной 30 символов = 3000000 вызовов функции, которая каждый раз создает один и тот же список.
У меня генерация паролей с указанными параметрами занимает 42 секунды.
Если использовать переменную, значением которой будет результат функции, то 9 секунд.

Буквы большие, буквы маленькие, и номера идут подряд. Что касается именно спецсимволов, то здесь ты прав, да они разбиты на 4 части. И это неудобно, если делать например прогу с возможностью выбора буквы/номера/спецсимволы. Придётся функцию для спецсимволов конкатенировать, например так:


Python:
def special_symbol():
    special_symbols1 = ([chr(s) for s in range(33, 47)])
    special_symbols2 = ([chr(s) for s in range(58, 64)])
    special_symbols3 = ([chr(s) for s in range(91, 96)])
    special_symbols4 = ([chr(s) for s in range(123, 126)])
    res = special_symbols1 + special_symbols2 + special_symbols3 + special_symbols4
    return res
А проверить на буквы/цифры?
Python:
symbols = []

for n in range(33, 126):
    char = chr(n)
    if char.isdigit() == False and char.isalpha() == False:
        symbols.append(char)

print(symbols)
 
  • Нравится
Реакции: Vertigo, explorer и f22

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
Python:
symbol()

for n in range(number):
Зачем Вы здесь вызываете функцию?

А проверить на буквы/цифры?
Python:
symbols = []

for n in range(33, 126):
    char = chr(n)
    if char.isdigit() == False and char.isalpha() == False:
        symbols.append(char)

print(symbols)

Вызов функции забыл убрать, после того как цикл добавил. Прекрасный вариант с проверкой вхождений )
 

f22

Codeby Academy
Gold Team
05.05.2019
1 929
226
BIT
1 704
Вызов функции забыл убрать, после того как цикл добавил. Прекрасный вариант с проверкой вхождений )
Ну да, прекрасный ) Вот только
if not char.isdigit() and not char.isalpha():
или
if not (char.isdigit() or char.isalpha()):
нагляднее
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
В общем заморочился и решил проверить алгоритмы.
Длина пароля каждый раз 10 символов, количество паролей 100, 1K, 10K, 100K
Python:
import random
import string
import secrets
import time

def my_main_code(number, length):
    strings = string.ascii_letters + string.digits + string.punctuation
    chars = list( ch for ch in strings )

    for n in range(number):
        random.shuffle(chars)
        symbols.append("".join(chars)[0:length])

def symbol():
    symbols = ([chr(s) for s in range(33, 127)])  # магия здесь
    return symbols
    
def explorer_main_code(number, length):
    for n in range(number):
        password = ''
        for i in range(length):
            password += secrets.choice(symbol())
        symbols.append(password)


symbols = []
passwords_qnt = [100, 1000 ,10000, 100000]

for _ in passwords_qnt:
    print("Количество создаваемых паролей: " + str(_) + "\nДлина пароля 10 символов.")

    symbols.clear()
    print("strings_type")
    start_time = time.time()
    my_main_code(_, 10)
    print("--- %s seconds ---" % round((time.time() - start_time), 4))
    
    symbols.clear()
    print("explorer_type")
    start_time = time.time()
    explorer_main_code(_, 10)
    print("--- %s seconds ---" % round((time.time() - start_time), 4) + "\n")

Ну и результаты
Code_ZKVmWSen3e.png
Если где-то накосячил, не обессудьте.
 
  • Нравится
Реакции: explorer

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
В общем заморочился и решил проверить алгоритмы.

Я со скоростью не заморачивался, просто привёл один из возможных вариантов. Спасибо, наглядно. Но если ты в своём коде конкатенацию с + заменишь на
strings = '{}{}{}'.format(string.ascii_letters, string.digits, string.punctuation)

то ещё больше будет выигрыш по времени.

1.png
 
  • Нравится
Реакции: f22

f22

Codeby Academy
Gold Team
05.05.2019
1 929
226
BIT
1 704
Но если ты в своём коде конкатенацию с + заменишь на
то ещё больше будет выигрыш по времени.
Да, согласен, в этом случае результат почти такой же, как и без объявления переменной
chars = list( ch for ch in string.ascii_letters + string.digits + string.punctuation )
Правда, в новом синтаксисе мне больше нравится
strings = f'{string.ascii_letters}{string.digits}{string.punctuation}'

Code_G4IPgDcpeP.png
 

Ruslan A

New member
31.10.2020
1
0
BIT
0
Подскажите, а как можно разделить пароль знаком тире (например 7rtvd-rthf-dsad) ?
 

Master Yoda

New member
15.01.2018
1
0
BIT
0
для работы с паролями и прочим есть библиотека string, конкретнее from string import printable. Подгружает ASCII символы. ссылка
 

AlexStep

Member
31.01.2021
7
0
BIT
0
Генератор кодов с сохранением в файл это конечно крутяк. Но например нужно пароль в 13 символов только большие английские буквы и цифры, все в консольке, при этом пароль должен иметь вид, например: MLW-JRZR-HJQ-4PO или 4D7-VQYC-DQX-W2K, (3-4-3-3 символа через тире, как сделать это тире постоянным и не изменным, но не влияющим на пароль) при этом получается что количество букы и цифр рандом. И хотелось бы спросить и понять, сколько всего сможет программа сгенерировать таких кодов если задействован весь английский алфавит и цифры?
 

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
Используя английские и цифры для 3-х символов: количество комбинаций: 46656
Используя английские и цифры для 4-х символов: количество комбинаций: 1679616

Ну и теперь нетрудно далее подсчитать для схемы 3-4-3-3 символов: 46656 + 1679616 + 46656 + 46656 = 1819584

Для всего английского алфавита и цифры для 3-х символов: количество комбинаций: 238328
Для всего английского алфавита и цифры для 4-х символов: количество комбинаций: 14776336

Вставить дефисы проще простого через конкатенацию например. Соответственно в эти переменные нужно сначала сгенерировать списки вариантов, и через цикл их склеить. Схематично так на выходе:


Python:
x = "123"
y = "jjja"
z = "jh2"
w = "f4l"
print(x + "-" + y + "-" + z + "-" + w)
 

AlexStep

Member
31.01.2021
7
0
BIT
0
Схематично в 1 тройке выйдут только цифры во 2 только буквы, в третей буквы и цифры, в 4 больше цифр чем букв? Так или нет? Или все равно это типа образец а генерировать рандомно будет.
 

AlexStep

Member
31.01.2021
7
0
BIT
0
Куда вставить последнее? как тогда будет выглядеть весь код в пайтен, и как будет выглядеть программа в консоле?
 

explorer

Platinum
05.08.2018
1 080
2 475
BIT
0
Схематично в 1 тройке выйдут только цифры во 2 только буквы, в третей буквы и цифры, в 4 больше цифр чем букв? Так или нет? Или все равно это типа образец а генерировать рандомно будет.
Нет, генерация всегда рамдомно делается. Разумеется там могут быть любые сочетания из заложенного в программе - только цифры, только буквы, и то и то. И количество букв и цифр тоже разное, ведь перебираются ВСЕ варианты.
 

AlexStep

Member
31.01.2021
7
0
BIT
0
Ну раз я сам заикнулся о варианте с сохранением в файл, то решил добавить эту функцию в программу. Теперь можно сгенерированные списки паролей сохранять.
Python:
# -*- coding:utf -8 -*-
#!/usr/bin/python3
__version__ = 'Version: 1.1'
from tkinter import *
import random
import string
from tkinter import filedialog as fd

root = Tk()
root.resizable(width=False, height=False)
root.title("Генератор паролей  " +str(__version__))
root.geometry("450x324+300+300")
calculated_text = Text(root,height=14, width=50)

def erase():
    calculated_text.delete('1.0', END)

chars = '+-/*!&$#?=@<>abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'

def password():
    for n in range(int(number_entry.get())):    
        password =''
        for i in range(int(length_entry.get())):
            password += random.choice(chars)
        calculated_text.insert(END, password + "\n")

def savepass():
    file_name = fd.asksaveasfilename(filetypes=(("TXT files", "*.txt"),                                    
                                                ("All files", "*.*")),defaultextension='')
    f = open(file_name, 'w')
    s = calculated_text.get(1.0, END)
    f.write(s)
    f.close()
     
display_button = Button(text="Сгенерить", command=password)
erase_button = Button(text="Очистить", command=erase)
save = Button(text="Сохранить", command=savepass)

number_entry = Entry(width=10, justify=CENTER)
length_entry = Entry(width=10, justify=CENTER)
number_entry.insert(0, "8")
length_entry.insert(0, "25")
 
number_label = Label(text="      Количество паролей")
length_label = Label(text="      Длина пароля")
number_label.grid(row=0, column=0, sticky="w")
length_label.grid(row=1, column=0, sticky="w")
number_entry.grid(row=0,column=1, padx=1, pady=5)
length_entry.grid(row=1,column=1, padx=1, pady=5)

save.grid(row=3, column=2, padx=50, pady=5, sticky="w")
display_button.grid(row=3, column=0, padx=30, pady=5, sticky="e")
erase_button.grid(row=3, column=1, padx=30, pady=5, sticky="e")

scrollb = Scrollbar(root, command=calculated_text.yview)
scrollb.grid(row=4, column=3, sticky='nsew')
calculated_text.grid(row=4, column=0, sticky='nsew', columnspan=3)
calculated_text.configure(yscrollcommand=scrollb.set)

root.mainloop()
Посмотреть вложение 22189
пароли каждый раз разные?рандомные?повторяются ли при большом количестве генераций паролей? и к стати что то исходник показывает мне другую консоль. Пробовал все разные ваши варианты исходников и не получатся генерировать ничего.
 

Вложения

  • 1.png
    1.png
    67,6 КБ · Просмотры: 187
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!