Friday, June 8, 2012

Offline Password Creator

UPDATE: Please read my update on password security, as this post is no longer good advice but will be left up for archival purposes.


Inspired by the xkcd comic Password Strength, I decided to write a python script that will create a password encryption scheme.

from xkcd.com
The problem I have with idea of choosing four random words is the fact that you still want a different set for each website (in case of attacks).

My solution was to create a list with a word associated with each letter from A to Z. The python script takes input from the given word list (aka dictionary) and randomly selects words for each letter and then spits out into a text file. It's quite easy to change the dictionary file just edit the line 
filename = "crossword_wordlist.txt"
to the file name you want. However the file must contains words that start with each letter (they do not have to be in order though).

The seed for the random number generator is based on the current time, and should be quite different for everyone to ensure it's difficult to duplicate.

Where to Download
You can grab a copy of the python script (with a random dictionary) from the gist/github page
For the lazy: Direct Download
(Code is pasted at the bottom as well)

How to Use
Here's my quick method for creating unique passwords for each site.
First save and/or print the file once you generate a list.
example list:
antileak
butles
collaged
duvet
egyptian
fenurons
gruyeres
hahas
ionogens
jovialty
kbars
logania
malteds
naturism
overdubs
prefire
quashers
releve
shickers
tavernas
undocile
varoomed
wonk
xanthans
yuppies
zlote
Then pick a website you want to create an account on. Let's say Blogger.com:
Take the first 4 letters of the site name (B, L, O, G in this case) and find the words for those letters and voila! You have your password! (butlesloganiaoverdubsgruyeres in this case).
Now some sites require upper-case and/or numbers so I'd use something easy like the first word in all caps, or every other letter in caps and then pick a number to use at a pre-determined spot. Then keep that little part consistent across sites (unless you want to come up with a system for caps and numbers. I may write a script to do it soon myself).

So this gives you a unique formula to create simple, secure passwords for any website without memorizing anything too crazy.

Comments and criticism are appreciated!


import os
import time
import random
 
## Variables ##
filename = "crossword_wordlist.txt" #file to load
path = os.path.abspath(os.curdir) #path to said file
 
output_filepath = path+"/offline_password_encryption_key.txt"
 
## Makes a list of lists. Each inner list (henceforth 'wordlist') will contain all the
## words starting with the appropriate letter (alphabet[0]=a, alphabet[1]=b, etc)
alphabet = [ list() for x in range(ord('a'),ord('z')+1)]
 
WORDFILE = open(path+"/"+filename, "r+") #gives us the file of words to use
code = "" #creates an empty string
random.seed(time.time()) #creates a random num generator with a unique seed based on the time you run the program
''' Intro '''
print "============================="
print "Offline Password Creator v1.0"
print "by James Firth"
print "============================="
 
 
 
''' Code that actually excutes stuff '''
 
 
#add all the words in the file to the appropriate wordlist
print "Adding words to dictionary..."
for line in WORDFILE:
 wordlist = alphabet[ord(line[0])-97] #find the index and grabs that wordlist
 wordlist.append(line) #append the new word to the wordlist
 
WORDFILE.close() #closing the file like a good little boy
 
 
print "Selecting our list of encryption words..."
 
#for all the letter in the alphabet
#picks a random number in the appropriate range
#grabs the right word. And appends to the encryption list
for wordlist in alphabet:
 if len(wordlist) > 0: 
  ranIndex = random.randint(0,len(wordlist)-1)
  chosen_word = wordlist[ranIndex] 
  code += (chosen_word)
  
OUTPUTFILE = open(output_filepath,"w+") #open the outpute file
print "Saving to file..."
OUTPUTFILE.write(code)
OUTPUTFILE.close()
print "~~ DONE!~~ \nYour Encryption Keys can be found at: "+output_filepath

2 comments:

  1. First of all, congratulations on such a quick reaction to your in-class inspiration. I can't do that even if I feel like coding occasionally :-)

    To my mind, however, having a password that consists of 27 words (if that is how much letters are considered in lover case dictionary of yours) is a bit hard-to-memorize-if-not-entirely-impossible. So it would be nice to "improve" it by having just 4 words (as that cartoon shows, it is quite sufficient) but then use a randomizer in a way that it would know which first letter it already picked.
    So say first words that pops out is "google", therefore, first letter is "g". You could make it so that it never considers words with "g" again - in that way it might be easier to memorize.

    Also, what I've just thought of, is it would be cool to search web for some dictionary that has a bunch of phrases, consisting of 2 words. Then, pick two randomly.

    Also, you can ask user for minimum password length, in characters - and then for number of words - and then match your result to user's specifications. But be careful here, since user might ask for 1000 as a minimum password length and just ask for one or two words, in which case you're doomed. (and you crash or die) :-)

    However, you might want to write an Exception handler for these cases - it will append a random letter until that word becomes large enough, I don't know, many things to do here.

    Also, I've seen some websites match your password to your login data. So they retain some of the login data in your password as well. OR some block that and don't allow it. You might think about that as just a login name and password creator - logic label works with existing login database (need a quick Action Handler here with a very,very quick search to tell if that login is available or not) and a password label (also with complicated Action Handler for any scans and checks you want to do)

    That might be just enough to give you some more ideas. Good job on Python, I still have to learn the syntax.

    ReplyDelete
  2. Neat, and fun.
    Thinking that having words shorter than 4 characters is probably a bad thing. Forked your gist, and made those changes. Merge 'em, man!
    Also, we can make this a CGI script really easily. Education!

    ReplyDelete

I appreciate feedback and discussion on these posts! If you post a question I'll try and get back to you soon. Please be kind to others.