Ich bin daran interessiert, einen sehr einfachen Zufallskennwortgenerator mit hoher (kryptografischer) Qualität zu erstellen. Gibt es einen besseren Weg, dies zu tun?
import os, random, string
length = 13
chars = string.ascii_letters + string.digits + '!@#$%^&*()'
random.seed = (os.urandom(1024))
print ''.join(random.choice(chars) for i in range(length))
random.seed
eine Methode nicht,random.seed = 'random_string'
zerstört sie also im Grunde genommen diese Methode und macht nichts? Meinst durandom.seed('random_string')
?os.urandom(1024)
ruft 1024 Bytes ab. Es scheint mir ein bisschen übertrieben. Vielleicht wäre das Seeding mit 16 oder 32 Bytes besser geeignet.Antworten:
Das Schwierige bei Passwörtern ist, sie stark genug zu machen und sich trotzdem an sie erinnern zu können. Wenn das Passwort nicht dazu gedacht ist, dass sich ein Mensch daran erinnert, ist es nicht wirklich ein Passwort.
Sie verwenden Pythons
os.urandom()
: das ist gut. Für jeden praktischen Zweck (sogar Kryptographie) ist die Ausgabe vonos.urandom()
nicht von wahrem Alea zu unterscheiden. Dann verwenden Sie es als Startwertrandom
, was weniger gut ist: Es handelt sich um ein nicht kryptografisches PRNG, und seine Ausgabe weist möglicherweise eine Struktur auf, die sich nicht in einem statistischen Messwerkzeug registriert, sondern von einem intelligenten Angreifer ausgenutzt wird. Sie sollten dieos.urandom()
ganze Zeit mit arbeiten. Um die Sache zu vereinfachen: Wählen Sie ein Alphabet mit der Länge 64, z. B. Buchstaben (Groß- und Kleinbuchstaben), Ziffern und zwei zusätzliche Satzzeichen (z. B. '+' und '/'). Holen Sie sich dann für jedes Kennwort ein Byte abos.urandom()
, reduzieren Sie den Wert modulo 64 (dies ist unverzerrt, da 64 256 teilt) und verwenden Sie das Ergebnis als Index in Ihremchars
Array.Mit einem Alphabet der Länge 64 erhalten Sie 6 Entropiebits pro Zeichen (weil 2 6 = 64). Mit 13 Zeichen erhalten Sie also 78 Entropiebits. Dies ist letztendlich nicht in allen Fällen stark, aber bereits sehr stark (es könnte mit einem Budget besiegt werden, das in Monaten und Milliarden von Dollar gezählt wird, nicht nur in Millionen).
quelle
os.urandom()
Typ zurückbytes
. Wie kann ich diesen Mod 64 reduzieren?chars[ord(os.urandom(1)) % len(chars)]
chars[]
Array, über das wir sprechen, die Länge 64 hat und 256 (die Anzahl der möglichen Werte für ein Byte) ein Vielfaches von 64 ist. Wenn Sie eine Array-Länge verwenden, die kein exakter Teiler von ist 256 dann wird die Auswahl verzerrt (einige der Zeichen sind wahrscheinlicher als andere).XKCD hat eine großartige Erklärung dafür, warum das, was Sie für sichere Passwörter halten, nicht der Fall ist .
Und wenn Sie die Mathematik hinter dem, was diese Abbildung erklärt , nicht verstehen , versuchen Sie nicht, etwas zu schreiben, das kryptografisch sicher sein sollte, da dies nicht der Fall ist. Legen Sie einfach die Maus hin und treten Sie von der Tastatur weg.
quelle
Vor zwei Tagen hat Kragen Javier Sitaker ein Programm dazu unter http://lists.canonical.org/pipermail/kragen-hacks/2011-September/000527.html veröffentlicht (jetzt weg - versuchen Sie es mit https://github.com / jesterpm / bin / blob / master / mkpasswd )
Generieren Sie ein zufälliges, einprägsames Passwort: http://xkcd.com/936/
Beispiellauf:
kragen bei unaufhaltsam: ~ / devel / unaufhaltsam-misc $ ./mkpass.py 5 12 Ihr Passwort lautet "Gelernte Schäden gerettet Wohnphasen". Das entspricht einem 60-Bit-Schlüssel.
Es würde 2,5e + 03 CPU-Jahre dauern, bis dieses Passwort auf meinem kostengünstigen Celeron E1200 aus dem Jahr 2008 geknackt ist, vorausgesetzt, es handelt sich um einen Offline-Angriff auf einen MS-Cache-Hash, der der schlechteste häufig verwendete Passwort-Hashing-Algorithmus ist, der etwas schlechter ist als selbst einfaches MD5.
Der heutzutage am häufigsten verwendete Passwort-Hashing-Algorithmus ist das iterierte MD5 von FreeBSD. Das Knacken eines solchen Hashs würde 5,2e + 06 CPU-Jahre dauern.
Aber eine moderne GPU kann ungefähr 250-mal so schnell knacken, so dass dieselbe iterierte MD5 in 2e + 04 GPU-Jahren fallen würde.
Die Ausführung dieser GPU im Jahr 2011 kostet ungefähr 1,45 US-Dollar pro Tag. Das Knacken des Passworts würde also ungefähr 3e + 09 US-Dollar kosten.
Ich habe angefangen, ein auf diese Weise generiertes Passwort anstelle eines 9-druckbaren ASCII-Zeichen-Zufallspassworts zu verwenden, das ebenso stark ist. Munroes Behauptung, dass diese Passwörter viel einfacher zu merken sind, ist richtig. Es gibt jedoch immer noch ein Problem: Da pro Zeichen viel weniger Entropiebits vorhanden sind (etwa 1,7 statt 6,6), ist das Kennwort sehr redundant, sodass Angriffe wie der ssh-Timing-Channel-Angriff (der Song, Angriffe von Wagner und Tian Herbivore, von denen ich vor Jahren in den frühen Morgenstunden von Bram Cohen im Bagdad Café erfahren habe, und Angriffe auf Audio-Tastaturaufzeichnungen haben eine viel bessere Chance, genügend Informationen zu erfassen, um das Passwort angreifbar zu machen.
Meine Gegenmaßnahme gegen den Herbivore-Angriff, der mit einem 9-stelligen Passwort gut funktioniert, aber mit meinem neuen Passwort äußerst ärgerlich ist, besteht darin, das Passwort mit einer Verzögerung von einer halben Sekunde zwischen den Zeichen einzugeben, damit der Timing-Kanal nicht viele Informationen über das enthält tatsächlich verwendete Zeichen. Darüber hinaus bietet die geringere Länge des 9-stelligen Passworts dem Herbivore-Ansatz von Natur aus viel weniger Informationen zum Kauen.
Andere mögliche Gegenmaßnahmen sind die Verwendung des Emacs-Shell-Modus, bei dem Sie lokal zur Eingabe des Kennworts aufgefordert werden, wenn eine Kennwortabfrage erkannt wird, das gesamte Kennwort auf einmal gesendet wird und das Kennwort von einer anderen Stelle kopiert und eingefügt wird.
Wie zu erwarten, dauert die Eingabe dieses Kennworts auch etwas länger: ca. 6 Sekunden statt ca. 3 Sekunden.
#!/usr/bin/python # -*- coding: utf-8 -*- import random, itertools, os, sys def main(argv): try: nwords = int(argv[1]) except IndexError: return usage(argv[0]) try: nbits = int(argv[2]) except IndexError: nbits = 11 filename = os.path.join(os.environ['HOME'], 'devel', 'wordlist') wordlist = read_file(filename, nbits) if len(wordlist) != 2**nbits: sys.stderr.write("%r contains only %d words, not %d.\n" % (filename, len(wordlist), 2**nbits)) return 2 display_password(generate_password(nwords, wordlist), nwords, nbits) return 0 def usage(argv0): p = sys.stderr.write p("Usage: %s nwords [nbits]\n" % argv0) p("Generates a password of nwords words, each with nbits bits\n") p("of entropy, choosing words from the first entries in\n") p("$HOME/devel/wordlist, which should be in the same format as\n") p("<http://canonical.org/~kragen/sw/wordlist>, which is a text file\n") p("with one word per line, preceded by its frequency, most frequent\n") p("words first.\n") p("\nRecommended:\n") p(" %s 5 12\n" % argv0) p(" %s 6\n" % argv0) return 1 def read_file(filename, nbits): return [line.split()[1] for line in itertools.islice(open(filename), 2**nbits)] def generate_password(nwords, wordlist): choice = random.SystemRandom().choice return ' '.join(choice(wordlist) for ii in range(nwords)) def display_password(password, nwords, nbits): print 'Your password is "%s".' % password entropy = nwords * nbits print "That's equivalent to a %d-bit key." % entropy print # My Celeron E1200 # (<http://ark.intel.com/products/34440/Intel-Celeron-Processor-E1200-(512K-Cache-1_60-GHz-800-MHz-FSB)>) # was released on January 20, 2008. Running it in 32-bit mode, # john --test (<http://www.openwall.com/john/>) reports that it # can do 7303000 MD5 operations per second, but I’m pretty sure # that’s a single-core number (I don’t think John is # multithreaded) on a dual-core processor. t = years(entropy, 7303000 * 2) print "That password would take %.2g CPU-years to crack" % t print "on my inexpensive Celeron E1200 from 2008," print "assuming an offline attack on a MS-Cache hash," print "which is the worst password hashing algorithm in common use," print "slightly worse than even simple MD5." print t = years(entropy, 3539 * 2) print "The most common password-hashing algorithm these days is FreeBSD’s" print "iterated MD5; cracking such a hash would take %.2g CPU-years." % t print # (As it happens, my own machines use Drepper’s SHA-2-based # hashing algorithm that was developed to replace the one # mentioned above; I am assuming that it’s at least as slow as the # MD5-crypt.) # <https://en.bitcoin.it/wiki/Mining_hardware_comparison> says a # Core 2 Duo U7600 can do 1.1 Mhash/s (of Bitcoin) at a 1.2GHz # clock with one thread. The Celeron in my machine that I # benchmarked is basically a Core 2 Duo with a smaller cache, so # I’m going to assume that it could probably do about 1.5Mhash/s. # All common password-hashing algorithms (the ones mentioned # above, the others implemented in John, and bcrypt, but not # scrypt) use very little memory and, I believe, should scale on # GPUs comparably to the SHA-256 used in Bitcoin. # The same mining-hardware comparison says a Radeon 5870 card can # do 393.46 Mhash/s for US$350. print "But a modern GPU can crack about 250 times as fast," print "so that same iterated MD5 would fall in %.1g GPU-years." % (t / 250) print # Suppose we depreciate the video card by Moore’s law, # i.e. halving in value every 18 months. That's a loss of about # 0.13% in value every day; at US$350, that’s about 44¢ per day, # or US$160 per GPU-year. If someone wanted your password as # quickly as possible, they could distribute the cracking job # across a network of millions of these cards. The cards # additionally use about 200 watts of power, which at 16¢/kWh # works out to 77¢ per day. If we assume an additional 20% # overhead, that’s US$1.45/day or US$529/GPU-year. cost_per_day = 1.45 cost_per_crack = cost_per_day * 365 * t print "That GPU costs about US$%.2f per day to run in 2011," % cost_per_day print "so cracking the password would cost about US$%.1g." % cost_per_crack def years(entropy, crypts_per_second): return float(2**entropy) / crypts_per_second / 86400 / 365.2422 if __name__ == '__main__': sys.exit(main(sys.argv))
quelle
generate_password()
(mitrandom.SystemRandom()
) ganz oben auf Ihre Antwort setzen? Es könnte LeutenImplementierung der @ Thomas Pornin-Lösung
import M2Crypto import string def random_password(length=10): chars = string.ascii_uppercase + string.digits + string.ascii_lowercase password = '' for i in range(length): password += chars[ord(M2Crypto.m2.rand_bytes(1)) % len(chars)] return password
quelle
% len(chars)
dieser Methode hat eine leichte Tendenz zu den ersten 8 Zeichen inchars
. Jeder dieser Buchstaben erscheint in 1,95% der Fälle, verglichen mit 1,56% bei den anderen Zeichen.Eine weitere Implementierung der XKCD-Methode:
#!/usr/bin/env python import random import re # apt-get install wbritish def randomWords(num, dictionary="/usr/share/dict/british-english"): r = random.SystemRandom() # i.e. preferably not pseudo-random f = open(dictionary, "r") count = 0 chosen = [] for i in range(num): chosen.append("") prog = re.compile("^[a-z]{5,9}$") # reasonable length, no proper nouns if(f): for word in f: if(prog.match(word)): for i in range(num): # generate all words in one pass thru file if(r.randint(0,count) == 0): chosen[i] = word.strip() count += 1 return(chosen) def genPassword(num=4): return(" ".join(randomWords(num))) if(__name__ == "__main__"): print genPassword()
Beispielausgabe:
quelle
Ich weiß, dass diese Frage bereits im Jahr 2011 gestellt wurde, aber für diejenigen, die jetzt im Jahr 2014 und darüber hinaus dazu kommen, muss ich eines sagen: Widerstehen Sie dem Drang, das Rad neu zu erfinden.
In diesen Situationen ist es am besten, nach Open-Source-Software zu suchen, z. B. Ihre Suche auf Github-Ergebnisse zu beschränken. Bei weitem das Beste, was ich gefunden habe:
https://github.com/redacted/XKCD-password-generator
quelle
Sie können dem Pseudozufallszahlengenerator von Python beim Generieren eines Passworts nicht vertrauen. Es ist nicht unbedingt kryptografisch zufällig. Sie setzen den Pseudozufallszahlengenerator ein, von
os.urandom
dem aus ein guter Anfang ist. Aber danach sind Sie auf Pythons Generator angewiesen.Eine bessere Wahl wäre die
random.SystemRandom()
Klasse, die Zufallszahlen aus derselben Quelle wie verwendeturandom
. Laut der Python-Dokumentation sollte dies für die kryptografische Verwendung ausreichend sein. DasSystemRandom
Klasse bietet Ihnen alles, was die Haupt-Zufallsklasse tut, aber Sie müssen sich keine Sorgen um die Pseudozufälligkeit machen.Beispielcode mit random.SystemRandom (für Python 3):
import random, string length = 13 chars = string.ascii_letters + string.digits + '!@#$%^&*()' rnd = random.SystemRandom() print(''.join(rnd.choice(chars) for i in range(length)))
Hinweis: Ihr Kilometerstand kann variieren. In der Python-Dokumentation heißt es, dass die Verfügbarkeit von random.SystemRandom je nach Betriebssystem unterschiedlich ist.
quelle
/dev/urandom
) gilt als kryptografisch sicher. Siehe security.stackexchange.com/questions/3936/… ./dev/urandom
) ist pseudozufällig, es sei denn, Sie haben spezielle Hardware.LavaRnd
).In Anbetracht Ihres Kommentars,
Anscheinend möchten Sie Ihr Programm zum Generieren von Passwörtern verwenden, anstatt es nur als Übung zu schreiben. Es ist vorzuziehen, eine vorhandene Implementierung zu verwenden, da die Ausgabe möglicherweise beeinträchtigt wird, wenn Sie einen Fehler machen. Lesen Sie mehr über Zufallszahlengenerator-Angriffe . Insbesondere ein bekannter RNG-Fehler in Debian enthüllte die privaten SSL-Schlüssel von Personen.
Erwägen Sie stattdessen die Verwendung
pwgen
. Es bietet verschiedene Optionen, die Sie auswählen sollten, je nachdem, wofür Sie die Kennwörter verwenden möchten.quelle
/dev/urando
&/dev/random
nicht von echten Zufällen zu unterscheiden (mit Ausnahme der ersten 10 Minuten oder so nach dem Systemstart)Zu Ihrer Information für alle, die im Jahr 2020+ auf diese Frage stoßen. Python 3.6+ verfügt über ein
secrets
Modul speziell für diesen Zweck:import secrets password_length = 13 print(secrets.token_urlsafe(password_length))
quelle
Es ist leicht :)
def codegenerator(): alphabet = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" pw_length = 8 mypw = "" for i in range(pw_length): next_index = random.randrange(len(alphabet)) mypw = mypw + alphabet[next_index] return mypw
und das tun:
print codegenerator()
Vielen Dank http://xkcd.com/936/
quelle
import random r = random.SystemRandom() def generate_password(words, top=2000, k=4, numbers=None, characters=None, first_upper=True): """Return a random password based on a sorted word list.""" elements = r.sample(words[:top], k) if numbers: elements.insert(r.randint(1, len(elements)), r.choice(numbers)) if characters: elements.insert(r.randint(1, len(elements)), r.choice(characters)) if first_upper: elements[0] = elements[0].title() return ''.join(elements) if __name__ == '__main__': with open('./google-10000-english-usa.txt') as f: words = [w.strip() for w in f] print(generate_password(words, numbers='0123456789', characters='!@#$%'))
os.urandom()
Sicher kann es verbessert werden, aber das ist was ich benutze.
quelle
Implenting @Thomas Pornin Lösung (kann @Yossi ungenaue Antwort nicht kommentieren):
import string, os chars = string.ascii_letters + string.digits + '+/' assert 256 % len(chars) == 0 # non-biased later modulo PWD_LEN = 16 print(''.join(chars[c % len(chars)] for c in os.urandom(PWD_LEN)))
AKTUALISIERT für Python3 dank Stephan Lukits
quelle
So funktioniert es. Es ist vollkommen in Ordnung. Wenn Sie zusätzliche Regeln hatten, z. B. das Ausschließen von Wörterbuchwörtern, möchten Sie möglicherweise auch diese Filter einschließen, aber die Wahrscheinlichkeit, mit diesem Setup zufällig ein Wörterbuchwort zu generieren, ist äußerst gering.
quelle
Es gibt einige Probleme mit Ihrer Implementierung:
random.seed = (os.urandom(1024))
Dadurch wird der Zufallszahlengenerator nicht gesetzt. Es ersetzt die
seed
Funktion durch einen Bytestring. Sie müssen anrufenseed
, wie ,random.seed(…)
.print ''.join(random.choice(chars) for i in range(length))
Pythons Standard-PRNG ist ein Mersenne Twister, bei dem es sich nicht um ein kryptografisch starkes PRNG handelt. Daher bin ich vorsichtig, es für kryptografische Zwecke zu verwenden. Das
random
Modul enthältrandom.SystemRandom
, die auf mindestens den meisten * nix-Systemen ein CSPRNG verwenden sollten. Allerdings ist… Wird implementiert als…
def choice(self, seq): """Choose a random element from a non-empty sequence.""" return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty
… In Python 2 . Leider gibt es
self.random
hier eine C-Funktion, so dass dies schwer zu erkennen ist. Der Code-Geruch hier ist, dass dieser Code mit ziemlicher Sicherheit nicht einheitlich wählt. Der Code hat sich in Python 3 vollständig geändert und sorgt viel besser für Einheitlichkeit. Die Python 3-Dokumente zurrandrange
Notiz,randrange
undchoice
beide rufen dieselbe Methode (_randbelow
) unter der Haube auf.In Python 3
choice
ist in Ordnung; in Python 2, kommt es nur nahe zu einer gleichmäßigen Verteilung, sie aber nicht garantieren. Da es sich um Krypto handelt, lehne ich mich an die Seite des Zauns, auf der ich kein Risiko eingehen möchte, und möchte diese Garantie haben.quelle
Ich habe meine eigene CLI-Antwort auf das jeweilige Thema erstellt (vollständiger Quellcode unter der folgenden URL):
http://0netenv.blogspot.com/2016/08/password-generator-with-argparse.html
Schrieb einen Passwortgenerator mit argparse. Hoffe, das hilft jemandem (entweder beim Erstellen eines Passwortgenerators oder beim Verwenden von Argparse)!
Auf jeden Fall hat es Spaß gemacht zu bauen!
$ ./pwgen.py -h usage: pwgen.py [-h] [-c COUNT] [-a] [-l] [-n] [-s] [-u] [-p] Create a random password Special characters, numbers, UPPERCASE -"Oscar", and lowercase -"lima" to avoid confusion. Default options (no arguments): -c 16 -a Enjoy! --0[email protected] optional arguments: -h, --help show this help message and exit -c COUNT, --count COUNT password length -a, --all same as -l -n -s -u -l, --lower include lowercase characters -n, --number include 0-9 -s, --special include special characters -u, --upper include uppercase characters -p, --license print license and exit
Hier ist der Code:
#!/usr/bin/env python2 # -*- coding: utf-8 -*- license = """ # pwgen -- the pseudo-random password generator # # This software is distributed under the MIT license. # # The MIT License (MIT) # # Copyright (c) 2016 0NetEnv [email protected] # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated # documentation files (the "Software"), to deal in the # Software without restriction, including without # limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies # of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice # shall be included in all copies or substantial portions # of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF # ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED # TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT # SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR # IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # # NOTE: # This software was tested on Slackware 14.2, Raspbian, & # Mac OS X 10.11 # """ import string import random import sys # first time using argparse library import argparse # wanted to change the formatting of the help menu a little bit, so used RawTextHelpFormatter directly from argparse import RawTextHelpFormatter typo = '' c = 16 counter = 0 line = '-' * 40 # CREATE FUNCTION for PWGEN def pwgen(z, t): # EMPTY SET OF CHARACTERS charsset = '' # UPPERCASE -"O" U = 'ABCDEFGHIJKLMNPQRSTUVWXYZ' # lowercase -"l" L = 'abcdefghijkmnopqrstuvwxyz' N = '0123456789' S = '!@#$%^&*?<>' # make sure we're using an integer, not a char/string z = int(z) for type in t: if 'u' in t: charsset = charsset + U if 'l' in t: charsset = charsset + L if 'n' in t: charsset = charsset + N if 's' in t: charsset = charsset + S if 'a' == t: charsset = charsset + U + L + N + S return ''.join(random.choice(charsset) for _ in range(0, int(z))) # GET ARGUMENTS using ARGPARSE parser = argparse.ArgumentParser(description='\n Create a random password\n\ Special characters, numbers, UPPERCASE -"Oscar",\n\ and lowercase -"lima" to avoid confusion.\n\ Default options (no arguments): -c 16 -a\n\ \t\tEnjoy! [email protected]', formatter_class=argparse.RawTextHelpFormatter) parser.add_argument("-c", "--count", dest="count", action="store", help="password length") parser.add_argument("-a", "--all", help="same as -l -n -s -u", action="store_true") parser.add_argument("-l", "--lower", help="include lowercase characters", action="store_true") parser.add_argument("-n", "--number", help="include 0-9", action="store_true") parser.add_argument("-s", "--special", help="include special characters", action="store_true") parser.add_argument("-u", "--upper", help="include uppercase characters", action="store_true") parser.add_argument("-p", "--license", help="print license and exit", action="store_true") # COLLECT ARGPARSE RESULTS results = args = parser.parse_args() # CHECK RESULTS # Check that a length was given. # If not, gripe and exit. if args.count == '0': print ("Input error:\nCannot create a zero length password.\nExiting") exit (0) # check character results and add to counter if # selection is made. if args.lower: typo = typo + 'l' counter = counter + 1 #print "lower" if args.number: typo = typo + 'n' counter = counter + 1 #print "number" if args.special: typo = typo + 's' counter = counter + 1 #print "special" if args.upper: typo = typo + 'u' counter = counter + 1 #print "upper" if args.all: typo = 'a' counter = counter + 1 #print "all" if args.license: print (license) exit (1) # CHECK COUNTER # Check our counter and see if we used any command line # options. We don't want to error out. # try it gracefully. If no arguments are given, # use defaults and tell the user. # args.count comes from argparse and by default requires # an input to '-c'. We want to get around that for the # sake of convenience. # Without further adieu, here's our if statement: if args.count: if counter == 0: typo = 'a' print ("defaulting to '--all'") print (line) print (pwgen(results.count,typo)) else: if counter == 0: typo = 'a' print ("defaulting to '--count 16 --all'") print (line) print (pwgen(c,typo)) print (line) #print typo
quelle
Mit Base64 können wir Binärdaten in einem vom Menschen lesbaren / beschreibbaren Modus ohne Datenverlust codieren.
import os random_bytes=os.urandom(12) secret=random_bytes.encode("base64")
quelle
Ich liebe Linguistik. In meinem Ansatz erschaffe ich unvergessliche Pseudowörter mit einem hohen Grad an Entropie, indem ich Konsonanten und Vokale abwechsle.
Python-Code:
import random import string def make_pseudo_word(syllables=5, add_number=False): """Create decent memorable passwords. Alternate random consonants & vowels """ rnd = random.SystemRandom() s = string.ascii_lowercase vowels = 'aeiou' consonants = ''.join([x for x in s if x not in vowels]) pwd = ''.join([rnd.choice(consonants) + rnd.choice(vowels) for x in range(syllables)]).title() if add_number: pwd += str(rnd.choice(range(10))) return pwd >>> make_pseudo_word(syllables=5) 'Bidedatuci' >>> make_pseudo_word(syllables=5) 'Fobumehura' >>> make_pseudo_word(syllables=5) 'Seganiwasi' >>> make_pseudo_word(syllables=4) 'Dokibiqa' >>> make_pseudo_word(syllables=4) 'Lapoxuho' >>> make_pseudo_word(syllables=4) 'Qodepira' >>> make_pseudo_word(syllables=3) 'Minavo' >>> make_pseudo_word(syllables=3) 'Fiqone' >>> make_pseudo_word(syllables=3) 'Wiwohi'
Nachteile:
quelle
Hier ist eine andere Implementierung (Python 2; würde einige kleinere Umschreibungen erfordern, damit es in 3 funktioniert), die viel schneller ist als die von OJW, die das Wörterbuch für jedes Wort zu durchlaufen scheint, trotz des gegenteiligen Kommentars / der gegenteiligen Implikation. Timing des OJW-Skripts auf meinem Computer mit einer 80.000-IOP-SSD:
real 0m3.264s user 0m1.768s sys 0m1.444s
Das folgende Skript lädt das gesamte Wörterbuch in eine Liste und wählt dann Wörter basierend auf einer zufälligen Auswahl des Indexwerts aus, wobei der reguläre Ausdruck von OJW zum Filtern verwendet wird.
Dies generiert auch 10 Passphrasensätze, ermöglicht das Übergeben von Befehlszeilenparametern zum Anpassen der Anzahl von Wörtern und fügt das Auffüllen von Zahlen und Symbolen hinzu (ebenfalls einstellbare Länge).
Beispielzeiten für dieses Skript:
real 0m0.289s user 0m0.176s sys 0m0.108s
Verwendung: xkcdpass-mod.py 2 4 (zum Beispiel; dies sind die Standardwerte).
Es druckt Leerzeichen in der Ausgabe, um das Lesen zu erleichtern, obwohl ich fast nie auf einen Onlinedienst gestoßen bin, der die Verwendung dieser Leerzeichen zulässt, sodass ich sie einfach ignorieren würde. Dies könnte definitiv mit argparse oder getopt bereinigt werden und Schalter zum Einschließen von Leerzeichen oder nicht, einschließlich / ohne Symbole, Großbuchstaben usw., sowie einige zusätzliche Umgestaltungen zulassen, aber ich bin noch nicht dazu gekommen. Also ohne weiteres:
#!/usr/bin/env python #Copyright AMH, 2013; dedicated to public domain. import os, re, sys, random from sys import argv def getargs(): if len(argv) == 3: numwords = argv[1] numpads = argv[2] return(numwords, numpads) elif len(argv) == 2: numwords = argv[1] numpads = 4 return (numwords, numpads) else: numwords = 2 numpads = 4 return (numwords, numpads) def dicopen(dictionary="/usr/share/dict/american-english"): f = open(dictionary, "r") dic = f.readlines() return dic def genPassword(numwords, numpads): r = random.SystemRandom() pads = '0123456789!@#$%^&*()' padding = [] words = dicopen() wordlist = [] for i in range (0,int(numpads)): padding.append(pads[r.randint(0,len(pads)-1)]) #initialize counter for only adding filtered words to passphrase j = 0 while (j < int(numwords)): inclusion_criteria = re.compile('^[a-z]{5,10}$') #Select a random number, then pull the word at that index value, rather than looping through the dictionary for each word current_word = words[r.randint(0,len(words)-1)].strip() #Only append matching words if inclusion_criteria.match(current_word): wordlist.append(current_word) j += 1 else: #Ignore non-matching words pass return(" ".join(wordlist)+' '+''.join(padding)) if(__name__ == "__main__"): for i in range (1,11): print "item "+str(i)+"\n"+genPassword(getargs()[0], getargs()[1])
Beispielausgabe:
[✗]─[user@machine]─[~/bin] └──╼ xkcdpass-mod.py item 1 digress basketball )%^) item 2 graves giant &118 item 3 impelled maniacs ^@%1
Und für die volle "richtige Pferdebatterie-Heftklammer" (CHBS), keine Polsterung:
┌─[user@machine]─[~/bin] └──╼ xkcdpass-mod.py 4 0 item 1 superseded warred nighthawk rotary item 2 idealize chirruping gabbing vegan item 3 wriggling contestant hiccoughs instanced
Laut https://www.grc.com/haystack.htm würde es für alle praktischen Zwecke unter der Annahme von 100 Billionen Vermutungen pro Sekunde (dh 100 TH / s) etwa 50-60 Millionen Jahrhunderte dauern, bis die Crack-Version geknackt ist. das volle CHBS = 1,24 hundert Billionen Billionen Jahrhunderte; Hinzu kommen 15,51 Billionen Billionen Billionen Jahrhunderte.
Selbst wenn das gesamte Bitcoin-Mining-Netzwerk (~ 2500 TH / s zum Zeitpunkt dieses Schreibens) in Anspruch genommen wird, würde es wahrscheinlich noch 250 bis 300 Millionen Jahre dauern, bis die Kurzversion funktioniert, was für die meisten Zwecke wahrscheinlich sicher genug ist.
quelle
import uuid print('Your new password is: {0}').format(uuid.uuid4())
quelle
Ein bisschen abseits des Themas, aber ich habe das gemacht, auch mit TKinter. Hoffe es kann helfen:
import os, random, string from tkinter import * def createPwd(): try: length = int(e1.get()) except ValueError: return chars = string.ascii_letters + string.digits + '!@#$%^&*()?\/' random.seed = (os.urandom(1024)) e2.config(state=NORMAL) e2.delete(0,'end') e2.insert(0,''.join(random.choice(chars) for i in range(length))) e2.config(state="readonly") mainWindow = Tk() mainWindow.title('Password generator') mainWindow.resizable(0,0) f0 = Frame(mainWindow) f0.pack(side=TOP,pady=5,padx=5,fill=X,expand=1) Label(f0,text="Length: ",anchor=E).grid(row=0,column=0,sticky=E) e1 = Entry(f0) e1.insert(0,'12') e1.grid(row=0,column=1) btn = Button(f0,text="Generate") btn['command'] = lambda: createPwd() btn.grid(row=0,column=2,rowspan=1,padx=10,ipadx=10) Label(f0,text="Generated password: ",anchor=E).grid(row=1,column=0,sticky=E) e2 = Entry(f0) e2.grid(row=1,column=1) createPwd() #starting main window mainWindow.mainloop()
quelle
Dies ist ein einfaches kleines Programm, das sich an Personen richtet, die keine sicheren Passwörter für ihre eigenen öffentlichen Konten finden können.
Führen Sie das Programm einfach auf einer Befehlskonsole aus und geben Sie eine Reihe von Buchstaben ein, die Ihnen bekannt vorkommen. Auf der Grundlage Ihrer Eingabe wird eine Folge von Symbolen generiert.
Natürlich unterstützt das Programm die Generierung mehrerer Sequenzen nicht.
Sie können den Code von meinem Github Pull herunterladen: https://github.com/abdechahidely/python_password_generator
from string import ascii_lowercase, ascii_uppercase, digits, punctuation from random import randint, choice, shuffle from math import ceil from re import finditer lower_cases = ascii_lowercase upper_cases = ascii_uppercase lower_upper = dict(zip(lower_cases, upper_cases)) upper_lower = dict(zip(upper_cases, lower_cases)) punctuations = '#$%&@!?.' space = ' ' class PunctOrDigit(): def __init__(self, number_of_punctuations, number_of_digits): self.puncts = number_of_punctuations self.digits = number_of_digits self.dupl_puncts = self.puncts self.dupl_digits = self.digits def PorD(self): symbol_type = choice('pd') if symbol_type == 'p': if self.puncts == 0: return 'd' else: self.puncts -= 1 return symbol_type if symbol_type == 'd': if self.digits == 0: return 'p' else: self.digits -= 1 return symbol_type def reset(self): self.puncts = self.dupl_puncts self.digits = self.dupl_digits def is_empty(text): for symbol in text: if symbol != space: return False return True def contain_unauthorized_symbols(text): for symbol in text: if symbol in punctuation or symbol in digits: return True return False def user_input(): user_input = input('-- Sentence to transform: ') while is_empty(user_input) or len(user_input) < 8 or contain_unauthorized_symbols(user_input): user_input = input('-- Sentence to transform: ') return user_input def number_of_punctuations(text): return ceil(len(text) / 2) - 3 def number_of_digits(text): return ceil(len(text) / 2) - 2 def total_symbols(text): return (number_of_digits(text) + number_of_punctuations(text), number_of_punctuations(text), number_of_digits(text)) def positions_to_change(text): pos_objct = PunctOrDigit(number_of_punctuations(text), number_of_digits(text)) positions = {} while len(positions) < total_symbols(text)[0]: i = randint(0,len(text)-1) while i in positions: i = randint(0,len(text)-1) positions[i] = pos_objct.PorD() pos_objct.reset() return positions def random_switch(letter): if letter in lower_cases: switch_or_pass = choice('sp') if switch_or_pass == 's': return lower_upper[letter] else: return letter if letter in upper_cases: switch_or_pass = choice('sp') if switch_or_pass == 's': return upper_lower[letter] else: return letter def repeated(text): reps = {} for letter in set(list(text)): indexs = [w.start() for w in finditer(letter, text)] if letter != ' ': if len(indexs) != 1: reps[letter] = indexs return reps def not_repeated(text): reps = {} for letter in set(list(text)): indexs = [w.start() for w in finditer(letter, text)] if letter != ' ': if len(indexs) == 1: reps[letter] = indexs return reps def generator(text, positions_to_change): rep = repeated(text) not_rep = not_repeated(text) text = list(text) for x in text: x_pos = text.index(x) if x not in positions_to_change: text[x_pos] = random_switch(x) for x in rep: for pos in rep[x]: if pos in positions_to_change: if positions_to_change[pos] == 'p': shuffle(list(punctuations)) text[pos] = choice(punctuations) if positions_to_change[pos] == 'd': shuffle(list(digits)) text[pos] = choice(digits) for x in not_rep: for pos in not_rep[x]: if pos in positions_to_change: if positions_to_change[pos] == 'p': shuffle(list(punctuations)) text[pos] = choice(punctuations) if positions_to_change[pos] == 'd': shuffle(list(digits)) text[pos] = choice(digits) text = ''.join(text) return text if __name__ == '__main__': x = user_input() print(generator(x, positions_to_change(x)))
quelle
Hier ist mein Zufallspasswortgenerator, nachdem ich dieses Thema untersucht habe:
`import os, random, string #Generate Random Password UPP = random.SystemRandom().choice(string.ascii_uppercase) LOW1 = random.SystemRandom().choice(string.ascii_lowercase) LOW2 = random.SystemRandom().choice(string.ascii_lowercase) LOW3 = random.SystemRandom().choice(string.ascii_lowercase) DIG1 = random.SystemRandom().choice(string.digits) DIG2 = random.SystemRandom().choice(string.digits) DIG3 = random.SystemRandom().choice(string.digits) SPEC = random.SystemRandom().choice('!@#$%^&*()') PWD = None PWD = UPP + LOW1 + LOW2 + LOW3 + DIG1 + DIG2 + DIG3 + SPEC PWD = ''.join(random.sample(PWD,len(PWD))) print(PWD)`
Dadurch wird ein zufälliges Passwort mit 1 zufälligen Großbuchstaben, 3 zufälligen Kleinbuchstaben, 3 zufälligen Ziffern und 1 zufälligen Sonderzeichen generiert - dies kann nach Bedarf angepasst werden. Dann kombiniert es jedes zufällige Zeichen und erstellt eine zufällige Reihenfolge. Ich weiß nicht, ob dies als "hohe Qualität" angesehen wird, aber es erledigt die Arbeit.
quelle
Meine Lösung basiert auf der Antwort von @Thomas Pornin (aktualisiert)
import os, string def get_pass(password_len=12): new_password=None symbols='+!' chars=string.ascii_lowercase+\ string.ascii_uppercase+\ string.digits+\ symbols while new_password is None or \ new_password[0] in string.digits or \ new_password[0] in symbols: new_password=''.join([chars[ord(os.urandom(1)) % len(chars)] \ for i in range(password_len)]) return new_password print(get_pass())
Diese Funktion gibt ein zufälliges Passwort zurück (ohne eine Zahl oder ein Symbol am Anfang des Passworts).
quelle
chars
Listenlänge 69 Zeichen und nicht 64 beträgt. Die Zeichen vor 'A' werden nur etwa 75% so oft angezeigt wie die anderen. Siehe stattdessen die Antwort von @foudfou. Außerdem funktioniert es überhaupt nicht ganz: Die letzte Zeile sollte seinprint(get_pass())
Ich habe erst kürzlich angefangen, Python zu lernen, und das habe ich heute geschrieben. Hoffe das hilft.
import random characters = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^()}{/<>' print('Password Length: ') passwordLength = int(input()) password = '' for i in range(passwordLength): password += random.choice(characters) print(password)
quelle
""" This code below in any shape or form is owned by A.S Gallery This code is the asnwer for Password Generator quiz - CodeHs This code works 100% Have fun exploring !!! """ # Imports import random import time print "Hi !!!" password_output = "this is your new password : " ask_name = input("Enter your Name : ") greetings_name = "Hi "+ str(ask_name) + "!!! " print greetings_name print "Now we will make your new password using the ULTIMATE password generator !!!" time.sleep(8) print "Our password generator will give you multiple choices, you can choose any password generator you want !!! " time.sleep(8) print "You can choose if you want a strong password or a weak password !! (strong recommended) " time.sleep(8) print "You can also make your own password, to make your own password type own !!! " time.sleep(8) print "If you want to choose strong type strong, if weak then type weak !!! " time.sleep(8) # Example: # Returns random number within and including 0 and 10. def strong_password(): user_input = int(input("Enter a number : ")) print type(user_input) time.sleep(3) # calculate_input = user_input * user_input calculate_types = input("Do you want to add, multiply or mod the numbers : ") time.sleep(3) if calculate_types == "add": calculate_input = user_input + user_input elif calculate_types == "multiply" : calculate_input = user_input * user_input elif calculate_types == "mod": calculate_input = user_input & user_input else: print "Check your spelling and try again :( " # Random element in a string time.sleep(4) want_symbols = input("Do you want symbols ?(Y/N) : ") time.sleep(4) random_element = random.choice('abcdefg345') if want_symbols == "Y": random_element2 = random.choice('@#()@*($*(@)(*^()*()(#$)*@#)*((@*()@*#)(*)@*($*(%#*)#(*@@_!_()(') elif want_symbols == "N": random_element2 = random.choice('29371294203712492703740182903820498201381204AKSJFKSHEHJKFJAODL') random_element3 = random.choice('abcdefghiiasudasdjsiasdhwudagsjdgaskdjsafgjasj') random_element4 = random.choice('abcdefghijsdhjaskdhkasjdhakdjhaskdasjdhakjsd') random_element5 = random.choice('abcdefghijsdhsakjdhsajdldasjdasdjasldas') random_elements6 = random.choice('129389230928308290382109830293943827492347') random_elements7 = random.choice('2473285473q9mdnuwyr8KSDJKDSJKL932uc3487389473289479h3289wjdi94802w') random_elements8 = random.choice('AKDJKAJDKJIKJDUIFHSJHUFRUDIJFDKLDJKDJLJFKLJKLDJLDJKLDJLDJLSKJDKLJDLJDKSLJD') time.sleep(8) print str(ask_name) + " " + str(password_output) + str(calculate_input) + str(random_element) + str(random_element2) + str(random_element3) + str(random_element4) + str(random_element5) + str(random_elements6) + str(random_elements7) + str(random_elements8) def weak_password(): user_input = int(input("Enter a number : ")) print type(user_input) time.sleep(3) # calculate_input = user_input * user_input calculate_types = input("Do you want to add, multiply or mod the numbers : ") time.sleep(3) if calculate_types == "add": calculate_input = user_input + user_input elif calculate_types == "multiply" : calculate_input = user_input * user_input elif calculate_types == "mod": calculate_input = user_input & user_input else: time.sleep(3) print "Check your spelling and try again :( " # Random element in a string random_ness = random.choice("ABCDEFGHI*(#*#$()#*$)(E)(UWIJEDSH(*#U$()UDSLKH)UW*)$(*&#*(YE(*DY#*YUHSLDF:LKDDSDK") my_tuple = (calculate_input, random_ness, user_input, ask_name) new_tuple = my_tuple[1] new_tuple1 = my_tuple[2] new_tuple2 = my_tuple[3] time.sleep(7) print str(ask_name) + str(password_output) + str(new_tuple) + str(new_tuple1) + str(new_tuple2) def own_password(): my_list = [] ask_times = int(input("How many characters do you want ? (between 1 - 8) : ")) time.sleep(10) if ask_times > 8: print "Invalid Request" elif ask_times < 1: print "Invalid Request" else: time.sleep(2) print "You CANNOT include symbols or numbers in this option !!! " for i in range(ask_times): user_ask = input("Enter the character: ") time.sleep(0.6) my_list.append(user_ask) own_password = "".join(map(str,my_list)) time.sleep(4) print "Your own password is : " + own_password strong_pass = input("Do you want a strong password or a weak one or make your own password !! ? : ") if strong_pass == "strong": strong_password() elif strong_pass == "weak": weak_password() elif strong_pass == "own": own_password() else : print "Invalid Request" time.sleep(3) print "Congrats, on creating your best password !!! I belived you used strong password generator because its the BEST !!" time.sleep(7) print "If not, no problem just restart the program and type strong when prompted !!! " time.sleep(6) print "Have a nice day !"
Dieser Code ist auch die Antwort für das CodeHs-Quiz (falls vorhanden) !!!
quelle
Ja, kein Amateur-Hacker wird dieses Passwort knacken. Danach empfehle ich, mit Ihrem Projekt zur Generierung zufälliger Kennwörter fortzufahren und eine Benutzeroberfläche oder GUI-Schnittstelle entweder mit Tkinter oder Flask zu erstellen, damit andere sie verwenden können. Zum Beispiel fand ich dieses nette kleine Projekt nur durch die Suche nach 'Passwortgenerator Python UI'. https://passwordgenerator.pythonanywhere.com/
Vielleicht möchten Sie etwas Ähnliches wie oben machen? Es ist eine gute Fähigkeit zu wissen, wie man Python in die Webentwicklung implementiert.
Viel Glück.
Entspann dich
quelle
Das ist mehr zum Spaß als alles andere. In passwordmeter.com positiv bewertet, aber nicht zu merken.
#!/usr/bin/ruby puts (33..126).map{|x| ('a'..'z').include?(x.chr.downcase) ? (0..9).to_a.shuffle[0].to_s + x.chr : x.chr}.uniq.shuffle[0..41].join[0..41]
quelle