# Copyright Hewlett-Packard, 2002, Hewlett-Packard
#
# A little program to hash a user password with a site-specific string
# The result is a random looking string that can be used as a password
# on that site.  This tool lets you use the same password string for
# all sites, but assures that the password sent to the site is
# different from that of any other site.
#
#  2/ 7/02 - Initial version 0.1
#  2/ 7/02 - Changed result field so it can be cut and pasted, version 0.2
#
# To do:
#
# 1. Make it prettier
# 2. Accept enter key
# 3. Put cursor in password input field at start
# 4. Make a browser plugin that pops up when a password field appears
# 5. Port to Jornada
#
# Alan Karp, alan.karp@hp.com, 7 February 2002

from Tkinter import *
version = "Version 0.2"

# Generate Help window

def gethelp():
  top = Toplevel()
  h = Frame(top)
  h.pack()
  m = Message(h,relief=SUNKEN, text = """
                   Site-specific Password Generator
                   (Patent Pending, Hewlett-Packard)

    Combines a name for a web site and your password to produce
    a password unique to the site.  This tool lets you use a single
    password for all your web logins without worrying that the owner
    of one site will use your password on another one, perhaps
    draining your bank account.

    There are two input fields.

       Your password 
             A string that you can remember.  It should still be
             hard to guess because this tool uses a well-known
             algorithm, and you use well-known site names.  Case
             sensitive.

       Site name
             Your name for the site.  For example, Schwab, or
             Amazon.  Case insensitive.

    Click on "Generate Password" to get a site-specific password.
    The result is 12 ASCII characters.  Some sites do not accept
    characters other than number or letters.  In this case, just
    don't use other characters when you enter your site-specific
    password in their login windows.
    """)
  m.pack()
  m.config(width=500)

  c = Button(h,text='Close',command=top.destroy)
  c.pack()

# Generate Error window

def error():
  top = Toplevel()
  h = Frame(top)
  h.pack()
  m = Message(h,relief=SUNKEN, text = "You forgot to enter a password.", width=150)
  m.pack()
  c = Button(h,text='Close',command=top.destroy)
  c.pack()

# Routine that does the actual work

import md5, base64
def genpw():

# Use MD5 hash to produce an unguessable string from the inputs

  m = md5.new()
  location = site.get()
  m.update(location.lower())
  password = pw.get()
  if len(password) == 0:
    error()
  m.update(password)

# Convert to ascii characters

  password = (base64.encodestring(m.digest()))[0:12]
  pwout.delete(0,END)
  pwout.insert(0,password)

# Main routine

# Header

root = Tk()
Label(root, text=("Site-specific Password "+version)).pack()

# Password entry field

f2 = Frame(root)
f2.pack()
Label(f2, text="Your password", relief=RIDGE, width=20, font = 'Courier').pack(side=LEFT)
pw = Entry(f2, show="*", relief=SUNKEN, font = 'Courier')
pw.pack(side=RIGHT, expand=YES, fill=X)

# Site entry field

f1 = Frame(root)
f1.pack()
Label(f1, text="Site name", relief=RIDGE, width=20, font = 'Courier').pack(side=LEFT)
site = Entry(f1, relief=SUNKEN, font = 'Courier')
site.pack(side=LEFT, expand=YES, fill=X)


# Output field

f3 = Frame(root)
f3.pack()
Label(f3, text="Site password", relief=RIDGE, width=20, font = 'Courier').pack(side=LEFT)
pwout = Entry(f3, font = 'Courier', relief=RIDGE)
pwout.pack(side=LEFT)

# Generate Buttons

f4 = Frame(root)
f4.pack()
Button(f4, text='Generate Password', command=genpw).pack(side=LEFT)
Button(f4, text='Help', command=gethelp).pack(side=RIGHT)
Button(f4, text='Close', command=root.destroy).pack(side=LEFT)

# Run it

root.mainloop()
