def download_helper1(self, name, stored_root, file_id, encryption_key, mac_key): ret_mac = self.storage_server.get(file_id +self.crypto.cryptographic_hash("mac", 'SHA256')) if ret_mac is None: return None mac_text = ret_mac[:64] if self.crypto.message_authentication_code(stored_root, mac_key, 'SHA256') != mac_text: raise IntegrityError() downlength = int(ret_mac[64:]) self.cipher_text_list[name] = [] for i in range(0, downlength): self.cipher_text_list[name].append(self.storage_server.get(file_id + str(i))) hash_list = [] for elem in self.cipher_text_list[name]: hash_list.append(self.crypto.cryptographic_hash(elem, 'SHA256')) new_temp_tree = MerkleTree(hash_list,self, name) new_temp_tree.pre_build() if new_temp_tree.root.val != stored_root: raise IntegrityError() plain_text_list = [] for elem in self.cipher_text_list[name]: IV = elem[:16] plain_text_list.append(self.crypto.symmetric_decrypt(elem[16:], encryption_key, 'AES', 'CBC',IV+IV ,None, None,None, 128)) self.stored_file[name] = ''.join(plain_text_list) return self.stored_file[name]
def read_verify_ptr(self, location, mac_key, decode_key): """ goes to location, reads and verifies the pointer there returns the location of the associated headerfile, and the username of the file owner """ raw = self.storage_server.get(location) if raw is None: return None, None mac_val = self.crypto.message_authentication_code(raw[MAC_LEN:], mac_key, hash_name='SHA256') flag = (mac_val == raw[:MAC_LEN]) if not flag: raise IntegrityError("pointer mac invalid") nonce = raw[MAC_LEN:MAC_LEN + NONCE_LEN] counter = self.crypto.new_counter(COUNTER_LEN, prefix=nonce) message = self.crypto.symmetric_decrypt(raw[MAC_LEN + NONCE_LEN:], decode_key, cipher_name='AES', mode_name='CTR', counter=counter) if not message[:3] == 'PTR': raise IntegrityError( "Value at this location is not actually pointer.") return message[3:LOC_LEN + 3], message[ LOC_LEN + 3:] # location, username of owner of file who controls this header block
def read_verify_header(self, location, mac_key, decode_key, include_metadata=False): """ goes to location, reads and verifies the header file there returns the location, decryption key, and mac key required to read/write the actual file if not chained else returns the location, username of the owner who controls next header, None if include_metadata, contains list of people shared with """ raw = self.storage_server.get(location) if raw is None: raise IntegrityError("header does not exist") mac_val = self.crypto.message_authentication_code(raw[MAC_LEN:], mac_key, hash_name='SHA256') flag = (mac_val == raw[:MAC_LEN]) if not flag: raise IntegrityError("header mac invalid") nonce = raw[MAC_LEN:MAC_LEN + NONCE_LEN] counter = self.crypto.new_counter(COUNTER_LEN, prefix=nonce) message = self.crypto.symmetric_decrypt(raw[MAC_LEN + NONCE_LEN:], decode_key, cipher_name='AES', mode_name='CTR', counter=counter) if not message[:3] == 'HDR' and not message[:3] == 'MET': raise IntegrityError( "Value at this location is not actually header.") if include_metadata: if not message[:3] == 'MET': return message[3:LOC_LEN + 3], None, None, None else: if not message[LOC_LEN + 3:LOC_LEN + 4] == '0': raise IntegrityError("Metatdata block is chained!" + message[LOC_LEN + 3:LOC_LEN + 4]) return message[3:LOC_LEN + 3], message[ LOC_LEN + 4:LOC_LEN + ENC_KEY_LEN + 4], message[LOC_LEN + ENC_KEY_LEN + 4:LOC_LEN + ENC_KEY_LEN + MAC_KEY_LEN + 4], message[LOC_LEN + ENC_KEY_LEN + MAC_KEY_LEN + 4:] else: if message[LOC_LEN + 3:LOC_LEN + 4] == '1': # chained return message[3:LOC_LEN + 3], message[LOC_LEN + 4:], None else: return message[3:LOC_LEN + 3], message[LOC_LEN + 4:LOC_LEN + ENC_KEY_LEN + 4], message[LOC_LEN + ENC_KEY_LEN + 4:LOC_LEN + ENC_KEY_LEN + MAC_KEY_LEN + 4]
def sym_unpack(self, ct, sk_m, sk_s, filename): """ symmetrically decrypts and verifies a ciphertext string :param ct: ciphertext to be unpacked :param sk_m: symmetric key for encrypting :param sk_s: symmetric key for signing :param str filename: the correct filename to avoid swap attacks :return: the plaintext :rtype: str """ if not ct: return None sign = ct[-64:] # get signature from end of msg CT resp = ct[:-64] # remove signature from msg CT if self.crypto.message_authentication_code( resp + self.hash(filename), sk_s, "SHA256") != sign: # verify raise IntegrityError("Bad Signature") try: iv = resp[-32:] # save the IV at the end of the message CT resp = resp[:(-32)] # remove IV from message CT resp = self.crypto.symmetric_decrypt(resp, sk_m, "AES", "CBC", iv) # decrypt msg w/AES-CBC except: # any exception should be due to bit flipping by malicious server. raise IntegrityError("Data Corrupt") return resp
def asym_unpack(self, ct, filename, sender=None): """unpack a symmetric key that has been stored on the insecure server :param str ct: The key to unpack. :param str sender: user who's public key is used to verify :param str filename: the correct filename to avoid swap attacks :returns: the symmetric key :rtype: str :raises IntegrityError: if the signature is invalid """ if not ct: return None if not sender: sender = self.username # verify the key is valid signed, check = ct[:512], ct[512:] + self.hash(sender + filename) + "ct" if self.crypto.asymmetric_verify(check, signed, self.pks.get_signature_key(sender)): ct = ct[512:] # if valid, extract the cipher text try: pt = self.crypto.asymmetric_decrypt( ct, self.elg_priv_key) # decrypt except: raise IntegrityError("decryption failure") else: raise IntegrityError("Bad Signature") return pt
def share(self, user, name): """ create a new entry on your key_list file and add the user you intend to share with, then create a signed message which will let them find your pointer, and access their entry on the key_list file with a symmetric key. :param user: Who you are sharing with :param name: the file you plan to share :return: message, which will be sent to 'user' :rtype: str """ uid = self.hash(path_join(self.username, name)) # join username and file name uid = self.crypto.message_authentication_code( uid, self.sk_n, "SHA256") # use HMAC to hash/salt # open the pointer pointer = self.storage_server.get(uid) pointer = pointer[10:] # remove [POINTER] tag signature = pointer[-512:] # remove signature key_list = pointer[:-512] # remove key_list if not self.crypto.asymmetric_verify( key_list + self.username, signature, self.pks.get_signature_key(self.username)): raise IntegrityError("bad key_list signature") key_list = json.loads(key_list) # Load the dictionary with names # Get the info for the Data/Pointer that this pointer is aimed at try: pointer = key_list[self.hash2(self.username, self.sk_n2)] pointer = [self.asym_unpack(p, uid) for p in pointer] except KeyError: raise IntegrityError("own key entry missing") # make the new pointer sk_m = self.crypto.get_random_bytes( 32) # generate a symmetric key for the message sk_s = self.crypto.get_random_bytes(32) # key for signing sk_n2 = pointer[ 4] # key for HMAC of name (shared for the whole pointer) pointer = [self.sym_pack(p, sk_m, sk_s, uid) for p in pointer] owner_access = [self.asym_pack(sk_m, uid), self.asym_pack(sk_s, uid) ] # let owner remember keys for revocation pointer += owner_access # append the owner's keys to the back of the pointer key_list[self.hash2(user, sk_n2)] = pointer key_list = json.dumps(key_list) signature = self.crypto.asymmetric_sign( key_list + self.username, self.rsa_priv_key) # sign key_list as owner key_list += signature key_list = "[POINTER] " + key_list self.storage_server.put(uid, key_list) msg = [uid, sk_m, sk_s, sk_n2] msg = [self.asym_pack(ms, "msg", user) for ms in msg] msg = json.dumps(msg) return msg
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 server_data(self, node, uid, ke, km): data = "" tree = LocalMerkleTree(self.hash, uid) tree.hash = node["h"] tree.left = node["l"] tree.right = node["r"] tree.length = node["n"] if node["r"] is None: data = self.get_server_node(node["l"], ke, km, isData=True) if self.hash(data) != node["h"]: raise IntegrityError() tree.left = DataNote(data, self.hash) tree.left.uid = node["l"] return data, tree else: left_node = self.get_server_node(node["l"], ke, km, isData=False) right_node = self.get_server_node(node["r"], ke, km, isData=False) if self.hash("{0}{1}".format(left_node["h"], right_node["h"])) != node["h"]: raise IntegrityError() tmp, tree.left = self.server_data(left_node, node["l"], ke, km) data += tmp tmp, tree.right = self.server_data(right_node, node["r"], ke, km) data += tmp return data, tree
def get_server_node(self, uid, ke, km, isData=False): res = self.resolve(uid, ke, km) if res is None: raise IntegrityError() _, _, _, server_root = res if not self.is_data_node(server_root): raise IntegrityError() if isData: return self.parse_data_node(server_root) else: return json.loads(self.parse_data_node(server_root))
def __init__(self, storage_server, public_key_server, crypto_object, username): super().__init__(storage_server, public_key_server, crypto_object, username) helper = self.string_concat(self.username, 'hello_world') uid = self.crypto.cryptographic_hash(helper, 'SHA256') helper2 = self.string_concat(self.username, 'dictionary') uid2 = self.crypto.cryptographic_hash(helper2, 'SHA256') if self.storage_server.get(uid) is None: #have no dictionary yet, and has no key for that dictionary yet self.dictionary = {} input_string = json.dumps(self.dictionary) God_key = self.crypto.get_random_bytes(16) encrypted_God_key= self.crypto.asymmetric_encrypt(God_key, self.pks.get_encryption_key(self.username)) signed_God_key = self.crypto.asymmetric_sign(encrypted_God_key, self.rsa_priv_key) self.storage_server.put(uid, signed_God_key+encrypted_God_key) #let encrypt the dictionary now IV = self.crypto.get_random_bytes(16) encry_dictionary =IV+ self.crypto.symmetric_encrypt(input_string, self.crypto.cryptographic_hash(God_key,'SHA256'), 'AES','CBC', IV, None,self.crypto.new_counter(128),None, 128) encry_dictionary_mac = self.crypto.message_authentication_code(encry_dictionary, self.crypto.cryptographic_hash(God_key+ "Dictionary_mac", 'SHA256'), 'SHA256') self.storage_server.put(uid2, encry_dictionary_mac+encry_dictionary) else: #To get the storage key total_key = self.storage_server.get(uid) signed_God_key = total_key[:512] encrypted_God_key = total_key[512:] if not self.crypto.asymmetric_verify(encrypted_God_key, signed_God_key, self.pks.get_signature_key(self.username)): raise IntegrityError() God_key = self.crypto.asymmetric_decrypt(encrypted_God_key, self.elg_priv_key) #Stoarge key obtained if self.storage_server.get(uid2) is None: dictionary = {} self.dictionary = dictionary input_string = json.dumps(dictionary) IV = self.crypto.get_random_bytes(16) encry_dictionary = IV + self.crypto.symmetric_encrypt(input_string, self.crypto.cryptographic_hash(God_key, 'SHA256'), 'AES','CBC',IV, None,self.crypto.new_counter(128),None, 128) encry_dictionary_mac = self.crypto.message_authentication_code(encry_dictionary, self.crypto.cryptographic_hash(God_key+ "Dictionary_mac"), 'SHA256') self.storage_server.put(uid2, encry_dictionary_mac+encry_dictionary) else: total_dictionary = self.storage_server.get(uid2) encry_dictionary_mac = total_dictionary[:64] encry_dictionary = total_dictionary[64:] IV = encry_dictionary[:32] if self.crypto.message_authentication_code(encry_dictionary,self.crypto.cryptographic_hash(God_key+ "Dictionary_mac",'SHA256'),'SHA256') !=encry_dictionary_mac : raise IntegrityError() input_string = self.crypto.symmetric_decrypt(encry_dictionary[32:],self.crypto.cryptographic_hash(God_key,'SHA256'), 'AES','CBC',IV, None,self.crypto.new_counter(128),None, 128) dictionary = json.loads(input_string) self.dictionary = dictionary #need a sharing key dictionary #meaning we are not store anything when we init self.stored_file = {} self.cipher_text_list = {} self.shared_dictionary= {}
def parse_pointer_node(self, value): assert self.is_pointer_node( value), "must be a data node for parse_share_node" prefix = "[POINTER]" value = value[len(prefix):] if "||" not in value: raise IntegrityError() parsed = value.split("||") if len(parsed) != 3: raise IntegrityError() ke, km, did = parsed return ke, km, did
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 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 resolve(self, uid): """ navigates through and unpacks a series of linked pointers until it reaches a [DATA] file. :param uid: starting location :return uid: The location of the [DATA] file :return sk_m: the decryption , symmetric key :return sk_s: the signature symmetric key :rtype str, str, str """ sk_n2 = self.sk_n2 sk_m = None sk_s = None sk_t = None owner = self.username requester = self.username while True: res = self.storage_server.get(uid) if res is None or res.startswith("[DATA]"): return uid, sk_m, sk_s, sk_t elif res.startswith("[POINTER]"): pointer = res[10:] # remove [POINTER] tag signature = pointer[-512:] key_list = pointer[:-512] if not self.crypto.asymmetric_verify( key_list + owner, signature, self.pks.get_signature_key(owner)): raise IntegrityError("bad key_list verification") key_list = json.loads( key_list) # Load the dictionary with names try: pointer = key_list[self.hash2( requester, sk_n2)] # go to your place in dictionary if sk_m and sk_s: # if you have symmetric keys, you are following the chain' for i in range(6): pointer[i] = self.sym_unpack( pointer[i], sk_m, sk_s, uid) else: # if you do not have symmetric keys, you should own this pointer. pointer = [self.asym_unpack(p, uid) for p in pointer] except KeyError: self.storage_server.put("invalid", "restricted") return "invalid", None, None, None requester = owner # you are now requesting as the owner of the last pointer uid, sk_m, sk_s, owner, sk_n2, sk_t = pointer[: 6] # update the location, keys and who owns the pointer else: raise IntegrityError()
def __init__(self, storage_server, public_key_server, crypto_object, username): super().__init__(storage_server, public_key_server, crypto_object, username) location = username + "my key" self.key = self.storage_server.get(location) if not self.key: self.key = self.crypto.get_random_bytes(32) encrypted_key = self.crypto.asymmetric_encrypt( self.key, self.pks.get_encryption_key(self.username)) encrypted_key += self.crypto.asymmetric_sign( encrypted_key, self.rsa_priv_key) self.storage_server.put(location, encrypted_key) else: sign = self.key[-512:] self.key = self.key[:-512] if self.crypto.asymmetric_verify( self.key, sign, self.pks.get_signature_key(self.username)): self.key = self.crypto.asymmetric_decrypt( self.key, self.elg_priv_key) else: print("Verification error") raise IntegrityError()
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()
def create_header(self, file_loc, arg1, arg2, chain=False, metadata=False): header_location = self.crypto.get_random_bytes(LOC_LEN)[:LOC_LEN] #idk if chain: if metadata: raise IntegrityError("can't create chinaed metadata block!") #TODO for sharing value = 'HDR' + file_loc + "1" + arg1 + arg2 else: if metadata: value = 'MET' + file_loc + "0" + arg1 + arg2 else: value = 'HDR' + file_loc + "0" + arg1 + arg2 aes_key = str(self.pks.get_encryption_key( self.username).y)[:ENC_KEY_LEN] mac_key = str(self.pks.get_encryption_key( self.username).y)[:ENC_KEY_LEN] nonce = self.crypto.get_random_bytes(NONCE_LEN // 2) counter = self.crypto.new_counter(COUNTER_LEN, prefix=nonce) aes_val = self.crypto.symmetric_encrypt(value, aes_key, cipher_name='AES', mode_name='CTR', counter=counter) mac_val = self.crypto.message_authentication_code(nonce + aes_val, mac_key, hash_name='SHA256') self.storage_server.put(header_location, mac_val + nonce + aes_val) return header_location
def share(self, user, name): SYMMETRIC_KEY_LENGTH = 16 # Get symmetric keys ke, km, kn = self.get_symmetric_keys() # Get shares directory shares = self.get_shares_directory() # Get ID for the key node of file NAME uid = self.get_kid(name, kn) # Get ke, km, uid that NAME links to for this client node = self.decrypt_values_at_id(uid, ke, km) if self.is_pointer_node(node): ke, km, uid = self.parse_pointer_node(node) elif not self.is_data_node(node): raise IntegrityError() # Create value stored at share node share_node_v = "[POINTER]{0}||{1}||{2}".format(ke, km, uid) # New key to encrypt share node ke2, km2, _ = self.new_symmetric_keys() # New share node of id DID did = self.new_did() # Encrypt share node with new keys share_node_v = self.encrypt_value_for_storage(did, share_node_v, ke2, km2) # Store share node at a random new data node id: did self.storage_server.put(did, share_node_v) # Construct the message to share msg = "[POINTER]{0}||{1}||{2}".format(ke2, km2, did) encrypt_k = self.pks.get_encryption_key(user) if encrypt_k is None: raise IntegrityError() ciphertext = self.crypto.asymmetric_encrypt(msg, encrypt_k) ciphertext_user = path_join([ciphertext, user], separator="/") # Sign the encryption sig = self.crypto.asymmetric_sign(ciphertext_user, self.rsa_priv_key) # Update information about shared node to the directory if name not in shares: shares[name] = dict() shares[name][user] = {"did": did, "ke": ke2, "km": km2} # Update shares directory self.put_shares_directory(shares) # Return the share message return path_join([ciphertext, sig], separator="||")
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 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 upload(self, name, value): # Get symmetric keys ke, km, kn = self.get_symmetric_keys() # Get ID for the key node of file NAME uid = self.get_kid(name, kn) # Get Ke, Km, and did for data node res = self.resolve(uid, ke, km) if res is None: # Create new data node ke2, km2, _ = self.new_symmetric_keys() did = self.new_did() key_node_v = "[POINTER]{0}||{1}||{2}".format(ke2, km2, did) key_node_v_enc = self.encrypt_value_for_storage( uid, key_node_v, ke, km) self.storage_server.put(uid, key_node_v_enc) uid = did ke, km = ke2, km2 isNew = True else: ke, km, uid, _ = res isNew = False tree = LocalMerkleTree(self.hash, uid=uid) tree.initialize(value, blocksize=1024, uid_gen=self.new_did) if name not in self.trees: if isNew: self.upload_updates(tree.all_nodes(), ke, km) else: server_root = self.get_server_node(uid, ke, km) if tree.length <= server_root["n"]: self.efficient_update(tree, ke, km) else: self.delete_server_tree(uid, ke, km) self.upload_updates(tree.all_nodes(), ke, km) self.trees[name] = tree else: if isNew: raise IntegrityError() local_tree = self.trees[name] server_root = self.get_server_node(uid, ke, km) tree.update_uids(local_tree.all_uids()) if local_tree.hash == server_root["h"]: if local_tree.length >= tree.length: self.upload_updates(local_tree.compare_and_update(tree), ke, km) self.trees[name] = local_tree else: self.delete_server_tree(uid, ke, km) self.upload_updates(tree.all_nodes(), ke, km) self.trees[name] = tree else: if local_tree.length >= tree.length: self.efficient_update(tree, ke, km) else: self.delete_server_tree(uid, ke, km) self.upload_updates(tree.all_nodes(), ke, km) self.trees[name] = tree
def resolve(self, uid): while True: res = self.storage_server.get(uid) if res is None or res.startswith("[DATA]"): return uid elif res.startswith("[POINTER]"): uid = res[10:] else: raise IntegrityError()
def resolve(self, uid): """Follows [P]'s until we reach the a None or [D]""" while True: res = self.storage_server.get(uid) if res is None or res.startswith("[D]"): return uid elif res.startswith("[P]"): uid = res[4:] else: raise IntegrityError()
def verify_signature_and_get_value(self, signer, data_id): value_string = self.storage_server.get(data_id) if not value_string: return None else: try: encrypted_content, signed_encrypted_content = util.from_json_string( value_string[7:]) except: raise IntegrityError() if self.crypto.asymmetric_verify(encrypted_content, signed_encrypted_content, self.pks.get_public_key(signer)): decrypted_content = self.crypto.asymmetric_decrypt( encrypted_content, self.private_key) return decrypted_content else: 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 getRoot(self, ID, sym_ka): meta = self.storage_server.get(path_join(ID, str(0))) if meta is None: return None try: meta = util.from_json_string(meta) numblocks = meta['numblocks'] mac = meta['mac'] meta_mac = self.crypto.message_authentication_code( str(numblocks), sym_ka, 'SHA') #SHA if meta_mac != mac: raise IntegrityError() except: raise IntegrityError() return numblocks
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 checkTreeNode(self, path, sym_Ka): resp = self.storage_server.get(path) if resp is None: return None try: resp = util.from_json_string(resp) except: raise IntegrityError() stored_hash = resp['hash'] mac = resp['mac'] newmac = self.crypto.message_authentication_code( stored_hash, sym_Ka, 'SHA') #SHA if mac != newmac: raise IntegrityError() return stored_hash
def resolve(self, uid, ke, km): node = self.decrypt_values_at_id(uid, ke, km) # resolve pointers until we reach a data node while True: if node is None: return None elif self.is_data_node(node): return ke, km, uid, node elif self.is_pointer_node(node): ke, km, uid = self.parse_pointer_node(node) else: raise IntegrityError() node = self.decrypt_values_at_id(uid, ke, km)
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