Überprüfung des erzeugten Passwortes auf richtige Konvention

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
Marek06
User
Beiträge: 13
Registriert: Dienstag 17. April 2012, 08:51

Wie kann das erzeugte Passwort auf die folgenden 4 Konventionen überprüft werden?

- mindestens ein Kleinbuchstabe
- mindestens ein Großbuchstabe
- mindestens eine Zahl
- mindestens ein Sonderzeichen

Das Problem ist hier, dass manchmal das Passwort nur mit 2 Konventionen erzeugt wird und nicht mit allen 4.
Wie kann ich das ändern?

Folgende Funktion wird aufgerufen:

Code: Alles auswählen

def createInitialPwd(col,key,config):
    flag = config.get(ldapConst.PWD_FLAG,0)
    if(flag):
        param=config[ldapConst.FCTS]
        length=utilGeneral.isInt(param.get(ldapConst.PWDLENGTH,8))
        chars=string.lowercase+string.uppercase+string.digits+string.punctuation
        newpwd=[]
        for i in range(length):
            newpwd.append(choice(chars))
        s=string.join(newpwd,'')
        config[ldapConst.PWD_TMP]=s
        return s
    return ''

def createInitialPwd2(col,key,config):
    pwd = config.get(ldapConst.PWD_TMP,'')
    return pwd
Zuletzt geändert von Anonymous am Dienstag 17. April 2012, 09:04, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Die Anforderungen sind doch leicht zu erfüllen: wähle einen zufälligen Kleinbuchstaben, wähle einen zufälligen Großbuchstaben, wähle eine zufällige Ziffer und dann wähle ein Sonderzeichen. Dann nimmst du dir noch so viele Zeichen wie nötig aus der Vereinigung von Kleinbuchstaben, Großbuchstaben, Ziffen und Sonderzeichen. Nun hast du alle Ziffern zusammen, durchmischt diese noch mit ``random.shuffle`` und anschließend machst du ein Kenwort draus.

Noch ein paar Anmerkungen zu deinem Code:
- Wirf bezüglich deiner Namensgebung und Formatierung mal ein Blick in PEP 8.
- Um die Bedingung beim if gehören keine Klammern
- Wenn du einen Index in eine for Schleife nicht benutzt, dann muss du diesen nicht an einen Namen binden. Statt ``i`` reicht dann ein ``_``. Es ist dann sofort ersichtlich, dass der Name nicht gebraucht wird.
- Statt deiner for-Schleife könnte man viel besser eine List-Comprehension verwenden
- Benutze nicht ``string.join``, Strings haben eine join-Methode. Bei dir würde es dann ``"".join(newpwd)`` heißen.

Sebastian
Das Leben ist wie ein Tennisball.
BlackJack

@Marek06: Statt auf Konventionen zu prüfen könntest Du auch einfach Passwörter generieren die auf jeden Fall die geforderten Kriterien erfüllen.

Du könntest auch mal einen Blick in PEP 8 -- Style Guide for Python Code werfen.

Funktionen aus dem `string`-Modul die es auch als Methoden auf `str` gibt, sind veraltet und sollten nicht mehr verwendet werden.

`isInt()` ist ein schlechter Name für eine Funktion die eine beliebige Zahl zurück gibt. Bei Funktionen mit Präfixen wie `is_*` oder `has_*` erwartet man einen Wahrheitswert als Ergebnis.

Ungetestete Prüffunktion:

Code: Alles auswählen

LOWER = set(string.lowercase)
UPPER = set(string.uppercase)
DIGITS = set(string.digits)
PUNCTUATION = set(string.punctuation)

# ...

def test(password):
    return all(
        any(c in cs for c in password)
        for cs in [LOWER, UPPER, DIGITS, PUNCTUATION]
    )
Marek06
User
Beiträge: 13
Registriert: Dienstag 17. April 2012, 08:51

Also ich habe jetzt folgendes gebastelt (bricht aber mit FM ab - kann random nicht identifzieren):

Code: Alles auswählen

...
length=utilGeneral.isInt(param.get(ldapConst.PWDLENGTH,8))
s=string.join(random.choice(string.lowercase+string.uppercase+string.digits+string.punctuation) for i in range(length))
config[ldapConst.PWD_TMP]=s
return s
...
Den Fehler konnte ich nachvollziehen (Funktion random muss importiert werden). Aber wäre dies syntaktisch richtig ??

Bin leider kein python Profi, aber über Tipps würde ich mich dazu freuen
:D
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn der Interpreter das Programm ohne eine Fehlermeldung startet, dann ist es zumindest syntaktisch korrekt. Ob die Semantik stimmt ist natürlich ein ganz andere Frage. Dein Code erzeugt aber noch immer nicht im jeden Fall Kennwörter, die den Anforderungen entsprechen. Diese stimmen nur zufällig, da zufällig die richtigen Zeichen ausgewählt werden. Versuche es doch einfach mal mit einer Konstruktion Schritt für Schritt, so wie BlackJack und ich es bereits beschrieben haben. Die Anmerkung mit dem string-Modul hast du übrigens noch nicht umgesetzt.

Und noch etwas Allgemeines: Wenn du eine Fehlermeldung bekommst und wir dir basierend darauf helfen sollen, dann Kopiere einfach die gesamte Fehlermeldung inklusive Traceback. Eine in Prosa zusammengefasste Fehlermeldung die dann auch noch schlecht übersetzt ist, hilft nicht weiter.
Das Leben ist wie ein Tennisball.
Marek06
User
Beiträge: 13
Registriert: Dienstag 17. April 2012, 08:51

Erstmal nochmal danke für die Tipps :) Waren sehr hilfreich.

Habe versucht die Tipps so weit wie mir möglich umzusetzen und jetzt eine Lösung gefunden, die so gut wie immer funktioniert (mindestens 3 Konventionen).
Musste noch ein wenig eingegrenzt werden1

Code: Alles auswählen

...
if flag:
        param=config[ldapConst.FCTS]
        chars=string.lowercase+string.uppercase+string.digits+string.punctuation
        chars_up_lo=string.lowercase+string.uppercase+string.digits
        s=''.join(random.choice(chars) for _ in range(7))
        y=''.join(random.choice(chars_up_lo) for _ in range(1))
        config[ldapConst.PWD_TMP]=s
        return y + s
...
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

"So gut wie immer funktioniert" ist in diesem Fall eine sehr seltsame Definition von funktionieren. Ganz offensichtlich ist es doch möglich, dass zum Beispiel immer Kleinbuchstaben gewählt werden. Damit hast du gleich drei Beschränkungen verletzt. Ich habe dir doch bereits in meiner ersten Antwort geschrieben, wie IMMER ein richtiges Kennwort erzeugt wird.

Code: Alles auswählen

>>> import random
>>> import string
>>> char_sets = [string.lowercase, string.uppercase, string.digits, string.punctuation]
>>> chars = []
>>> for s in char_sets:
...     chars.append(random.choice(s))
... 
>>> while len(chars) < 8:
...     chars.append(random.choice("".join(char_sets)))
... 
>>> random.shuffle(chars)
>>> "".join(chars)
'6em6=qUV'
Das Leben ist wie ein Tennisball.
Marek06
User
Beiträge: 13
Registriert: Dienstag 17. April 2012, 08:51

Ok, danke, wusste nicht genau wie ich das in Python umsetzen sollte, aber funzt damit jetzt 100% :D

Ergebnis ist hiermit(erste Buchstabe kein Sonderzeichen, ist so beabsichtigt!):

Code: Alles auswählen

if flag:
        param=config[ldapConst.FCTS]
        char_sets=[string.lowercase+string.uppercase+string.digits+string.punctuation]
        chars_up_lo=string.lowercase+string.uppercase+string.digits
        chars=[]
        for s in char_sets:
        	chars.append(random.choice(s))
        while len(chars) < 7:
        	chars.append(random.choice(''.join(char_sets)))
        random.shuffle(chars)
        s=''.join(chars)
        y=''.join(random.choice(chars_up_lo) for _ in range(1))
        config[ldapConst.PWD_TMP]=s
        return y + s
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Darin

Code: Alles auswählen

y=''.join(random.choice(chars_up_lo) for _ in range(1))
steckt viel unnötiges :-D Überlege noch mal, was `random.choice` genau macht...

Und Dein `join(charsets)` ist auch überflüssig, weil Du ja keine Menge von Strings hast, sondern oben mittels `+` *einen* einzigen Gesamtstring zusammenbaust...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Nein, du hast es immer noch nicht richtig umgesetzt. Bei dir enthält ``char_sets`` einen einzigen String, bei mir sind es vier. ``+`` und``,`` machen schon einen Unterschied. Die Zeile

Code: Alles auswählen

y=''.join(random.choice(chars_up_lo) for _ in range(1))
ist übrigens genau das selbe wie

Code: Alles auswählen

random.choice(chars_up_lo)
Das Leben ist wie ein Tennisball.
Marek06
User
Beiträge: 13
Registriert: Dienstag 17. April 2012, 08:51

Stimmt, hatte mich schon gewundert, warum dann immer noch Passwörter mit nicht allen Konventionen generiert werden. War wohl nur im ersten Test 100%.
Jetzt sieht es aber richtig aus. Nachdem ich das jetzt korrigiert hab, sieht es gut aus.

Danke nochmal für die Hilfe :D :D :D
Antworten