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 µùûÜ
ùùùÜùùµÜܵµµÜùûÜûµÜÜÜûûÜûûùùùûܵ