comparison cutils/genpwd.py @ 235:11819361ea39

Implement option "-e" for genpwd to require a binary length instead of the output length. This is effectively a minimum length.
author Franz Glasner <fzglas.hg@dom66.de>
date Fri, 07 Feb 2025 19:32:45 +0100
parents c7dc57c44e8b
children 939a8da6bc92
comparison
equal deleted inserted replaced
234:c7dc57c44e8b 235:11819361ea39
39 aparser = argparse.ArgumentParser( 39 aparser = argparse.ArgumentParser(
40 description="A simple password generator for password of a given" 40 description="A simple password generator for password of a given"
41 " length within a character repertoire", 41 " length within a character repertoire",
42 fromfile_prefix_chars='@') 42 fromfile_prefix_chars='@')
43 aparser.add_argument( 43 aparser.add_argument(
44 "--version", "-v", action="version",
45 version="%s (rv:%s)" % (__version__, __revision__))
46 aparser.add_argument(
47 "-e", dest="use_bin_length", action="store_true",
48 help="For some repertoires make OUTPUT-LENGTH the number of bytes"
49 " that is to be read from random sources instead of output bytes")
50 aparser.add_argument(
44 "--repertoire", "--type", "-t", 51 "--repertoire", "--type", "-t",
45 choices=("web", "web-safe", "web-safe2", 52 choices=("web", "web-safe", "web-safe2",
46 "base64", "urlsafe-base64", "urlsafe", "base32", "ascii85", ), 53 "base64", "urlsafe-base64", "urlsafe", "base32", "ascii85", ),
47 default="web-safe2", 54 default="web-safe2",
48 help="Select the character repertoire. Default: web-safe2") 55 help="Select the character repertoire. Default: web-safe2")
49 aparser.add_argument(
50 "--version", "-v", action="version",
51 version="%s (rv:%s)" % (__version__, __revision__))
52 aparser.add_argument( 56 aparser.add_argument(
53 "req_length", metavar="OUTPUT-LENGTH", type=int, 57 "req_length", metavar="OUTPUT-LENGTH", type=int,
54 help="The required length of the generated password") 58 help="The required length of the generated password")
55 59
56 opts = aparser.parse_args(args=argv) 60 opts = aparser.parse_args(args=argv)
61 pwd = gen_web(opts.req_length, WEB_SAFE_CHARS) 65 pwd = gen_web(opts.req_length, WEB_SAFE_CHARS)
62 elif opts.repertoire == "web-safe2": 66 elif opts.repertoire == "web-safe2":
63 pwd = gen_web(opts.req_length, WEB_SAFE2_CHARS) 67 pwd = gen_web(opts.req_length, WEB_SAFE2_CHARS)
64 elif opts.repertoire == "base64": 68 elif opts.repertoire == "base64":
65 encoder = base64.b64encode 69 encoder = base64.b64encode
66 pwd = gen_bin(opts.req_length, encoder) 70 pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder,
71 rstrip_chars=b"=")
67 elif opts.repertoire in ("urlsafe-base64", "urlsafe"): 72 elif opts.repertoire in ("urlsafe-base64", "urlsafe"):
68 encoder = base64.urlsafe_b64encode 73 encoder = base64.urlsafe_b64encode
69 pwd = gen_bin(opts.req_length, encoder) 74 pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder,
75 rstrip_chars=b"=")
70 elif opts.repertoire == "base32": 76 elif opts.repertoire == "base32":
71 encoder = base64.b32encode 77 encoder = base64.b32encode
72 pwd = gen_bin(opts.req_length, encoder) 78 pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder,
79 rstrip_chars=b"=")
73 elif opts.repertoire == "ascii85": 80 elif opts.repertoire == "ascii85":
74 encoder = base64.a85encode 81 encoder = base64.a85encode
75 pwd = gen_bin(opts.req_length, encoder) 82 pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder)
76 else: 83 else:
77 raise NotImplementedError("type not yet implemented: %s" 84 raise NotImplementedError("type not yet implemented: %s"
78 % opts.repertoire) 85 % opts.repertoire)
79 assert len(pwd) == opts.req_length 86 if opts.use_bin_length:
87 if len(pwd) < opts.req_length:
88 raise AssertionError("internal length mismatch")
89 else:
90 if len(pwd) != opts.req_length:
91 raise AssertionError("internal length mismatch")
80 if not PY2: 92 if not PY2:
81 pwd = pwd.decode("ascii") 93 pwd = pwd.decode("ascii")
82 print(pwd) 94 print(pwd)
83 95
84 96
100 else: 112 else:
101 pwd = bytes(pwd) 113 pwd = bytes(pwd)
102 return pwd 114 return pwd
103 115
104 116
105 def gen_bin(length, encoder): 117 def gen_bin(length, use_bin_length, encoder, rstrip_chars=None):
106 pwd = encoder(os.urandom(length)) 118 pwd = encoder(os.urandom(length))
107 return pwd[:length] 119 return pwd.rstrip(rstrip_chars) if use_bin_length else pwd[:length]
108 120
109 121
110 if __name__ == "__main__": 122 if __name__ == "__main__":
111 main() 123 main()