Skip to content
Advertisement

Python password generation

I need to generate random passwords for my company’s 200k+ customers.

The password complexity requirement is a common one:

  1. length > 8
  2. contains at least one upper case character
  3. contains at least one lower case character
  4. contains at least one number
  5. 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)) 
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement