-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmkpwd
executable file
·120 lines (94 loc) · 3.43 KB
/
mkpwd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env python3
# vim: set ft=python syntax=python ts=4 sts=4 sw=4 et ai enc=utf-8 fenc=utf-8
"""
/usr/local/bin/mkpwd
Description: A simple password generator written in python,
to create strong random passwords.
Author: Eric F <[email protected]>
Copyright: 2023, Eric F
Source: https://gitlab.com/iefdev/mkpwd
License: GPLv3
"""
__version__ = 'v0.99-20230829'
from os.path import basename
from random import shuffle
from string import ascii_lowercase, ascii_uppercase, digits, punctuation
import sys
_basename = basename(__file__)
USAGE = f"""Version:
{__version__}
Usage:
{_basename} [ -h | -c ] [ size ] [ nr of pwds ]
{_basename} Enter a number at the prompt
{_basename} 24 24 character pwd
{_basename} 36 10 10x 36 character pwd
Options:
-h Display this help.
-c Clean mode (only the pwd(s) in output).
Useful for scripting.
"""
# --- Settings & text strings ---------------- #
# Set min/max length: 12/72 (use sane defaults).
# [ref]: Bcrypt has a max length of 72.
MIN_LENGTH = 12
MAX_LENGTH = 72
DEFAULT_LENGTH = 18
# Text strings
MSG_INPUT = f'Password length [default: {DEFAULT_LENGTH}]: '
MSG_TOO_SHORT = f'The entered value is too short (<{MIN_LENGTH}).'
MSG_TOO_LONG = f'The entered value is too long (>{MAX_LENGTH}).'
# --- [end] Settings & text strings --------- #
# Display help/usage with "-h", and exit
if len(sys.argv) >= 2 and sys.argv[1] == '-h':
sys.exit(USAGE)
# Don't print PROGRAM in clean mode (-c")
if len(sys.argv) >= 2 and sys.argv[1] == '-c':
QUIET = True
PROGRAM = None
sys.argv.pop(1)
else:
QUIET = None
# Red colons when too short/long
PREFIX = '::'
ERR_PREFIX = f'\x1b[1;31m{PREFIX}\x1b[0m'
# Password length: Take from argv, or ask for password length
U_INPUT = int(sys.argv[1]) if len(sys.argv) >= 2 else input(f'{PREFIX} {MSG_INPUT}')
while True:
try:
PWD_LENGTH = int(U_INPUT)
if PWD_LENGTH < int(MIN_LENGTH):
print(f'{ERR_PREFIX} {MSG_TOO_SHORT}')
U_INPUT = input(f'{PREFIX} {MSG_INPUT}')
elif PWD_LENGTH > int(MAX_LENGTH):
print(f'{ERR_PREFIX} {MSG_TOO_LONG}')
U_INPUT = input(f'{PREFIX} {MSG_INPUT}')
else:
break
except ValueError:
# Use the default...
U_INPUT = int(DEFAULT_LENGTH)
# Character lists
# All strings combined will give the maximum length of 52, and then you get:
# "IndexError: list index out of range". So we must double the size (104)
# to get to MAX_LENGTH (72).
L_CASE = list(ascii_lowercase * 2)
U_CASE = list(ascii_uppercase * 2)
DIGITS = list(digits * 2)
PUNCTS = list(punctuation * 2)
# Number of password(s)
NUMBER_OF_PWDS = int(sys.argv[2]) if len(sys.argv) >= 3 else 1
# Output
for n in range(NUMBER_OF_PWDS):
for l in (L_CASE, U_CASE, DIGITS, PUNCTS):
shuffle(l)
# Ratio: 60/40 between ascii_* and digits/punctuation
LETTERS_RATIO = round(PWD_LENGTH * (30/100))
NON_LETTERS_RATIO = round(PWD_LENGTH * (20/100))
result = [x for x in range(LETTERS_RATIO) for x in (L_CASE[x], U_CASE[x])]
result.extend([x for x in range(NON_LETTERS_RATIO) for x in (DIGITS[x], PUNCTS[x])])
shuffle(result)
OUTPUT = ''.join(result)
PWD_NR = f' #{n + 1}' if NUMBER_OF_PWDS > 1 else ''
PROGRAM = f'{_basename}{PWD_NR}:\t' if QUIET is None else ''
print(f'{PROGRAM}{OUTPUT}'.expandtabs(4))
sys.exit()