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.
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
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
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
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))