Once again in the password trenches, or, take a look at my shiny new quick Python code for making random passwords

[Contact Me] | [FAQ]

[Some "Dougisms" Defined]

[About Dickens of a Blog]

[Jump to Site Links]

Summary: Changing out passwords is everybody's worst friend, or best enemy, or whatever you would call it when it is necessary but it just bugs the hell out of you. Here is one program that I came up with to help speed it up.

BLOT: (04 Feb 2014 - 08:10:14 PM)

Once again in the password trenches, or, take a look at my shiny new quick Python code for making random passwords

I have written about passwords, coming up with good ones and the act of changing them out and common mistakes and such, before. I've written other bits on the topic, some good and some piss-poor, and this is not going to be a further assault on said senses. Instead, I am just going to share with you a program I wrote to generate "by-the-character" random passwords. In other words, it doesn't generate patterns or passwords out of seeds. It simply takes some basic variables—subsets of characters, number of passwords to make, length of passwords to make, whether every letter should be unique, whether there should be at least one character from every subset—and it spits out a hunk of passwords.

The downs. These passwords are only as random as "import random" guarantees. They are not human-friendly, so you would probably need some sort of password manager to keep track of more than a couple of them. The options are written directly into the program, so to change out options you'll have to edit the file itself, first [I've included notes]. I am not a Python mastermind so don't expect to be utterly amazed at my sweet, sweet algorithms.

The ups! Runs very quickly. Can make really long passwords. Allows you to edit character sets as you see fit. I've tried to make variables and functions fairly logical so that you can hack whatever you want into the code for your own use. I've also tried writing it in such a way that even people who don't know Python3 should feel comfortable with tweaking things, so hopefully someone will have fun just playing around with it.

The Code!

passwordgen.py.txt [rename to passwordgen.py or whatever you want to call it, had to slap a txt file extension to make the server happy]. You can browse it below [but due to Python's need for white-space, I wouldn't copy and paste it from there].

# Doug's Random By-Character Password Generator # # This is a fairly simple random-by-character-passwword # generator. I'm considering it 'public domain' for all intents # and purposes. It uses Python3, but I think could work for # Python2 if you tweak the print statements. # # Right now, it is its own config file. The options are listed # below, with comments. It is not super-hard to change the # file to read from a config file or to read from the command- # line, but I would consider such extraneous unless you wanted # to make it much more 'on the fly', in which cases choices # could be simplified down. # # The basic settings are to combine upper- and lowercase # letters, numbers, and symbols to form a character-set which # is then chosen from, one at a time, to generate a certain # length random password. There are tools in place to make # sure that characters aren't repeated and to make sure # types of characters are all included. Comments will explain # how to tweak this behavior or expand upon it. import random # If for some reason you want to change the character set, you # can do it here. The most logical one to change is the # "symbols" subset , but the others are up to change as well if # you want to use a non-English set of letters, or to # exclude commonest use letters, etc. # # symbols = mostly the characters from the number keys, plus # a comma and period. Most websites take this, but not all. # It is probably quicker to leave it as such and then edit down # as needed to fit site requirement. # # I've included a subset for 'esoteric' (i.e., symbols # not standard on keyboards) but have purposefully left blank, # for obvious reasons. If you have a keyboard/OS that supports # such characters, though, it can make for interesting choices. uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" lowercaseLetters = "abcdefghijklmnopqrstuvwxyz" numbers = "0123456789" symbols = "!@#$%^&*(),." esoteric = "" # The pattern is the subsets of characters that will be # used. Each subset can be used more than once. # Since there are more upper- and lowercase letters # available than the other sets, multiples of the other sets # are added in to increase their odds. # # The pattern below is one that I have good luck with, feel # free to alter it to fit your needs. # # Perhaps obvious, but # U/u = uppercaseLetters # L/l = lowercaseLetters # N/n = numbers # S/s = symbols # E/e = esoteric # # Other options can be encoded in, but as it stands, other # letters (etc) will be ignored. pattern = "ULLNNNSS" # Many websites want passwords less than about 20-32 characters # so length is set to 20, here, which is still a fairly hard # length to crack. You can always make it longer and only retain # a proper lengthed-substring as you wish. # # As a note, if you set this to large number and you keep # makeUnique as True, you must have at least as many *unique* # characters in your set as characters in the password. # # Conversely, if passwordLength is *less* than the number # of *potential* subsets, it will break the program. For such # reasons, it should probably be greater than 5. Technically, # this issue can be avoided by setting includeOneOfEach to # False. passwordLength = 20 if passwordLength < 5: passwordLength = 5 # You can generate as many as you want. All will be outputted # at once. passwordCount = 10 # If file name is left blank, will ouptut to terminal. outfile = "passwords.txt" try: if outfile is not '': passwordFile = open(outfile, 'w') except: outfile = "" # If makeUnique is set to True, then each character will only # be used once. If you leave it blank or set it to False, the # characters may be used multiple times (and probably will be) # # If you are making very long passwords, you probably want to # to turn this off since it will delete *any* and *all* # matching characters. makeUnique = True # There is logic built in that it has to have one character # from each subset. Based on your subset choices, it will # switch the need to have that subset automatically. # # Note: If you only call a small character set once, # it can greatly add to the time it takes to run the # program since most runs will fail. For similar reasons, do # not call upon a blank set, or all will fail and it will # infiniloop. needsUpper = False needsLower = False needsNumber = False needsSymbol = False needsEsoteric = False # If do not care if it has one of each subset, you can set # includeOneOfEach to False and it will ignore such checks includeOneOfEach = True characters = "" # Just in case you type in the subset codes in lowercase, this # gets it all on the same page. pattern = pattern.upper() for p in pattern: addition = p if addition == "U": characters = characters + uppercaseLetters if includeOneOfEach: needsUpper = True elif addition == "L": characters = characters + lowercaseLetters if includeOneOfEach: needsLower = True elif addition == "N": characters = characters + numbers if includeOneOfEach: needsNumber = True elif addition == "S": characters = characters + symbols if includeOneOfEach: needsSymbol = True elif addition == "E": characters = characters + esoteric if includeOneOfEach: needsEsoteric = True else: characters = characters print ("Characters being used: ", characters) print ("Generating ", passwordCount, " passwords at ", passwordLength, " characters per password.") pc = 0 while (pc < passwordCount): thisPass = "" theseCharacters = characters pwl = 1 hasUpper = False hasLower = False hasNumber = False hasSymbol = False hasEsoteric = False while (pwl < passwordLength): thisChar = theseCharacters[random.randint(0, len(theseCharacters)-1)] if makeUnique: for checkChar in theseCharacters: if checkChar in thisChar: theseCharacters = theseCharacters.replace(thisChar, "") if thisChar in uppercaseLetters: hasUpper = True if thisChar in lowercaseLetters: hasLower = True if thisChar in numbers: hasNumber = True if thisChar in symbols: hasSymbol = True if thisChar in esoteric: hasEsoteric = True thisPass = thisPass + thisChar pwl = pwl + 1 # Possibly the most Pythonic if-then statement I have # ever written... if ((hasUpper or not needsUpper) and (hasLower or not needsLower) and (hasNumber or not needsNumber) and (hasSymbol or not needsSymbol) and (hasEsoteric or not needsEsoteric)): if outfile is not '': print (thisPass, file=passwordFile) else: print (thisPass) pc = pc + 1 # By the way, at this point, if the password doesn't pass the # "has one character from each subset" test, it simply doesn't # get recorded or counted and the program goes back through. # There are other ways to handle it but this works for me.

Computer Security


Written by Doug Bolden

For those wishing to get in touch, you can contact me in a number of ways

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

The longer, fuller version of this text can be found on my FAQ: "Can I Use Something I Found on the Site?".

"The hidden is greater than the seen."