#!/usr/bin/env python3 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. """generates passwords by character-type Written by Cody A. Taylor (more well known as code_m). First major project in any programming language, and I am quite satified with the end result. This took about 14 weeks to write in all, with servel small changes as I learned the Python language. This will continue to be my pet project for a long time, so I hope it comes to some use. Report bugs or sugestions to codemister99@yahoo.com """ __all__ = ['character_lists', 'get_int', 'get_ans', 'input_opts', 'main', 'generate_password'] __author__ = "Cody A. Taylor ( codemister99@yahoo.com )" __version__ = "1.0.2 Beta" import random import optparse def character_lists(): """Create lists needed through the program I made this function for two reasons: can be used in other programs, and avoids global 'variables' Returns a dict so order does not need to be known to reuse variables """ lowercase = [] lowercase += "abcdefghijklmnopqrstuvwxyz" uppercase = [] uppercase += "ABCDEFGHIJKLMNOPQRSTUVWXYZ" numbers = [] numbers += "1234567890" symbols = [] symbols += "`~!@#$%^&*(){}[]<>-_=+/?|;:,.'\"" return {"lowercase": lowercase, "uppercase": uppercase, "numbers": numbers, "symbols": symbols} def get_int(msg, min, default): """Simple get integer function Used to get amount and length information. >>> get_int("Value?", 4, 8) """ while True: try: i = input(msg) if not i and default is not None: return default value = int(i) if value < int(min): print("Can not be less than {0}".format(min)) continue else: return value except ValueError as err: print(err) continue def get_ans(msg, default): """Quick boolean "yes" or "no" function Thanks to the magic of the builtin str.lower(), the user can input any capital variant of "y", "yes", "n", "no". >>> get_characters("Use the file '{0}'?".format(filename), False) """ while True: i = input(msg).lower() if not i and default is not None: return default elif i in {"y", "yes"}: return True elif i in {"n", "no"}: return False else: print("Type \"Yes\" or \"No\".") continue def input_opts(): """Input information Two methods are even to the user; optparse or function-questions """ parser = optparse.OptionParser(version="{0:>7}{1}\n{2:>45}".format("", __version__, __author__), description="A quick password generator, using 'character-types' for ease", usage="Usage: %prog [-Q] [-luns] [-a AMOUNT] [-L LENGTH]") parser.add_option("-Q", "--questions", dest="ask", action="store_true", default=False, help="Use the (old) question style program") parser.add_option("-l", "--lowercase", dest="lower", action="store_true", default=False, help="allow lowercase characters") parser.add_option("-u", "--uppercase", dest="upper", action="store_true", default=False, help="allow uppercase characters") parser.add_option("-n", "--numbers", dest="numbers", action="store_true", default=False, help="allow number characters") parser.add_option("-s", "--symbols", dest="symbols", action="store_true", default=False, help="allow symbol characters") parser.add_option("-a", "--amount", dest="amount", type="int", default=10, help="number of passwords to output [default: %default]") parser.add_option("-L", "--length", dest="length", type="int", default=8, help="length of password [default: %default]") opts, args = parser.parse_args() if opts.amount < 1: print("Error: too few passwords given to amount") exit() if opts.length < 4: print("Error: will not allow length less than 4") exit() if opts.ask == True: print("Use 'Enter' for defaults.", "Passwords can not be shorter than 4 characters.", "\nDefaults: length=8; amount=10; Lowercase=Yes; Uppercase=Yes; Numbers=Yes; Symbols=Yes") opts.length = get_int("Length: ", 4, 8) opts.amount = get_int("Number of passwords: ", 1, 10) opts.lower = get_ans("Use lowercase? ", True) opts.upper = get_ans("Use Uppercase? ", True) opts.numbers = get_ans("Use numbers? ", True) opts.symbols = get_ans("Use symbols? ", True) if opts.lower == False and opts.upper == False and opts.numbers == False and opts.symbols == False: opts.lower, opts.upper, opts.numbers, opts.symbols = True, True, True, True if opts.ask == True: print("All 'types' are False, reverting to all True") return ({"amount": opts.amount, "length": opts.length}, {"lowercase": opts.lower, "uppercase": opts.upper, "numbers": opts.numbers, "symbols": opts.symbols}) def main(): """Generate and print passwords (simple as possible) """ values, bool_opts = input_opts() for count in range(1, (values["amount"] + 1)): print("{0:>{1}}: {2}".format(count, len(str(values["amount"])), generate_password(values["length"], bool_opts, character_lists()))) def generate_password(length, use_characters={}, list_of_characters={}): """Generate a random password using character "types" Function Order: assert that each key of "use" is in "list_of", only to help debug a new build append key to local list while password length is not met: random key from list shuffle that "type" append random character "type" to password """ _use_characters = [] for key in use_characters.keys(): assert key in list_of_characters.keys(), "list_of_characters does not contain key: {}".format(key) if use_characters[key] == True: _use_characters.append(key) password = [] while len(password) < length: key = random.choice(_use_characters) random.shuffle(list_of_characters[key]) password.append(random.choice(list_of_characters[key])) return "".join(password) if __name__ == "__main__": main()