Merge pull request #21 from gissehel/sharedfolders

Shared keys now works for file comming from shared folders that aren't shared anymore
This commit is contained in:
Richard O'Dwyer 2013-04-15 07:56:57 -07:00
commit 10b4a883a8

View file

@ -38,7 +38,6 @@ class Mega(object):
def _login_process(self, resp, password): def _login_process(self, resp, password):
encrypted_master_key = base64_to_a32(resp['k']) encrypted_master_key = base64_to_a32(resp['k'])
self.master_key = decrypt_key(encrypted_master_key, password) self.master_key = decrypt_key(encrypted_master_key, password)
self.users_keys = dict()
if 'tsid' in resp: if 'tsid' in resp:
tsid = base64_url_decode(resp['tsid']) tsid = base64_url_decode(resp['tsid'])
key_encrypted = a32_to_str( key_encrypted = a32_to_str(
@ -100,23 +99,33 @@ class Mega(object):
else: else:
raise RequestError('Url key missing') raise RequestError('Url key missing')
def process_file(self, file): def process_file(self, file, shared_keys):
""" """
Process a file Process a file
""" """
if file['t'] == 0 or file['t'] == 1: if file['t'] == 0 or file['t'] == 1:
keys = dict(keypart.split(':',1) for keypart in file['k'].split('/'))
uid = file['u'] uid = file['u']
keys = file['k'].split('/')
regex = re.compile('^%s:.*$' % uid)
key = None key = None
for keytmp in keys:
if regex.match(keytmp):
key = keytmp[keytmp.index(':') + 1:]
break
# my objects # my objects
if key: if uid in keys :
key = decrypt_key(base64_to_a32(key), self.master_key) key = decrypt_key(base64_to_a32( keys[uid] ), self.master_key)
# shared folders
elif 'su' in file and 'sk' in file and ':' in file['k']:
shared_key = decrypt_key(base64_to_a32(file['sk']),self.master_key)
key = decrypt_key(base64_to_a32(keys[file['h']]),shared_key)
if file['su'] not in shared_keys :
shared_keys[file['su']] = {}
shared_keys[file['su']][file['h']] = shared_key
# shared files
elif file['u'] and file['u'] in shared_keys :
for hkey in shared_keys[file['u']] :
shared_key = shared_keys[file['u']][hkey]
if hkey in keys :
key = keys[hkey]
key = decrypt_key(base64_to_a32(key),shared_key)
break
if key is not None :
# file # file
if file['t'] == 0: if file['t'] == 0:
k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6], k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
@ -129,39 +138,6 @@ class Mega(object):
attributes = base64_url_decode(file['a']) attributes = base64_url_decode(file['a'])
attributes = decrypt_attr(attributes, k) attributes = decrypt_attr(attributes, k)
file['a'] = attributes file['a'] = attributes
# shared folders
elif 'su' in file and 'sk' in file and ':' in file['k']:
user_key = decrypt_key(base64_to_a32(file['sk']),
self.master_key)
key = decrypt_key(base64_to_a32(file['k'].split(':')[1]),
user_key)
# save user_key to decrypt shared files
self.users_keys[file['su']] = user_key
if file['t'] == 0:
k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
key[3] ^ key[7])
file['iv'] = key[4:6] + (0, 0)
file['meta_mac'] = key[6:8]
else:
k = key
attributes = base64_url_decode(file['a'])
attributes = decrypt_attr(attributes, k)
file['a'] = attributes
# shared files
elif file['u'] and ':' in file['k']:
user_key = self.users_keys[file['u']]
key = decrypt_key(base64_to_a32(file['k'].split(':')[1]),
user_key)
if file['t'] == 0:
k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
key[3] ^ key[7])
file['iv'] = key[4:6] + (0, 0)
file['meta_mac'] = key[6:8]
else:
k = key
attributes = base64_url_decode(file['a'])
attributes = decrypt_attr(attributes, k)
file['a'] = attributes
# other => wrong object # other => wrong object
elif file['k'] == '': elif file['k'] == '':
file['a'] = False file['a'] = False
@ -176,6 +152,24 @@ class Mega(object):
file['a'] = {'n': 'Rubbish Bin'} file['a'] = {'n': 'Rubbish Bin'}
return file return file
def init_shared_keys(self,files,shared_keys) :
'''
Init shared key not associated with a user.
It seems to happen when a folder is shared,
some files are exachanged and then the
folder is not shared anymore.
Keys are stored in files['s'] and files['ok']
'''
ok_dict = {}
for ok_item in files['ok'] :
shared_key = decrypt_key(base64_to_a32(ok_item['k']),self.master_key)
ok_dict[ok_item['h']] = shared_key
for s_item in files['s'] :
if s_item['u'] not in shared_keys :
shared_keys[s_item['u']] = {}
if s_item['h'] in ok_dict :
shared_keys[s_item['u']][s_item['h']] = ok_dict[s_item['h']]
########################################################################## ##########################################################################
# GET # GET
def find(self, filename): def find(self, filename):
@ -193,8 +187,10 @@ class Mega(object):
''' '''
files = self.api_request({'a': 'f', 'c': 1}) files = self.api_request({'a': 'f', 'c': 1})
files_dict = {} files_dict = {}
shared_keys = {}
self.init_shared_keys(files,shared_keys)
for file in files['f']: for file in files['f']:
processed_file = self.process_file(file) processed_file = self.process_file(file,shared_keys)
#ensure each file has a name before returning #ensure each file has a name before returning
if processed_file['a']: if processed_file['a']:
files_dict[file['h']] = processed_file files_dict[file['h']] = processed_file
@ -261,8 +257,10 @@ class Mega(object):
node_id = self.get_node_by_type(target) node_id = self.get_node_by_type(target)
files = self.api_request({'a': 'f', 'c': 1}) files = self.api_request({'a': 'f', 'c': 1})
files_dict = {} files_dict = {}
shared_keys = {}
self.init_shared_keys(files,shared_keys)
for file in files['f']: for file in files['f']:
processed_file = self.process_file(file) processed_file = self.process_file(file,shared_keys)
if processed_file['a'] and processed_file['p'] == node_id[0]: if processed_file['a'] and processed_file['p'] == node_id[0]:
files_dict[file['h']] = processed_file files_dict[file['h']] = processed_file
return files_dict return files_dict