Matze: Passwort Prüffunktion

Hallo,

ich habe mir gerade eine Funktion geschrieben.
Sie soll überprüfen, ob ein übergebenes Passwort sinnvoll ist oder nur aus einer Zeichenfolge besteht.
Dabei hab ich zu meinem erstaunen fest gestellt, dass der Operator ++ auch mit Buchstaben funktioniert. Das war mir neu.

Ansonten würde ich den Code gern mal von euch bewerten lassen. Ist er fehlerfrei? Verbesserungswürdig? Überhaupt sinnvoll? Und sollte ich bei Passwortfeldern nur Zahlen und Buchstaben zulassen sind Sonderzeichen 'zulässig'? Mich stören sie eigentlich nicht.

Hier der Code[1]

  
 ## Passwort Prüffunktion  
  
 function good_pwd($pwd){  
  $lenght = strlen($pwd);        # Länge des Strings ermitteln  
  $chars = array();         # leeres Array erstellen  
  $chars = str_split($pwd);       # String in Array 'splitten'  
  for($i = 0; $i < $lenght; $i++){     # Schleife in Stringlänge falls kein Abbruch  
   if(!isset($charold)){ $charold = $chars[$i]; # beim ersten Durchlauf Variable auf erstes Zeichen setzen  
   }else{ $charold++;}        # beim nächsten Durchlauf um 1 erhöhen  
   if($chars[$i] == $charold){      # wenn aktuelles Zeichen = Variable  
    $bad_pwd = '1';        # ist das schlecht (auch immer beim ersten Zeichen)  
   }else{           # wenn nicht  
    $bad_pwd = '0';        # ist das gut  
    $i = $lenght;        # und die Schleife wird beendet  
   }  
  }  
  if($bad_pwd == '1'){ return false;     # wenn der String eine fortlaufende Zeichenkette enthält (z.B. 1234) false  
  }elseif($bad_pwd == '0'){ return true; }   # wenn nicht true  
 }  

Danke und Grüße, Matze

[1] Wie krieg ich hier eigentlich Tabs in den Text gesetzt?
Die werden beim speichern des Threads in Leerzeichen verwandelt.
Hab in der Forumshilfe leider nichts gefunden.

  1. Hallo,

    also die Idee ist sicher gut - wenn auch nicht neu;).
    Also eine bestimmte mindestzeichenzahl, kombination Buchstaben und Zahlen, vielleicht noch eine überprüfung, ob das ganze nicht zum beispiel schon als Name oder sonnst etwas genutzt wird...

    Dein Code an sich schaut irgendwie nicht richtig aus. Habe es jetzt nicht getestet aber ich denke er erfüllt nicht deinen Zweck, oder?

    Außerdem würde ich das ganze in JavaScript machen und dann "on the fly" die sicherheit des PWD anzeigen lassen.
    Ansonnsten muss der Nutzer ja erst das Formular absenden und dann nochmal ein neues PWD suchen...Natürlich geht dass nur wenn du die Sicherheit als Tipp nimmst, d.h. wenn auch thoretisch unsicher PWD akzeptiert werden (JavaScript hat ja nicht jeder und auf den Tipp wird auch nicht jeder hören)

    mfg
    Alex

  2. Hallo Matze,

    Sie soll überprüfen, ob ein übergebenes Passwort sinnvoll ist oder nur aus einer Zeichenfolge besteht.

    Dein Code sieht nach PHP aus, wirf mal einen kleinen Blick auf die inzwischen in PECL verschobenen Crack-Funktionen.

    Dabei hab ich zu meinem erstaunen fest gestellt, dass der Operator ++ auch mit Buchstaben funktioniert. Das war mir neu.

    aber dokumentiert.

    Ansonten würde ich den Code gern mal von euch bewerten lassen. Ist er fehlerfrei?

    Nein, auch konsequent durchgehaltene Rechtschreibfehler wie lenght statt length sind ein Fehler :-)

    Verbesserungswürdig?

    Definitiv, weil ...

    Überhaupt sinnvoll?

    Nein. Es fehlt viel zu viel.

    Und sollte ich bei Passwortfeldern nur Zahlen und Buchstaben zulassen

    Nein.

    sind Sonderzeichen 'zulässig'? Mich stören sie eigentlich nicht.

    Ja, sie sind sehr wünschenswert.

    Passwort Prüffunktion

    // Hier fehlt einfach alles:
    // Welche Überprüfungen werden vorgenommen, Beispiele
    // a) Mindestlänge,
    // b) erlaubter Zeichenvorrat,
    // c) vorgeschriebene Zeichengruppen, die vorkommen müssen,
    // d) Hält das Passwort einem Wörterbuchangriff stand,

    // Bei einer solchen Überprüfung geht es normalerweise um die Angriffsfläche,
    // die ein Passwort gegen Brute-Force- und Wörterbuchangriff bietet.
    // Die Regeln sind dem Angreifer bekannt, Du musst sie ja schließlich selbst
    // dem Anwender vorgeben.

    // Je größer die Länge des Passwortes, um so stärker ist es
    // Je größer der Zeichenvorrat der erlaubten Zeichen, um so stärker ist es
    // Nur wenn Zeichen aus verschiedenen Gruppen auftreten, ist es wirklich stark
    // Wenn Gruppen mehrfach vorkommen, dann ist das besser
    // Das Passwort sollte nicht in einem Wörterbuch gefunden werden

    // Daher sollte die Funktion auch keinen Wahrheitswert zurückliefern, sondern
    // einen Stärkewert, so wie es auch die entsprechende Crack-Funktion macht ...

    // Das gehört alles in die Dokumentation, den Kommentar zur Funktion, siehe
    // dazu auch [pref:t=166913;m=1088534] und
    // folgender von dedlfix verlinkter [link:http://shiflett.org/blog/2007/dec/php-advent-calendar-day-2@title=Blogartikel] zur Dokumentation von Code.

    function good_pwd($pwd){

    // [...]

      
    
    > [1] Wie krieg ich hier eigentlich Tabs in den Text gesetzt?  
      
    Wandle sie mit der entsprechenden Funktion Deines Editors in Leerzeichen um.  
      
    Bis auf die Wörterbuchüberprüfung könntest Du - wie von Alex vorgeschlagen - die Überprüfung ergänzend bereits auf dem Client vornehmen, für den Wörterbuchangriff könntest Du, falls möglich, auf Ajax zurückgreifen. Wie üblich ersetzt das nicht Deine serverseitige Überprüfung :-)  
      
      
    Freundliche Grüße  
      
    Vinzenz
    
    1. Hallo,

      Nein, auch konsequent durchgehaltene Rechtschreibfehler wie lenght statt length sind ein Fehler :-)

      eigentlich hab ich mich nur 1 mal vertippt, dann aber das zweite dahingehend (falsch) geändert weil ich mir nicht sicher war welche Version richtig ist :)

      // a) Mindestlänge,

      Mir ging es primär um den Sinn meiner Funktion. Die Abfrage nach der Mindestlänge habe ich der Übersicht halber raus gelassen. Erlaubt sind 6 bis 16 Zeichen. Eine Maximallänge vorzuschreiben ist zwar IMHO blödsinn, aber so fange ich irgendwelchen Murks ab falls ein User nur mal kurz wild auf der Tastatur rum tippt. Ebenso dürfen Name und Passwort nicht vom gleichen Typ mit dem selben Wert sein.

      // b) erlaubter Zeichenvorrat,

      Nun nachdem wir uns einig sind, dass Sonderzeichen im PW sinnvoll sind, brauch ich da überhaupt noch eine Prüfung nach dem Zeichenvorrat oder sollte ich nicht vielleicht alles durch lassen? Vielleicht nur Leerzeichen filtern.

      // c) vorgeschriebene Zeichengruppen, die vorkommen müssen,

      Wie Alex richtig vermutet hat ("Natürlich geht dass nur wenn du die Sicherheit als Tipp nimmst, d.h. wenn auch thoretisch unsicher PWD akzeptiert werden"), geht es mir nicht um ein "absolut sicheres" Passwort, eher um eine Abfrage um den gröbsten Unfug abzufangen.

      // d) Hält das Passwort einem Wörterbuchangriff stand (...)
      // Das Passwort sollte nicht in einem Wörterbuch gefunden werden

      Das mit dem Wörterbuchangriff find ich interessant. Nur wie soll ich prüfen, ob das übergebene PW ein Wort ist? In der Richtung hab ich mich noch nie beschäftigt.

      Wenn das PW allerdings wirklich so kryptisch sein soll, empfiehlt es sich da nicht das PW gleich selbst zu kreieren?

      Ungefähr so (ungetestet):

        
       function xstring($leng){  
        $zeichen = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz12345678901234567890";  
        for($i = 0; $i < $leng; $i++ ){  
         $n = rand() % strlen($zeichen);  
         $randstring .= substr($zeichen,$n,1);}  
        return $randstring;  
       }  
      
      

      Müsste man natürlich noch um ein paar Sonderzeichen erweitern.

      // Daher sollte die Funktion auch keinen Wahrheitswert zurückliefern, sondern
      // einen Stärkewert, so wie es auch die entsprechende Crack-Funktion macht ...

      Schau ich mir an, danke.

      [1] Wie krieg ich hier eigentlich Tabs in den Text gesetzt?

      Wandle sie mit der entsprechenden Funktion Deines Editors in Leerzeichen um.

      Ich meinte eigentlich hier im Forum :)

      @Alex: Doch doch, der Code tut genau das was ich will (trotz Rechtschreibfehler^^)

      Grüße, Matze

      1. Hallo Matze,

        // a) Mindestlänge,

        Mir ging es primär um den Sinn meiner Funktion. Die Abfrage nach der Mindestlänge habe ich der Übersicht halber raus gelassen.

        äh nein. Das hat nichts mit Übersicht zu tun. So kann man Deine Frage nicht beantworten. Wie angemerkt, so wie vorgestellt, ist die Funktion meiner Meinung nach völlig sinnfrei und kann der Einfachheit halber weggelassen werden. Du überprüfst einen kleinen Punkt eines Wörterbuchangriffs, nicht mehr.

        Wenn das PW allerdings wirklich so kryptisch sein soll, empfiehlt es sich da nicht das PW gleich selbst zu kreieren?

        Nein, Benutzer mögen keine Passwörter, die ihnen vorgeschrieben werden. Die können sie sich nämlich nicht merken. Willst Du überall einen Zettel auskramen, auf dem 20 Passwörter für 20 verschiedene, zum Teil hochsensible, Anwendungen stehen. Keine gute Idee. Vermittle lieber Deinen Anwendern Strategien, wie man sich starke und doch gut merkbare Passwörter ausdenken kann.

        Eine Anmerkung zu Deiner einzigen vorgestellten Prüfung:

        "abcd" ist nicht unsicherer als "aaaa" und genauso unsicher wie "asdf" oder "qwer". Zweites ist bei reinem Brute-Force natürlich gleich geknackt. Aber bevor man zu Brute-Force greift, versucht man es mit einem Wörterbuch.

        Zwei Sekunden Zwangspause nach drei oder fünf Fehlversuchen sind übrigens ein hervorragendes Mittel gegen Brute-Force-Angriffe. Viel längere Zwangspausen ermöglichen hingegen DOS-Attacken (Denial of Service) auf den legitimen Nutzer, sind daher keine gute Idee.

        Freundliche Grüße

        Vinzenz

        1. Hallo,

          äh nein. Das hat nichts mit Übersicht zu tun. So kann man Deine Frage nicht beantworten. Wie angemerkt, so wie vorgestellt, ist die Funktion meiner Meinung nach völlig sinnfrei und kann der Einfachheit halber weggelassen werden.(...)

          "abcd" ist nicht unsicherer als "aaaa" und genauso unsicher wie "asdf" oder "qwer".

          dann versuch ich es doch noch einmal vollständig und erweitert um die Prüfung nach z.B. aaaa, 1111 usw.
          Das mit dem Wörterbuch krieg ich nicht hin, ich komm nicht an die CrackLib.

          Zwei Sekunden Zwangspause nach drei oder fünf Fehlversuchen sind übrigens ein hervorragendes Mittel gegen Brute-Force-Angriffe.

          Ich hab jetzt am Ende der Funktion ein sleep(120);, glaube aber, dass das dort an der falschen Stelle ist oder?

          hier noch einmal der Code (erweitert und vollständig)

            
          function good_pwd($string, $minlenght, $maxlenght, $refstring){  
            
                  # Wenn String leer  
            
                  if(empty($string)) $error = '1';  
            
                  # Wenn String zu lang oder zu kurz  
            
                  if(strlen($string) < $minlenght || strlen($string) > $maxlenght) $error = '2';  
            
                  # Wenn String fortlaufender Folge ist  
            
                  $length = strlen($string);  
                  $chars = array();  
                  $chars = str_split($string);  
                  for($i = 0; $i < $length; $i++){  
                          if(!isset($charold)){  
                                  $charold = $chars[$i];  
                          }else{  
                                  $charold++  
                          }  
            if($chars[$i] == $charold){  
                                  $error = '3';  
                          }else{  
                                  $i = $length;  
                          }  
                  }  
            
                  # Wenn String = Referenzstring (z.B. Passwort = Name)  
            
                  if(strtolower($string) == strtolower($refstring)) $error = '4';  
            
                  # Wenn String nur aus einem Zeichen besteht  
            
                  $length = strlen($string);  
                  $chars = array();  
                  $chars = str_split($string);  
                  for($i = 0; $i < $length; $i++){  
                          if(!isset($charold)) $charold = $chars[$i];  
                          if($chars[$i] == $charold){  
                                  $error = '5';  
                          }else{  
                                  $i = $length;  
                          }  
                  }  
                  if(!isset($error)) error = '0';  
                  sleep(120);  
                  return $error;  
          }  
          
          

          Mittlerweile liefert die Funktion einen Errorcode, diesen kann man dann z.B. mit einer Switch-Funktion bequem auswerten bzw. den Switch-Teil gleich mit in die Funktion schreiben und eine vollständige Fehlermeldung ausgeben, das wollte ich mir jetzt aber ersparen.

          Ist die Funktion so jetzt einigermaßen brauchbar?

          Danke und Grüße, Matze

          1. Hallo,

            ich habe gerade gemerkt, das ich im letzten Teil

            # Wenn String nur aus einem Zeichen besteht

            einen Fehler gemacht habe. Das wird noch korrigiert.

            Grüße, Matze

            1. Hallo nochmal^^,

              da waren noch mehr Fehler 'versteckt'. Ich hoffe das waren jetzt alle.
              Also hier zum (hoffentlich) letzten mal.

                
              function good_pwd($string, $minlenght, $maxlenght, $refstring){  
                
                      # Wenn String leer  
                
                      if(empty($string)) $error = '1';  
                
                      # Wenn String zu lang oder zu kurz  
                
                      if(strlen($string) < $minlenght || strlen($string) > $maxlenght) $error = '2';  
                
                      # Wenn String fortlaufender Folge ist  
                
                      $length = strlen($string);  
                      $chars = array();  
                      $chars = str_split($string);  
                      for($i = 0; $i < $length; $i++){  
                              if(!isset($charold)){  
                                      $charold = $chars[$i];  
                              }else{  
                                      $charold++  
                              }  
                              if($chars[$i] == $charold){  
                                      $bad_pwd = '1';  
                              }else{  
                 $bad_pwd = '0';  
                                      $i = $length;  
                              }  
                      }  
               if($bad_pwd == '1') $error = '3';  
                
                      # Wenn String = Referenzstring (z.B. Passwort = Name)  
                
                      if(strtolower($string) == strtolower($refstring)) $error = '4';  
                
                      # Wenn String nur aus einem Zeichen besteht  
                
                      $length = strlen($string);  
                      $chars = array();  
                      $chars = str_split($string);  
                      for($i = 0; $i < $length; $i++){  
                              if(!isset($charold)) $charold = $chars[$i];  
                              if($chars[$i] == $charold){  
                                      $bad_pwd = '1';  
                              }else{  
                                      $bad_pwd = '0';  
                                      $i = $length;  
                              }  
                      }  
                      if($bad_pwd == '1') $error = '5';  
                
               # Wenn kein Fehler gefunden wurde  
                
                      if(!isset($error)) $error = '0';  
                
               # Errorstatus zurück geben  
                
                      sleep(120);  
                      return $error;  
              }  
              
              

              Sorry.

              Grüße, Matze

          2. Hallo Matze,

            Zwei Sekunden Zwangspause nach drei oder fünf Fehlversuchen sind übrigens ein hervorragendes Mittel gegen Brute-Force-Angriffe.

            Ich hab jetzt am Ende der Funktion ein sleep(120);, glaube aber, dass das dort an der falschen Stelle ist oder?

            Ja, diese Prüfung ist unabhängig davon, ob das Passwort gut oder schlecht ist.
            Da geht es um das Mitloggen erfolgreicher und nicht erfolgreicher Anmeldungen.
            Das bedeutet, dass Du die Prüfung bei der Anmeldung vornehmen musst. Genau dort, nicht woanders. Ob Du die (relevanten letzten) Anmeldeversuche in einer Datei oder einer DB speicherst, das spielt prinzipiell keine Rolle. Du musst es nur richtig machen :-)

            hier noch einmal der Code (erweitert und vollständig)

            function good_pwd($string, $minlenght, $maxlenght, $refstring){

            Grr, bitte einige Dich mit Dir darauf, in Zukunft generell length zu schreiben.

            Ist die Funktion so jetzt einigermaßen brauchbar?

            Irgendwie ist mir immer noch unklar, wozu Du diese Prüfung machst. Gegen welche Angriffszenarien möchtest Du den Anwender schützen?

            Schreibst Du zum Beispiel die Verwendung verschiedener Zeichenklassen vor, z.B. mindestens Groß- und Kleinbuchstaben oder Buchstaben plus Ziffern, dann kannst Du Dir die Prüfung auf nur gleiche Zeichen oder auf eine Sequenz sparen.

            Trotzdem noch ein Hinweis, wie Du Deinen Code vereinfachen kannst.

            statt (hier Deine Version aus [pref:t=167103;m=1090026]):
            [code lang=php]
                    # Wenn String nur aus einem Zeichen besteht

            $length = strlen($string);
                    $chars = array();
                    $chars = str_split($string);
                    for($i = 0; $i < $length; $i++){
                            if(!isset($charold)) $charold = $chars[$i];
                            if($chars[$i] == $charold){
                                    $bad_pwd = '1';
                            }else{
                                    $bad_pwd = '0';
                                    $i = $length;
                            }
                    }
                    if($bad_pwd == '1') $error = '5';

              
            arbeitet bestimmt nicht korrekt, ich verstehe ehrlich gesagt überhaupt nicht, was das soll. Kommentiere Deinen Code!  
              
            Mein Vorschlag wäre:  
              
            ~~~php
              
                # Wenn String nur aus einem Zeichen besteht  
                // Erzeuge ein Array der einzelnen Zeichen  
                $chars = [link:http://www.php.net/manual/de/function.str-split.php@title=str_split]($string);  
              
                // Entferne doppeltes Auftreten  
                $chars_unique = [link:http://www.php.net/manual/de/function.array-unique.php@title=array_unique]($chars);  
              
                // Wenn das resultierende Array nur einen Wert enthält, dann gab es nur  
                // ein unterschiedliches Zeichen  
                if (count($chars_unique) == 1) {  
                    // Hmm, klemmte da eine Taste :-)  
                    $error = 5;  
                }  
            
            

            bzw.

              
                // Wenn das um die Dubletten bereinigte Array der Zeichen der Zeichenkette  
                // nur ein Element enthält, dann ist etwas faul im Staate Dänemark ...  
                if (count(array_unique(str_split($string))) == 1) {  
                    $error = 5;  
                }  
            
            

            Alternativ böte sich auch array_count_values() an.

            Ach ja, ich halte es für eine gute Idee, die einzelnen Prüfungen in hübsche kleine einzelne und gut testbare Funktionen zu packen. Das ganze könntest Du dann in eine kleine Klasse packen. Mit dieser Klasse kannst Du dann auf einfache Weise und flexibel die Anforderungen abprüfen, die Du je nach Anwendungsfall hast. Somit hast Du wieder ein Stück wiederverwertbaren Code geschrieben und für die Zukunft Arbeit erspart.

            Freundliche Grüße

            Vinzenz

            1. Hallo,

              Grr, bitte einige Dich mit Dir darauf, in Zukunft generell length zu schreiben.

              habs gemerkt, ich versuch es gerade, jetzt dürfte alles auf "length" gestellt sein ;)

              Schreibst Du zum Beispiel die Verwendung verschiedener Zeichenklassen vor (..)

              Eigentlich will ich mir genau das ersparen und trotzdem ein halbwegs vernünftiges Passwort "erzwingen". Also wirklich nur "Müll" raus filtern.

              statt (hier Deine Version aus

                
                  # Wenn String nur aus einem Zeichen besteht  
                
                  # Stringlänge ermitteln  
                  $length = strlen($string);  
                
                  # Leeres Array erstellen  
                  $chars = array();  
                
                  # Einzelne Zeichen in Array aufsplitten  
                  $chars = str_split($string);  
                
                  # einzelne Buchstaben auslesen bis Arrayende, $i auf ersten Schlüssel (0) setzen  
                  for($i = 0; $i < $length; $i++){  
                
                  # Kontrollvariable beim ersten Durchlauf auf aktuelles Zeichen setzen  
                     if(!isset($charold)) $charold = $chars[$i];  
                
                  # wenn Kontrollvariable = aktuelles Zeichen  
                     if($chars[$i] == $charold){  
                  # Fehlervariable auf 1 setzen (beim ersten Durchlauf)  
                         $bad_pwd = '1';  
                     }else{  
                  # wenn Kontrollvariable nicht dem aktuellen Zeichen entspricht  
                  # Fehlervariable auf 0 setzen  
                         $bad_pwd = '0';  
                  # Schleife beenden  
                         $i = $length;  
                     }  
                  }  
                  # Fehlervariable übergeben  
                  if($bad_pwd == '1') $error = '5';  
              
              

              arbeitet bestimmt nicht korrekt, ich verstehe ehrlich gesagt überhaupt nicht, was das soll. Kommentiere Deinen Code!

              So besser? Wenn die Schleife, ohne das $bad_pwd auf 0 gesetzt wird weil ein neues Zeichen auftritt, beendet oder durchlaufen wird sind mindestens 2 verschiedene Zeichen im String. Aber wieso ist er nicht fehlerfrei?
              Ich hab aber deine Variante übernommen, danke! Ich bin leider nicht so fit mit den Array-Funktionen.

              Ach ja, ich halte es für eine gute Idee, die einzelnen Prüfungen in hübsche kleine einzelne und gut testbare Funktionen zu packen.

              hmpf, deshalb war im Ausgangspost auch nur der eine Teil ;)

              Das ganze könntest Du dann in eine kleine Klasse packen.(...)

              So war das geplant ;)

              Ich versuch mich jetzt noch an einer Abfrage um z.B. "4321" zu unterbinden.
              Ich such grad eine Funktion um heraus zu kriegen wieviel Schlüssel ein Array hat. Nicht schlagen, ich hab Arrays irgendwie echt vernachlässigt.

              Wie ich "dcba" vermeiden kann weiß ich noch nicht.

              Grüße, Matze

              1. Hallo Matze,

                Eigentlich will ich mir genau das ersparen und trotzdem ein halbwegs vernünftiges Passwort "erzwingen". Also wirklich nur "Müll" raus filtern.

                statt (hier Deine Version aus

                # Wenn String nur aus einem Zeichen besteht

                # Stringlänge ermitteln
                    $length = strlen($string);

                # Leeres Array erstellen
                    $chars = array();

                # Einzelne Zeichen in Array aufsplitten
                    $chars = str_split($string);

                # einzelne Buchstaben auslesen bis Arrayende, $i auf ersten Schlüssel (0) setzen
                    for($i = 0; $i < $length; $i++){

                # Kontrollvariable beim ersten Durchlauf auf aktuelles Zeichen setzen
                       if(!isset($charold)) $charold = $chars[$i];

                # wenn Kontrollvariable = aktuelles Zeichen
                       if($chars[$i] == $charold){
                    # Fehlervariable auf 1 setzen (beim ersten Durchlauf)
                           $bad_pwd = '1';
                       }else{
                    # wenn Kontrollvariable nicht dem aktuellen Zeichen entspricht
                    # Fehlervariable auf 0 setzen
                           $bad_pwd = '0';
                    # Schleife beenden
                           $i = $length;
                       }
                    }
                    # Fehlervariable übergeben
                    if($bad_pwd == '1') $error = '5';

                
                > > arbeitet bestimmt nicht korrekt, ich verstehe ehrlich gesagt überhaupt nicht, was das soll. Kommentiere Deinen Code!  
                >   
                > So besser? Wenn die Schleife, ohne das $bad\_pwd auf 0 gesetzt wird weil ein neues Zeichen auftritt, beendet oder durchlaufen wird sind mindestens 2 verschiedene Zeichen im String. Aber wieso ist er nicht fehlerfrei?  
                  
                Hmm ja, scheint zu funktionieren, ist aber umständlich und schwer nachzuvollziehen.  
                  
                Verbesserungsvorschläge:  
                a) Initialisiere Dein $charold von vornherein mit $chars[0]  
                b) Beginne die Schleife daher mit $i = 1  
                c) Nutze zum Abbruch die Anweisung [break](http://www.php.net/manual/de/control-structures.break.php)  
                  
                Nur als Grundideen für vergleichbare Fälle.  
                  
                
                > > Ach ja, ich halte es für eine gute Idee, die einzelnen Prüfungen in hübsche kleine einzelne und gut testbare Funktionen zu packen.  
                >   
                > hmpf, deshalb war im Ausgangspost auch nur der eine Teil ;)  
                  
                ja - und genau deswegen hättest Du Dein Konzept im Ausgangspost vorstellen  
                sollen. Verstehst Du, der geneigte Leser weiß nichts von Deinem Gesamtkonzept.  
                  
                
                > Ich versuch mich jetzt noch an einer Abfrage um z.B. "4321" zu unterbinden.  
                > Ich such grad eine Funktion um heraus zu kriegen wieviel Schlüssel ein Array hat. Nicht schlagen, ich hab Arrays irgendwie echt vernachlässigt.  
                >   
                > Wie ich "dcba" vermeiden kann weiß ich noch nicht.  
                  
                Beides geht gleich:  
                Prinzipiell genauso wie aufsteigende Folgen. Nutze den Dekrementoperator :-)  
                Alternative: Kehre die Zeichenkette (bzw. das Array) um und prüfe auf aufsteigend ...  
                  
                Eine Anmerkung noch zum Schluss:  
                Die Überprüfung auf Stärke eines Passwortes ist nicht besonders häufig erforderlich. Die Geschwindigkeit der Prüfung ist meiner persönlichen Meinung nach völlig irrelevant.  
                  
                  
                Freundliche Grüße  
                  
                Vinzenz
                
                1. Hallo,

                  nungut, ab 9 wirds bei der Funktion zur Erkennung von einer aufsteigenden Reihe schwierig. Praktisch kommt danach die 10, für PHP aber 1 und 0. Somit ist das ganze Konstrukt, so schön es auch war ^^, unbrauchbar.

                  Verbesserungsvorschläge:
                  a) Initialisiere Dein $charold von vornherein mit $chars[0]
                  b) Beginne die Schleife daher mit $i = 1

                  Gut, damit spar ich mir einen Schleifendurchlauf, hast aber recht. Danke.

                  c) Nutze zum Abbruch die Anweisung break

                  Tja und da dachte ich wieder break gibts nur für switch. Lesen bildet. Nochmal danke.

                  hmpf, deshalb war im Ausgangspost auch nur der eine Teil ;)

                  ja - und genau deswegen hättest Du Dein Konzept im Ausgangspost vorstellen
                  sollen. Verstehst Du, der geneigte Leser weiß nichts von Deinem Gesamtkonzept.

                  Sicher, aber ich dachte auch daran nur relevanten Code zu präsentieren.
                  Charta und so ;) Ich habs wohl 'zu gut gemeint'.

                  Wie ich "dcba" vermeiden kann weiß ich noch nicht.

                  Beides geht gleich:
                  Prinzipiell genauso wie aufsteigende Folgen. Nutze den Dekrementoperator :-)

                  Nö, weil:
                  "PHP folgt bei der Behandlung arithmetischer Operationen an Zeichenvariablen der Perl-Konvention und nicht der von C. Zum Beispiel wird in Perl aus 'Z'+1 'AA', während aus 'Z'+1 in C '[' wird ( ord('Z') == 90, ord('[') == 91 ). Beachten Sie, dass Zeichenvariablen zwar inkrementiert aber nicht dekrementiert werden können."

                  Das heißt doch, dass b-- nicht gleich a ist oder?

                  Alternative: Kehre die Zeichenkette (bzw. das Array) um und prüfe auf aufsteigend ...

                  Bin grad dabei ;)

                  Hast du vielleicht noch andere Ideen was ich prüfen könnte?
                  An das aaa bzw. 111 hatte ich heut morgen z.B. noch gar nicht gedacht, obwohl es doch so naheliegend ist.

                  Danke und Grüße, Matze

                  1. Hallo Matze,

                    nungut, ab 9 wirds bei der Funktion zur Erkennung von einer aufsteigenden Reihe schwierig. Praktisch kommt danach die 10, für PHP aber 1 und 0. Somit ist das ganze Konstrukt, so schön es auch war ^^, unbrauchbar.

                    ich denke, Du denkst zu kompliziert.
                    Es geht Dir hier um *einfache* Überprüfungen.
                    Es geht um einfache Überprüfungen von _Zeichen_ einer Zeichengruppe.
                    Es geht nicht um die Bedeutung von zusammengesetzten Zeichen.
                    Genauso könntest Du argumentieren:

                    56710

                    ist nicht erlaubt, da vier aufeinanderfolgende Zahlen im Oktalsystem

                    1112123

                    ist nicht erlaubt, da es aufeinanderfolgende Stundenzahlen einer Analoguhr sind.

                    27281

                    ist nicht erlaubt, weil es aufeinanderfolgende Tage im Februar/März eines Nichtschaltjahres sind.

                    Wie willst Du 117118 berücksichtigen, wie 127012 oder 127001002 wegen 128-er-System?

                    Alles nicht besonders sinnvolle Prüfungen (meiner Meinung nach). Das gehört bestenfalls in ein Wörterbuch.

                    Aufsteigend in einer Zeichengruppe wäre - und Du musst das definieren und dokumentieren - z.B. 3456 und 7890.

                    Ähnlich verhält es sich mit Buchstaben:

                    xyzabc wäre z.B. als aufsteigend definierbar.
                    Aber was machst Du, wenn Du statt der 26 Buchstaben des englischen Alphabets den UTF-8-Zeichenvorrat zulässt? Wie prüfst Du dann? Siehe z.B. dieses Archivposting von dedlfix.

                    Hast du vielleicht noch andere Ideen was ich prüfen könnte?
                    An das aaa bzw. 111 hatte ich heut morgen z.B. noch gar nicht gedacht, obwohl es doch so naheliegend ist.

                    Prüf' nicht zuviel :-)
                    Wenn Du mehr als eine Zeichengruppe verlangst, dann werden andere Prüfungen obsolet. Ein "##" oder ein "aa" oder "ab" in einem Passwort, das aus mehreren Zeichengruppen besteht schadet im Allgemeinen nicht.

                    Wichtig ist, dass Du Dir die Regel, nach der eine Prüfung stattfindet vorher aufschreibst, im Kommentar zur Funktion dokumentierst. Wie Du diese Regel prüfst, das wiederum ist für die Anwendung der Prüfung selbst völlig gleichgültig - Hauptsache das Ergebnis ist gemäß Prüfrichtlinie korrekt.

                    Wenn Du also 78901 nicht als aufsteigend definierst, dann muss

                    bool function ist_aufsteigend($string)

                    false zurückliefern. Definierst Du 78901 als aufsteigend, dann eben true.
                    Nochmals:
                    1. Schritt: Definition der Prüfrichtlinie
                    2. Schritt: Dokumentation der Prüfrichtlinie
                    3. Schritt: Erstellen eines Testes für die Funktion
                    4. Schritt: Umsetzen in einen Algorithmus
                    5. Schritt: Testen der Funktion

                    Später kannst Du alternative Algorithmen (siehe z.B. die Varianten mit Array-Funktionen) durchtesten und ggf. ersetzen. Wichtig ist, dass die Funktion gemäß Spezifikation korrekt arbeitet. Wie sie das macht, ist zweitrangig.

                    Freundliche Grüße

                    Vinzenz

                    1. Hallo,

                      ich denke, Du denkst zu kompliziert.
                      Es geht Dir hier um *einfache* Überprüfungen.

                      genau, ich denk da hast du recht. Wenn ich anfange Zusammenhänge zu prüfen, kann ichs auch gleich ordentlich machen. In dem Fall reicht meine Prüfung wohl aus.

                      Nochmals:

                      1. Schritt: Definition der Prüfrichtlinie

                      Naja, es fallen einem ja meißt immer neue Sachen ein. Aber sonst kein Problem.

                      1. Schritt: Dokumentation der Prüfrichtlinie

                      Dafür gibt es ja den Errorcode der mir sagt gegen welche Regel ich verstossen hab. Ich glaub sich aufzuschreiben was man _nicht_ darf ist weniger als das was man darf.

                      1. Schritt: Erstellen eines Testes für die Funktion
                      2. Schritt: Umsetzen in einen Algorithmus
                      3. Schritt: Testen der Funktion

                      Kein Problem. Allerdings würde ich doch lieber gern die Funktionen benutzen, die dafür gedacht sind, anstatt mir selbst irgendwelche Schleifen zusammen zu schreiben die den selben Zweck erfüllen ;)
                      Ich hab auch so meine Probleme mit der Kommentierung. Es ist halt komisch zu wissen was andere wissen wollen wenn man es selbst weiß.

                      Das einzige, was mir jetzt noch fehlt, wäre halt die Prüfung nach 'zyxw'.
                      Die hätte ich schon gern noch. Oder ist das dann doch zu weit her geholt?

                      Ich mein der 'Durchschnittsmensch' kann kaum 4 Buchstaben flüssig rückwärts genannt, da wird er sowas nicht versuchen einzutippen wenn er es nicht _ernsthaft_ will oder? Was mich zu der Überlegung bringt es sogar explizit zu erlauben... *grübel

                      Genau wie Leerzeichen. Sinnvoll oder nicht? Sollte ich sie akzeptieren?
                      Also auch Passwörter wie "t e s t" ?
                      Oder sollte ich vielleicht die Menge der Leerzeichen im Verhältnis zu den übergebenen Zeichen betrachten? Oder sind wir da wieder bei dem Thema, dass ich eine 'einfache Prüfung' auch einfach eine 'einfache Prüfung' sein lassen soll?

                      Danke und Grüße, Matze

                      1. Hallo

                        Das einzige, was mir jetzt noch fehlt, wäre halt die Prüfung nach 'zyxw'.
                        Die hätte ich schon gern noch. Oder ist das dann doch zu weit her geholt?

                        Sie ist einfach. Zeichenkette umdrehen und auf aufsteigend testen.
                        Den Test hast Du doch schon :-)
                        Zeichenkette oder Array umdrehen, wo ist das Problem?

                        strrev()
                        array_reverse()

                        Handbuch, angemessenen Abschnitt auswählen, Funktionsliste durchgehen, was finden, glücklich sein :-)

                        Genau wie Leerzeichen. Sinnvoll oder nicht? Sollte ich sie akzeptieren?
                        Also auch Passwörter wie "t e s t" ?

                        Nein, Leerzeichen in Passwörtern sind definitiv keine gute Idee. Bist Du schon mal einer Anwendung begegnet, die Leerzeichen in Passwörtern erlaubt? Ich kann mich an keine erinnern.

                        Freundliche Grüße

                        Vinzenz

                        1. Hallo,

                          Sie ist einfach. Zeichenkette umdrehen und auf aufsteigend testen.
                          Den Test hast Du doch schon :-)
                          Zeichenkette oder Array umdrehen, wo ist das Problem?

                          strrev()
                          array_reverse()

                          ähm ja sicher, ich steh nur irgendwie grad auf dem Schlauch. array_reverse() brauch ich schonmal gar nicht weil ich die 'Richtung' des Durchlaufs schon mit der for()-Schleife steuern kann. strrev() war was ich suchte, danke.

                          Genau wie Leerzeichen. Sinnvoll oder nicht? Sollte ich sie akzeptieren?
                          Also auch Passwörter wie "t e s t" ?

                          Nein, Leerzeichen in Passwörtern sind definitiv keine gute Idee. Bist Du schon mal einer Anwendung begegnet, die Leerzeichen in Passwörtern erlaubt? Ich kann mich an keine erinnern.

                          Naja das klingt nach "das machen alle so, also ich auch".
                          Aber der Grund leuchtet mir schon ein - es wäre dann ziemlich unsicher.
                          Unter Umständen evtl. auch schwer zu verarbeiten wenn das Erste ein Leerzeichen ist.

                          Danke erstmal soweit, ich werde den Code dann morgen nochmal fertig posten. Vielleicht kann ihn ja mal jemand gebrauchen.
                          Für heute reichts.

                          Grüße, Matze

                        2. Hallo Vinzenz,

                          Nein, Leerzeichen in Passwörtern sind definitiv keine gute Idee. Bist Du schon mal einer Anwendung begegnet, die Leerzeichen in Passwörtern erlaubt? Ich kann mich an keine erinnern.

                          Huh? Mir fällt im Moment auf Anhieb keine Software ein, die Leerzeichen in Passwörtern *nicht* erlauben würde. Klar, sowas gibt's sicherlich, bin ich auch sicher schonmal begegnet, aber das dürfte die *absolute* Ausnahme sein.

                          Und ich selbst verwende durchaus auch Leerzeichen in einigen Passwörtern, die ich nutze. Zumindest dort, wo ich sie verwende, hatte ich nie Probleme mit ihnen.

                          Viele Grüße,
                          Christian

                          1. Hallo Christian,

                            Huh? Mir fällt im Moment auf Anhieb keine Software ein, die Leerzeichen in Passwörtern *nicht* erlauben würde. Klar, sowas gibt's sicherlich, bin ich auch sicher schonmal begegnet, aber das dürfte die *absolute* Ausnahme sein.

                            was Ausnahme angeht, keine Ahnung. Ich vermute es ist das "Was der Bauer nicht kennt ... "-Syndrom :-)

                            Danke für Deinen Hinweis, den werd' ich in den nächsten Tagen einfach mal ausprobieren.

                            Freundliche Grüße

                            Vinzenz

                          2. Hallo,

                            Huh? Mir fällt im Moment auf Anhieb keine Software ein, die Leerzeichen in Passwörtern *nicht* erlauben würde. Klar, sowas gibt's sicherlich, bin ich auch sicher schonmal begegnet, aber das dürfte die *absolute* Ausnahme sein.

                            das finde ich aber nicht klug. So kann man aus einem 10 stelligen String bequem einen 5 stelligen machen. Ob das im Sinne der Überlegung ist, einen mindestens 6 stelligen String vorzuschreiben weiß ich nicht. Andererseits könnte man das Leerzeichen auch durch jedes beliebige andere Zeichen ersetzen und dann wär es wieder egal. Was soll ein Unterschied sein zwischen "t e s t" und "t1e1s1t"? Ich hab die Überprüfung nach Leerzeichen raus genommen.

                            Ich könnte mich allerdings auch an keinen Fall erinnern wo ich Leerzeichen verwende. (wo erlaubt kann ich nicht sagen, ich benutze keine PWs mit Leerzeichen)

                            Danke für deinen Hinweis!

                            Ich bin gerade dabei ein komplettes Login-Script mit der diskutierten Funktion zu schreiben. Wenn ich fertig bin, stelle ich es mal online.
                            Die Funktion eignet sich ja nicht nur zur Überprüfung von Passwörtern, sondern auch Benutzernamen, Straßennamen usw. Eigentlich jeder Art Daten die irgendwie Sinn ergeben sollen.
                            Und da könnte sie später vielleicht doch mal dem ein oder anderem nützen.

                            Die Funktion soweit (erfolgreich getestet aber nicht kommentiert)

                              
                             function good_string($string, $minlength, $maxlength, $refstring = NULL){  
                                    # Stringlänge ermitteln  
                              
                                    $length = strlen($string);  
                              
                                    # String in Array aufsplitten  
                              
                                    $chars = array();  
                                    $chars = str_split($string);  
                              
                                    # Wenn String zu kurz oder zu lang  
                              
                                    if(strlen($string) < $minlength || strlen($string) > $maxlength) $error = '1';  
                              
                                    # Wenn String = Referenzstring (z.B. Passwort = Name)  
                              
                                    if(strtolower($string) == strtolower($refstring)) $error = '2';  
                              
                                    # Wenn String nur aus einem Zeichen besteht z.B. "1111", "aaaa"  
                              
                                    if(count(array_unique(str_split($string))) == 1) $error = '3';  
                              
                                    # Wenn String aufsteigender Folge ist z.B. "1234", "abcd"  
                              
                                    for($i = 0; $i < $length; $i++){  
                                            if(!isset($charold)){  
                                                    $charold = $chars[$i];  
                                            }else{  
                                                    $charold++;  
                                            }  
                                            if($chars[$i] == $charold){  
                                                    $bad_pwd = '1';  
                                            }else{  
                                                    $bad_pwd = '0';  
                                                    break;  
                                            }  
                                    }  
                                    if($bad_pwd == '1') $error = '4';  
                              
                                    # Wenn String in absteigender Folge ist z.B. "4321", "dcba"  
                                    $flipchars = array_reverse($chars);  
                                    for($i = 0; $i < $length; $i++){  
                                            if(!isset($char)){  
                                                    $char = $flipchars[$i];  
                                            }else{  
                                                    $char++;  
                                            }  
                                            if($flipchars[$i] == $char){  
                                                    $bad_pwd = '1';  
                                            }else{  
                                                    $bad_pwd = '0';  
                                                    break;  
                                            }  
                                    }  
                                    if($bad_pwd == '1') $error = '5';  
                              
                              # Wenn String leer  
                              
                              if(empty($string)) $error = '6';  
                              
                                    # Wenn kein Fehler gefunden wurde  
                              
                                    if(!isset($error)) $error = '0';  
                              
                                    # Errorstatus zurück geben  
                                    return $error;  
                             }  
                            
                            

                            Ich hab auch so meine Mühe mit der Kommentierung, ich weiß immer nicht genau was ich schreiben soll. Nur eine Übersetzung von z.B. empty, if, else halte ich für sinnfrei.

                            Grüße, Matze