Last active
March 28, 2023 16:14
-
-
Save creisor/8fb5ba300e65f2e02e32475ef831b567 to your computer and use it in GitHub Desktop.
A python (python3) password generator, possibly overkill
This file contains hidden or 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 string | |
import secrets | |
# https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_passwords_account-policy.html#default-policy-details | |
SYMBOLS='!@#$%^&*()_+-=[]{}|' | |
def gen_password(length=20, symbols=True, uppercase=True, lowercase=True, digits=True): | |
choices = '' | |
if symbols: | |
choices += SYMBOLS | |
if uppercase: | |
choices += string.ascii_uppercase | |
if lowercase: | |
choices += string.ascii_lowercase | |
if digits: | |
choices += string.digits | |
while True: | |
symbols_satisfied = False if symbols else True | |
uppercase_satisfied = False if uppercase else True | |
lowercase_satisfied = False if lowercase else True | |
digits_satisfied = False if digits else True | |
password = ''.join(secrets.choice(choices) for i in range(length)) | |
# ensure we have at least all the required things | |
if not symbols_satisfied: | |
if set(SYMBOLS) & set(password): | |
symbols_satisfied = True | |
if not uppercase_satisfied: | |
if (any(c.isupper() for c in password)): | |
uppercase_satisfied = True | |
if not lowercase_satisfied: | |
if (any(c.islower() for c in password)): | |
lowercase_satisfied = True | |
if not digits_satisfied: | |
if sum(c.isdigit() for c in password) >= 3: | |
digits_satisfied = True | |
if (symbols_satisfied | |
and uppercase_satisfied | |
and lowercase_satisfied | |
and digits_satisfied): | |
break | |
return password |
This file contains hidden or 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 unittest | |
import string | |
from . import util | |
class TestUtil(unittest.TestCase): | |
def test_gen_password_len(self): | |
tests = (20, 30, 100) | |
for length in tests: | |
with self.subTest(length=length): | |
self.assertEqual( | |
len(util.gen_password(length=length)), | |
length) | |
def test_gen_password_symbols(self): | |
reps = 20 | |
for i in range(1, reps): | |
pw = util.gen_password(symbols=True) | |
with self.subTest(pw=pw): | |
self.assertTrue(set(util.SYMBOLS) & set(pw)) | |
for i in range(1, reps): | |
pw = util.gen_password(symbols=False) | |
with self.subTest(pw=pw): | |
self.assertFalse(set(util.SYMBOLS) & set(pw)) | |
def test_gen_password_cases(self): | |
reps = 20 | |
for i in range(1, reps): | |
pw = util.gen_password(uppercase=True) | |
with self.subTest(pw=pw): | |
self.assertTrue(set(string.ascii_uppercase) & set(pw)) | |
for i in range(1, reps): | |
pw = util.gen_password(uppercase=False) | |
with self.subTest(pw=pw): | |
self.assertFalse(set(string.ascii_uppercase) & set(pw)) | |
for i in range(1, reps): | |
pw = util.gen_password(lowercase=True) | |
with self.subTest(pw=pw): | |
self.assertTrue(set(string.ascii_lowercase) & set(pw)) | |
for i in range(1, reps): | |
pw = util.gen_password(lowercase=False) | |
with self.subTest(pw=pw): | |
self.assertFalse(set(string.ascii_lowercase) & set(pw)) | |
def test_gen_password_digits(self): | |
reps = 20 | |
for i in range(1, reps): | |
pw = util.gen_password(digits=True) | |
with self.subTest(pw=pw): | |
self.assertTrue(set(string.digits) & set(pw)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment