2
\$\begingroup\$

I made a simple password generator (once again).

import random
import string
import pyperclip

class Password:
    def __init__(self, length, contains_lowercase, contains_uppercase, contains_digits, contains_symbols):
        self.length = length
        self.contains_lowercase = contains_lowercase
        self.contains_uppercase = contains_uppercase
        self.contains_digits = contains_digits
        self.contains_symbols = contains_symbols

    def generate(self):
        asciii = ""

        # adding parts of ascii code characters depending on corresponding booleans

        if self.contains_lowercase: 
            asciii += string.ascii_lowercase 

        if self.contains_uppercase:
            asciii += string.ascii_uppercase

        if self.contains_digits:
            asciii += string.digits

        if self.contains_digits:
            asciii += string.punctuation

        password = ""

        # appending random characters to an empty string from the ascii string until a its length reaches a certain value

        while len(password) < self.length:
            password += asciii[ random.randint(0, len(asciii) - 1) ]  

        return password


while True:
    length = input("\nEnter the length of your password: ")

    if length.isdigit() and int(length) > 0 and not length.startswith('0'):
        length = int(length)
        break

# empty strings converted to booleans are false

contains_lowercase = bool(input("\nWill it contain lowercase characters (a-z)? [ENTER] if not. "))

contains_uppercase = bool(input("\nWill it contain uppercase characters (A-Z)? "))

contains_digits = bool(input("\nDigits (0-9)? "))

contains_symbols = bool(input("\nSymbols? ")) 

password = Password(length, contains_lowercase, contains_uppercase, contains_digits, contains_symbols).generate()

print('\n' + password)

pyperclip.copy(password)

print("\nCopied to clipboard!")

input("Press [ENTER] to quit: ")

I kinda dislike the last part, because of similar looking lines...

And also if checks in the Password class are repetitive

I would like to see some different approaches.

\$\endgroup\$
2
2
\$\begingroup\$

Complexity

First: enforcing specific requirements around character types in an attempt to promote password complexity is outdated and shown to do more harm than help:

The forcing of lowercase, uppercase alphabetic characters, numbers and symbols in passwords was common policy, but has been found to actually decrease security, by making it easier to crack. Research has shown how very predictable common use of such symbols are, and the USA, UK government cyber security departments advise against forcing their inclusion in password policy. Complex symbols also makes remembering passwords much harder, which increases writing down, password resets and password reuse - all of which lower rather than improve password security. The original author of password complexity rules Bill Burr has apologised and admits they actually decrease security, as research has found, which was widely reported in the media in 2017.

It's a better idea to either:

  • more generally measure the entropy of a password and compare that to some minimum (if the password is user-provided);
  • use as broad a character set as at all possible if the password is being randomly generated and will be stored in a manager; or
  • use a passphrase instead of a password, if it's to be memorized.

You might need code like yours to accommodate websites with misdesigned password character criteria, but in the general case you should strongly prefer a non-constrained character set.

Secure PRNGs

You received an analogous comment on your previous password generator last year: the general-purpose random number generator provided by a framework is wholly insufficient for the purposes of secure password generation. Read the big, angry, red callout in the documentation:

Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module.

You should address these two fundamentals before continuing.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ What;s the take-away of your first part, i.e, what changes to the code would you make because of that? \$\endgroup\$ Aug 21 '21 at 19:57
  • 1
    \$\begingroup\$ The code doesn't "enforcing specific requirements around character types". The code builds a pool of characters to then build from, which you've said to do "use as broad a character set as at all possible if the password is being randomly generated and will be stored in a manager". Not all sites support all character sets, which is why password generators allow users to pick which character sets to pool from. \$\endgroup\$
    – Peilonrayz
    Aug 22 '21 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.