Last active
June 14, 2020 16:26
-
-
Save mprentice/1818fa86e6f4adb014449c74fc5a1feb to your computer and use it in GitHub Desktop.
genpasswd.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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