Reputation: 15227
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
Upvotes: 0
Views: 3442
Reputation: 61
I prefer to keep my generated passwords a little more complex. You can change the variation of amount of upper, lower, punctuation or numbers in the if statement:
import string
import secrets
opts = string.ascii_letters + string.digits + string.punctuation
#Generate a random password with at least two lower case, two upper case, one digit, and two symbols
while True:
psswd = ''.join(secrets.choice(opts) for i in range(12))
if (sum(c.islower() for c in psswd) >=2 and
sum(c.isupper() for c in psswd) >=2 and
sum(c in string.punctuation for c in psswd) >=2 and
any(c.isdigit() for c in psswd) ):
break
return psswd
Upvotes: 2
Reputation: 183
For anyone looking for something a lot simpler, you could just use the faker
package. There's a method .password()
you can feed args to, to make your passwords more or less complex.
Obviously, install faker
: pip install faker
Then, just 3 lines of code:
from faker import Faker
fake = Faker()
print(fake.password())
This will output a string of length 10, these are the default arguments you can use:
password(length=10, special_chars=True, digits=True, upper_case=True, lower_case=True)
This is just a simple run in my terminal:
from faker import Faker
fake = Faker()
fake.password()
'S9tBRdbf^C'
fake.password()
'NWN8FB4ku&'
fake.password()
'*0B7Z_TisD'
fake.password()
'L2R_bTkw_^'
Feel free to comment if you got questions.
Upvotes: 1
Reputation: 42143
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))
Upvotes: 1
Reputation: 17
import random
import string
def get_random_string(length):
letters = string.ascii_letters + string.digits + string.punctuation
result_str = ''.join(random.choice(letters) for i in range(length))
print("Random string of length", length, "is:", result_str)
get_random_string(8)
get_random_string(8)
get_random_string(6)
get_random_string(11)
get_random_string(22)
Upvotes: 1