After giving a couple of well-received answers to similar questions, I thought I'd try to come up with my own solution.
I believe that a good password generator can and should be quite simple without sacrificing security or usability.
Also, this is the first time I actually code a command-line utility (as a Windows user, command-line tools aren't part of my usual work-flow).
I'm interested in any remark about my code, especially regarding security and features.
''' Command-line utility program for generating passwords ''' from argparse import ArgumentParser, RawTextHelpFormatter import secrets from string import ascii_lowercase, ascii_uppercase, digits, punctuation ESCAPES = { r'\l' : ascii_lowercase, r'\u' : ascii_uppercase, r'\d' : digits, r'\s' : punctuation } def generate_password(length, alphabet): return ''.join(secrets.choice(alphabet) for _ in range(length)) def _parse_alphabet(specifiers): ranges = [] for escape, characters in ESCAPES.items(): if escape in specifiers: ranges.append(characters) specifiers = specifiers.replace(escape, '') ranges.append(specifiers) return ''.join(set(''.join(ranges))) if __name__ == '__main__': parser = ArgumentParser( prog='Password generator', formatter_class=RawTextHelpFormatter) parser.add_argument( '-l', '--length', default=32, type=int, help='length of password to be generated') parser.add_argument( '-a', '--alphabet', default=r'\l\u\d\s', help=r'''alphabet to use for password generation. The following escape sequences are supported: * \u: uppercase ASCII letters. * \l: lowercase ASCII letters. * \d: digits. * \s: other printable ASCII characters. Any other specified character will also be included.''') args = parser.parse_args() print(generate_password(args.length, _parse_alphabet(args.alphabet)))
Example uses:
# show help (base) [...]>python password.py -h usage: Password generator [-h] [-l LENGTH] [-a ALPHABET] optional arguments: -h, --help show this help message and exit -l LENGTH, --length LENGTH length of password to be generated -a ALPHABET, --alphabet ALPHABET alphabet to use for password generation. The following escape sequences are supported: * \u: uppercase ASCII letters. * \l: lowercase ASCII letters. * \d: digits. * \s: other printable ASCII characters. Any other specified character will also be included. # generate a password with default settings: (base) [...]>python password.py y3S%iR!O=zNhcWYf-f9@87m_FC'WGr+^ # generate a 6-digit PIN (eg. for phone unlocking): (base) [...]>python password.py -l 6 -a \d 310696 # generate a password with smaller length and only some special chars (eg. for website compatibility): (base) [...]>python password.py -l 16 -a "\u\l\d_-&@!?" bP7L?_uuGbdHFww@ # generate a long password: (base) [...]>python password.py -l 250 FO_Hy1O,7#z}M'5K/,=:Al"dK-w{VIC:G$[Xqm|GRw8Uou@d^peD1vk$:76)n#28f112w"vz<F+-c\it$7@fb9Xq@3\[)7+*R7PTa(gdMb&\,?n6GRT93jD'L!6Ww)u:-}rWyXq&?V!pw>9<&.Nt4S!+a9X6f~z+?DZeB:);`-!{K;ftB(/;"TEeKi%yV,-,H3{2!x2Y"]'?[3$/'QM=K5mSo[!D~#;!iuY]=BF3=LLkGK92Nm4kttc\*S # generate a password with non-ASCII characters: (base) [...]>python password.py -a µùûÜ ùùùÜùùµÜܵµµÜùûÜûµÜÜÜûûÜûûùùùûܵ