# HG changeset patch # User Bernhard Reiter # Date 1516261473 -3600 # Node ID 200c2c3c5f671b1ad252bcf8c74e8c3a4dc3d88c # Parent 8b2f8f4398179b55bf146b4a79b96e6880136bb9 Adds comfort. * Adds options ** '--just-passphrase': to get a passphrase on one line for use in skripts. ** '--number-of-words': the passphrase shall consists of * Refactors to implement the options and preparing for future developments: ** Warnings will be written to stderr and tained will bail out with sys.exit(). ** The output_string is build before printing. diff -r 8b2f8f439817 -r 200c2c3c5f67 ppgen.py --- a/ppgen.py Tue Feb 21 14:14:08 2017 +0100 +++ b/ppgen.py Thu Jan 18 08:44:33 2018 +0100 @@ -21,7 +21,7 @@ https://bitbucket.org/s_l_teichmann/ppgen -Copyright 2016, 2017 by Intevation GmbH. +Copyright 2016, 2017, 2018 by Intevation GmbH. Author: Bernhard E. Reiter This file is Free Software under the Apache 2.0 license and thus @@ -51,9 +51,9 @@ #d = [''.join('A' * 1000) for _ in range(1000)] # Using the dictionary from Ding **customize** - d = readDingDict(filename="/usr/share/trans/de-en", useLeft=True) + d = readDingDict(options, filename="/usr/share/trans/de-en", useLeft=True) - ## for debugging purposes, dump dictionary + # for debugging purposes, dump dictionary if options.ddump_filename: print("Writing out dictionary in '{}'.".format(options.ddump_filename)) with open(options.ddump_filename, "w") as f: @@ -62,19 +62,21 @@ # Print some stats on the dictionary to be used dl = len(d) - print("Found {:d} dictionary entries.".format(dl)) + if not options.just_passphrase: + print("Found {:d} dictionary entries.".format(dl)) + print("|= Number of words |= possibilities |") + for i in range(1, 5): + print("| {:2d} | 2^{:4.1f} |".format( + i, math.log(dl**i, 2))) + if dl < 8000: - print("!Your dictionary is below 8k entries, that is quite small!") + sys.stderr.write("!Your dictionary is below 8k entries, " + "that is quite small!\n") tainted = True - - print("|= Number of words |= possibilities |") - for i in range(1, 5): - print("| {:2d} | 2^{:4.1f} |".format( - i, math.log(dl**i, 2))) return d -def readDingDict(filename="/usr/share/trans/de-en", useLeft=False): +def readDingDict(options, filename="/usr/share/trans/de-en", useLeft=False): """Read dictionary with unique words from file in Ding format. useLeft: Boolean to control which language to use @@ -90,7 +92,8 @@ |\s+ # by whitespace """, re.VERBOSE) - print("Reading entries from {}.".format(filename), end='') + if not options.just_passphrase: + print("Reading entries from {}.".format(filename), end='') counter = 0 # for progress or stopping early with open(filename, "r") as f: for line in f: @@ -111,10 +114,11 @@ counter += 1 ## stop early when debugging #if counter > 10: break - if not counter % 10000: + if not options.just_passphrase and counter % 10000 == 0: print('.', end='') sys.stdout.flush() - print() + if not options.just_passphrase: + print() return list(dset) @@ -122,34 +126,48 @@ def main(): global tainted - parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + parser = argparse.ArgumentParser( + description=__doc__.splitlines()[0], + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--number-of-words', type=int, default=4, + help='how many words to draw for the passphrase, ' + 'most useful with -j') + parser.add_argument('-j', '--just-passphrase', action="store_true", + help='only output the passphrase on a single line') parser.add_argument('--ddump-filename', help='filename to dump the dictionary to') options = parser.parse_args() dictionary = buildDictionary(options) - howMany = 4 + how_many = options.number_of_words - # use a dictionary with lower cased words for a simple check if - # our random source is okay - print("\nGenerated passphrase with {} randomly selected words:\n".format( - howMany)) - print(" ", end='') + output_string = "" + if not options.just_passphrase: + print("\nGenerated passphrase with {}" + " randomly selected words:\n".format(how_many)) + print(" ", end='') + separator = '\n ' + else: + separator = ' ' + + # use a dictionary `words` with lower cased words for a rudimentary check words = {} - for x in range(howMany): + for x in range(how_many): word = _srandom.choice(dictionary) words[word.lower()] = True - print(word, end='\n ') - print("\n") + output_string += word + separator - if len(words) < howMany: - print("! Your random generator is weak") - print("! or you are being very lucky.") + print(output_string) + + if len(words) < how_many: + sys.stderr.write("! You've drawn a word more than once, this means:\n" + "! Your random generation is weak" + " or you are being very lucky.\n") tainted = True if tainted: - print("!!! Don't use the resulting passphrase !!!") + sys.exit("!!! Don't use the resulting passphrase !!!") if __name__ == "__main__": main()