48 lines
1.7 KiB
Python
48 lines
1.7 KiB
Python
import argparse
|
|
import secrets
|
|
import string
|
|
import sys
|
|
|
|
def generate_password(length, pools, ensure_each=True):
|
|
if not pools:
|
|
raise ValueError("No character sets selected")
|
|
password = []
|
|
if ensure_each:
|
|
if length < len(pools):
|
|
raise ValueError("Password length too small")
|
|
for pool in pools:
|
|
password.append(secrets.choice(pool))
|
|
all_chars = "".join(pools)
|
|
while len(password) < length:
|
|
password.append(secrets.choice(all_chars))
|
|
secrets.SystemRandom().shuffle(password)
|
|
return "".join(password)
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(prog="genpass", description="Secure password generator")
|
|
parser.add_argument("-l", "--length", type=int, default=16)
|
|
parser.add_argument("-n", "--count", type=int, default=1)
|
|
parser.add_argument("--lower", action="store_true")
|
|
parser.add_argument("--upper", action="store_true")
|
|
parser.add_argument("--digits", action="store_true")
|
|
parser.add_argument("--symbols", action="store_true")
|
|
parser.add_argument("--symbol-set", default="!@#$%^&*()-_=+[]{};:,.<>?")
|
|
parser.add_argument("--no-ensure", action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
pools = []
|
|
if args.lower: pools.append(string.ascii_lowercase)
|
|
if args.upper: pools.append(string.ascii_uppercase)
|
|
if args.digits: pools.append(string.digits)
|
|
if args.symbols: pools.append(args.symbol_set)
|
|
|
|
if not pools:
|
|
print("Select at least one character set", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
for _ in range(args.count):
|
|
print(generate_password(args.length, pools, ensure_each=not args.no_ensure))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|