Password Generator

February 4, 2020

Many web sites require passwords that have particular combinations of various types of characters; for instance, a web site might require a password that has at least ten characters, including at least one each from the sets of lower-case letters, upper-case letters, digits, and special characters.

Your task is to write a program that generates passwords according to specifications that you define. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.


Pages: 1 2

6 Responses to “Password Generator”

  1. Zack said

    Here is my take on it in Julia:
    I defined just 3 sets of characters but if one requires special characters too, one can define a forth set too and incorporate it in the program. Personally I find that easier to remember passwords that are of larger length are more effective and practical. Cheers!

  2. Daniel said

    Here’s a solution in Python.

    import random
    import string
    def generate(lower, upper, digits, special):
        output = random.choices(string.ascii_lowercase, k=lower)
        output.extend(random.choices(string.ascii_uppercase, k=upper))
        output.extend(random.choices(string.digits, k=digits))
        output.extend(random.choices(string.punctuation, k=special))
        return ''.join(output)
    print(generate(6, 6, 4, 2))

    Example output:

  3. John Cowan said

    Technically off-topic, but NIST has issued a new set of recommendations representing the state of the art in password choice: 8-64 characters, any Unicode character is valid (but normalize), check against known-bad and known-broken password databases, no password hints, no expiration. The idea is to make passwords both easier to remember and harder to break. There are other recommendations as well, like always allowing paste (to help password managers) and having an option to enable echoing while typing.

    So hopefully code like this will eventually be obsolete.

  4. Mayer Goldberg said

    I think the interface is more interesting than the code itself. Here’s mine (done in Chez Scheme):

    The password-generator takes a string in a DSL for specifying passwords, and optionally, minimum and maximum lengths.
    The password-generator can take categories of characters:

    Any capital letter (e.g., A or M) represents capital letters
    Any lowercase letter represents lowercase letters
    Any digit represents digits

    Thus AAA represents 3 capital letters. Optionally, I can specify the length in braces: A{2–5} represents anywhere between 2 and 5 capital letters.

    A user-defined category is specified in single quotes: ‘@$’ means one of the @ or $ characters

    What password-generator returns is a thunk that generates suggestions based on the specification. The suggested passwords are permuted

    Special syntax exists for specifying an initial, unpermuted substring, in case the password, e.g., MUST begin with a lowercase character… etc.

    Whitespaces are ignored in the specification string, and the range can be specified by any number of hyphens: E.g., —– would work just fine.

    I implemented this some time ago using my parsing-combinator library (which is why I’m not including the code, because I’d have to upload the library too).

    The way I use it is to define various generators based on the specific password syntax required by various sites, at work or on various online shops. Many sites & installations have their own idiosyncratic requirements for passwords, and I grew tired of having to think up a password that fit their specific nonsensical restrictions (e.g., requiring that there be exactly 2 digits or that the password starts with a lowercase character, actually makes it simpler and reduces the potential search space needed).

    One amusing consequence of using this password-generator is that I discovered many platforms that publish one set of rules for their passwords, and actually implement a slightly different set of rules. :-)

    ;;; > (define q
    ;;; (password-generator
    ;;; “A{2–3} a{4–8} 9{1–2} ‘!$@+'{1–2}”
    ;;; ;; optional: minimum & maximum lengths
    ;;; 7 9))
    ;;; > (q)
    ;;; “59vGSsz
    ;;; > (q)
    ;;; “vScH3r+eH”
    ;;; > (q)
    ;;; “0AshS+iv”
    ;;; > (q)
    ;;; “$t0z!hXkA”

    ;;; To specify initial, unpermuted elements, use an ! to separate
    ;;; the fixed from the permuted:
    ;;; > (define q (password-generator “a ! a{2-4}A{1-2}”))
    ;;; > (q)
    ;;; “eLza”
    ;;; > (q)
    ;;; “uUtq”
    ;;; > (q)
    ;;; “kxQp”

  5. Alex B said

    My go to password generator: Python 3 and uses the third-party pyperclip module ( to copy directly to the clipboard if required.

    import secrets
    import string
    import pyperclip
    def password(length=12, copy_to_cb=False, *,
                 allow_lower=True, num_lower=1,
                 allow_upper=True, num_upper=1,
                 allow_digit=True, num_digit=1,
                 allow_symbol=True, num_symbol=1,
        """Generate a random password conforming to the input parameters"""
        SYMBOLS = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
        allowed_chars = ''
        allowed_chars += string.ascii_uppercase if allow_upper else ''
        allowed_chars += string.ascii_lowercase if allow_lower else ''
        allowed_chars += string.digits if allow_digit else ''
        allowed_chars += SYMBOLS if allow_symbol else ''
        if allow_symbol and disallowed_symbols is not None:
            for sym in disallowed_symbols:
                allowed_chars = allowed_chars.replace(sym, '')
        if allowed_chars == '':
            raise Exception(
                'Cannot forbid all character types')
        if not allow_lower:
            num_lower = 0
        if not allow_upper:
            num_upper = 0
        if not allow_digit:
            num_digit = 0
        if not allow_symbol:
            num_symbol = 0
        if num_lower+num_upper+num_digit+num_symbol > length:
            raise ValueError(
                'Length cannot be less than sum of character requirements')
        while True:
            cand = ''.join(secrets.choice(allowed_chars) for i in range(length))
            if (sum(c.islower() for c in cand) >= num_lower
                    and sum(c.isupper() for c in cand) >= num_upper
                    and sum(c.isdigit() for c in cand) >= num_digit
                    and sum(c in SYMBOLS for c in cand) >= num_symbol):
                if copy_to_cb:
                    print('Password copied to clipboard')
                    return cand
  6. Patrik said

    (define (passgen len)
    (let*-values ([(genlist) (λ(x) (flatten (make-list len x)))]
    [(s n l u)
    (genlist (range 35 46))
    (genlist (range 48 57))
    (genlist (range 65 90))
    (genlist (range 97 122)))]
    [(i->c->s) (λ(x) (map (compose string integer->char) (shuffle x)))]
    [(lst) (for/fold
    ([acc ‘()])
    ([symbol (i->c->s s)]
    [number (i->c->s n)]
    [ll (i->c->s l)]
    [ul (i->c->s u)])
    (append (list symbol number ll ul) acc))]
    [(password) (string-join (take lst len) “”)])

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: