Skip to content

Instantly share code, notes, and snippets.

@mprentice
Last active June 14, 2020 16:26
Show Gist options
  • Save mprentice/1818fa86e6f4adb014449c74fc5a1feb to your computer and use it in GitHub Desktop.
Save mprentice/1818fa86e6f4adb014449c74fc5a1feb to your computer and use it in GitHub Desktop.
genpasswd.py
#!/usr/bin/env python3
import argparse
import logging
import math
import random
import string
import typing
DEFAULT_DICT_FILE = "/usr/share/dict/words"
DEFAULT_WORD_COUNT = 3
DEFAULT_SYMBOL_COUNT = 10
SYMBOLS = string.ascii_letters = string.digits + string.punctuation
def main() -> None:
parser = make_argparser()
args = parser.parse_args()
num_words = init_from_args(args)
log = logging.getLogger(__name__)
if args.symbols:
sep = ""
elements: typing.Union[list, str] = SYMBOLS
log.info("Using %d symbols from: %s", num_words, elements)
else:
sep = "-"
dict_file = args.dict_file
if not dict_file:
dict_file = open(DEFAULT_DICT_FILE, "r")
log.info("Using %d words from: %s", num_words, dict_file.name)
elements = [w.strip() for w in dict_file.readlines() if len(w.strip()) > 2]
randgen = random.SystemRandom()
choices = [randgen.choice(elements) for _ in range(num_words)]
log.info("Entropy: %.2f bits", math.log2(len(elements) ** num_words))
print(sep.join(choices))
def make_argparser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Generate a random password according to https://xkcd.com/936/."
)
parser.add_argument(
"-s",
"--symbols",
action="store_true",
default=False,
help="Generate random symbols instead of words.",
)
parser.add_argument(
"-n",
"--num-words",
dest="num_words",
default=None,
type=int,
help=(
"Number of words or symbols to generate. "
"Default is {} words or {} symbols if using -s option."
).format(DEFAULT_WORD_COUNT, DEFAULT_SYMBOL_COUNT),
)
parser.add_argument("-f", "--dict-file", type=argparse.FileType("r"), default=None)
parser.add_argument(
"-v", "--verbose", action="count", default=0, help="Verbose mode."
)
return parser
def init_from_args(args) -> int:
if args.verbose:
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig()
num_words = args.num_words
if not num_words:
if args.symbols:
num_words = DEFAULT_SYMBOL_COUNT
else:
num_words = DEFAULT_WORD_COUNT
return num_words
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment