def receive_share(self, from_username, newname, message): (sign_encrypt_message, encrypt_message) = util.from_json_string(message) user_public_key = self.pks.get_public_key(from_username) right_sign = self.crypto.asymmetric_verify(encrypt_message, sign_encrypt_message, user_public_key) if not right_sign: raise IntegrityError # Message_from is [encrypt_key, mac_keys, share_node_keys, nonce] message_from = self.crypto.asymmetric_decrypt(encrypt_message, self.private_key) message_from = util.from_json_string(message_from) key_node = self.node(message_from[2], message_from[0], message_from[1]) # store the key_node in the server.\ 'Need to grab ivs for this file' share_node, share_iv = self.fetch_and_decrypt(message_from[2], message_from[0], message_from[1]) # Recreate merkle tree data_node = share_node root_node = share_node while isinstance(data_node, self.node): root_node = data_node data_node, data_iv = self.fetch_and_decrypt( data_node.pointer, data_node.encryption, data_node.mac_keys) #if data_node is None: # return data_node #self.merkle_tree = data_node #self.client_dictionary[newname] = {} self.encryption_ivs[newname] = [] self.reconstruct_merkle(data_node, root_node.encryption, root_node.mac_keys, newname) 'Need to grab ivs for this file' key_node_id = self.crypto.symmetric_encrypt( self.crypto.cryptographic_hash(path_join(self.username, newname), 'SHA256'), self.iv, 'AES', 'CBC', IV=None) file_iv = self.crypto.get_random_bytes(16) self.encrypt_and_put(key_node, key_node_id, self.iv, self.iv_mac, file_iv) # Create user_list for file and upload to server. user_list = [] userlist_iv = self.crypto.get_random_bytes(16) user_list_id = self.crypto.symmetric_encrypt( self.crypto.cryptographic_hash( path_join(self.username, newname) + "User_lists", "SHA"), self.iv, 'AES', 'CBC', IV=None) self.encrypt_and_put(user_list, user_list_id, self.iv, self.iv_mac, userlist_iv)
def receive_share(self, from_username, newname, message): # Replace with your implementation (not needed for Part 1) try: encrypted_keys_filename_string, signed_encrypted_keys_filename_string = util.from_json_string( message) except: raise IntegrityError() if self.crypto.asymmetric_verify( encrypted_keys_filename_string, signed_encrypted_keys_filename_string, self.pks.get_public_key(from_username)): decrypted_keys_filename_string = self.crypto.asymmetric_decrypt( encrypted_keys_filename_string, self.private_key) ka, ke, encrypted_original_filename = util.from_json_string( decrypted_keys_filename_string) k = self.get_unique_symmetric_key() encrypted_newfilename = self.crypto.message_authentication_code( newname, k, "MD5") half = int(len(encrypted_newfilename) / 4) encrypted_newfilename = encrypted_newfilename[:half] fid = path_join(self.username, encrypted_newfilename, "keys") keys_link = path_join(self.username, encrypted_original_filename, "keys") self.re_sign_keys(keys_link, from_username) self.storage_server.put(fid, "[POINTER] " + keys_link) uid = path_join(self.username, encrypted_newfilename) link = path_join(self.username, encrypted_original_filename) self.storage_server.put(uid, "[POINTER] " + link) else: raise IntegrityError()
def fetch_and_decrypt(self, encrypted_id, key_encrypt, key_auth): string_data = self.storage_server.get(encrypted_id) ##print(string_data) if string_data is None: return None, None try: encrypt_node, sign_encrypt_node, file_iv = util.from_json_string( string_data) except ValueError: raise IntegrityError # Check encrypt_key_node signature string_encrypt_node = util.to_json_string([encrypt_node, file_iv]) new_auth_encrypt_node = self.crypto.message_authentication_code( string_encrypt_node, key_auth, 'SHA512') if new_auth_encrypt_node != sign_encrypt_node: raise IntegrityError # Decrypt encrypt_key_node json_data = self.crypto.symmetric_decrypt(encrypt_node, key_encrypt, 'AES', 'CBC', IV=file_iv) data = util.from_json_string(json_data) if len(data) == 4 and data[3] == "node": data = self.node(data[0], data[1], data[2]) elif len(data) == 6 and data[5] == "merkle-node": data = self.merkle_node(data[0], data[1], data[2], data[3], data[4]) return data, file_iv
def share(self, user, name): # Replace with your implementation (not needed for Part 1) random_key_for_dictionary = self.storage_server.get("dict_key") dictionary_items_as_string = self.storage_server.get("dict") if dictionary_items_as_string is None: return None dictionary_items_as_list = util.from_json_string( dictionary_items_as_string) dictionary_iv = dictionary_items_as_list[0] encrypted_dictionary = dictionary_items_as_list[1] decrypted_dictionary = self.crypto.symmetric_decrypt( encrypted_dictionary, random_key_for_dictionary, 'AES', 'CBC', dictionary_iv) actual_dictionary = util.from_json_string(decrypted_dictionary) random_keys = actual_dictionary.get(uid) if random_keys is None: return None random_id = random_keys[0] sharename = path_join(self.username, "sharewith", user, name) self.storage_server.put(sharename, "[POINTER] " + path_join(self.username, name)) return sharename
def grabData(self, lst, e_key, m_key): """lst is the list of the top root node""" if len(lst) == 3: # We hit a leaf node pkt = self.storage_server.get(lst[2]) # Split the packet into the encrypted stuff and the mac that came along with it iv_encrypted_value, mac = pkt[:len(pkt) - 64], pkt[len(pkt) - 64:] # Recreate the mac using m_key and compare it with the one that came along with it try: testmac = self.crypto.message_authentication_code( iv_encrypted_value, m_key, 'SHA256') except: raise IntegrityError if testmac != mac: raise IntegrityError # Split into iv and the encrypted file value and decrypt accordingly iv = iv_encrypted_value[:32] encrypted_value = iv_encrypted_value[32:] value = self.crypto.symmetric_decrypt(encrypted_value, e_key, 'AES', 'CBC', iv) return value else: # Basically when len(lst) == 4 pkt1 = self.storage_server.get(lst[2]) pkt2 = self.storage_server.get(lst[3]) # Split the packet into the encrypted stuff and the mac that came along with it iv_encrypted_value1, mac1 = pkt1[:len(pkt1) - 64], pkt1[len(pkt1) - 64:] iv_encrypted_value2, mac2 = pkt2[:len(pkt2) - 64], pkt2[len(pkt2) - 64:] # Recreate the mac using m_key and compare it with the one that came along with it try: testmac1 = self.crypto.message_authentication_code( iv_encrypted_value1, m_key, 'SHA256') testmac2 = self.crypto.message_authentication_code( iv_encrypted_value2, m_key, 'SHA256') except: raise IntegrityError if testmac1 != mac1 or testmac2 != mac2: raise IntegrityError # Split into iv and the encrypted file value and decrypt accordingly iv1 = iv_encrypted_value1[:32] iv2 = iv_encrypted_value2[:32] encrypted_value1 = iv_encrypted_value1[32:] encrypted_value2 = iv_encrypted_value2[32:] lst1 = from_json_string( self.crypto.symmetric_decrypt(encrypted_value1, e_key, 'AES', 'CBC', iv1)) lst2 = from_json_string( self.crypto.symmetric_decrypt(encrypted_value2, e_key, 'AES', 'CBC', iv2)) # print("left") # print(self.grabData(lst1, e_key, m_key)) # print("right") # print(self.grabData(lst2, e_key, m_key)) return self.grabData(lst1, e_key, m_key) + self.grabData( lst2, e_key, m_key)
def download(self, name): # Replace with your implementation uid = self.resolve(path_join(self.username, name)) random_key_for_dictionary = self.storage_server.get("dict_key") dictionary_items_as_string = self.storage_server.get("dict") if dictionary_items_as_string is None: return None dictionary_items_as_list = util.from_json_string(dictionary_items_as_string) dictionary_iv = dictionary_items_as_list[0] encrypted_dictionary = dictionary_items_as_list[1] ############### encrypted_dictionary_signature = dictionary_items_as_list[2] #if not self.crypto.asymmetric_verify(encrypted_dictionary, encrypted_dictionary_signature, self.private_key.publickey()): #raise IntegrityError() #pass ############### #encrypted_dictionary = dictionary_items_as_string #decrypted_dictionary = self.crypto.asymmetric_decrypt(encrypted_dictionary, self.private_key) decrypted_dictionary = self.crypto.symmetric_decrypt(encrypted_dictionary, random_key_for_dictionary, 'AES', 'CBC', dictionary_iv) actual_dictionary = util.from_json_string(decrypted_dictionary) #actual_dictionary = dictionary_items_as_list #print(uid) random_keys = actual_dictionary.get(uid) if random_keys is None: return None #random_key_for_name = random_keys[0] random_id = random_keys[0] random_key_for_value = random_keys[1] #resp = self.storage_server.get(uid) #encrypted_name = self.crypto.symmetric_encrypt(uid, random_key_for_name, 'AES') #resp = self.storage_server.get(encrypted_name) resp = self.storage_server.get(random_id) if resp is None: return None list_of_value_items_as_string = resp[7:] list_of_value_items = util.from_json_string(list_of_value_items_as_string) value_iv = list_of_value_items[0] encrypted_value = list_of_value_items[1] ''' encrypted_value_signature = list_of_value_items[2] ########### signed_name_and_value = list_of_value_items[3] if not self.crypto.asymmetric_verify(random_id+encrypted_value, signed_name_and_value, self.private_key.publickey()): raise IntegrityError() ########### if not self.crypto.asymmetric_verify(encrypted_value, encrypted_value_signature, self.private_key.publickey()): raise IntegrityError() #pass ''' decrypted_value = self.crypto.symmetric_decrypt(encrypted_value, random_key_for_value, 'AES', 'CBC', value_iv) return decrypted_value
def download(self, name): # Replace with your implementation ka, ke = self.get_file_keys(name) k = self.get_unique_symmetric_key() cipher_name = self.crypto.message_authentication_code(name, k, "MD5") half = int(len(cipher_name) / 4) cipher_name = cipher_name[:half] uid = self.revolve(path_join(self.username, cipher_name)) res = self.storage_server.get(uid) if not res: return None else: cipher_all_string = res[7:] try: IV, cipher_value, old_tag = util.from_json_string( cipher_all_string) except: raise IntegrityError() new_tag = self.crypto.message_authentication_code( IV + cipher_value + uid, ka, "MD5") if old_tag != new_tag: raise IntegrityError() else: chunk_num_string = self.crypto.symmetric_decrypt( cipher_value, ke, "AES", "CBC", IV) chunk_num = int(chunk_num_string) value = "" for i in range(chunk_num): uid_i = path_join(uid, str(i)) res = self.storage_server.get(uid_i) if not res: return None else: cipher_all_string = res[7:] try: IV, cipher_value, old_tag = util.from_json_string( cipher_all_string) except: raise IntegrityError() new_tag = self.crypto.message_authentication_code( IV + cipher_value + uid_i, ka, "MD5") if old_tag != new_tag: raise IntegrityError() else: value += self.crypto.symmetric_decrypt( cipher_value, ke, "AES", "CBC", IV) return value
def share(self, user, name): # Replace with your implementation (not needed for Part 1) uid = path_join(self.username, name) username_keys = path_join(self.username, "dict_keys") username_dictionary = path_join(self.username, "dictionary") random_key_for_dictionary = self.storage_server.get(username_keys) #print(random_key_for_dictionary) random_key_for_dictionary = self.crypto.asymmetric_decrypt(random_key_for_dictionary, self.private_key) dictionary_items_as_string = self.storage_server.get(username_dictionary) #print(dictionary_items_as_string) if dictionary_items_as_string is None: return None dictionary_items_as_list = util.from_json_string(dictionary_items_as_string) dictionary_iv = dictionary_items_as_list[0] encrypted_dictionary = dictionary_items_as_list[1] decrypted_dictionary = self.crypto.symmetric_decrypt(encrypted_dictionary, random_key_for_dictionary, 'AES', 'CBC', dictionary_iv) actual_dictionary = util.from_json_string(decrypted_dictionary) random_keys = actual_dictionary.get(uid) #print(random_keys) if random_keys is None: return None random_id = random_keys[0] random_id_key = random_keys[1] random_id_mac = random_keys[2] e_key = self.crypto.asymmetric_encrypt(random_id_key, self.public_key_server.get_public_key(user)) if self.storage_server.get(random_id+"shared_file") == None: shared_dict_as_string = util.to_json_string({self.username: None}) #SHADYYYYYYYYYYY; how do you initialize shizzzzzzzz #don't need to encrypt shared_dict since it's public info shared_dict_mac = self.crypto.message_authentication_code(shared_dict_as_string, random_id_key, 'SHA256') shared_dict_values = [shared_dict_as_string, shared_dict_mac] shared_dict_values_as_string = util.to_json_string(shared_dict_values) self.storage_server.put(random_id+"shared_file", shared_dict_values_as_string) shared_dict = self.storage_server.get(random_id+"shared_file") calculated_mac = self.crypto.message_authentication_code(shared_dict, random_id_key, 'SHA256') if calculated_mac != shared_dict[1]: raise IntegrityError() #is this the right error shared_dict = util.from_json_string(shared_dict) shared_dict[self.username] = shared_dict[self.username].append({user: None}) msg_as_list = [random_id, e_key, random_id+"shared_file"] msg_as_string = util.to_json_string(msg_as_list) #they're not gonna test if you call share on something you don't own #return None if a user tries to download a file that they don't have access to, not IntegrityError() return msg_as_string
def receive_share(self, from_username, newname, message): sender_pub_key = self.pks.get_public_key(from_username) try: output = util.from_json_string(message) crypted, sign = output except: raise IntegrityError() # DECRYPT RECEIVED MESSAGE if self.crypto.asymmetric_verify(crypted, sign, sender_pub_key): msg = self.crypto.asymmetric_decrypt(crypted, self.private_key) msg = util.from_json_string(msg) session_key = msg['session_key'] file_id = msg['file_id'] else: raise IntegrityError() # GET DIRECTORY KEYS directory_keys = self.get_directory_keys() sym_ke, sym_ka = directory_keys # GET DIRECTORY client_ID = path_join(self.username, "directory") resp = self.storage_server.get(client_ID) if resp is None: directory = { newname: { "keys": session_key, "shared": [], "file_id": file_id } } else: directory = self.decrypt_directory(resp, sym_ke, sym_ka) directory[newname] = { "keys": session_key, "shared": [], "file_id": file_id } # can cache directory here self.directory[newname] = { "keys": session_key, "shared": [], "file_id": file_id } self.encrypt_directory(client_ID, directory, sym_ke, sym_ka)
def init_dir_keys(self): self.dir_keys_loc = self.username + '/dir_keys' value = self.storage_server.get(self.dir_keys_loc) if not value: # key not already on the server self.dir_enc_key = self.crypto.get_random_bytes(32) self.dir_mac_key = self.crypto.get_random_bytes(32) dir_keys = { 'dir_enc_key': self.dir_enc_key, 'dir_mac_key': self.dir_mac_key } dir_keys_str = to_json_string(dir_keys) enc_value = self.crypto.asymmetric_encrypt(dir_keys_str, self.private_key) sig = self.crypto.asymmetric_sign(self.dir_keys_loc + enc_value, self.private_key) dir_keys_pkg = {'enc_value': enc_value, 'sig': sig} value = to_json_string(dir_keys_pkg) if not self.storage_server.put(self.dir_keys_loc, value): # unable to upload sym_key to storage server raise IntegrityError else: # keys fetched from server try: dir_keys_pkg = from_json_string(value) sig = dir_keys_pkg['sig'] enc_value = dir_keys_pkg['enc_value'] if not self.crypto.asymmetric_verify( self.dir_keys_loc + enc_value, sig, self.private_key): raise IntegrityError dir_keys_str = self.crypto.asymmetric_decrypt( enc_value, self.private_key) dir_keys = from_json_string(dir_keys_str) self.dir_enc_key = dir_keys['dir_enc_key'] self.dir_mac_key = dir_keys['dir_mac_key'] except (ValueError, TypeError, KeyError, CryptoError): # malformed key package raise IntegrityError
def download(self, name): self.get_dir() if not name in self.dir: # file not part of user's dir return None file_record = self.dir[name] loc = file_record['loc'] enc_key = file_record['enc_key'] mac_key = file_record['mac_key'] if file_record['is_gateway']: target = self.follow_gateways(file_record['loc'], file_record['enc_key'], file_record['mac_key']) enc_key = target['enc_key'] mac_key = target['mac_key'] meta_val = self.get(target['loc'], target['enc_key'], target['mac_key']) else: meta_val = self.get(loc, enc_key, mac_key) if not meta_val: raise IntegrityError meta = from_json_string(meta_val) value, root_hash = self.download_merkle(meta['tree'], enc_key, mac_key) merkle = self.create_merkle(value) if merkle.hash != root_hash: raise IntegrityError return value
def revoke(self, user, name): # Replace with your implementation (not needed for Part 1) old_keys = self.get_file_keys(name) old_ka, old_ke = old_keys k = self.get_unique_symmetric_key() cipher_name = self.crypto.message_authentication_code(name, k, "MD5") half = int(len(cipher_name) / 4) cipher_name = cipher_name[:half] interface_id = path_join(user, cipher_name) self.storage_server.delete(interface_id) new_keys = self.re_encrypt_file(name) new_ka, new_ke = new_keys owner, encrypted_original_filename = self.get_owner_and_encrypted_original_filename( name) share_id = path_join(self.username, encrypted_original_filename, "shared_with") share_list_string = self.check_integrity_and_get_value( old_ka, share_id) share_list = util.from_json_string(share_list_string) if user in share_list: share_list.remove(user) self.re_distribute_keys(share_id, share_list, encrypted_original_filename, old_ka, new_keys)
def share(self, user, name): # Replace with your implementation (not needed for Part 1) keys = self.get_file_keys(name) ka, ke = keys file_info = self.get_owner_and_encrypted_original_filename(name) encrypted_original_filename = file_info[1] share_id = path_join(self.username, encrypted_original_filename, "shared_with") share_list_string = self.storage_server.get(share_id) if share_list_string == None: share_list = [user] else: share_list_string = self.check_integrity_and_get_value( ka, share_id) share_list = util.from_json_string(share_list_string) share_list.append(user) share_list_string = util.to_json_string(share_list) self.MAC_and_store(share_list_string, ka, share_id) self.share_keys_with_user(user, encrypted_original_filename, keys) self.make_bridge(user, encrypted_original_filename) keys_filename = (ka, ke, encrypted_original_filename) keys_filename_string = util.to_json_string(keys_filename) encrypted_keys_filename_string = self.crypto.asymmetric_encrypt( keys_filename_string, self.pks.get_public_key(user)) signed_encrypted_keys_filename_string = self.crypto.asymmetric_sign( encrypted_keys_filename_string, self.private_key) msg = util.to_json_string((encrypted_keys_filename_string, signed_encrypted_keys_filename_string)) return msg
def grab_sdirectory(self, enc_key, mac_key): """Returns the sharing directory in the form of a dictionary of this user""" # Grab the encrypted packet and divide it into the encrypted part and the mac packet = self.storage_server.get(path_join(self.username, "sdir")) iv_encrypted_dir, mac = packet[:len(packet) - 64], packet[len(packet) - 64:] # Recreate the mac using mac_key and compare it with the one that came along with it try: testmac = self.crypto.message_authentication_code( iv_encrypted_dir, mac_key, 'SHA256') except: raise IntegrityError if testmac != mac: raise IntegrityError # If we reach here, we have verified that our directory is good try: # Split iv_encrypted_dir into an iv and the encrypted_dir iv = iv_encrypted_dir[:32] encrypted_dir = iv_encrypted_dir[32:] # Decrypt and also convert back into a python dictionary directory = from_json_string( self.crypto.symmetric_decrypt(encrypted_dir, enc_key, 'AES', 'CBC', iv)) except: raise IntegrityError return directory
def receive_share(self, from_username, newname, message): # Replace with your implementation (not needed for Part 1) decryptedMessage = util.from_json_string( self.crypto.asymmetric_decrypt(message, self.private_key)) fileID = decryptedMessage[0] key1 = decryptedMessage[1] key2 = decryptedMessage[2] # if no directory yet if self.storage_server.get(self.username + "/directory") is not None: encryptedDictionaryAndKey = util.from_json_string( self.storage_server.get(self.username + "/directory")) enDictionary = encryptedDictionaryAndKey[0] enKey = encryptedDictionaryAndKey[1] directoryKey = self.crypto.asymmetric_decrypt( enKey, self.private_key) dictionary = util.from_json_string( self.crypto.symmetric_decrypt(enDictionary, directoryKey, 'AES')) dictionary[newname] = fileID decryptedDicKey = self.crypto.asymmetric_decrypt( ESymms, self.private_key) encryptedDictionary = self.crypto.symmetric_encrypt( util.to_json_string(dictionary), decryptedDicKey, 'AES') self.storage_server.put( self.username + "/directory", util.to_json_string((encryptedDictionary, enKey))) else: dictionary = {newname: fileID} dictionaryKey = self.crypto.get_random_bytes(16) encryptedDictionary = self.crypto.symmetric_encrypt( util.to_json_string(dictionary), dictionaryKey, 'AES') encryptionOfDictionaryKey = self.crypto.asymmetric_encrypt( dictionaryKey, self.pks.get_public_key(self.username)) self.storage_server.put( self.username + "/directory", util.to_json_string( (encryptedDictionary, encryptionOfDictionaryKey))) pubKey = self.pks.get_public_key(self.username) symmKeys = (key1, key2) encryptionOfSymmKeys = self.crypto.asymmetric_encrypt( util.to_json_string(symmKeys), pubKey) signedEncryptionOfSymmKeys = self.crypto.asymmetric_sign( encryptionOfSymmKeys, self.private_key) self.storage_server.put( self.username + "/dir_keys/" + fileID, util.to_json_string( (encryptionOfSymmKeys, signedEncryptionOfSymmKeys)))
def safe_decrypt(self, resp): pub_key = self.private_key.publickey() try: key_info = util.from_json_string(resp) encrypted_keys = key_info["encrypted_keys"] signed_keys = key_info["signed_keys"] except: raise IntegrityError() if not self.crypto.asymmetric_verify(encrypted_keys, signed_keys, pub_key): raise IntegrityError() decrypted_keys = self.crypto.asymmetric_decrypt( encrypted_keys, self.private_key) return util.from_json_string(decrypted_keys)
def get_file_keys(self, name): k = self.get_unique_symmetric_key() encrypted_filename = self.crypto.message_authentication_code( name, k, "MD5") half = int(len(encrypted_filename) / 4) encrypted_filename = encrypted_filename[:half] fid = self.revolve(path_join(self.username, encrypted_filename, "keys")) fkeys = self.storage_server.get(fid) if fkeys == None: return self.make_file_keys(fid) else: owner, encrypted_original_filename = self.get_owner_and_encrypted_original_filename( name) if self.username != owner: kid = path_join(self.username, encrypted_original_filename, "keys") keys_string = self.storage_server.get(kid) if not keys_string: return None else: try: encrypted_keys_string, signed_encrypted_keys_string = util.from_json_string( keys_string[7:]) except: raise IntegrityError() if self.crypto.asymmetric_verify( encrypted_keys_string, signed_encrypted_keys_string, self.pks.get_public_key(owner)): keys_string = self.crypto.asymmetric_decrypt( encrypted_keys_string, self.private_key) self.sign_and_store(keys_string, self.username, kid) elif self.crypto.asymmetric_verify( encrypted_keys_string, signed_encrypted_keys_string, self.pks.get_public_key(self.username)): pass else: raise IntegrityError() keys_string = self.verify_signature_and_get_value( self.username, fid) keys = util.from_json_string(keys_string) return keys
def efficient_update(self, merkle, node_loc, enc_key, mac_key, root=True): server_node_val = self.storage_server.get(node_loc) if not server_node_val: raise IntegrityError try: server_node = from_json_string(server_node_val) if root: server_node = from_json_string(server_node['value']) if merkle.hash == server_node['hash']: return node = { 'hash': merkle.hash, 'left': server_node['left'], 'right': server_node['right'], 'iv': None, 'data': None } if merkle.data: node['iv'] = merkle.iv node['data'] = self.sym_enc(merkle.data, merkle.iv, enc_key) node_value = to_json_string(node) if root: if not self.put_no_enc(node_value, node_loc, mac_key): raise IntegrityError else: if not self.storage_server.put(node_loc, node_value): raise IntegrityError if merkle.left: self.efficient_update(merkle.left, server_node['left'], enc_key, mac_key, False) if merkle.right: self.efficient_update(merkle.right, server_node['right'], enc_key, mac_key, False) except: raise IntegrityError
def decrypt_directory(self, resp, sym_ke, sym_ka): try: directory_info = util.from_json_string(resp) IV = directory_info['IV'] encrypted_keys = directory_info["encrypted_keys"] signed_keys = directory_info["signed_keys"] except: raise IntegrityError() signed_dir = self.crypto.message_authentication_code( encrypted_keys, sym_ka, 'SHA256') if signed_dir != signed_keys: raise IntegrityError() directory = self.crypto.symmetric_decrypt(encrypted_keys, sym_ke, 'AES', 'CBC', IV) directory = util.from_json_string(directory) return directory
def get_shared_info( self, uid, data_key, data_mac_key ): #add stuff to decrypt the [DATA] [random_id, random_key] #get decrypted value of random_id try: list_of_data_items_as_string = self.storage_server.get(uid)[7:] list_of_data_items = util.from_json_string( list_of_data_items_as_string) data_iv = list_of_data_items[0] encrypted_data_as_string = list_of_data_items[1] data_mac = list_of_data_items[2] calculated_data_mac = self.crypto.message_authentication_code( encrypted_data_as_string, data_mac_key, 'SHA256') if calculated_data_mac != data_mac: raise IntegrityError() shared_info = self.crypto.symmetric_decrypt( encrypted_data_as_string, data_key, 'AES', 'CBC', data_iv) info_as_list = util.from_json_string(shared_info) random_id = info_as_list[0] random_key_for_value = info_as_list[1] random_key_for_value_mac = info_as_list[2] resp = self.storage_server.get(random_id) if resp is None: return None list_of_value_items_as_string = resp[7:] list_of_value_items = util.from_json_string( list_of_value_items_as_string) value_iv = list_of_value_items[0] encrypted_value = list_of_value_items[1] name_and_value_encrypt_mac = list_of_value_items[2] calculated_mac = self.crypto.message_authentication_code( random_id + encrypted_value, random_key_for_value_mac, 'SHA256') if calculated_mac != name_and_value_encrypt_mac: raise IntegrityError() decrypted_value = self.crypto.symmetric_decrypt( encrypted_value, random_key_for_value, 'AES', 'CBC', value_iv) return decrypted_value except: raise IntegrityError()
def retrieve_dict(self): username_dictionary = path_join(self.username, "dictionary") username_keys = path_join(self.username, "dict_keys") if self.storage_server.get(username_dictionary) is None: dictionary = {} return dictionary d_key = self.storage_server.get(username_keys) decrypted_d_key = self.crypto.asymmetric_decrypt( d_key, self.private_key) dictionary_items_as_string = self.storage_server.get( username_dictionary) dictionary_items_as_list = util.from_json_string( dictionary_items_as_string) the_iv = dictionary_items_as_list[0] dictionary = dictionary_items_as_list[1] dictionary = self.crypto.symmetric_decrypt(dictionary, decrypted_d_key, 'AES', 'CBC', the_iv) dictionary = util.from_json_string(dictionary) return dictionary
def receive_share(self, from_username, newname, message): #print(message) message_as_list = util.from_json_string(message) sharename = message_as_list[0] data_key = message_as_list[1] data_mac_key = message_as_list[2] dictionary = None uid = self.resolve(path_join(self.username, newname)) random_id = self.crypto.get_random_bytes(16) random_key_for_value = self.crypto.get_random_bytes(16) random_key_for_dictionary = self.crypto.get_random_bytes(16) random_key_for_value_mac = self.crypto.get_random_bytes(16) random_key_for_dict_mac = self.crypto.get_random_bytes(16) value_iv = self.crypto.get_random_bytes(16) encrypted_random_key_for_dictionary = self.crypto.asymmetric_encrypt( random_key_for_dictionary, self.private_key.publickey()) username_keys = path_join(self.username, "dict_keys") username_dictionary = path_join(self.username, "dictionary") if self.storage_server.get(username_keys) is None: self.storage_server.put(username_keys, encrypted_random_key_for_dictionary) else: e_random_key_for_dictionary = self.storage_server.get( username_keys) random_key_for_dictionary = self.crypto.asymmetric_decrypt( e_random_key_for_dictionary, self.private_key) dictionary = self.retrieve_dict() dictionary[path_join(self.username, newname)] = [ random_id, random_key_for_value, random_key_for_value_mac, data_key, data_mac_key ] dictionary_iv = self.crypto.get_random_bytes(16) dictionary_as_string = util.to_json_string(dictionary) dictionary_encrypt = self.crypto.symmetric_encrypt( dictionary_as_string, random_key_for_dictionary, 'AES', 'CBC', dictionary_iv) dictionary_encrypt_mac = self.crypto.message_authentication_code( dictionary_encrypt, random_key_for_dict_mac, 'SHA256') list_of_items = [ dictionary_iv, dictionary_encrypt, dictionary_encrypt_mac ] list_of_items_as_string = util.to_json_string(list_of_items) self.storage_server.put(username_dictionary, list_of_items_as_string) #my_id = path_join(self.username, newname) my_id = random_id self.storage_server.put( my_id, "[POINTER] " + sharename) #message[i] if we add more stuff to message
def receive_share(self, from_username, newname, message): # Replace with your implementation (not needed for Part 1) ''' d_key = self.storage_server.get("dict_key") dictionary_items_as_string = self.storage_server.get("dict") dictionary_items_as_list = util.from_json_string(dictionary_items_as_string) the_iv = dictionary_items_as_list[0] dictionary = dictionary_items_as_list[1] dictionary_signature = dictionary_items_as_list[2] dictionary = self.crypto.symmetric_decrypt(dictionary, d_key, 'AES', 'CBC', the_iv) dictionary = util.from_json_string(dictionary) random_id = self.crypto.get_random_bytes(16) random_key_for_value = self.crypto.get_random_bytes(16) dictionary[uid] = (random_id, random_key_for_value) ''' d_key = self.storage_server.get("dict_key") dictionary_items_as_string = self.storage_server.get("dict") dictionary_items_as_list = util.from_json_string(dictionary_items_as_string) the_iv = dictionary_items_as_list[0] dictionary = dictionary_items_as_list[1] dictionary_signature = dictionary_items_as_list[2] dictionary = self.crypto.symmetric_decrypt(dictionary, d_key, 'AES', 'CBC', the_iv) dictionary = util.from_json_string(dictionary) from_users_random_id = dictionary.get(path_join(from_username, newname)) my_id = path_join(self.username, newname) dictionary[my_id] = from_users_random_id dictionary_iv = self.crypto.get_random_bytes(16) string_dict = util.to_json_string(dictionary) dictionary_encrypt = self.crypto.symmetric_encrypt(string_dict, d_key, 'AES', 'CBC', dictionary_iv) list_of_items = [dictionary_iv, dictionary_encrypt, 'LOL'] list_of_items_as_string = util.to_json_string(list_of_items) self.storage_server.put("dict", list_of_items_as_string) self.storage_server.put(my_id, "[POINTER] " + message)
def get_dir(self): value = self.storage_server.get(self.dir_loc) if not value: return False try: dir_pkg = from_json_string(value) iv = dir_pkg['iv'] mac = dir_pkg['mac'] enc_value = dir_pkg['enc_value'] if not self.verify_mac(self.dir_loc + iv + enc_value, self.dir_mac_key, mac): raise IntegrityError dir_str = self.sym_dec(enc_value, iv, self.dir_enc_key) self.dir = from_json_string(dir_str) return True except (ValueError, TypeError, KeyError, CryptoError): raise IntegrityError
def share(self, user, name): # Replace with your implementation (not needed for Part 1) sharename = path_join(self.username, "sharewith", user, name) uid = path_join(self.username, name) random_key_for_dictionary = self.storage_server.get("dict_key") dictionary_items_as_string = self.storage_server.get("dict") if dictionary_items_as_string is None: return None dictionary_items_as_list = util.from_json_string(dictionary_items_as_string) dictionary_iv = dictionary_items_as_list[0] encrypted_dictionary = dictionary_items_as_list[1] encrypted_dictionary_signature = dictionary_items_as_list[2] decrypted_dictionary = self.crypto.symmetric_decrypt(encrypted_dictionary, random_key_for_dictionary, 'AES', 'CBC', dictionary_iv) actual_dictionary = util.from_json_string(decrypted_dictionary) random_keys = actual_dictionary.get(uid) #if random_keys is None: #return None random_id = random_keys[0] random_key_for_value = random_keys[1] ''' #share_uid = path_join(user, name) actual_dictionary[uid] = (random_id, random_key_for_value) dictionary_iv = self.crypto.get_random_bytes(16) string_dict = util.to_json_string(actual_dictionary) dictionary_encrypt = self.crypto.symmetric_encrypt(string_dict, random_key_for_dictionary, 'AES', 'CBC', dictionary_iv) dictionary_encrypt_sign = self.crypto.asymmetric_sign(dictionary_encrypt, self.private_key) list_of_items = [dictionary_iv, dictionary_encrypt, dictionary_encrypt_sign] list_of_items_as_string = util.to_json_string(list_of_items) self.storage_server.put("dict", list_of_items_as_string) ''' self.storage_server.put(sharename, "[POINTER] " + random_id) return sharename
def follow_gateways(self, loc, enc_key, mac_key): """ returns a link to the actual file, as well as the keys used to access it. """ value = self.storage_server.get(loc) if not value: # we know we uploaded the file, and it was later deleted raise IntegrityError() try: pkg = from_json_string(value) iv = pkg['iv'] mac = pkg['mac'] enc_value = pkg['enc_value'] if not self.verify_mac(loc + iv + enc_value, mac_key, mac): raise IntegrityError value = self.sym_dec(enc_value, iv, enc_key) gateway_record = from_json_string(value) next_loc = gateway_record['loc'] next_enc_key = gateway_record['enc_key'] next_mac_key = gateway_record['mac_key'] if gateway_record['is_leaf']: return { 'loc': next_loc, 'mac_key': next_mac_key, 'enc_key': next_enc_key } else: return self.follow_gateways(next_loc, next_enc_key, next_mac_key) except (ValueError, TypeError, KeyError, CryptoError): raise IntegrityError
def download_merkle(self, loc, enc_key, mac_key, root=True): server_node_val = self.storage_server.get(loc) if not server_node_val: raise IntegrityError try: server_node = from_json_string(server_node_val) if root: # check top hash validity node_pkg = server_node server_node = from_json_string(node_pkg['value']) if self.mac(loc + node_pkg['value'], mac_key) != node_pkg['mac']: raise IntegrityError data = '' if server_node['data']: data += self.sym_dec(server_node['data'], server_node['iv'], enc_key) if server_node['left']: data += self.download_merkle(server_node['left'], enc_key, mac_key, False) if server_node['right']: data += self.download_merkle(server_node['right'], enc_key, mac_key, False) if root: return (data, server_node['hash']) else: return data except: raise IntegrityError
def receive_share(self, from_username, newname, message): # Replace with your implementation (not needed for Part 1) from_pub_key = self.pks.get_public_key(from_username) if not from_pub_key: return False try: msg = from_json_string(message) enc_value = msg['enc_value'] enc_enc_key = msg['enc_enc_key'] iv = msg['iv'] sig = msg['sig'] if not self.crypto.asymmetric_verify(enc_enc_key + iv + enc_value, sig, from_pub_key): raise IntegrityError enc_key = self.crypto.asymmetric_decrypt(enc_enc_key, self.private_key) value = self.sym_dec(enc_value, iv, enc_key) share_record = from_json_string(value) file_record = { 'loc': share_record['loc'], 'enc_key': share_record['enc_key'], 'mac_key': share_record['mac_key'], 'is_gateway': True, 'shared': {} } self.get_dir() self.dir[newname] = file_record self.upload_dir() except (ValueError, TypeError, KeyError, CryptoError): raise IntegrityError
def resolve(self, uid, e_key, m_key, mode=None): """Follows [P]'s until we reach the a None or [D] and return the data""" while True: pkt = self.storage_server.get(uid) if pkt is None: return None elif pkt.startswith("[P]"): uid = pkt[4:] else: # Split the packet into the encrypted stuff and the mac that came along with it iv_encrypted_value, mac = pkt[:len(pkt) - 64], pkt[len(pkt) - 64:] # Recreate the mac using m_key and compare it with the one that came along with it try: testmac = self.crypto.message_authentication_code( iv_encrypted_value, m_key, 'SHA256') except: raise IntegrityError if testmac != mac: raise IntegrityError # Split into iv and the encrypted file value and decrypt accordingly iv = iv_encrypted_value[:32] encrypted_value = iv_encrypted_value[32:] value = self.crypto.symmetric_decrypt(encrypted_value, e_key, 'AES', 'CBC', iv) if value.startswith("[D]"): if mode == "update": return uid, e_key, m_key else: value = value[4:] test_swap_check = value[:32] value = value[ 32:] # This value should be a json stringed list if test_swap_check != uid: raise IntegrityError return self.grabData(from_json_string(value), e_key, m_key) uid = value[:32] e_key = value[32:64] m_key = value[64:]
def check_integrity_and_get_value(self, ka, data_id): all_value_string = self.storage_server.get(data_id) if not all_value_string: return None else: try: value_string, MACed_value_string = util.from_json_string( all_value_string[7:]) except: raise IntegrityError() if self.crypto.message_authentication_code( value_string, ka, "MD5") == MACed_value_string: return value_string else: raise IntegrityError()