#!/usr/bin/env python import os, sys, md5, shelve from Crypto.Cipher import Blowfish from optparse import OptionParser from getpass import getpass try: database = shelve.open("%s/.zpass/zpass.dbm" % os.environ["HOME"]) except: print "Cant create file database, check permissions" sys.exit(1) def show_record(record): if database.has_key(record): record = database[record] print "Your username is: \n%s " % _decode_data(record[0]) print "Your password is: \n%s" % _decode_data(record[1]) print "Additional information: \n%s" % _decode_data(record[2]) else: print "No such record. Execute '%s -l' to list all records avialable" % sys.argv[0] def add_record(record): if database.has_key(record): print "This record already exists" else: username = raw_input("Please enter an username:\n") password = raw_input("Please enter an password:\n") comment = raw_input("Please enter additional information:\n") database[record] = map(_encode_data, (username, password, comment)) database.close() def list_records(): for key in database.keys(): if key != '__passphrase': print key def modify_record(record): if not database.has_key(record): print "No such record in database" else: username = raw_input("Please enter an username: (leave blank to retain old username)\n") password = raw_input("Please enter an password: (leave blank to retain old password)\n") comment = raw_input("Please enter an comment: (leave blank to retain old comment)\n") if not username: username = _decode_data(database[record][0]) if not password: password = _decode_data(database[record][1]) if not comment: comment = _decode_data(database[record][2]) database[record] = map(_encode_data, (username, password, comment)) database.close() def delete_record(record): if not database.has_key(record): print "No such record in database" else: yesno = raw_input("Are you sure you want to delete %s? (y/n): " % record) if yesno == 'y': del database[record] print "Record %s successfully deleted" % record else: print "The only allowed variants is 'y' for yes, and 'n' for no" database.close() def controller(): parser = OptionParser(description="Python password reminder", prog="zpass", version="0.1", usage="%prog [-a|s|m|d|l|h|v] [arg1]") parser.add_option('--add', '-a', metavar="record", help="Add new record to database") parser.add_option('--show', '-s', metavar="record", help="Show record data") parser.add_option('--modify', '-m', metavar="record", help="Modify record data in database") parser.add_option('--delete', '-d', metavar="record", help="Delete record data from database") parser.add_option('--list', '-l', action="store_true", help="List all record names in database") options, arguments = parser.parse_args() if len(arguments) != 0: parser.error("You should use option and one record name") elif options.add and options.show: parser.error("options -a and -s are mutually exclusive") elif options.add: add_record(options.add) elif options.show: show_record(options.show) elif options.list: list_records() elif options.modify: modify_record(options.modify) elif options.delete: delete_record(options.delete) def check_passphrase(): global user_passphrase user_passphrase = getpass("Please enter an passphrase\n") if database.has_key('__passphrase'): if not md5.new(user_passphrase).hexdigest() == database['__passphrase']: print "Wrong passphrase" sys.exit(1) else: database['__passphrase'] = md5.new(user_passphrase).hexdigest() return controller() def _encode_data(value): return Blowfish.new(user_passphrase, Blowfish.MODE_CFB).encrypt(value) def _decode_data(value): return Blowfish.new(user_passphrase, Blowfish.MODE_CFB).decrypt(value) check_passphrase()