Created
October 9, 2011 13:29
-
-
Save j605/1273689 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys, string, hashlib, getpass | |
ask_silent = getpass.getpass | |
def ask_normal(str): | |
sys.stderr.write(str) | |
return sys.stdin.readline()[0:-1] # remove the newline | |
def ask_master(): | |
mastone = 'x' | |
masttwo = 'y' | |
while mastone != masttwo: | |
mastone = ask_silent("Enter the master password: ") | |
masttwo = ask_silent("Retype the master password: ") | |
if mastone != masttwo: | |
sys.stderr.write("Password entries don't match, try again\n") | |
return mastone | |
def ask_length(): | |
passlength = 'ten' | |
while type(passlength) != type(10): | |
try: | |
passlength = int(ask_normal("Enter desired number of characters: ")) | |
except ValueError: | |
sys.stderr.write("Please enter a number.\n") | |
return passlength | |
def generate(master, reason, length): | |
characters = string.ascii_letters + string.digits # add other characters that can be used in your passwords here | |
hash = hashlib.sha256() | |
len_to_go = length | |
pwd = '' | |
while len_to_go: | |
hash.update(master) | |
hash.update(reason) | |
binary_pass = [ord(c) for c in hash.digest()] | |
pwd_part = ''.join([characters[i % len(characters)] for i in binary_pass])[0:len_to_go] | |
len_to_go -= len(pwd_part) | |
pwd += pwd_part | |
return pwd | |
def main_console(argv): | |
if '-s' in argv or '--silent' in argv: | |
global ask_normal | |
ask_normal = getpass.getpass | |
else: | |
sys.stderr.write('Warning, by default the reason and password length are not' | |
' read as passwords (your console will show what you type). If you do not ' | |
' want this, use the -s or --silent option.\n') | |
if '-u' in argv or '--unsafe' in argv: | |
master = ask_silent("Enter the master password: ") | |
else: | |
master = ask_master() | |
reason = ask_normal("Enter the reason: ") | |
length = ask_length() | |
sys.stderr.write('Your password is:\n') | |
sys.stdout.write(generate(master, reason, length) + '\n') | |
class PWGen_Window: | |
def __init__(self, gtk, silent, unsafe): | |
self.gtk = gtk | |
self.silent = silent | |
self.unsafe = unsafe | |
self.window = self.gtk.Window(self.gtk.WINDOW_TOPLEVEL) | |
self.window.set_title("PWGen") | |
self.window.connect("destroy", lambda w: self.gtk.main_quit()) | |
self.vbox = self.gtk.VBox() | |
self.add_mastone() | |
self.add_masttwo() | |
self.add_reason() | |
self.add_size() | |
self.add_buttons() | |
self.pwlabel = self.gtk.Label() | |
self.pwlabel.set_size_request(200, 20) | |
self.vbox.pack_start(self.pwlabel, True, True, 5) | |
self.window.add(self.vbox) | |
self.window.show_all() | |
self.clip = self.gtk.Clipboard() | |
def add_mastone(self): | |
box = self.gtk.HBox() | |
label = self.gtk.Label("The master password:") | |
label.set_size_request(165, 20) | |
label.set_alignment(0, 0.5) | |
box.pack_start(label, False, True, 5) | |
self.mastone = self.gtk.Entry() | |
self.mastone.set_visibility(False) | |
box.pack_start(self.mastone, True, True, 5) | |
self.vbox.pack_start(box, False, False, 2) | |
def add_masttwo(self): | |
if self.unsafe: | |
self.masttwo = None | |
else: | |
box = self.gtk.HBox() | |
label = self.gtk.Label("Retype master password:") | |
label.set_size_request(165, 20) | |
label.set_alignment(0, 0.5) | |
box.pack_start(label, False, True, 5) | |
self.masttwo = self.gtk.Entry() | |
self.masttwo.set_visibility(False) | |
box.pack_start(self.masttwo, True, True, 5) | |
self.vbox.pack_start(box, False, False, 2) | |
def add_reason(self): | |
box = self.gtk.HBox() | |
label = self.gtk.Label("the reason:") | |
label.set_size_request(165, 20) | |
label.set_alignment(0, 0.5) | |
box.pack_start(label, False, True, 5) | |
self.reason = self.gtk.Entry() | |
if self.silent: | |
self.reason.set_visibility(False) | |
box.pack_start(self.reason, True, True, 5) | |
self.vbox.pack_start(box, False, False, 2) | |
def add_size(self): | |
box = self.gtk.HBox() | |
label = self.gtk.Label("the password size:") | |
label.set_size_request(165, 20) | |
label.set_alignment(0, 0.5) | |
box.pack_start(label, False, True, 5) | |
self.size = self.gtk.Entry() | |
self.size.set_text('10') | |
if self.silent: | |
self.size.set_visibility(False) | |
box.pack_start(self.size, True, True, 5) | |
self.vbox.pack_start(box, False, False, 2) | |
def add_buttons(self): | |
box = self.gtk.HBox() | |
self.show_button = self.gtk.Button("Show password") | |
self.show_button.connect("clicked", self.show_pwcallback) | |
box.pack_start(self.show_button, True, True, 5) | |
self.clip_button = self.gtk.Button("Copy password to clipboard") | |
self.clip_button.connect("clicked", self.clip_pwcallback) | |
box.pack_start(self.clip_button, True, True, 5) | |
self.vbox.pack_start(box, False, False, 2) | |
def show_pwcallback(self, data): | |
if self.pwlabel.get_text(): | |
self.pwlabel.set_text('') | |
self.show_button.set_label("Show password") | |
else: | |
pwd = self.generate() | |
if not pwd: | |
return | |
self.pwlabel.set_text(pwd) | |
self.show_button.set_label("Clear password") | |
def clip_pwcallback(self, data): | |
pwd = self.generate() | |
if not pwd: | |
return | |
self.clip.set_text(pwd) | |
def generate(self): | |
mastone = self.mastone.get_text() | |
if self.masttwo: | |
masttwo = self.masttwo.get_text() | |
reason = self.reason.get_text() | |
if self.masttwo and mastone != masttwo: | |
dialog = self.gtk.MessageDialog(parent = self.window, | |
flags = self.gtk.DIALOG_MODAL | self.gtk.DIALOG_DESTROY_WITH_PARENT, | |
type = self.gtk.MESSAGE_WARNING, | |
buttons = self.gtk.BUTTONS_OK, | |
message_format = "\nThe master password is incorrect.") | |
dialog.run() | |
dialog.destroy() | |
return | |
try: | |
size = int(self.size.get_text()) | |
except ValueError: | |
dialog = self.gtk.MessageDialog(parent = self.window, | |
flags = self.gtk.DIALOG_MODAL | self.gtk.DIALOG_DESTROY_WITH_PARENT, | |
type = self.gtk.MESSAGE_WARNING, | |
buttons = self.gtk.BUTTONS_OK, | |
message_format = "\nNeed a number for size.") | |
dialog.run() | |
dialog.destroy() | |
return | |
return generate(mastone, reason, size) | |
def main_gtk(argv): | |
import pygtk | |
pygtk.require('2.0') | |
import gtk | |
silent = False | |
if '-s' in argv or '--silent' in argv: | |
silent = True | |
unsafe = False | |
if '-u' in argv or '--unsafe' in argv: | |
unsafe = True | |
window = PWGen_Window(gtk, silent, unsafe) | |
gtk.main() | |
def usage(argv): | |
sys.stderr.write('usage: {0:s} [options]\n'.format(argv[0]) | |
+ 'possible options are:\n' | |
+ ' -c, --console Don\'t open the GUI.\n' | |
+ ' -s, --silent Don\'t show the reason and password size.\n' | |
+ ' -u, --unsafe Don\'t ask to confirm the master password.\n\n') | |
def main(argv): | |
if '-h' in argv or '--help' in argv: | |
usage(argv) | |
return | |
if '-c' in argv or '--console' in argv: | |
main_console(argv) | |
else: | |
main_gtk(argv) | |
if __name__ == '__main__': | |
main(sys.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment