# HG changeset patch # User Franz Glasner # Date 1738953165 -3600 # Node ID 11819361ea3945f82472b1586d55cced2827ed35 # Parent c7dc57c44e8beb98a0de7b583bd2d00e2c1a2258 Implement option "-e" for genpwd to require a binary length instead of the output length. This is effectively a minimum length. diff -r c7dc57c44e8b -r 11819361ea39 cutils/genpwd.py --- a/cutils/genpwd.py Fri Feb 07 13:43:14 2025 +0100 +++ b/cutils/genpwd.py Fri Feb 07 19:32:45 2025 +0100 @@ -41,15 +41,19 @@ " length within a character repertoire", fromfile_prefix_chars='@') aparser.add_argument( + "--version", "-v", action="version", + version="%s (rv:%s)" % (__version__, __revision__)) + aparser.add_argument( + "-e", dest="use_bin_length", action="store_true", + help="For some repertoires make OUTPUT-LENGTH the number of bytes" + " that is to be read from random sources instead of output bytes") + aparser.add_argument( "--repertoire", "--type", "-t", choices=("web", "web-safe", "web-safe2", "base64", "urlsafe-base64", "urlsafe", "base32", "ascii85", ), default="web-safe2", help="Select the character repertoire. Default: web-safe2") aparser.add_argument( - "--version", "-v", action="version", - version="%s (rv:%s)" % (__version__, __revision__)) - aparser.add_argument( "req_length", metavar="OUTPUT-LENGTH", type=int, help="The required length of the generated password") @@ -63,20 +67,28 @@ pwd = gen_web(opts.req_length, WEB_SAFE2_CHARS) elif opts.repertoire == "base64": encoder = base64.b64encode - pwd = gen_bin(opts.req_length, encoder) + pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder, + rstrip_chars=b"=") elif opts.repertoire in ("urlsafe-base64", "urlsafe"): encoder = base64.urlsafe_b64encode - pwd = gen_bin(opts.req_length, encoder) + pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder, + rstrip_chars=b"=") elif opts.repertoire == "base32": encoder = base64.b32encode - pwd = gen_bin(opts.req_length, encoder) + pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder, + rstrip_chars=b"=") elif opts.repertoire == "ascii85": encoder = base64.a85encode - pwd = gen_bin(opts.req_length, encoder) + pwd = gen_bin(opts.req_length, opts.use_bin_length, encoder) else: raise NotImplementedError("type not yet implemented: %s" % opts.repertoire) - assert len(pwd) == opts.req_length + if opts.use_bin_length: + if len(pwd) < opts.req_length: + raise AssertionError("internal length mismatch") + else: + if len(pwd) != opts.req_length: + raise AssertionError("internal length mismatch") if not PY2: pwd = pwd.decode("ascii") print(pwd) @@ -102,9 +114,9 @@ return pwd -def gen_bin(length, encoder): +def gen_bin(length, use_bin_length, encoder, rstrip_chars=None): pwd = encoder(os.urandom(length)) - return pwd[:length] + return pwd.rstrip(rstrip_chars) if use_bin_length else pwd[:length] if __name__ == "__main__":