I need to generate random passwords for my company’s 200k+ customers.
The password complexity requirement is a common one:
- length > 8
- contains at least one upper case character
- contains at least one lower case character
- contains at least one number
- contains at least one symbols (e.g. @#$%)
Here is the python 3.8 code I used to generate a random password string following the guides on Google search result(like this and this):
import secrets
import string
def getRandomPasswordString(length):
    
    alphabet = string.ascii_letters + string.digits + string.punctuation
    password = ''.join(secrets.choice(alphabet) for i in range(length))
    return password
This works fine for most of the time but for some rare cases that the password generated does not comply with the complexity requirement like below:
=Y[&PE-XXP[//F, (missing lower case letter)
^f~+””uwan]ny)b (missing upper case letter)
AQvoMApuNFyRkJd (missing symbols and numbers)
I know that I can do something like this to ensure each types of character are chosen:
import secrets
import string
def getRandomPasswordString(length):
    
    alphabet = string.ascii_letters + string.digits + string.punctuation
    password = secrets.choice(string.ascii_uppercase) + 
            secrets.choice(string.ascii_lowercase) + 
            secrets.choice(string.digits) + 
            secrets.choice(string.punctuation) + 
            ''.join(secrets.choice(alphabet) for i in range(length-4))
    return password
This works ok, but I am not sure if imposing some password patterns in the first 4 characters will cause any problem or not(i.e. the pattern is UPPERCASE > LOWERCASE > DIGIT > SYMBOLS)
Therefore, I would like to explore if there is any clean, one-line/shorter solution for generating the required passwords.
Many thanks in advance
Advertisement
Answer
simply shuffle the resulting password at the end by adding this:
password = "".join(random.sample(password,len(password)))
This way you meet the requirements without creating a pattern.
or you could shuffle the requirements and write the function like this:
from random  import sample
from secrets import choice
from string  import *
def getRandomPassword(length):
    alphabet      = ascii_letters + digits + punctuation
    requirements  = [ascii_uppercase,        # at least one uppercase letter
                     ascii_lowercase,        # at least one lowercase letter
                     digits,                 # at least one digit
                     punctuation,            # at least one symbol
                     *(length-4)*[alphabet]] # rest: letters digits and symbols
    return "".join(choice(req) for req in sample(requirements,length)) 
