Last active
October 16, 2019 11:27
-
-
Save AberrantWolf/86b0431b76024b07e70ff61017a51033 to your computer and use it in GitHub Desktop.
Generate random passwords that meet some criteria
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
import random | |
import string | |
NUM_CHARS = 7 | |
# pick types are "random", "first", and "last" | |
PICK_TYPE = "last" | |
# options are "allowed", "required", and "none" | |
UPPER_CASE = "required" | |
LOWER_CASE = "required" | |
NUMBER = "required" | |
SYMBOL = "required" | |
# VALID_SYMBOLS = "!@#$%^&*()_+-=" | |
ALLOWED_TYPES = [] | |
def init_valid_types(): | |
if LOWER_CASE is not "none": | |
ALLOWED_TYPES.append("lower") | |
if UPPER_CASE is not "none": | |
ALLOWED_TYPES.append("upper") | |
if NUMBER is not "none": | |
ALLOWED_TYPES.append("number") | |
if SYMBOL is not "none": | |
ALLOWED_TYPES.append("symbol") | |
class PasswordCharMeta: | |
def __init__(self): | |
self.selected_type = pick_value(ALLOWED_TYPES) | |
self.is_protected = False | |
def pick_value(options): | |
if PICK_TYPE is "random": | |
return random.choice(options) | |
elif PICK_TYPE is "first": | |
return options[0] | |
elif PICK_TYPE is "last": | |
idx = len(options) - 1 | |
return options[idx] | |
else: | |
print("ERROR: invalid pick type specified (" + PICK_TYPE + ")") | |
return None | |
def get_char(kind = "any"): | |
if kind is "lower": | |
return pick_value(string.ascii_lowercase) | |
elif kind is "upper": | |
return pick_value(string.ascii_uppercase) | |
elif kind is "number": | |
return pick_value(string.digits) | |
elif kind is "symbol": | |
return pick_value(string.punctuation) | |
else: | |
return "[INVALID TYPE: " + kind + "]" | |
def get_unprotected_indices(passwordMetas): | |
indices = [] | |
for i, m in enumerate(passwordMetas): | |
if not m.is_protected: | |
indices.append(i) | |
return indices | |
def enforce_category_helper(passwordMetas, category_name, category_class): | |
if category_class is "required": | |
category_idxs = [] | |
for i, m in enumerate(passwordMetas): | |
if m.selected_type is category_name: | |
category_idxs.append(i) | |
if len(category_idxs) < 1: | |
print("Forcing category: " + category_name) | |
valid_indices = get_unprotected_indices(passwordMetas) | |
if len(valid_indices) < 1: | |
print("ERROR: No valid available slots for required category " + category_name) | |
return | |
rand_idx = pick_value(valid_indices) | |
passwordMetas[rand_idx].selected_type = category_name | |
category_idxs.append(rand_idx) | |
passwordMetas[pick_value(category_idxs)].is_protected = True | |
def enforce_required_categories(passwordMetas): | |
enforce_category_helper(passwordMetas, "upper", UPPER_CASE) | |
enforce_category_helper(passwordMetas, "lower", LOWER_CASE) | |
enforce_category_helper(passwordMetas, "number", NUMBER) | |
enforce_category_helper(passwordMetas, "symbol", SYMBOL) | |
def gen_password(): | |
passwordMetas = list() | |
for _ in range(0, NUM_CHARS): | |
passwordMetas.append(PasswordCharMeta()) | |
enforce_required_categories(passwordMetas) | |
password = "" | |
for ch in passwordMetas: | |
password = password + get_char(ch.selected_type) | |
return password | |
if __name__ == "__main__": | |
init_valid_types() | |
print("Your password is: " + gen_password()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment