[NEM] 2008-11-27: Here's a [Tk] version of the Site Password program by Alan Karp at HP Labs [http://www.hpl.hp.com/personal/Alan_Karp/site_password/]. Instead of storing lots of passwords for every website you visit, or using the same password everywhere, this program lets you ''calculate'' a password based on a master password and an easy to remember site name. It works by concatenating the master password and the site name, taking the [MD5] hash of these and [base64] encoding the result. It works quite nicely. The version here improves on the [Python] version on the site by using [Ttk] widgets and allowing you to save previously entered site names. This version also support a command-line only mode: simply pass the sitename as an argument: sitepw.tcl ?sitename ?-alphanumeric 0|1?? (Note: command-line only works on UNIX-like systems that have [stty]). [http://www.cs.nott.ac.uk/~nem/sitepw.png] **Usage** Simply type in your master password and then enter the website name. The site-specific password will appear in the Site Password box. You can copy this password to the clipboard using the Copy button (or select and Ctrl-C as usual). The Add button saves the current website name to a preferences file (don't worry -- the site name is not sufficient to calculate your passwords). On UNIX this prefs file is stored in ~/.sitepw, on Windows in ~/Application Data/sitepw.rc (may need to be localised?), and on Mac in ~/Library/Preferences/sitepw.rc. The Done button exits the application. ====== #!/usr/bin/env tclsh # sitepw.tcl package require Tcl 8.5 package require md5 2.0 package require base64 2.3 proc sitepw args { if {[llength $args] >= 1} { set pw [readpw] puts [password $pw {*}$args] } else { package require Tk 8.5 CreateGUI } } proc readpw {} { # Read password from stdin in a safe-ish manner puts -nonewline "Password: " flush stdout exec stty -echo gets stdin pw exec stty echo return $pw } # Compute a site-specific password proc password {master sitename args} { array set ops { -alphanumeric 0 -length 12 } array set ops $args # Compute MD5 hash of inputs to generate unique password set sitename [string tolower $sitename] set digest [md5::md5 $sitename$master] set digest [base64::encode $digest] if {$ops(-alphanumeric)} { set digest [string map {/ "" + ""} $digest] } return [string range $digest 0 [expr {$ops(-length)-1}]] } proc CreateGUI {} { set f [ttk::frame .f] ttk::label $f.pl -text "Master Password:" -anchor e ttk::entry $f.passwd -textvariable ::master -show * ttk::label $f.sl -text "Website:" -anchor e ttk::combobox $f.site -textvariable ::site ttk::label $f.gl -text "Site Password:" -anchor e ttk::entry $f.spass -textvariable ::sitepw ttk::checkbutton $f.alpha -text "Letters/numbers only" -variable ::alpha set tb [ttk::frame .tb] ttk::button $tb.done -text "Done" -command Exit ttk::button $tb.save -text "Add" -command [list AddSite $f.site] ttk::button $tb.copy -text "Copy" \ -command [list Copy $f.spass] bind . [list $tb.copy invoke] set ::master "" set ::site "" set ::sitepw "" set ::alpha 0 LoadSites $f.site wm protocol . WM_DELETE_WINDOW Exit grid $f.pl $f.passwd -sticky ew grid $f.sl $f.site -sticky ew grid $f.gl $f.spass -sticky ew grid $f.alpha - grid columnconfigure $f 1 -weight 1 grid $tb.done $tb.save $tb.copy -sticky e -padx 10 -pady 2 grid $f -sticky ew grid $tb -sticky ew grid columnconfigure . 0 -weight 1 wm resizable . 1 0 wm title . "Site Password" trace add variable ::master write UpdatePW trace add variable ::site write UpdatePW trace add variable ::alpha write UpdatePW } # Load list of previously accessed sites into the combobox w proc LoadSites w { catch { set in [open [PrefFile] r] set sites [split [string trim [read $in]] \n] close $in $w configure -values $sites } } proc SaveSites w { set out [open [PrefFile] w] puts $out [join [$w cget -values] \n] close $out } proc Exit {} { SaveSites .f.site exit } proc AddSite w { set sites [$w cget -values] set site [$w get] lappend sites $site set sites [lsort -unique -dictionary $sites] $w configure -values $sites } proc PrefFile {} { switch -exact [tk windowingsystem] { x11 { return [file normalize ~/.sitepw] } win { return [file normalize "~/Application Data/sitepw.rc"] } aqua { return [file normalize ~/Library/Preferences/sitepw.rc] } } } proc Copy w { clipboard clear clipboard append [$w get] } proc UpdatePW {args} { global master site sitepw alpha set sitepw [password $master $site -alphanumeric $alpha] } sitepw {*}$argv ====== See also: [Password Gorilla] ---- !!!!!! %| [Category Application] | [Category Security] |% !!!!!!