aboutsummaryrefslogtreecommitdiffstats
path: root/makepass.py
diff options
context:
space:
mode:
Diffstat (limited to 'makepass.py')
l---------[-rwxr-xr-x]makepass.py319
1 files changed, 1 insertions, 318 deletions
diff --git a/makepass.py b/makepass.py
index 233ae7d..b6e1064 100755..120000
--- a/makepass.py
+++ b/makepass.py
@@ -1,318 +1 @@
-#!/usr/bin/env python3
-#
-# Author : Dennis Eriksen <d@ennis.no>
-# File : makepass.py
-# Created : 2023-09-14
-# License : BSD-3-Clause
-#
-# Copyright (c) 2018-2023 Dennis Eriksen <d@ennis.no>
-
-import argparse
-import os
-import random
-import sys
-
-# Global variables
-
-MAX = 255
-RANGE_MAX = 42
-RANGE_MIN = 8
-PASS_WORDS = 8
-
-LOWER = "abcdefghijklmnopqrstuvwxyz"
-UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-DIGIT = "0123456789"
-OTHER = "!$%&#/()=?+-_,.;:<>[]{}|@*"
-
-ALPHA = LOWER + UPPER
-ALNUM = ALPHA + DIGIT
-EVERY = ALNUM + OTHER
-
-NORMAL = ALNUM + "_-"
-SPECIAL = EVERY
-
-DEFAULT_LENGTH = 0
-DEFAULT_NUMBER = 10
-DEFAULT_WORDLIST = "/usr/share/dict/words"
-
-
-class CommonPrintData:
- def __init__(self, length, printbool, printlen, col_width, col_num):
- self.length = length
- self.printbool = printbool
- self.printlen = printlen
- self.col_num = col_num
- self.col_width = col_width
-
-
-#
-# Main function
-#
-def main():
- normal = os.getenv("MAKEPASS_NORMAL") or NORMAL
- special = os.getenv("MAKEPASS_SPECIAL") or SPECIAL
- wordlist_file = os.getenv("MAKEPASS_WORDLIST") or DEFAULT_WORDLIST
-
- # Initialize parser
- parser = argparse.ArgumentParser(
- description="Process some strings.", add_help=False
- )
-
- # Add arguments
- parser.add_argument("-h", "--help", action="store_true")
- parser.add_argument("-l", "--length", type=int, help="Length of strings")
- parser.add_argument("-n", "--number", type=int, help="Number of strings")
- parser.add_argument("-p", "--printlen", action="store_true")
- parser.add_argument("arg_length", type=int, nargs="?")
-
- # Parse arguments
- args = parser.parse_args()
-
- if args.help:
- usage()
-
- # Some error-checking
- # length
- try:
- # env or default
- length = int(os.getenv("MAKEPASS_LENGTH") or DEFAULT_LENGTH)
-
- # -l flag
- if args.length is not None:
- if args.length < 0 or MAX < args.length:
- raise ValueError("-l")
- length = args.length
-
- # solo argument
- if args.arg_length is not None:
- length = args.arg_length
-
- # check result
- if length < 0 or MAX < length:
- raise ValueError("length")
- except ValueError as e:
- print(f"{e} must be a number between 0 and {MAX}")
- sys.exit(1)
-
- # number
- try:
- # env or default
- number = int(os.getenv("MAKEPASS_NUMBER") or DEFAULT_NUMBER)
-
- # -n flag
- if args.number is not None:
- if args.number < 1 or MAX < args.number:
- raise ValueError("-n")
- number = args.number
-
- # check result
- if number < 1 or MAX < number:
- raise ValueError("number")
- except ValueError as e:
- print(f"{e} must be a number between 1 and {MAX}")
- sys.exit(1)
-
- # Set some other stuff
-
- printbool = args.printlen
- if printbool:
- printlen = 3 if length < 100 else 4
- else:
- printlen = 0
-
- # get terminal width
- try:
- xwidth = os.get_terminal_size().columns
- except Exception as _:
- xwidth = 1
-
- # get width of columns to print
- if length == 0:
- col_width = RANGE_MAX + 2
- else:
- col_width = length + 2
-
- # number of columns to print
- col_num = int(xwidth / (col_width + printlen))
- if col_num == 0:
- col_num = 1
-
- # config
- config = CommonPrintData(
- length=length,
- printbool=printbool,
- printlen=printlen,
- col_width=col_width,
- col_num=col_num,
- )
-
- #
- # print passwords
- #
-
- # Generate and print normal and special passwords
- print_columns("Normal passwords", number, normal, config)
-
- print()
-
- print_columns(
- "Passwords with special characters", int(number / 3 * 2 + 1), special, config
- )
-
- # Generate and print passphrases if wordlist exists
- if os.path.isfile(wordlist_file):
- print()
-
- print("Generating passphrases: ")
- passphrase(int(number / 2), wordlist_file)
-
-
-#
-# Print passwords in neat columns
-#
-def print_columns(title: str, num: int, chars: str, c: CommonPrintData):
- # Generate random strings
- strings = [randstring(c.length, chars) for _ in range(num)]
-
- print(f"{title}:")
-
- for i in range(num):
- # Print the length of the string if printlen is set
- if c.printbool:
- print(f"{len(strings[i]):0{c.printlen-1}}", end=" ")
-
- # Print the string, left justified based on column width
- print(f"{strings[i]:<{c.col_width}}", end="")
-
- # If we have printed enough strings for a single line or the
- # rest of strings are fewer than column number, we break lines.
- i += 1
- if i % c.col_num == 0 or (i == num and i % c.col_num > 0):
- print()
-
-
-#
-# Generate random strings that can work as passwords
-#
-def randstring(length, chars):
- """
- Generate a random password of the specified length. Use special
- characters if special_chars option is True.
- """
- if length == 0:
- length = random.randint(RANGE_MIN, RANGE_MAX)
-
- password = []
- password.append(random.choice(ALPHA))
- for i in range(length - 2):
- password.append(random.choice(chars))
- password.append(random.choice(ALNUM))
-
- # Randomly reorder the characters
- return "".join(password)
-
-
-#
-# Passphrases!
-#
-def passphrase(number, file_name):
- """
- Generate a number of random passphrases from the wordlist.
- """
- try:
- with open(file_name, "r") as f:
- lines = f.read().splitlines()
- except IOError:
- print(f"Cannot open file: {file_name}")
- sys.exit(1)
-
- for i in range(number):
- word_list = random.choices(lines, k=5)
- passphrase = "-".join(word_list)
- print(passphrase)
-
-
-def usage():
- text = """NAME
- makepass - create several random passwords
-
-SYNOPSIS
- makepass [OPTIONS] [NUM]
-
- If a NUM is provided, passwords will be NUM characters long.
-
- By default `makepass` will output passwords from the three following classes:
-
- - Normal passwords - random strings with letters (both lower and upper
- case), numbers, and dashes and underscores.
-
- - Passwords with special characters - random strings generated from lower
- and upper case letters, numbers, and the following characters:
- !#$%&/()=?+-_,.;:<>[]{}|@*
-
- - Passphrases - if we find a dictionary, a series of eight random words
- from the dictionary, separated by dashes. The number of words can not be
- changed, but you do not have to use all of them. Use as mane as you want.
-
- The first character will always be alphabetic, and the last will always be
- alphanumeric.
-
-DESCRIPTION
- makepass has the following options:
-
- -h
- output this help-text
- -l
- length of passwords. See MAKEPASS_LENGTH below
- -n
- number of passwords. See MAKEPASS_NUMBER below
- -p
- print length of number
-
-ENVIRONMENT
- makepass examines the following environmental variables.
-
- MAKEPASS_LENGTH
- Specifies the length of passwords. Valid values are 0-255. If 0, a
- random value between 8 and 42 will be used for each password. -l
- overrides this environmental variable, and the argument NUM overrides
- that again. So `MAKEPASS_LENGTH=10 makepass -l 12 14` will give
- passwords that are 14 characters long, even though both -l and
- MAKEPASS_LENGTH also specifies a length.
-
- MAKEPASS_NUMBER
- The number of passwords to generate. This formula is used to determine
- how many passwords from each group should be generated:
- - (n) normal passwords
- - (n / 3 * 2 + 1) special passwords
- - (n / 2) passphrases
- Where n is 10 by default. Valid values for n are 1-255. Floating-poing
- math is not used, so results may vary.
-
- MAKEPASS_PRINTLEN
- If 1, print length of all passwords. If 0, don\'t.
-
- MAKEPASS_NORMAL
- String of characters from which to generate "normal" passwords.
- Defaults to:
- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_
-
- MAKEPASS_SPECIAL
- String of characters from which to generate passwords with special
- characters. Defaults to the same characters as in MAKEPASS_NORMAL, plus
- these:
- !#$%&/()=?+-_,.;:<>[]{}|@*
-
- MAKEPASS_WORDLIST
- Specifies the dictionary we find words for passphrases in. If this is
- unset or empty, we try "/usr/share/dict/words". If that file does not
- exist, no passphrases will be provided.
-
-AUTHOR
- Dennis Eriksen <https://dnns.no>"""
- print(text)
- sys.exit(0)
-
-
-if __name__ == "__main__":
- main()
+src/python/makepass.py \ No newline at end of file