Last active
February 19, 2021 12:47
-
-
Save therightstuff/0384b4b1201a2679eee9f2fd49e69c9c to your computer and use it in GitHub Desktop.
Generate a secure python password with no dependencies
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
""" | |
A simple password generator that produces secure passwords of a given length | |
without requiring the installation of additional modules. | |
The four valid password characters classes - lowercase, uppercase, digits and | |
punctuation - are inserted randomly into the password using cryptographically | |
strong random numbers from the secrets module until the password length | |
requirement is met, ensuring that each of the classes is included in the password. | |
Password strength verified with https://www.security.org/how-secure-is-my-password/ | |
NOTE: I've put a lower limit of 8 characters, which is standard, but the very first | |
example this produced was "b`q8M1N/", which can apparently be cracked in about 12 | |
hours. Longer passwords are better. See https://xkcd.com/936/ | |
""" | |
import secrets | |
import string | |
def generate_password(desired_length): | |
# don't even bother with passwords shorter than 8 characters | |
if desired_length < 8: | |
raise Exception("Passwords should be 8 characters or more") | |
# randomly select at least enough characters from each character class | |
valid_char_classes = [ | |
string.ascii_lowercase, | |
string.ascii_uppercase, | |
string.digits, | |
string.punctuation ] | |
# generate an array of password characters | |
password = [] | |
# loop over the character classes until we've completed the password | |
while True: | |
for char_class in valid_char_classes: | |
# randomly select a character from the class | |
random_char = secrets.choice(char_class) | |
# randomly select the insert position | |
insert_position = secrets.randbelow(len(password) + 1) | |
# insert the character at that position | |
password.insert(insert_position, random_char) | |
# return the password string when complete | |
if len(password) == desired_length: | |
return "".join(password) | |
# choose a password length between 8 and 20 | |
desired_length = 8 + secrets.randbelow(13) | |
print(f"Generated password of length {desired_length}: {generate_password(desired_length)}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment