Python . Подскажите, как упростить код генератора паролей
# Генератор паролей
# Пароль должен быть не меньше 8 символов
# должен содержать как минимум одну заглавную букву
# должен содержать как минимум одну строчную букву
# должен содержать как минимум одну цифру
# должен содержать как минимум один спец-символ (!&? и прочие)
# а еще он не должен содержать некоторые символы, чтобы не поломать bash-скрипты
import random
import string
password = []
forbidden = ['+', '-', ',', '`', '^'] # запрещенные символы
lis_uppercase = [] # создание списков из строк ascii
for f in string.ascii_uppercase:
lis_uppercase.append(f)
lis_lowercase = []
for f in string.ascii_lowercase:
lis_lowercase.append(f)
lis_octdigits = []
for f in string.octdigits:
lis_octdigits.append(f)
lis_punctuation = []
for f in string.punctuation:
lis_punctuation.append(f)
for f in forbidden: # удаление запрещенных символов из списка
lis_punctuation.remove(f)
password.append(random.choice(lis_uppercase)) # по одному элементу с каждого списка,
password.append(random.choice(lis_lowercase)) # всего списков 4
password.append(random.choice(lis_octdigits))
password.append(random.choice(lis_punctuation))
length = int(input('Length: ')) # ввод длины пароля
while length <= 0 or length > 15:
print('Ошибка ввода')
length = int(input('Length: '))
lis_all = lis_uppercase + lis_lowercase + lis_octdigits + lis_punctuation # обьединяем списки
for f in range(length - 4): # от длины вычитаем количество списков(т.е. 4 элемента)
length -= 1
password.append(random.choice(lis_all)) # добавляем остальные символы
if length == 0:
break
password = ''.join(password)
print(password)
Ответы (2 шт):
Автор решения: Zhihar
→ Ссылка
решение в лоб, правда не очень эффективное, потому что пароль может генерироваться в течении нескольких проходов, зато самое короткое решение, а при большой длине пароля кол-во проходов будет минимальным:
import random
password = ''
while True:
dictionary = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!&?'
password = ''.join(random.choices(dictionary, k=random.randint(8, 16)))
if any(l.isdigit() for l in password) and any(l.isupper() for l in password) and any(l.islower() for l in password) and any(l in '!&?' for l in password):
break
print(password)
А вот так выглядит однопроходный алгоритм:
import random
dictionary = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!&?'
dictionaries = ['abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789', '!&?']
password = [random.choice(d) for d in dictionaries] + random.choices(dictionary, k=random.randint(8, 16) - 4)
random.shuffle(password)
password = ''.join(password)
print(password)
ну или вот так, чтобы избавиться от дублирования словарей:
import random
dictionaries = ['abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789', '!&?']
password = [random.choice(d) for d in dictionaries] + random.choices(''.join(dictionaries), k=random.randint(8, 16) - 4)
random.shuffle(password)
password = ''.join(password)
print(password)
Автор решения: GrAnd
→ Ссылка
import random, string
forbidden = set('+-,`^') # запрещенные символы
special_symbols = set(string.punctuation) - forbidden
password_len = 10
password = []
all_symbols = set()
for seq in (string.ascii_lowercase, string.ascii_uppercase, string.digits, special_symbols):
password.append(random.choice(list(seq)))
all_symbols.update(seq)
password.extend(random.choices(list(all_symbols), k=password_len-4))
random.shuffle(password)
password = ''.join(password)
print(password)