Python Programm: Zufälliges Passwort generieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Sio
User
Beiträge: 2
Registriert: Montag 19. Juli 2021, 12:40

Hallo zusammen,

ich habe ein Programm geschrieben, welches mir ein zufälliges Passwort generiert.

import random
hallo = 'a','b','c','d','e','f','g','h','i','k','l','m','n','o','p','q','r','s','t','v','w','x','y','z','A','B','C','D','E','F','G','H','I','K','L','M','N','O','P','Q','R','S','T','V','W','X','Y','Z','1','2','3','4','5','7','8','9','0'
Ausgabe = ''
b = int(input("Aus wie vielen Zeichen soll das Passwort bestehen?>>"))
for i in range(b):
Ausgabe = Ausgabe + random.choice(hallo)
print(Ausgabe)

Möchte man zum Beispiel eine Länge von 9 Buchstaben haben, dann kriegt man zum Beispiel : svYo1GT4D

Ich möchte aber das bei der Ausgabe, nach drei Zeichen, immer ein Bindestrich hinzugefügt wird, also so:
svY-o1G-T4D

Kann mir jemand weiter helfen bitte?
Mein Ansatz war, die Variable ,, Ausgabe " zu verändern, ich weiß aber nicht wie.

Danke im voraus.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Sio,

So zum Beispiel:

Code: Alles auswählen

import textwrap

print("-".join(textwrap.wrap("svYo1GT4D", 3)))

"""
Ausgabe:
svY-o1G-T4D
"""
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Sio,

Noch ein Hinweis:
Man kann die Buchstabenliste auch generieren:

Code: Alles auswählen

import random
import textwrap

letters = [chr(index) for index in range(65,123) if index < 91 or index > 96]

count = int(input("Aus wie vielen Zeichen soll das Passwort bestehen?>>"))

output = "".join([random.choice(letters) for _ in range(count)])

dashed_output = "-".join(textwrap.wrap(output, 3))

print(dashed_output)
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@rogerb: dazu muß man aber wissen, wo welche Zahlen für welche Zeichen stehen. Zudem hast Du die Zahlen vergessen.
Dagegen gibt es das string-Modul, das die Zeichen schon als Konstanten enthält:

Code: Alles auswählen

import string
CHARACTERS = string.ascii_letters + string.digits

count = int(input("Aus wie vielen Zeichen soll das Passwort bestehen?>>"))

output = "".join("-" if i % 4 == 3 else random.choice(CHARACTERS)
    for i in range(count + (count - 1) // 3))
Benutzeravatar
Strawk
User
Beiträge: 227
Registriert: Mittwoch 15. Februar 2017, 11:42
Wohnort: Aachen
Kontaktdaten:

Hallo!
Hab ich mal so gemacht:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf-8 -*-
from __future__ import print_function, division
#-------------------------------------------------------------------------------
# Name:        password_generator.py
# Purpose:     create 1 12-digit-password
#              containing at least 1 number
#                         at least 1 upper case character
#                         at least 1 lower case character
#                         at least 1 special character
#
# Author:      Thomas Graeber
#
# Created:     12/04/2019
# Licence:     n/a
#-------------------------------------------------------------------------------
import random

def create_group_09():
    '''
    create char-group of numbers
    '''
    group_09 = []
    for i in range(48,58):
        if i == 48: # prevent confusable chars from being in password (0)
            continue
        group_09.append(chr(i))
    return group_09

def create_group_AZ():
    '''
    create char-group of upper-case
    '''
    group_AZ = []
    for i in range(65,91):
        if i == 73 or i == 79: # prevent confusable chars from being in password (I, O)
            continue
        group_AZ.append(chr(i))
    return group_AZ

def create_group_az():
    '''
    create char-group of lower-case
    '''
    group_az = []
    for i in range(97,123):
        if i == 108 or i == 111: # prevent confusable chars from being in password (l, o)
            continue
        group_az.append(chr(i))
    return group_az

def create_group_special_chars():
    '''
    create special-char-group
    '''
    group_special_chars = []
    group_special_chars.extend((chr(33), chr(36), chr(37), chr(38),
                       chr(40), chr(41), chr(43), chr(44), chr(45),
                       chr(46), chr(47), chr(58), chr(59), chr(60),
                       chr(61), chr(62), chr(63), chr(91), chr(93),
                       chr(95), chr(123), chr(125)
                       ))
    return group_special_chars

def create_allowed_chars(group_09, group_AZ, group_az, group_special_chars):
    '''
    sum up 4 groups
    Out:
    allowed_chars
    '''
    allowed_chars = []
    allowed_chars.extend(group_09)
    allowed_chars.extend(group_AZ)
    allowed_chars.extend(group_az)
    allowed_chars.extend(group_special_chars)
    return allowed_chars

def attempt_password(allowed_chars, password_length):
    '''
    create a password to be checked
    In:
    allowed_chars, password_length
    Out:
    password to be checked
    '''
    password_chars = []
    for i in range(password_length):
        password_chars.append(random.choice(allowed_chars))
    password_attempt = ''.join(password_chars)
    return password_attempt

def check_password_attempt(password_attempt, group_09, group_AZ, group_az, group_special_chars):
    '''
    check attempted password for criteria: at least ...
    In:
    password_attempt, groups
    Out:
    depends on result of check: password_ok (True/False), password_attempt
    '''
    password_group_09_ok = False
    password_group_AZ_ok = False
    password_group_az_ok = False
    password_group_special_chars_ok = False
    
    for item in password_attempt:
        if item in group_09:
            password_group_09_ok = True
        if item in group_AZ:
            password_group_AZ_ok = True
        if item in group_az:
            password_group_az_ok = True
        if item in group_special_chars:
            password_group_special_chars_ok = True
        
    if password_group_09_ok and password_group_AZ_ok and password_group_az_ok and password_group_special_chars_ok:
    # = 4 criteria
        return True, password_attempt
    else:
        return False, False

def main():
    group_09 = create_group_09()
    group_AZ = create_group_AZ()
    group_az = create_group_az()
    
    group_special_chars = create_group_special_chars()
    allowed_chars = create_allowed_chars(group_09, group_AZ, group_az, group_special_chars)
    
    password_ok = False
    while password_ok == False:
        password_attempt = attempt_password(allowed_chars, password_length=12)
        password_ok, password = check_password_attempt(password_attempt, group_09, group_AZ, group_az, group_special_chars)
    print(password)
    
if __name__ == "__main__":
    main()
Grüße, Strawk
Ich programmiere erfolglos, also bin ich nicht.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@Strawk: auch bei Dir sind die magischen Zeichenwerte nicht sehr lesbar. Abmildern kann man das, indem man `ord` benutzt.

Code: Alles auswählen

def create_group_09():
    '''
    create char-group of numbers
    '''
    group_09 = []
    for i in range(ord('0'), ord('9')):
        if i == ord('0'): # prevent confusable chars from being in password (0)
            continue
        group_09.append(chr(i))
    return group_09
Der Code ist aber schon so umfangreich, dass es lesbarer wäre, die Zahlen explizit anzugeben: "23456789" (Warum darf 1 dabei bleiben, wo es doch mit I verwechselbar ist?)
Ganz extrem wird es ja bei special_chars, wo nichteinmal eine Schleife vorkommt: "!$%&()+,-./:;<=>?[]_{}".
Will man Zeichen ausschließen, geht das einfach mit Sets:

Code: Alles auswählen

LETTERS = list(set(string.ascii_letters) - set("IOlo"))
Statt in vielen Funktionen jeweils vier Zeichengruppen herumzureichen, wäre es einfacher und flexibler, einfach eine Liste von Gruppen zu nehmen. Dann kann man auch einfach bestimmte Gruppen weglassen oder hinzufügen.
Am Beispiel von check_password_attempt sähe das z.B. so aus:

Code: Alles auswählen

def check_password_attempt(password_attempt, character_groups):
    '''
    check attempted password for criteria: at least ...
    In:
    password_attempt, groups
    Out:
    password_ok (True/False)
    '''
    missing_character_groups = character_groups
    for character in password_attempt:
        # remove groups from the list, that contains the character
        missing_character_groups = [group for group in missing_character_groups if character not in group]
        
    # if the list is empty, at least one character of each group was present in the password
    return not missing_character_groups
An `check_password_attempt` war komisch, dass es zwei unterschiedliche Typen von Rückgabewerten gab, einmal (bool, str) und einmal (bool, bool). Das macht die weitere Verarbeitung komplizierter. Hier ist einer der Rückgabewerte ein Wert, der die Funktion bereits als Argument betritt. Der aufrufende Code kennt also schon das Ergebnis, kann man also weglassen.

Wenn man eine while-Schleife hat, die nur betreten wird, wenn eine Variable vorinitialisiert wird, dann hat man eigentlich eine while-True Schleife:

Code: Alles auswählen

    while True:
        password_attempt = attempt_password(allowed_chars, password_length=12)
        if check_password_attempt(password_attempt, [group_09, group_AZ, group_az, group_special_chars]):
            break
    password = password_attempt
    print(password)
Sio
User
Beiträge: 2
Registriert: Montag 19. Juli 2021, 12:40

@rogerb
Danke für die Hilfe, ich habe deine Ideen benutzt und mein Programm angepasst. Die Zahl Null, und die Buchstaben i, I , o, O habe ich entfernt, damit es nicht zu Verwirrung führt.
import random
import textwrap

Pool = 'a','b','c','d','e','f','g','h','k','m','n','p','q','r','s','t','v','w','x','y','z','A','B','C','D','E','F','G','H','K','L','M','N','P','Q','R','S','T','V','W','X','Y','Z','1','2','3','4','5','7','8','9'

b = int(input("Aus wie vielen Zeichen soll das Passwort bestehen?>>"))

output = "".join([random.choice(Pool) for _ in range(b)])

dashed_output = "-".join(textwrap.wrap(output, 3))

print(dashed_output)

Danke ebenfalls an den Rest für die Ideen, super Forum, hilft Anfängern!
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Sio,

Okay, aber der Vorschlag von Sirius3 war eigentlich besser. Auch da kannst du ja die verwirrenden Zeichen entfernen.

Code: Alles auswählen

Pool =  [letter for letter in string.ascii_letters + string.digits if letter not in ['i', 'o', 'I', 'O']]
Antworten