Welcome, guest | Sign In | My Account | Store | Cart

Since everyone is posting one of these, I thought I'd post mine. I wrote this many years ago and use it everywhere.

Python, 52 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python

import string
from time import time
from itertools import chain
from random import seed, choice, sample


def mkpasswd(length=8, digits=2, upper=2, lower=2):
    """Create a random password

    Create a random password with the specified length and no. of
    digit, upper and lower case letters.

    :param length: Maximum no. of characters in the password
    :type length: int

    :param digits: Minimum no. of digits in the password
    :type digits: int

    :param upper: Minimum no. of upper case letters in the password
    :type upper: int

    :param lower: Minimum no. of lower case letters in the password
    :type lower: int

    :returns: A random password with the above constaints
    :rtype: str
    """

    seed(time())

    lowercase = string.lowercase.translate(None, "o")
    uppercase = string.uppercase.translate(None, "O")
    letters = "{0:s}{1:s}".format(lowercase, uppercase)

    password = list(
        chain(
            (choice(uppercase) for _ in range(upper)),
            (choice(lowercase) for _ in range(lower)),
            (choice(string.digits) for _ in range(digits)),
            (choice(letters) for _ in range((length - digits - upper - lower)))
        )
    )

    return "".join(sample(password, len(password)))


print mkpasswd()
print mkpasswd(12)
print mkpasswd(digits=3)
print mkpasswd(12, upper=4)

ChangeLog:

  • Fixed missing import of sample(...)
  • Fixed several issues with the sets of lower and upper case letters. Thanks for the comments!

9 comments

James Mills (author) 11 years, 1 month ago  # | flag

An interactive version of this here:

http://codepad.org/WkWX1FUg

--JamesMills / prologic

James Mills (author) 11 years, 1 month ago  # | flag

An improved version of this:

http://codepad.org/BRf7it2s

--JamesMills / prologic

Grijesh Chauhan 11 years, 1 month ago  # | flag

Hi James Mill,

Your code is beautiful and very good documentation.

Thanks!!

Grijesh Chauhan 11 years, 1 month ago  # | flag

I have a doubt in your code.

In your code line:

>>> letters = string.letters.strip("oO") 
do nothing

To remove small and Capital O one should use translate().

>>> import string
>>> letters = string.letters
>>> letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> letters.translate(None,'oO')
'abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ'

Am I correct?

Grijesh Chauhan 11 years, 1 month ago  # | flag

The line

>>>   letters = string.letters.strip("oO")

can be replace by

>>>   letters = string.letters.translate(None,'oO')
James Mills (author) 11 years, 1 month ago  # | flag

@Grijesh: Thank you for your comments. I have fixed the sets of letters :)

NB: This only works on Python 2.6 and 2.7 now.

--JamesMills / prologic

Martin Miller 10 years, 2 months ago  # | flag

The documentation for therandommodule specifically says:

Warning: The pseudo-random generators of this module should not be used for security purposes. Useos.urandom()orSystemRandomif you require a cryptographically secure pseudo-random number generator.

Which means usingrandom.choice()to generate passwords might not be such a good idea.

Martin Miller 10 years, 2 months ago  # | flag

To follow-up on my previous comment/criticism, from looking at the current (v2.7.6 and v3.3.3) source code for the random module, fortunately there appears to be a simple way to make the methods in it use a random.SystemRandom class instance as its source of pseudo-random numbers.

Just change the beginning of the script to the following:

import string
from time import time
from itertools import chain
# patch module to use cryptographically secure source of numbers
import random
random._inst = random.SystemRandom()
from random import seed, choice, sample

Note that the documentation says that SystemRandom isn't available on all systems, so doing this makes the script slightly less portable, but it will fail in that case, rather than generate less secure passwords.

James Mills (author) 10 years, 2 months ago  # | flag

@Martin Miller: Thanks! I'll do that :) TBH I don't know a terrible lot about the internals of random nor much about cryptography in general (as much as the next developer I guess).

It seems to me though; that it isn't completely necessary to have a source of cryptographically secure random numbers or a true random number generator to generator good passwords? Maybe that's a bad assumption as hackers with similar or identical hardware could potentially generate a dictionary of the same passwords?