XKCD Passwort Generator


34

Einführung

Offensichtlich hat diese Frage gebeten worden , hier und es leider geschlossen. Ich fand es eine gute Idee, es noch einmal zu versuchen, aber richtig gemacht.

XKCD untersucht, wie wir darin geschult sind, "schwer zu merkende Passwörter" zu verwenden. Wir sind der Meinung, dass dies sicher ist, aber stattdessen würde ein Computer 3 Tage brauchen , um zu knacken. Auf der anderen Seite bringt das Erinnern von 4-5 Wörtern Kuan Password Intropy und ist leicht zu merken. Verrückt, wie das funktioniert?

Herausforderung

Der Job heute ist es, 5 Passwörter mit Worten zu erstellen. 4 Wörter pro Passwort und mindestens 4 Buchstaben pro Wort, jedoch kein Maximum. Kuans Passwort-Intropy muss für jedes Passwort berechnet werden, es wird jedoch kein erzwungenes Minimum festgelegt.

Was ist Kuans Passwort-Intropy?

Laut Kuan ist die Kennwort-Eingabe in Kuan ein Maß dafür, wie unvorhersehbar ein Kennwort ist. Es ist eine einfache Rechnung: E = log 2 (R) * L . E ist Kuans Password Intropy, R steht für den Bereich der verfügbaren Zeichen und L für die Kennwortlänge.

Der Bereich der verfügbaren Zeichen ist selbsterklärend. Es ist der Bereich von Zeichen, den ein Passwort haben kann, in diesem Fall Groß- und Kleinschreibung. Da das Alphabet 26 Zeichen enthält, sind 26 x 2 = 52 Zeichen im gesamten Bereich des Kennworts.

Die Passwortlänge ist auch selbsterklärend. Dies ist die Gesamtlänge des Kennworts nach der Erstellung.

Einschränkungen

  • Keine Eingabe.
  • Ein Wort kann nicht im selben Kennwort erneut angezeigt werden.
  • In einem Passwort sind keine Symbole oder Zahlen zulässig.
  • 4 Wörter pro Passwort, jedoch mindestens 4 Buchstaben pro Wort.
  • Keine Leerzeichen zwischen Wörtern.
  • Sie können nicht immer und immer wieder dasselbe Passwort generieren.
  • Jedes Wort muss in einem Passwort groß geschrieben werden.
  • Die Ausgabe muss für Menschen lesbar sein und einen Abstand zueinander haben. Muss auch Kuans Password Intropy des Passworts mit einbeziehen, indem die obige Password Intropy-Gleichung von Kuan verwendet wird.
  • Wörterbuch . Sie müssen diese verwenden, als Textdatei herunterladen und entsprechend integrieren. Dies ist die Liste, aus der Sie Wörter abrufen. Ihr Code sollte als verfügbar gelten.
  • Das ist , der Gewinn mit den kürzesten Bytes.

Ausgabe

TriedScarProgressPopulation 153.9
TryingPastOnesPutting 119.7
YearnGasesDeerGiven 108.3
DoubtFeetSomebodyCreature 142.5
LiquidSureDreamCatch 114.0

16
Warum variiert die Kennwortentropie in den Testfällen ? Alle 4-Wort-Passwörter, die aus demselben Wörterbuch generiert wurden, sollten dieselbe Entropie haben.
NonlinearFruit

20
Die Kennwortentropie ist vom Symbolsatz abhängig. Wenn Ihr Kennwort aus NSymbolen aus dem Satz besteht S, lautet die Kennwortentropie log2(|S|)*N. Hier entspricht die Größe des Symbolsatzes der Größe des Wörterbuchs ( |S|=4284) und die Anzahl der Symbole der Anzahl der Wörter ( N=4), sodass die Entropie für jedes Kennwort gleich ist 48.3.
NonlinearFruit

48
Diese Definition von Entropie ist gefährlich falsch! Wenn jedes Zeichen einheitlich zufällig aus einer Menge der Größe R ausgewählt wird, hat ein Passwort der Länge L tatsächlich R ^ L-Möglichkeiten, daher ist die Entropie das log davon: log & sub2; (R ^ L) = log & sub2; (R) * L Welches ist Ihre Formel. Wenn Kennwörter jedoch zufällig aus einem anderen Satz ausgewählt werden (z. B. haben Sie nie ein Kennwort wie 3t1ta#asd), ist die Entropie der Logarithmus der Anzahl der möglichen Kennwörter. Wenn Sie in einem Wörterbuch mit 4284 Wörtern immer 4 Wörter nach dem Zufallsprinzip auswählen, gibt es 4284 ^ 4 Kennwörter mit jeweils einem Entropielog₂ (4284) * 4 ≈ 48.26.
ShreevatsaR

5
Diese Art von Passwörtern geht dem XKCD-Comic voraus. Sie werden "Diceware" -Passwörter genannt.
user2428118

5
Abgesehen von der Ausgabe von Wörtern mit weniger Entropie als zufälligen Zeichen erfordert Ihre Frage, dass die Wörter groß geschrieben werden, was bedeutet, dass der Fall festgelegt ist und nicht für die Entropie gezählt werden kann.
Niet the Dark Absol

Antworten:


13

Python 2, 102 101 97 91 Bytes

from random import*
exec"x=''.join(x.title()for x in sample(f,4));print(x,57*len(x)/10);"*5

Nimmt das Wörterbuch als Liste mit dem Namen an f.

Kann getestet werden, indem die Datei gespeichert dict.txtund aufgerufen wird

f = open('dict.txt').readlines()

Python-Listen haben keine Shuffle-Methode, und Sie können in Python 2 zwei Bytes speichern, indem Sie die Klammern entfernen exec( execist ein Schlüsselwort in Python 2).
Konrad Borowski

@ xfix Ja, das sollte es sein shuffle(f);.
Jonathan Allan

Whoops, das so
schnell wie möglich zu

4
Sie können meinen Trick anwenden, um festzustellen, dass die Rundung bei 5,7 auf 1 Dezimalstelle in Ordnung ist, solange keine Gleitkommafehler eingeführt werden, und mit 5 Bytes sparen 57*len(x)/10.. Speichern Sie ein weiteres Byte, indem Sie die Klammern entfernen, damit der Ausdruck ein Tupel aufnimmt. Hier ist eine gekürzte Version: TIO
Jonathan Allan

Verwenden Sie sample(f,4)anstelle von shuffle. Auch fkann nur sein open('dict.txt').read().split('\n'), open('dict.txt').readlines()oder einfach nur open('dict.txt')(ich weiß es nicht golfed ist aber immer noch).
Alex Hall

10

PowerShell (3.0+), 77 Byte

1..5|%{($p=-join($d|random -c 4|%{culture|% te*|% tot* $_}));57*$p.Length/10}

Probieren Sie es online!

Mit Jonathan Allan ‚s 57*len/10Trick.

$denthält das Wörterbuch als Array von Wörtern. Wenn Sie zu Hause spielen und füllen möchten $d:

$d=-split(irm pastebin.com/raw/eMRSQ4u2)

Verwenden einer Golfversion von (Get-Culture).TextInfo.ToTitleCase(), um den ersten Buchstaben in Großbuchstaben zu schreiben ; Ich glaube nicht, dass es einen kürzeren Weg gibt, dies in PowerShell zu tun.

Der Rest ist ziemlich einfach, denke ich.

Der TIO-Link enthält das gesamte Wörterbuch. den Cache deaktivieren und verrückt werden!


Kann mich jemand auf eine Referenz für "Jonathan Allans 57 * len / 10 Trick" verweisen?
James Curran

@JamesCurran Hier finden Sie die Aufschlüsselung seiner Antwort sowie seinen Kommentar zu dieser Antwort .
Briantist

Dies wird in 2.0 nicht korrekt funktionieren. Das sollte im Titel vermerkt werden. Ich denke auch, dass Sie einlesen müssen, um $ddavon auszugehen, dass es in der Umgebung vorhanden ist. (gc d)| random..Dabei ist das Wörterbuch eine Datei mit dem Namen d im selben Verzeichnis.
Matt

1
@Matt auf SO Ich bin vielleicht sehr bemüht, mit v2 eine Antwort zu erstellen (oder mache 2 Versionen), aber das ist Code Golf Man! Je arkaner
desto

1
Ich versuche nur, Bytes in meinen Antworttiteln zu speichern.
Matt

7

Jelly , 22 Bytes

Ẋḣ4ŒtFµL×57÷⁵⁸,K
çЀ5Y

Ein monadischer Link, der eine Liste von Zeichen aufnimmt, das analysierte Wörterbuch (wie im Chat erlaubt ).

Probieren Sie es online! (Klicken Sie auf "Argumente", um das Wörterbuch auszublenden und den Bildlauf zu reduzieren.)

Wie?

Da das Wörterbuch nur gültige Wörter enthält (nur 4Zeichen oder mehr [a-z]), muss diese Bedingung nicht überprüft werden.

Da alle Wörter im Wörterbuch Längen in [4-8]den möglichen Passwortlängen haben [16,32], werden die möglichen Entropien niemals anders auf eine Dezimalstelle gerundet als durch Ersetzen log(52,2)durch 5.7. Das einzige Problem ist , dass ein Gleitkommawert der Verwendung 5.7wird Gleitkomma geben Fehler für Längen Rundung 18, 26und 31. Das Multiplizieren mit 57und anschließendes Dividieren 10mit ×57÷⁵vermeidet dies jedoch (obwohl es immer noch ein Byte kürzer ist als das Drucken des vollständigen Gleitkomma-Genauigkeitswerts mit ×52l2¤).

çЀ5Y - Main link: list of list of characters (the parsed dictionary)
   5  - literal 5
 Ѐ   - map across the implicit range [1,2,3,4,5]:
ç     -   last link (1) as a dyad
    Y - join with newlines
      - implicit print

Ẋḣ4ŒtFµL×57÷⁵⁸,K - Link 1, get password and entropy: list of lists of characters, number
Ẋ                - shuffle the list of lists (shuffle all the words)
 ḣ4              - head to 4 (the first four words)
   Œt            - title case (make the first letter of each uppercase)
     F           - flatten into one list of characters
      µ          - monadic chain separation, call that p
       L         - length of p
         57      - 57
        ×        - multiply
            ⁵    - 10
           ÷     - divide -> entropy to 1 decimal place
             ⁸   - link's left argument, p
              ,  - pair -> [p, entropy]
               K - join with (a) space(s)

5

Ruby, 89 83 Bytes

d.select!{|w|w[3]}
5.times{p w=d.sample(4).map(&:capitalize)*'',5.700439718*w.size}

Es wird davon ausgegangen, dass die Kennwörter in der Variablen gespeichert sind d. Sie können diese Zeile vor dem Code einfügen:

d=$<.map(&:chomp)

und rufen Sie das Skript zum Beispiel so auf:

$ ruby generate_passwords.rb < dictionary_file.txt

Beispielausgabe:

"MarginStarvedOnusInsulted"
142.51099295
"KitchenMiseryLurkJoints"
131.110113514
"InducesNotablePitfallsPrecede"
165.312751822
"FarmersAbortFutileWrapper"
142.51099295
"RoutesBishopGlowFaithful"
136.81055323200002

KücheMiseryLurkJoints ... wow.


-6 Bytes von Ajedi32


1
Vielleicht in der Lage , ein paar Bytes durch Entfernen zu sparen shuffle!und das Ersetzen popmit sample.
Ajedi32

@ Ajedi32 Oh, du hast recht! Eigentlich habe ich darüber nachgedacht, aber ich hatte diese Regel falsch verstanden A word cannot reappear in the same password, weil ich dachte, es bedeute keine Wiederverwendung von Wörtern über alle Passwörter hinweg. Danke :)
daniero

4

Mathematica, 178 Bytes

t=1;l=Length;While[t<6,s=RandomChoice[Import["https://pastebin.com/raw/eMRSQ4u2"],4];c=Capitalize/@s;f=Flatten@Characters[c];Print[StringJoin[c]," ",Log[2,l@Union@f]*l@f//N];t++]

Probieren Sie es online aus

Kopieren und Einfügen mit Strg-V und drücken Sie UMSCHALT + EINGABETASTE, um auszuführen


Mathematica, 136 Bytes

Angenommen, m ist das Wörterbuch, in dem sich der Code befindet

m=ImportString[Import["C:\a.txt"]]

.

t=1;l=Length;While[t<6,s=RandomChoice[m,4];c=Capitalize/@s;f=Flatten@Characters[c];Print[StringJoin[c]," ",Log[2,l@Union@f]*l@f//N];t++]

"Der Job heute ist es, 5 Passwörter mit Worten zu erstellen." Benötigen Sie 5 anstelle von einem.
KuanHulio

ok ... 5 Passwörter .. behoben ..
J42161217

Warum haben Sie das Wörterbuch nicht lokal verfügbar gemacht, um den Code zu verkürzen, indem Sie den Hyperlink-Text vermieden haben?
Sergiol

um es für Sie einfach zu testen ...
J42161217

Es ist am besten, einen einfachen Helfercode ohne Golf zu verwenden, um das Testen zu vereinfachen, als Ihre Vorlage weniger zu bearbeiten, damit sie in sich geschlossen ist. Außerdem sollte das Wörterbuch variabel sein, ohne den lokalen DNS-Server zu überfallen (oder die hostsDatei zu ändern ).
wizzwizz4

4

Bash ,66 65 Bytes

for w in `shuf -n4 -`;{((l+=${#w}));printf ${w^};};bc<<<$l*5.7004

Probieren Sie es online!

Das Wörterbuch wird von STDIN erhalten. Mischt alle Wörter im Wörterbuch und gibt zuerst 4 aus.

Addiert für jedes Wort seine Länge in var l und gibt das großgeschriebene Wort wieder. Am Ende ruft bc, um die Rechnung zu machen.

Awk-Lösung, 112 Bytes, vier Passwörter:

shuf -n16 -|xargs -n4|awk '{for(i=1;i<5;i++)printf toupper(substr($i,1,1))substr($i,2);print(length($0)-3)*5.7}'

3

(Dies ist eine Adaption der Antwort von Martmists, aber ich habe nicht den Repräsentanten, um einen Kommentar abzugeben.)

Python 88 86 Bytes

g={*f}
exec('x="".join(g.pop().title()for i in "a"*4);print(x,len(x)*5.700439718);'*5)

Indem Sie ausnutzen, wie nicht setdeterministisch ist, müssen Sie keine Zufallsbibliotheken importieren.


Dies erzeugt für mich immer die gleiche Ausgabe. Wenn es bei einer Implementierung funktioniert, können Sie auf diese Weise einige Bytes einsparen set(f).pop().
Jonathan Allan

1
Ich denke nicht, dass das wirklich gültig ist. Es ist nicht deterministisch, daher kann nicht garantiert werden, dass dasselbe Kennwort erstellt wird, in der Praxis werden jedoch selten unterschiedliche Ergebnisse erzielt.
DJMcMayhem

Ich hatte den Verdacht, dass dies von der Implementierung abhängt. Ich habe es auf einer frisch installierten Windows-Version von Anaconda Python 3 gemacht, und es hat funktioniert. Funktioniert set(f).pop()aber nicht, ich habe es versucht. Es gibt jedes Mal das gleiche Ergebnis.
25.

„In der Praxis wird es selten unterschiedliche Ergebnisse erzeugen“ - es für mich scheint, hier ist ein Beispiel: pastebin.com/raw/ZHiHgzxV
dain

@dain Ich bin neugierig. Bitte geben Sie Informationen zu Ihrem Python-Build an.
wizzwizz4


3

JavaScript (ES6), 164 Byte

d=>{for(i=5;i--;)console.log(p="....".replace(/./g,_=>(w=d.splice(Math.random()*d.length|0,1)[0])[0].toUpperCase()+w.slice(1)),(Math.log2(52)*p.length).toFixed(1))}

Angenommen, das Wörterbuch wird als Array an die Funktion übergeben.

Testschnipsel


2

Mathematica, 71 Bytes

Angenommen, das Wörterbuch ist bereits in ein Array namens geladen d.

Table[{#,Log[2,52]StringLength[#]}&[""<>Capitalize@d~RandomSample~4],5]

Erklärung:

                                        Capitalize@d                    - Capitalize all the dictionary
                                                    ~RandomSample~4     - make an array with 4 values. By default values can not repeat.
                                    ""<>                                - Concatenate with empty string to turn array into single string.
      {#,Log[2,52]StringLength[#]}&[                               ]    - Put current string next to log(2,52) times length of current string
Table[                                                              ,5] - Repeat this 5 times.

Was ist mit der Entropiezahl ?!
Jonathan Allan

Hoppla, ich habe das ein bisschen verpasst. Aktualisiert.
Ian Miller

2

ColdFusion 216 Bytes

p={};z=arrayLen(c);for(x=0;x<5;x++){pw="";r={};while(structCount(r)<4){n=RandRange(1,z);r.append({"#c[n]#":true});}for(w in structKeyList(r)){pw&=REReplace(w,"\b(\w)","\u\1","All");};p.append({"#pw#":57*len(pw)/10})}

Dies funktioniert in ColdFusion 11+ und Lucee 4.5+

So führen Sie es aus: https://trycf.com/gist/ff14e2b27d66f28ff69ab90365361b12/acf11?theme=monokai

Der TryCF-Link hat weniger Golf-Charakter, aber den gleichen Code.

Ich hatte nicht wirklich damit gerechnet, eine konkurrenzfähige Golfantwort zu haben. Ich wollte nur sehen, was erforderlich ist, um diese Herausforderung in ColdFusion abzuschließen. Zumal in diesen Antworten nicht viel CF steckt. :-) Nach dem Setup war es überraschend kürzer als ich erwartet hatte.

Mein erster Versuch war etwas kürzer, bis ich mich daran erinnerte, dass dasselbe Wort nur einmal verwendet werden kann. Auch wenn es sehr unwahrscheinlich ist, dass der Zufallsgenerator denselben Index mehr als einmal auswählt, werden die Indizes in die Schlüssel einer Struktur geschrieben, wodurch eine Duplizierung verhindert wird. Dann benutze ich diese Liste von Schlüsseln, um meine endgültige Passwort-Zeichenfolge zu erstellen. Ich habe auch den mathematischen Trick benutzt, um die Entropie zu finden.


2

PHP , 136 129 Bytes

-7 Bytes, danke Jörg

for(shuffle($a);$i++<5;){for($s='',$c=0;$c<4;)strlen($w=$a[$k++])<4?:$s.=ucfirst($w).!++$c;echo$s.' '.log(52, 2)*strlen($s)."
";}

Probieren Sie es online!


@ JörgHülsermann Das scheint zu funktionieren, danke.
ME

2

Python 3, 252 Bytes

Dies ist meine erste Code Golf Challenge, die ich gemacht habe! Ich weiß, dass es hier andere Python-Antworten gibt (die wahrscheinlich besser sind als meine), aber das sah lustig aus, und deshalb wollte ich es trotzdem versuchen. Hier ist die Golfversion:

import random, math
with open("d") as f: d=f.read()
l=d.split()
for a in range(5):
 u=[]
 p=""
 for b in range(4):
  w=random.choice([w for w in l if not w in u and len(w)>=4])
  u.append(w)
  w=w.title()
  p+=w
 print("%s %s"%(p,math.log2(52)*len(p)))

Ich würde es online ausprobieren! Link, aber das unterstützt nicht mehrere Dateien. Hier ist also ein Link zu repl.it: https://repl.it/InIl/0

Hier ist auch die ungolfed Version:

import random
import math
with open("d") as f:
    dictionary = f.read() #this is the dictionary text file, simply saved as "d" as to use as few bytes as possible
words = dictionary.split() #here we turn that dictionary string into a list
for a in range(5): #here we iterate through 5 passwords
    used_words = []
    password = ""
    for b in range(4): #here we iterate through the 4 words in each password
        word = ""
        word = random.choice([word for word in words if not word in used_words and len(word) >= 4]) #Thanks to blackadder1337 from #python on freenode IRC for helping me with this.
        used_words.append(word)
        word = word.title()
        password = password + word
    print("%s %s"%(password, math.log2(52) * len(password)))

Wie ich schon sagte, dies ist mein erstes Mal Code Gofling, also bin ich sicher, dass dies viel verbessert werden könnte.


Willkommen bei PPCG!
Taylor Scott

2

tcl, 137

Sicher kein Gewinner, aber ich denke, es kann ein bisschen mehr golfen werden.

time {set p "";time {set p [string totitle [lindex $d [expr int(rand()*[llength $d])]]]$p} 4;puts $p\ [expr 5.7004*[string length $p]]} 5

demo - Der Zweck von Zeile 1 besteht nur darin, den Wörterbuchinhalt in die Variable einzufügend


Sie könnten wahrscheinlich Golf spielen, da das Passwort 4 Wörter anstelle von 5 erfordert.
KuanHulio

Und Sie fragten nach 5 Passwörtern anstelle von 4. LOL! Ich stimmte nicht mit den Zahlen überein!
Sergiol

Hahaha! @sergiol
KuanHulio

Fest! @KuanHulio
sergiol

Das ist besser. Gute Arbeit.
KuanHulio

0

Vim, 87 Tastenanschläge

qq:r!echo "$RANDOM"l<CR>D:w o|e w<CR>@"ev4bd:w|bp<CR>p0~wX~wX~wX~Y:.!wc -c<CR>A*5.7003<Esc>:.!bc<CR>PJq4@q

Angenommen, das Wörterbuch befindet sich in einer Datei mit dem Namen w. Verwendet immer 4 aufeinanderfolgende Wörter.

Erläuterung:

qq                       Start recording a macro named 'q'
:r!echo "$RANDOM"l<CR>   Append the result of the shell command `echo "$RANDOM"l`
D                        Delete what you just appended
:w o|                    Save the buffer to the file 'o' and ..
e w<CR>                  Open the file 'w'
@"                       Execute the text we deleted as a normal-mode command
                         This will move the cursor a random number of characters
                         to the right
e                        Go to the end of the next word
v4bd                     Delete 4 words backwards
:w|                      Save the file and ..
bp<CR>                   Open the last buffer (the 'o' file)
p                        Paste the 4 words we deleted
0                        Move the cursor to the beginning of the line
~wX~wX~wX~               Remove the spaces between the words and capitalize
Y                        Copy current line
:.!wc -c<CR>             Pipe the current line through 'wc -c'
A*5.7003<Esc>            Append "*5.7003" to the end of the line
:.!bc<CR>                Pipe the current line through 'bc'
P                        Paste the password above the current line
J                        Join with line bellow
q                        Stop recording the 'q' macro
4@q                      Run the 'q' macro 4 times

0

q / kdb + 76 74 65 56 Bytes

Lösung:

{(x;5.70044*(#)x)}(,/)@[;0;upper]each -4?" "vs(*)(0:)`:w

Beispiel:

q){(x;5.70044*(#)x)}(,/)@[;0;upper]each -4?" "vs(*)(0:)`:w
"RulingOverheadSaddensPriest"
153.9119

Erläuterung:

Lesen Sie die Wortliste ein, teilen Sie sie mit "" auf, wählen Sie 4 zufällige Wörter aus dieser Liste aus, schreiben Sie den ersten Buchstaben jedes Wortes in Großbuchstaben und fügen Sie sie dann zusammen. Geben Sie dies in eine Lambda-Funktion ein, die das Passwort und die berechnete 'Entropie' zurückgibt:

                                                     `:w / the wordlist is a file called 'w'
                                                 (0:)    / read in the file list (\n separated list)
                                              (*)        / take first (and only) item in the list
                                         " "vs           / split this on " "
                                      -4?                / take 4 random items from this list, neg means 'dont put back'
                      @[; ;     ]                        / apply a function to variable at indices (variable is implicit)
                           upper                         / uppercase (the function being applied)
                         0                               / index 0, the first character
                                 each                    / each of the 4 random items
                  (,/)                                   / 'raze' (flatten lists)
{                }                                       / anonymous lambda function
 (x;            )                                        / a 2-item list, x is first item
            (#)x                                         / count x, return the length of the list
    5.70044*                                             / multiply by 5.70044

Anmerkungen:

Ich gab nach und benutzte 5.70044 anstatt 2 xlog 52 xexp...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.