JavaScript Passwort Generator

Driver78

Lt. Junior Grade
Registriert
Feb. 2005
Beiträge
407
Hallo,

ich habe im Netz einen Passwort Generator gefunden, der das macht was er soll. Und ich weiß es gibt gefühlt eine Millionen kostenfreie....
Doch ich möchte meinen eigenen ;)

Leider habe ich absolut keine Ahnung von Javascript (steht auf der to-do Liste) und hoffe jemand von euch kann mir weiterhelfen. Innerhalb des Scripts kann nur ein eine definierte Nummer gewählt werden bzw. eine Special Characteristic was auch definiert ist. Ich fände es besser, wenn man die Option anhakt, dass aus einer Auswahl von Nummern oder Zeichen eines gewählt wird. Kann einer das von euch realisieren?

PHP:
<script>
      function generatePassword() {
          var wordlist = document.getElementById("wordlist").value.split(" ");

          var password = "";

          var num = document.getElementById("numwords").value;
          for (var i = 0; i < num; i++) {
              var word = wordlist[Math.floor(Math.random() * wordlist.length)];
              if (document.getElementById("upchar").checked)
                  word = word.charAt(0).toUpperCase() + word.slice(1);
              password += word;
              if (document.getElementById("spaces").checked)
                  password += " ";
          }
          if (document.getElementById("spchar").checked)
              password += "_";

          if (document.getElementById("number").checked)
              password += "0";

          document.getElementById("password").value = password;
      }

      generatePassword();
    </script>
 
PHP:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Online Passwortgenerator</title>
	    <link rel="stylesheet" href="../css/bulma.css">
    <link rel="stylesheet" href="../css/ch.css">
  </head>
  <body>
                <div class="column is-narrow">
            </div>
          </div>
        </div>
      </header>
    </section>


    <section class="section">
      <div class="container">
        <h1 class="title">Dein Correct-Horse-Password</h1>
        <h2 class="subtitle">Klicke auf den Button um ein neues zu erzeugen</h2>
        <hr>
        <div class="columns">
          <div class="column">
            <p class="control">
               <button class="button is-primary is-medium" onclick="generatePassword();">Neues erzeugen</button>
            </p>
            <p class="control">
              <input class="input is-medium is-success" type="text" placeholder="" id="password">
            </p>
          </div>
          <div class="column">
            <p>Das Passwort wird aus den folgenden Wörtern gebildet:</p>
			
            <p class="control">
             
			  <textarea class="textarea" placeholder="" id="wordlist" rows="10" cols="50">
			  
<?php
$file = file("../txt/4.txt", FILE_SKIP_EMPTY_LINES);
 foreach($file as $content) {
    echo"".$content."";
}
echo"</textarea>";
?></textarea>
            </p>
          </div>
        </div>
        <div class="columns">
          <div class="column">
            <label class="label">Anzahl Wörter</label>
            <p class="control">
              <input class="input" size="5" type="number" value="4" name="quantity" min="1" max="10" id="numwords" onchange="generatePassword();">
            </p>
            <p class="control">
              <label class="checkbox">
                <input type="checkbox" id="spaces" onchange="generatePassword();">
                Trenne Wörter mit Leerzeichen
              </label>
            </p>
          </div>
          <div class="column">
            Ich brauche:
            <p class="control">
              <label class="checkbox">
                <input type="checkbox" id="upchar" checked="checked" onchange="generatePassword();">
                Großbuchstaben
              </label>
            </p>
            <p class="control">
              <label class="checkbox">
                <input type="checkbox" id="number" onchange="generatePassword();">
                Mindestens eine Ziffer
              </label>
            </p>
            <p class="control">
              <label class="checkbox">
                <input type="checkbox" id="spchar" onchange="generatePassword();">
                Mindestens ein Sonderzeichen
              </label>
            </p>
          </div>
        </div>
      </div>
    </section>



    
    <script>
      function generatePassword() {
          var wordlist = document.getElementById("wordlist").value.split(" ");

          var password = "";

          var num = document.getElementById("numwords").value;
          for (var i = 0; i < num; i++) {
              var word = wordlist[Math.floor(Math.random() * wordlist.length)];
              if (document.getElementById("upchar").checked)
                  word = word.charAt(0).toUpperCase() + word.slice(1);
              password += word;
              if (document.getElementById("spaces").checked)
                  password += " ";
          }
          if (document.getElementById("spchar").checked)
              password += ":0)";

          if (document.getElementById("number").checked)
              password += "0";

          document.getElementById("password").value = password;
      }

      generatePassword();
    </script>


  </body>
</html>
 
Das haut vom Ansatz her nicht hin, denke ich.

Stattdessen müßtest Du eine Variable führen, wo drinsteht, was zulässige Zeichen sein sollen. Dann gibt's eine PW-Länge - entweder hardcodiert oder per Eingabefeld.

Dann kann aus der Liste mit den zulässigen Zeichen per floor() und random() mehr oder weniger gleichverteilt jeweils ein Zeichen ausgewählt werden und ans Ergebnis hintendrangehängt werden.

Du bräuchtest also für die einzelnen Optionen Substrings. Einen mit Kleinbuchstaben a-z. Einen mit entsprechenden Großbuchstaben. Einen mit Ziffern und einen mit Sonderzeichen. Ggf extra Substrings für Leerzeichen, wenn das kein Sonderzeichen sein soll.

Dann, onsubmit() sozusagen, müßte geschaut werden, was angehakt war, und die einzelnen Substrings (mit checked === true) zum Gesamt-Zeichensatz zusammengefügt werden. Optional könnte man schauen, diese Substrings und ggf den Zusammenbau nochmal zu randomisieren... ob das viel bringt, sei aber dahingestellt.

Obligatorisches Caveat: Hier geht's um Paßwörter; ob man sich auf Sicherheit derart generierter PWs verlassen kann, sei dahingestellt. Keine Gewehre.
 
Hi, danke für Deine Erläuterung, doch das überschreitet meinen Horizont. Ich wüsste (noch) nichts damit anzufangen.
Ich wäre sehr Dankbar, wenn jemand dieses Script entsprechend anpassen könnte.

Das halt statt eines festen und hinterlegten Symbol oder Zahl eine zufällige stattdessen genommen wird, wenn diese Option angewählt ist.

Bezüglich der Sicherheit der Passwörter, nun ja, es bleibt immer ein gewisses Restrisiko. Doch ich denke, durch die Einzigartige Auswahl, die Anzahl der Wörtern und den zufälligen Zahlen und Sonderzeichen sollte eine gewisse Sicherheit gewährleistet sein.
Bin auch keiner der ein Passwort für alles hat, glaube da liegt die größte Gefahr bei den meisten.
 
Du schreibst es gibt Millionen andere im Netz willst aber einen eigenen, den Dir jemand anders geschrieben hat. Sinn? Der ist doch dann wie jeder andere aus dem Netz auch, den Du nicht verstehst...
 
Nun, jemand der Ahnung davon hat ist vielleicht auch bereit es zu erläutern. Dadurch lernt man eben auch.
 
Erläutern gerne, aber implementieren? Das versteht man dann nicht. Besonders, wenn man die Implementation selbst nicht nachvollziehen kann.

Deshalb versuchen wir das als erstes von vorne, statt eine Implementierung rückwärts aufzurollen:

-1- Was will ich?
Einen PW-Generator.

-2- Genauer, bitte?
Ich möchte eine Möglichkeit haben, mit Eingabe einer Länge und Auswahl von verschiedenen Zeichenklassen eine zufällige Zeichenfolge generiert haben, welche so lang ist wie ich das angegeben hatte, welche aus Zeichen derjenigen Klassen zusammengesetzt ist, die ich vorher angehakt hatte.

-3- Wie stelle ich das an?
* Wir wollen etwas "zufällig" haben => Randomisier-Funktion.

* Wir wollen was mit Zeichen bzw Zeichenketten machen => Zeichen haben einen numerischen Code, in Unicode-Terminologie: Codepoint; mit Zahlwerten arbeitet es sich einfacher als mit Text. Außerdem wollen wir Zeichenklassen. Wir schauen also in die Unicode-Spezifikation, ob nicht vielleicht Zeichenklassen bereits irgendwie definiert sind, sodaß wir ohne weiteren Aufwand uns auf vordefinierte Konstanten beziehen können. Geht das nicht, erfreuen wir uns daran, daß in Zeichensätzen Zeichenklassen zusammenhängend aufgeführt sind, sodaß wir unsere Zeichenklassen als numerisches Intervall spezifizieren können. Beispiel: klein-A = 1; klein-Z = 26; beides stecken wir in zB ein Objekt (Array genügt) sodaß nun var lcase = array(1,26) entsteht. Dasselbe machen wir mit den anderen Zeichenklassen auch. Die Zeichentabelle hilft uns dabei, die Zuordnung Zahl-zu-Zeichen herzustellen. Unser Array erlaubt uns dann anhand einer Basis das richtige Zeichen auszuwählen (das nennt man dann Offset).

* Wir haben eine variable Länge der Ausgabezeichenfolge, die von nichts weiter abhängt als einem numerischen Zahlwert (der Länge) => FOR()-Schleife von 1 bis Länge; ggf 0 bis Länge-1, weil Scriptsprachen üblicherweise 0-basiert arbeiten. Außerdem müssen die Zeichen irgendwie zusammenhängend ausgegeben werden. Idealerweise machen wir das per interner Verkettung; Zeichen einzeln ausgeben ginge zwar auch, ist aber aufwendiger und unser Script genügt dann nicht der Anforderung, mit "createPassword(x)" eine Zeichenkette der Länge x zu generieren.
Für die Umsetzung haben wir mehrere Möglichkeiten: entweder wir bauen eine Zeichenkette innerhalb der Schleife zusammen oder aber wir basteln ein Array mit den Codepoints der Zeichen drin und konvertieren das erst zum Abschluß in eine Zeichenkette. Das ist dann Geschmackssache.


Die Implementierung oben hat das Problem, daß da drin alles zusammengewurschtelt wird, was zusammengewurschtelt werden konnte. Das macht es unübersichtlich und schwer nachzuvollziehen... und zu warten.

Man könnte das Ganze aufdröseln in seine Zuständigkeitsbereiche:
-1- Das HTML-Formular.
-2- Eine JScript-Funktion, welche die übergebenen Daten aus dem Formular holt und aufbereitet, sodaß also am Ende verwendbare Werte im richtigen Format vorliegen.
-3- Eine JScript-Funktion zur PW-Generierung, der Länge und - in zu überlegender Form -- Hinweise auf die Methodik zu übergeben sind -- und sei es nur als function createPw(int Länge, array akzeptableZeichen). Weitergehend kann man das natürlich noch einstampfen, daß zB nur eine numerische Konstante übergeben wird, aus der dann die zu verwendenden Zeichen abzuleiten sind. (Mindestens) Zwei Parameter sollten es aber bleiben.

Der Generator reduziert sich dann aufs Semantische und man versteht, was da passiert. Beispiel, nicht in JS:
Code:
function generatePW(int länge, array Zeichensatz)
{
string output = '';
int Zeichenzahl = Arraylänge(Zeichensatz) // Wieviele Zeichen stecken im Zeichensatz?
for i = 1 To länge
 {
 // Bestimme einen zufälligen Wert aus dem Intervall (0, Zeichenzahl) und berücksichtige dabei, daß wir Ganzzahlen brauchen -- floor() --- und daß wir auch das letzte Zeichen im Zeichensatz mitnehmen wollen, welches sonst wegen floor() eher nicht erreicht werden wird. 
// Dies unter der Annahme, daß random() eine gebrochene Zahl zurückliefert; für ganzzahlige Ergebnisse ist das nicht notwendig.

   int indexDesZeichens = floor(random(Zeichenzahl+1)) 

// Wir haben jetzt eine Zahl, die auf eines der Elemente aus dem Array Zeichensatz verweist. Welches? Keine Ahnung wegen random().

//  Dieses Zeichen anfügen ans Ergebnis.

output += Zeichensatz[indexdesZeichens]
 }

// ... zum Abschluß das Ganze ausgeben.

return output
}

Was bleibt ist neben der erwähnten Funktion zur Ermittlung der Formularfeldvariablen noch eine Funktion, welche aus eben jenen Formularfeldvariablen das Array Zeichensatz erstellt. Das kann man dann zB mit einem switch() abhandeln, nachdem man das Array zunächst leer definiert hat und dann, je nach Eingabeparametern, mit Zeichen aus den angehakten Zeichenklassen auffüllt.

"Theoretisch" kann man das dann natürlich auch in eine einzelne Funktion stopfen. Gründe dafür gibt es aber keine konkreten.
 
Zuletzt bearbeitet von einem Moderator:
@RalphS bitte nicht .random im Zusammenhang mit Sicherheit posten! Bitte sofort ausbessern, dass ist einfach bad practice und niemand sollte es lernen.

"Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the window.crypto.getRandomValues() method."

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
 
Er schreibt explizit, dass der Pseudocode nicht JS ist, und du erzählst ihm vom unsicheren Random in JS? ;)

Von dieser Spitze mal abgesehen hast du recht, dass es in manchen Programmiersprachen einen Unterschied macht, Java hat das gleiche Problem. Insofern bietet es sich an, bei Recherchen nach "cryptographically secure random number" zu suchen, nicht nur nach "random number".
 
Sorry, falls daß mißverständlich war. Ich hatte weiter oben (in #4) explizit darauf verwiesen, daß man sich auf solche PWs nicht zu verlassen hat - implizit, wie Du schreibst, daß man sich auf die Arbeit von Personen verlassen sollte, die auch Ahnung von sowas haben --- das war vielleicht etwas untergegangen.

#8 soll eher bildenden Charakter haben und einen Ansatz aufzeigen, wie man von "Problem" über "Umsetzung" zu "Lösung" kommen könnte, insbesondere ohne Spezifika anzusprechen. Deswegen reduziert sich an dieser Stelle "Zufallszahl" auf "random()": nicht wegen der Funktion random() selber, sondern deswegen, daß es für Realität X ein Abbild Y gibt, welches man nutzen kann.

*Welche* random()-Variante man am Ende hernimmt, ist dann kontextabhängig und wieder Teil der Implementierung.
"'Ich will Zufallszahl' ergibt sich zu 'nimm sha256()'"? Warum das denn? Warum nicht sha512() oder blowfish() oder schlachmichtothash5()? Nope - für Zufallswerte gibt es eine Funktion random(), gerne als Pseudofunktion zu verstehen, die alle möglichen Ausprägungen annehmen kann.


Und an dieser Stelle nochmal wiederholt: man kann einen PW-Generator gerne selber bauen als proof-of-concept -- andere bauen halt Taschenrechner in JScript. Nur den generierten Paßwörtern sollte man halt nur eingeschränkt vertrauen.
 
Erst einmal vielen Dank für die Diskussion, ich stehe dem sehr aufgeschlossen gegenüber. Auch wenn mir das nur bedingt weiterhilft.

Was mich an der Stelle interessieren würde, was macht denn die random() Funktion so unsicher? Ist es im Umkehrschluss möglich, ein Passwort zu errechnen, wenn man ein anderes aus der Berechnung nutzt?

Bezüglich meiner Intention, warum ich "meinen eigenen" Passwort Generator haben möchte, ist einfach das ich nicht "den einen" gefunden habe der mir zusagt. Und somit versuche ich mir einen zu basteln, komme aber halt nicht drumherum manche Sachen zu erfragen. Leider habe ich keinen im Bekanntenkreis der auf solche Fragen eine Antwort weiß. Somit wende ich mich an eine große Community mit Menschen, wo vielleicht der ein oder andere dabei ist, der Unterstützen kann. Das es Menschen gibt, die solche Vorhaben für "Albern" halten, interessieren mich dabei nicht sonderlich.
 
Ein Standardzufallsgenerator benutzt einen Startwert (Seed) um die Zufallszahlen zu erzeugen. Gleicher Seed bedeutet gleiche Zahlenfolgen. Der Seed ist oft Datum/Uhrzeit in Ticks oder so. Das ist besonders für die Kryptographie nachteilhaft. Für Deinen Passwortgenerator heißt das gleicher Seed=gleiche Passwörter, was aber relativ schwierig zu reproduzieren sein sollte. Generell ist so ein Zufallsgenerator aber für viele Fälle ausreichend und nicht teuer/rechenintensive.

Ein echter Zufallszahlengenerator benutzt einen zufälligen Seed aus einem analogen Zufallsignal oder berechnet den Zufallswert direkt anhand des Signals. Im einfachen Fall können das Tastaturanschlöge oder die Mausbewegung sein, wenn es ganz sicher und absolut zufällig sein soll, gibt es auch Spezialhardware die atomare Strahlung zB als Grundlage nimmt.

https://de.m.wikipedia.org/wiki/Zufallszahlengenerator
 
Zuletzt bearbeitet:
Zurück
Oben