Wohlklingende Passwörter

Da ich derzeit an einer kompletten Neuentwicklung für eine Community-Software sitze, stehe ich unter anderem vor dem Problem, dem Benutzer neue Passwörter vorzuschlagen bzw. auch automatisch neue Passwörter generieren zu lassen. Diese Passwörter sollten natürlich sicher sein. Doch was ist dazu zu beachten?

Generell sollte man natürlich darauf achten, dass das Passwort nicht mit Hilfe eines Wörterbuchs herausfindbar ist. Durch solche Passwörter ist es Hackern ein Leichtes, schnell an das nötige Passwort zu kommen. Beispiele für solche sehr schlechten Passwörter sind “MeinNameIstHans” oder “SicheresPasswort1”.
Sollte ein Wörterbuch nicht mehr beim Hacken ausreichen, wird ein BruteForce-Algorithmus angewendet, der praktisch mit roher Gewalt alle möglichen Buchstaben und Wortkombinationen ausprobiert, um ans Ziel zu kommen. Dass diese Methode nicht abwegig ist, zeigt der Artikel Password Recovery Speed: so kann ein 9-stelliges Passwort, das nur aus Zahlen besteht, auf einem Pentium-100 in 28 Stunden geknackt werden. Auf heutigen Rechnern dürfte sich dann nicht mal das Anschalten der Kaffeemaschine lohnen. Erst bei der Verwendung des vollen Alphabets (groß und klein) sowie von Zahlen und Sonderzeichen ergibt sich ein Passwort, das ab einer gewissen Mindestlänge auch auf leistungsstarken Rechnern aufwendig zu knacken ist und damit relativ sicher sein sollte.

Das Problem an diesen Passwörtern ist aber: wer kann sie sich merken? Es gibt sicherlich Software, welche die Passwörter für mich speichert (darunter zähle ich jetzt auch einfach mal die bekannten Haftnotizen, die viele Bildschirme veredeln). Dies macht die Sache aber nicht sicherer.

Eine Lösung stellen mnemonische Verfahren dar (siehe Mnemonik), die versuchen, Passwörter derart zu generieren, dass sie aussprechbar sind. Und ein solches versuchte ich nun zu implementieren. Da ich den Code für recht hilfreich finde, veröffentliche ich ihn hier:

function createRandomPassword() {
 $vokale = "aeiouy";
 $konsonanten = "bcdfghjklmnprstvwxz";
 $special = '!#$%&*+-/< =>?@^_~';
 $password = "";
 //zufällige Länge zwischen 4 und 10 Zeichen festlegen
 $sizeCharacter = mt_rand(3,7);
 for($i = 1; $i &lt;= $sizeCharacter; $i++) {
   $passwort .= substr($konsonanten,
   mt_rand(0, strlen($konsonanten)-1), 1);
   $passwort .= substr($vokale, mt_rand(0, strlen($vokale)-1), 1);
 }
 //zufälliges Sonderzeichen einfügen
 $passwort .= substr($special, mt_rand(0, strlen($special)-1), 1);
 //Zufällige Anzahl an Zahlen einfügen
 $sizeNumbers = mt_rand(1,3);
 for($i = 1; $i &lt;= $sizeNumbers; $i++) {
   $passwort .= mt_rand(0,9);
 }
 return $passwort;
}

Diese Funktion erzeugt Passwörter mit mindestens 6 Zeichen, maximal 14 Zeichen. Zur einfachen Aussprache wechselt sie zufällig Vokale (inkl. y!) und Konsonanten aus. Erzeugte Passwörter sehen z.B. so aus:

  • givubyru@956
  • wasurityzujasy!39
  • jumexa@13
  • hutydorufanuwy#44
  • zidacy%4
  • hafiby!35
  • fadujudimy%52
  • wykigy%263
  • feweda@202

Sicher nicht jedes perfekt, aber meiner Meinung nach schon recht gut. Anderer Meinung? Verbesserungsvorschläge?

[Update]
Mit den Vorschlägen von Martin (siehe Kommentare) hab ich die Funktion jetzt etwas angepasst. Sie kann jetzt auch Großbuchstaben (hatte ich in der ersten Funktion komplett vergessen). Dabei wird berücksichtigt, dass zuviele Großbuchstaben schwer zu merken sind und dass dies noch einfacher fällt, wenn die Großbuchstaben nur Konsonanten sind.

function st_createRandomPassword($minpairs = 2, $maxpairs = 5,
                          $minnumbers = 1, $maxnumbers = 3){
 $vowels  = "aeiou";
 $consonants = "bcdfghjklmnprstvwxz";
 $specialchars = '!#$%&*+-/< =>?@^_~';
 $password = "";

 $pairs = mt_rand($minpairs, $maxpairs);
 $lenv = strlen($vowels)-1;
 $lenc = strlen($consonants)-1;

 $usedBig = false; //Großbuchstabe bereits eingefügt wurde
 for($i = 1; $i < = $pairs; $i++) {
  $password .= $vowels[mt_rand(0, $lenv)];
   if (mt_rand(0,1)==0 && !$usedBig) {
    $password .= strtoupper($consonants[mt_rand(0, $lenc)]);
    if (mt_rand(0,1)==0) $usedBig=true;
   } else {
    $password .= $consonants[mt_rand(0, $lenc)];
   }
 }
 //zufälliges Sonderzeichen einfügen
 $password .= $specialchars[mt_rand(0, strlen($specialchars)-1)];
 //Zufällige Anzahl an Zahlen einfügen
 $sizeNumbers = mt_rand($minnumbers, $maxnumbers);
 for($i = 1; $i <= $sizeNumbers; $i++) {
  $password .= mt_rand(0,9);
 }
 return $password;
}

[Update 2]
In aktuellen PHP-Versionen scheint die eckige-Klammmer-Variante nicht mehr zu gehen. Deshalb hier die korrigierte Version:

function st_createRandomPassword($minpairs = 2, $maxpairs = 5,
                          $minnumbers = 1, $maxnumbers = 3){
 $vowels  = "aeiou";
 $consonants = "bcdfghjklmnprstvwxz";
 $specialchars = '!#$%&*+-/< =>?@^_~';
 $password = "";

 $pairs = mt_rand($minpairs, $maxpairs);
 $lenv = strlen($vowels)-1;
 $lenc = strlen($consonants)-1;

 $usedBig = false; //Großbuchstabe bereits eingefügt wurde
 for($i = 1; $i < = $pairs; $i++) {
  $password .= $vowels{mt_rand(0, $lenv)};
   if (mt_rand(0,1)==0 && !$usedBig) {
    $password .= strtoupper($consonants{mt_rand(0, $lenc)});
    if (mt_rand(0,1)==0) $usedBig=true;
   } else {
    $password .= $consonants{mt_rand(0, $lenc)};
   }
 }
 //zufälliges Sonderzeichen einfügen
 $password .= $specialchars{mt_rand(0, strlen($specialchars)-1)};
 //Zufällige Anzahl an Zahlen einfügen
 $sizeNumbers = mt_rand($minnumbers, $maxnumbers);
 for($i = 1; $i <= $sizeNumbers; $i++) {
  $password .= mt_rand(0,9);
 }
 return $password;
}

Erzeugte Passwörter:

  • oWatus^885
  • aToDosop@03
  • iWiwatur+48
  • eNiguTad!7
  • adalowiLuv-350
  • ajoW=3
  • uSapen%61
  • ozaDokaLes=417
  • iNesebav%456
  • oKaPogoz>5

19 Gedanken zu „Wohlklingende Passwörter

  1. Hier meine Abwandlung mit leichten Verbesserungen (Anzahlen als Parameter, einheitliche Sprache, nur einmalige Aufrufe von strlen(), Vereinfachung von substr(), ‘ statt “):

    
    < ?php
    function createMnemonicPassword($minpairs = 3, $maxpairs = 7, $minnumbers = 1, $maxnumbers = 3) {
        $vowels = 'aeiouy';
        $consonants = 'bcdfghjklmnprstvwxz';
        $specialchars = '!#$%&*+-/=<>?@^_~';
        $password = '';
        //zufällige Länge festlegen
        $pairs = mt_rand($minpairs, $maxpairs);
        for($i = 1, $lenv = strlen($vowels), $lenc = strlen($consonants); $i < = $length; $i++) {
            $password .= vowels[mt_rand(0, $lenv)]; // in älteren PHP-Versionen geschweifte statt eckige Klammern benutzen
            $password .= consonants[mt_rand(0, $lenc)];
        }
        //zufälliges Sonderzeichen einfügen
        $passwort .= $specialchars[mt_rand(0, strlen($specialchars))];
        //Zufällige Anzahl an Zahlen einfügen
        $numbers = mt_rand($minnumbers, $maxnumbers);
        for($i = 1; $i <= $sizeNumbers; $i++) {
            $passwort .= mt_rand(0,9);
        }
        return $password;
    }
    ?>
    
  2. Ja genau, $pairs wäre richtig. Hab’s nicht getestet 😉
    Und von strlen() muss auch noch eins abgezogen werden, die erste Schleife müsste also etwa so aussehen:

    for($i = 1, $maxv = strlen($vowels) - 1, $maxc = strlen($consonants) - 1; $i <= $length; $i++) {
    $password .= vowels[mt_rand(0, $maxv)]; // in älteren PHP-Versionen geschweifte statt eckige Klammern benutzen
    $password .= consonants[mt_rand(0, $maxc)];
    }

    Eine Kommentarvorschau wäre nicht verkehrt.

  3. Ja, das Typecasting kann oft zu unerwarteten Ergebnissen führen. Halte ich hier aber für unproblematisch, da mt_rand() ganz sicher eine Zahl zurückgibt. Wenn ich auf Gleichheit prüfe, dann mach ich das eigentlich auch immer mit ===, das geht auch schneller. Also würde ich das zumindest in ===0 ändern.

    Und hier mal ein paar üble Beispiele für das Typecasting 😉 (Man beachte, es werden Strings mit Strings verglichen, ich käme nie auf die Idee, da ein Typecasting zu machen, ist aber offenbar so gewollt, wie man nach einer Recherche auf bugs.php.net feststellen muss.)

    var_dump('01'=='1',
    '01' == '1.0',
    '11111111111111111' == '11111111111111112',
    '1E1' == '010');

  4. Servus,

    wie ich schon geschrieben habe, die Fehlermeldung lautet:

    Parse error: parse error, unexpected ‘[‘ in C:\Tools\xampp\htdocs\pass3.php on line 15

    Ich denke das das an der eckigen Klammer liegt. Denn in dieser Zeile ist die Schleife:

    for($i = 1, $lenv = strlen($vowels), $lenc = strlen($consonants); $i

  5. Und das Ganze dann nochmal auf das wesentliche reduziert, dann wird es auch ein schöner kleiner Schnipsel (ausschneiden und sammeln!) 😉 :

    
    function createPassword($size=0) {
      if ($size<6) $size=6;
      $letters = ceil($size/2)+mt_rand(1,floor($size/2))-1;
      $password = '';
      while(strlen($password) < $letters) {
          $vowel = substr('aeiouy', mt_rand(0,5), 1);
          $consonant = substr('bcdfghjklmnprstvwxz', mt_rand(0,18), 1);
          $password.= (mt_rand(0,3)<3)?$vowel:strtoupper($vowel);
          if (strlen($password) < $letters)
             $password.= (mt_rand(0,3)<3)?$consonant:strtoupper($consonant);
      }
      while(strlen($password) < $size)
          $password.= mt_rand(0,9);
      return $password;
    }
    

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.