Added "change-password" subcommand

This commit is contained in:
Jonas Borgström 2011-10-27 22:17:47 +02:00
parent 9e5b13df44
commit f282fd6930
3 changed files with 34 additions and 15 deletions

View file

@ -42,15 +42,24 @@ class Archiver(object):
return StoreServer().serve()
def do_init(self, args):
print 'Initializing store "%s"' % args.store.orig
store = self.open_store(args.store, create=True)
Key.create(store, args.store.to_key_filename(),
password=args.password)
key = Key(store)
key = Key.create(store, args.store.to_key_filename(), password=args.password)
print 'Key file "%s" created.' % key.path
print 'Remember that this file (and password) is needed to access your data. Keep it safe!'
print
manifest = Manifest(store, key, dont_load=True)
manifest.write()
store.commit()
return self.exit_code
def do_chpasswd(self, args):
key = Key()
key.open(args.store.to_key_filename())
key.chpasswd()
print 'Key file "%s" updated' % key.path
return self.exit_code
def do_create(self, args):
t0 = datetime.now()
store = self.open_store(args.archive)
@ -300,6 +309,12 @@ class Archiver(object):
type=location_validator(archive=False),
help='Store to create')
subparser = subparsers.add_parser('change-password', parents=[common_parser])
subparser.set_defaults(func=self.do_chpasswd)
subparser.add_argument('store', metavar='STORE',
type=location_validator(archive=False),
help='Key file to operate on')
subparser = subparsers.add_parser('create', parents=[common_parser])
subparser.set_defaults(func=self.do_create)
subparser.add_argument('-s', '--stats', dest='stats',

View file

@ -13,6 +13,7 @@ import sys
import time
import urllib
class Manifest(object):
MANIFEST_ID = '\0' * 32
@ -327,6 +328,7 @@ class Location(object):
r'(?P<path>[^:]*)(?:::(?P<archive>.+))?')
def __init__(self, text):
self.orig = text
if not self.parse(text):
raise ValueError

View file

@ -19,9 +19,9 @@ PREFIX = '\0' * 8
class Key(object):
FILE_ID = 'DARC KEY'
def __init__(self, store=None):
def __init__(self, store=None, password=None):
if store:
self.open(self.find_key_file(store))
self.open(self.find_key_file(store), password=password)
def find_key_file(self, store):
id = store.id.encode('hex')
@ -34,17 +34,18 @@ class Key(object):
return filename
raise Exception('Key file for store with ID %s not found' % id)
def open(self, filename):
def open(self, filename, prompt=None, password=None):
prompt = prompt or 'Enter password for %s: ' % filename
with open(filename, 'rb') as fd:
lines = fd.readlines()
if not lines[0].startswith(self.FILE_ID) != self.FILE_ID:
raise ValueError('Not a DARC key file')
self.store_id = lines[0][len(self.FILE_ID):].strip().decode('hex')
cdata = (''.join(lines[1:])).decode('base64')
self.password = ''
data = self.decrypt_key_file(cdata, '')
self.password = password or ''
data = self.decrypt_key_file(cdata, self.password)
while not data:
self.password = getpass('Key password: ')
self.password = getpass(prompt)
if not self.password:
raise Exception('Key decryption failed')
data = self.decrypt_key_file(cdata, self.password)
@ -59,6 +60,7 @@ class Key(object):
self.id_key = key['id_key']
self.chunk_seed = key['chunk_seed']
self.counter = Counter.new(64, initial_value=1, prefix=PREFIX)
self.path = filename
def post_manifest_load(self, config):
iv = bytes_to_long(config['aes_counter'])+100
@ -69,7 +71,7 @@ class Key(object):
def encrypt_key_file(self, data, password):
salt = get_random_bytes(32)
iterations = 2000
iterations = 10000
key = pbkdf2(password, salt, 32, iterations, hashlib.sha256)
hash = HMAC.new(key, data, SHA256).digest()
cdata = AES.new(key, AES.MODE_CTR, counter=Counter.new(128)).encrypt(data)
@ -106,9 +108,9 @@ class Key(object):
with open(path, 'wb') as fd:
fd.write('%s %s\n' % (self.FILE_ID, self.store_id.encode('hex')))
fd.write(data.encode('base64'))
print 'Key file "%s" created' % path
self.path = path
def chpass(self):
def chpasswd(self):
password, password2 = 1, 2
while password != password2:
password = getpass('New password: ')
@ -130,8 +132,8 @@ class Key(object):
else:
password, password2 = 1, 2
while password != password2:
password = getpass('Key password: ')
password2 = getpass('Key password again: ')
password = getpass('Key file password (Leave blank for no password): ')
password2 = getpass('Key file password again: ')
if password != password2:
print 'Passwords do not match'
key = Key()
@ -148,7 +150,7 @@ class Key(object):
if key.chunk_seed & 0x80000000:
key.chunk_seed = key.chunk_seed - 0xffffffff - 1
key.save(path, password)
return 0
return Key(store, password=password)
def id_hash(self, data):
"""Return HMAC hash using the "id" HMAC key