Esempio n. 1
0
    def encrypt_and_put(self, data, data_id, key_encryption, key_auth,
                        data_iv):
        # Re-encrypt the data.
        if isinstance(data, self.node):
            data = data.to_json_obj()
        elif isinstance(data, self.merkle_node):
            data = data.to_json_obj()
        json_data = util.to_json_string(data)
        new_encrypt_data = self.crypto.symmetric_encrypt(json_data,
                                                         key_encryption,
                                                         'AES',
                                                         'CBC',
                                                         IV=data_iv)

        string_new_encrypt_data = util.to_json_string(
            [new_encrypt_data, data_iv])
        sign_new_encrypt_data = self.crypto.message_authentication_code(
            string_new_encrypt_data, key_auth, 'SHA512')
        # Put new_encrypt_data back in server
        string_data = util.to_json_string(
            (new_encrypt_data, sign_new_encrypt_data, data_iv))
        self.storage_server.put(data_id, string_data)
        # 'MERKEL TREE'
        self.crypto.cryptographic_hash(string_data, 'SHA256')
        return self.crypto.cryptographic_hash(string_data, 'SHA256')
Esempio n. 2
0
    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
Esempio n. 3
0
    def __init__(self, storage_server, public_key_server, crypto_object,
                 username):

        super().__init__(storage_server, public_key_server, crypto_object,
                         username)

        self.threshold = 128

        k1 = path_join(self.username, "dir_keys")
        k2 = path_join(self.username, "dir")
        k3 = path_join(self.username, "sdir_keys")
        k4 = path_join(self.username, "sdir")

        # We only create a directory for the user if this is the first time the user uses the client
        if self.storage_server.get(k1) is None and self.storage_server.get(
                k2) is None:
            # Create keys to encrypt directory for user
            enc_key = self.crypto.get_random_bytes(16)
            mac_key = self.crypto.get_random_bytes(16)

            # Grab user's public key
            pub_key = self.pks.get_public_key(self.username)

            # Generate the encryption of the keys as well as the signature for it
            encryption = self.crypto.asymmetric_encrypt(
                enc_key + mac_key, pub_key)
            sig = self.crypto.asymmetric_sign(encryption, self.private_key)

            # Store the keys and their signature in the storage server
            self.storage_server.put(k1, encryption + sig)

            # Generate the encryption of the directory as well as a mac for it
            directory = {}
            toStore = e_and_m(self.crypto, enc_key, mac_key,
                              to_json_string(directory))
            self.storage_server.put(k2, toStore)

        # We only create a sharing directory for the user if this is the first time the user uses the client
        if self.storage_server.get(k3) is None and self.storage_server.get(
                k4) is None:
            # Create keys to encrypt directory for user
            enc_key = self.crypto.get_random_bytes(16)
            mac_key = self.crypto.get_random_bytes(16)

            # Grab user's public key
            pub_key = self.pks.get_public_key(self.username)

            # Generate the encryption of the keys as well as the signature for it
            encryption = self.crypto.asymmetric_encrypt(
                enc_key + mac_key, pub_key)
            sig = self.crypto.asymmetric_sign(encryption, self.private_key)

            # Store the keys and their signature in the storage server
            self.storage_server.put(k3, encryption + sig)

            # Generate the encryption of the sharing directory as well as a mac for it
            sdirectory = {}
            toStore = e_and_m(self.crypto, enc_key, mac_key,
                              to_json_string(sdirectory))
            self.storage_server.put(k4, toStore)
Esempio n. 4
0
    def share(self, user, name):
        self.get_dir()
        if not name in self.dir:
            # file not part of user's dir
            return None
        file_record = self.dir[name]

        target_pub_key = self.pks.get_public_key(user)
        if not target_pub_key:
            # can't find user to share with
            return None

        # generate new share record
        loc = self.crypto.get_random_bytes(32)
        enc_key = self.crypto.get_random_bytes(32)
        mac_key = self.crypto.get_random_bytes(32)

        share_record = {
            'loc': loc,
            'enc_key': enc_key,
            'mac_key': mac_key,
        }

        file_record['shared'][user] = share_record
        self.upload_dir()

        # create and upload a gateway file
        gateway_record = {
            'loc': file_record['loc'],
            'enc_key': file_record['enc_key'],
            'mac_key': file_record['mac_key'],
            'is_leaf': not file_record['is_gateway']
        }

        value = to_json_string(gateway_record)

        self.put(value, loc, enc_key, mac_key)

        # construct sharing message

        value = to_json_string(share_record)
        iv = self.crypto.get_random_bytes(16)
        enc_key = self.crypto.get_random_bytes(32)
        enc_value = self.sym_enc(value, iv, enc_key)
        enc_enc_key = self.crypto.asymmetric_encrypt(enc_key, target_pub_key)
        msg = {
            'enc_value':
            enc_value,
            'iv':
            iv,
            'enc_enc_key':
            enc_enc_key,
            'sig':
            self.crypto.asymmetric_sign(enc_enc_key + iv + enc_value,
                                        self.private_key)
        }

        return to_json_string(msg)
Esempio n. 5
0
    def receive_share(self, from_username, newname, message):
        """Agrees to the access granted from from_username and user will access this file using the filename 
           newname. First, we create a mapping from newname to an (id, encryption_key, mac_key) and store it 
           into user's directory. Then, we store the id : sharename mapping into the server. Recall that sharename
           is a [P].
        """
        if message is not None:  # Make sure that something is really shared to us
            # Grab the directory keys of user
            keys1 = self.grab_directory_keys()
            enc_key1 = keys1[0]
            mac_key1 = keys1[1]

            # Grab the sharing directory of this user
            keys2 = self.grab_sdirectory_keys()
            enc_key2 = keys2[0]
            mac_key2 = keys2[1]

            # Grab the directories of using the keys above
            directory = self.grab_directory(enc_key1, mac_key1)
            sdirectory = self.grab_sdirectory(enc_key2, mac_key2)

            # Verify the message
            msg = message[:512]
            sig = message[512:]

            # Test if our message aren't messed with
            if not self.crypto.asymmetric_verify(
                    msg, sig, self.pks.get_public_key(from_username)):
                raise IntegrityError
            # If we reach here, we have verified that our message are good

            decrypted_value = self.crypto.asymmetric_decrypt(
                msg, self.private_key)
            share_id = decrypted_value[:32]
            share_ekey = decrypted_value[32:64]  # Got directory encryption key
            share_mkey = decrypted_value[64:]  # Got directory mac key

            # Generate (file_id, encryption_key, mac_key) tuple
            file_id = self.crypto.get_random_bytes(16)
            tup = (file_id, share_ekey, share_mkey)

            # Store a mapping of newname : tuple into directory, encrypt the directory and then store it into the server
            directory[
                newname] = tup  # Replaces tup at newname even if it already has a value
            toStore = e_and_m(self.crypto, enc_key1, mac_key1,
                              to_json_string(directory))
            k1 = path_join(self.username, "dir")
            self.storage_server.put(k1, toStore)

            # Store a mapping of id : sharename_pointer into the storage server
            self.storage_server.put(file_id, "[P] " + share_id)

            # Create an empty dictionary under this filename for our sharing directory
            sdirectory[newname] = {}
            toStore = e_and_m(self.crypto, enc_key2, mac_key2,
                              to_json_string(sdirectory))
            k2 = path_join(self.username, "sdir")
            self.storage_server.put(k2, toStore)
Esempio n. 6
0
    def revoke(self, user, name):
        """This method basically allows user to revoke any other user that he/she shared the file with.
           Once revoked, that user and every other person that he/she shared this file with will no longer 
           have access to the destination of the share chain, i.e. the real copy of the file.
        """
        # Grab the directory keys of user
        keys1 = self.grab_directory_keys()
        enc_key1 = keys1[0]
        mac_key1 = keys1[1]

        # Grab the sharing directory of this user
        keys2 = self.grab_sdirectory_keys()
        enc_key2 = keys2[0]
        mac_key2 = keys2[1]

        # Grab the directories of using the keys above
        directory = self.grab_directory(enc_key1, mac_key1)
        sdirectory = self.grab_sdirectory(enc_key2, mac_key2)

        # Download our file and update our directory so that we can correctly upload our file again
        content = self.download(name)
        directory.pop(name)
        toStore = e_and_m(self.crypto, enc_key1, mac_key1,
                          to_json_string(directory))
        k1 = path_join(self.username, "dir")
        self.storage_server.put(k1, toStore)
        self.upload(name, content)

        # Re-grab our directory
        directory = self.grab_directory(enc_key1, mac_key1)

        # Grab the tuple corresponding to the filename name
        tup = directory.get(name)
        if tup is None:  # Case when such tuple doesn't exist. Nothing to share here
            return None
        else:  # Case when such a tuple does exist
            # Grab the id that corresponds to this filename in the user's directory as well as the keys
            new_file_id, new_ekey, new_mkey = tup[0], tup[1], tup[2]

        # We delete user from our updates list and update the others
        d = sdirectory.get(name)
        d.pop(user)
        for k, v in d.items():
            share_id = v[0]
            share_ekey = v[1]
            share_mkey = v[2]
            toStore = e_and_m(self.crypto, share_ekey, share_mkey,
                              new_file_id + new_ekey + new_mkey)
            self.storage_server.put(share_id, toStore)

        # Update our sharing directory with the revoked user revoked
        sdirectory[name] = d
        toStore = e_and_m(self.crypto, enc_key2, mac_key2,
                          to_json_string(sdirectory))
        name = path_join(self.username, "sdir")
        self.storage_server.put(name, toStore)
Esempio n. 7
0
    def revoke(self, user, name):
        value = self.download(name)
        if not value:
            return False

        file_record = self.dir[name]
        shares = file_record['shared']

        # check to make sure we've shared with that user
        if not user in shares:
            return False
        else:
            shares.pop(user)

        # re-encrypt and upload the file again
        new_mac_key = self.crypto.get_random_bytes(32)
        new_enc_key = self.crypto.get_random_bytes(32)

        file_record['enc_key'] = new_enc_key
        file_record['mac_key'] = new_mac_key

        # upload actual file
        merkle = self.create_merkle(value)

        file_meta = {
            'length': len(value),
            'tree': merkle.loc,
        }

        self.upload_merkle(merkle, new_enc_key, new_mac_key)

        file_meta_value = to_json_string(file_meta)

        self.put(file_meta_value, file_record['loc'], new_enc_key, new_mac_key)

        self.upload_dir()

        for u in shares:
            share_record = shares[u]
            loc = share_record['loc']
            enc_key = share_record['enc_key']
            mac_key = share_record['mac_key']

            gateway_record = {
                'loc': file_record['loc'],
                'enc_key': new_enc_key,
                'mac_key': new_mac_key,
                'is_leaf': not file_record['is_gateway']
            }

            value = to_json_string(gateway_record)

            self.put(value, loc, enc_key, mac_key)

        return True
Esempio n. 8
0
    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
Esempio n. 9
0
    def share(self, user, name):
        # 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:
            return None

        directory = self.decrypt_directory(resp, sym_ke, sym_ka)

        if name not in directory:
            return None

        file = directory[name]
        # directory[name] = {"keys": (keys, session_key), "shared": [], "file_id": self.crypto.get_random_bytes(16)}}
        # owner sharing w/ child
        if len(file["file_id"]) == 32:
            keys = file["keys"][0]
            session_key = file["keys"][1]
            file_id = path_join(user, self.username, file["file_id"])
            self.encrypt_filepath(file_id, session_key, keys, name)

        # directory[name] = {"keys": session_key, "shared": [], "file_id": B/A/random 16 bytes}
        # child sharing w/ grandchild
        else:
            file_id = file["file_id"]
            session_key = file["keys"]

        directory[name]["shared"].append(user)

        self.encrypt_directory(client_ID, directory, sym_ke, sym_ka)

        # cache directory
        self.directory[name]["shared"].append(user)

        # ENCRYPT MESSAGE TO SEND
        recipient_pub_key = self.pks.get_public_key(user)

        share_info = {"session_key": session_key, "file_id": file_id}
        share_info = util.to_json_string(share_info)

        crypted = self.crypto.asymmetric_encrypt(share_info, recipient_pub_key)
        sign = self.crypto.asymmetric_sign(crypted, self.private_key)

        output = (crypted, sign)
        output = util.to_json_string(output)

        return output
Esempio n. 10
0
    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
Esempio n. 11
0
    def encrypt_directory(self, client_ID, directory, sym_ke, sym_ka):
        directory = util.to_json_string(directory)

        IV = self.crypto.get_random_bytes(16)
        encrypted_dir = self.crypto.symmetric_encrypt(directory, sym_ke, 'AES',
                                                      'CBC', IV)
        signed_dir = self.crypto.message_authentication_code(
            encrypted_dir, sym_ka, 'SHA256')

        directory_info = {
            "IV": IV,
            "encrypted_keys": encrypted_dir,
            "signed_keys": signed_dir
        }
        self.storage_server.put(client_ID, util.to_json_string(directory_info))
Esempio n. 12
0
    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
Esempio n. 13
0
    def hashTree(self, ID, d, sym_ke, sym_ka):
        tree = {}

        if len(d.keys()) == 1:
            return d

        for i in d.keys():
            if i % 2 == 0:
                # even binary tree
                if i + 1 in d:
                    cipher = self.crypto.cryptographic_hash(
                        d[i] + d[i + 1], 'SHA')  #SHA
                # odd binary tree
                else:
                    cipher = self.crypto.cryptographic_hash(d[i], 'SHA')  #SHA

                path = path_join(ID, str(i // 2))
                mac = self.crypto.message_authentication_code(
                    cipher, sym_ka, 'SHA')  #SHA
                cipher_info = {"hash": cipher, "mac": mac}
                self.storage_server.put(path, util.to_json_string(cipher_info))

                tree[i // 2] = cipher

        return self.hashTree(ID, tree, sym_ke, sym_ka)
Esempio n. 14
0
 def MAC_and_store_2(self, value_string, ka, data_id):
     MACed_value_string = self.crypto.message_authentication_code(
         value_string, ka, "MD5")
     half = int(len(MACed_value_string) / 4)
     all_value = (value_string, MACed_value_string[:half])
     all_value_string = util.to_json_string(all_value)
     self.storage_server.put(data_id, all_value_string)
Esempio n. 15
0
 def make_file_keys(self, fid):
     ka = self.crypto.get_random_bytes(16)
     ke = self.crypto.get_random_bytes(16)
     keys = (ka, ke)
     keys_string = util.to_json_string(keys)
     self.sign_and_store(keys_string, self.username, fid)
     return keys
Esempio n. 16
0
    def receive_share(self, from_username, newname, message):
        """Agrees to the access granted from from_username and user will access this file using the filename 
           newname. First, we create a mapping from newname to an (id, encryption_key, mac_key) and store it 
           into user's directory. Then, we store the id : sharename mapping into the server. Recall that sharename
           is a [P].
        """
        if message is not None:  # Make sure that something is really shared to us
            # Grab the directory keys of user
            keys = self.grab_directory_keys()
            enc_key = keys[0]
            mac_key = keys[1]

            # Grab the directory using the keys above
            directory = self.grab_directory(enc_key, mac_key)

            # Generate (file_id, encryption_key, mac_key) tuple
            file_id = self.crypto.get_random_bytes(16)
            e_key = message[1]
            m_key = message[2]
            tup = (file_id, e_key, m_key)

            # Store a mapping of newname : tuple into directory, encrypt the directory and then store it into the server
            directory[
                newname] = tup  # Replaces tup at newname even if it already has a value
            iv = self.crypto.get_random_bytes(16)
            enc = self.crypto.symmetric_encrypt(to_json_string(directory),
                                                enc_key, 'AES', 'CBC', iv)
            mac = self.crypto.message_authentication_code(
                iv + enc, mac_key, 'SHA256')
            name = path_join(self.username, "dir")
            self.storage_server.put(name, iv + enc + mac)

            # Store a mapping of id : sharename_pointer into the storage server
            k = path_join(self.username, "files", file_id)
            self.storage_server.put(k, "[P] " + message[0])
Esempio n. 17
0
    def revoke(self, user, name):
        """This method basically allows user to revoke any other user that he/she shared the file with.
           Once revoked, that user and every other person that he/she shared this file with will no longer 
           have access to the destination of the share chain, i.e. the real copy of the file.
        """
        # Grabs the sharing directory keys of user
        keys = self.grab_sdirectory_keys()
        enc_key = keys[0]
        mac_key = keys[1]

        # Grabs the sharing directory of user
        sdirectory = self.grab_sdirectory(enc_key, mac_key)

        # Grabs the file id of the corresponding user + name combo and make sure that it exists
        file_id = sdirectory.get(user + name)
        if file_id is not None:  # We are only able to revoke a user of a file if it exists
            # Generate the sharename that user wants to delete
            sharename = path_join(self.username, "sharewith", user, file_id)
            # Delete the sharename so that the shared user and the people they shared with cannot reach the destination
            # of the share chain anymore
            self.storage_server.delete(sharename)

            # Remove this sharing instance from the sdirectory and store it back into the storage server
            sdirectory.pop(user + name)
            iv = self.crypto.get_random_bytes(16)
            enc = self.crypto.symmetric_encrypt(to_json_string(sdirectory),
                                                enc_key, 'AES', 'CBC', iv)
            mac = self.crypto.message_authentication_code(
                iv + enc, mac_key, 'SHA256')
            name = path_join(self.username, "sdir")
            self.storage_server.put(name, iv + enc + mac)
Esempio n. 18
0
    def upload_dir(self):
        iv = self.crypto.get_random_bytes(16)
        dir_str = to_json_string(self.dir)
        enc_value = self.sym_enc(dir_str, iv, self.dir_enc_key)

        dir_pkg = {
            'iv': iv,
            'mac': self.mac(self.dir_loc + iv + enc_value, self.dir_mac_key),
            'enc_value': enc_value
        }

        value = to_json_string(dir_pkg)

        if not self.storage_server.put(self.dir_loc, value):
            # need to keep dir updated at all times
            raise IntegrityError
Esempio n. 19
0
 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
Esempio n. 20
0
    def upload_merkle(self, node, enc_key, mac_key, root=True):
        node_value = {
            'hash': node.hash,
            'left': node.left.loc if node.left else None,
            'right': node.right.loc if node.right else None,
            'iv': None,
            'data': None
        }

        if node.data:
            node_value['iv'] = node.iv
            node_value['data'] = self.sym_enc(node.data, node.iv, enc_key)

        value = to_json_string(node_value)

        if root:
            self.put_no_enc(value, node.loc, mac_key)
        else:
            self.storage_server.put(node.loc, value)

        if not node.data:
            if node.left:
                self.upload_merkle(node.left, enc_key, mac_key, False)
            if node.right:
                self.upload_merkle(node.right, enc_key, mac_key, False)
Esempio n. 21
0
 def hashData(self, ID, message, sym_ke, sym_ka):
     IV = self.crypto.get_random_bytes(16)
     encrypted_message = self.crypto.symmetric_encrypt(
         message, sym_ke, 'AES', 'CBC', IV)
     mac = self.crypto.message_authentication_code(encrypted_message + ID,
                                                   sym_ka, 'SHA256')
     message_info = {"IV": IV, "encrypted": encrypted_message, "mac": mac}
     self.storage_server.put(ID, util.to_json_string(message_info))
Esempio n. 22
0
 def sign_and_store(self, value_string, user, data_id):
     encrypted_value_string = self.crypto.asymmetric_encrypt(
         value_string, self.pks.get_public_key(user))
     signed_encrypted_value_string = self.crypto.asymmetric_sign(
         encrypted_value_string, self.private_key)
     all_value = (encrypted_value_string, signed_encrypted_value_string)
     all_value_string = util.to_json_string(all_value)
     self.storage_server.put(data_id, "[DATA] " + all_value_string)
Esempio n. 23
0
    def safe_encrypt(self, keys):
        pub_key = self.private_key.publickey()
        key_str = util.to_json_string(keys)

        encrypted_keys = self.crypto.asymmetric_encrypt(key_str, pub_key)
        signed_keys = self.crypto.asymmetric_sign(encrypted_keys,
                                                  self.private_key)

        return {"encrypted_keys": encrypted_keys, "signed_keys": signed_keys}
Esempio n. 24
0
 def receive_share(self, from_username, newname, message):
     # # Replace with your implementation (not needed for Part 1)
     # raise NotImplementedError
     if self.storage_server.get(self.username + "/shared") is None:
         dictionary = {newname : (message[1], from_username, message[0])}
     else:
         dictionary = self.storage_server.get(self.username + "/shared")
         dictionary[newname] = (message[1], from_username, message[0])
     self.storage_server.put(self.username + "/shared", util.to_json_string(dictionary))
Esempio n. 25
0
 def AES_CBC_and_store(self, string, keys, uid):
     ka, ke = keys
     IV = self.crypto.get_random_bytes(16)
     cipher_string = self.crypto.symmetric_encrypt(string, ke, "AES", "CBC",
                                                   IV)
     tag = self.crypto.message_authentication_code(IV + cipher_string + uid,
                                                   ka, "MD5")
     cipher_all = (IV, cipher_string, tag)
     cipher_all_string = util.to_json_string(cipher_all)
     self.storage_server.put(uid, "[DATA] " + cipher_all_string)
Esempio n. 26
0
    def share(self, user, name):
        share_file = None
        if self.storage_server.get(path_join(self.username, "share_file",
                                             name)) is None:
            share_file = []
        else:
            share_file_as_string = self.storage_server.get(
                path_join(self.username, "share_file", name))
            share_file = util.from_json_string(share_file_as_string)

        share_file.append(user)
        share_file_as_string = util.to_json_string(share_file)
        self.storage_server.put(path_join(self.username, "share_file", name),
                                share_file_as_string)

        uid = self.resolve(path_join(self.username, name))

        sharename = path_join("[SHARE]", self.username, "sharewith", user,
                              name)

        if uid.startswith("[SHARE]"):
            shared_info = self.get_shared_random_shit(uid)
            #encrypt the shared_info
            self.storage_server.put(
                sharename, "[POINTER] " + path_join(self.username, name))
            return sharename  #msg = [sharename]

        dictionary = self.retrieve_dict()

        random_keys = dictionary.get(path_join(self.username, name))

        if random_keys is None:  #when you try to share something you don't have access to; get rid of this?
            return None

        random_id = random_keys[0]
        random_key_for_value = random_keys[1]
        random_key_for_value_mac = random_keys[2]
        message = [random_id, random_key_for_value, random_key_for_value_mac]
        message_as_string = util.to_json_string(message)
        self.storage_server.put(sharename, "[DATA] " + message_as_string)
        return sharename
Esempio n. 27
0
    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)
Esempio n. 28
0
    def put_no_enc(self, value, loc, mac_key):
        pkg = {
            'mac': self.mac(loc + value, mac_key),
            'value': value,
        }

        value = to_json_string(pkg)

        if not self.storage_server.put(loc, value):
            # already updated directory but can't upload file
            return False

        return True
Esempio n. 29
0
    def get_directory_keys(self):
        dir_ID = path_join("information", self.username)

        resp = self.storage_server.get(dir_ID)

        if resp is None:
            keys = self.dir_keys()
            key_info = self.safe_encrypt(keys)
            self.storage_server.put(dir_ID, util.to_json_string(key_info))
        else:
            keys = self.safe_decrypt(resp)

        return keys
Esempio n. 30
0
    def share(self, user, name):
        """Creates an intermediate sharename that can be deleted only by the user since it is tied to the id
           that is in the directory of this user. Then, stores a mapping of the sharename to a pointer that will 
           links to the destination of the real file. Returns a tuple with sharename and the keys needed to update
           or download this file.
        """
        # Grab the directory keys of user
        keys1 = self.grab_directory_keys()
        enc_key1 = keys1[0]
        mac_key1 = keys1[1]

        # Grab the sharing directory of this user
        keys2 = self.grab_sdirectory_keys()
        enc_key2 = keys2[0]
        mac_key2 = keys2[1]

        # Grab the directories of using the keys above
        directory = self.grab_directory(enc_key1, mac_key1)
        sdirectory = self.grab_sdirectory(enc_key2, mac_key2)

        # Grab the tuple corresponding to the filename name
        tup = directory.get(name)
        if tup is None:  # Case when such tuple doesn't exist. Nothing to share here
            return None
        else:  # Case when such a tuple does exist
            # Grab the id that corresponds to this filename in the user's directory as well as the keys
            file_id, e_key, m_key = tup[0], tup[1], tup[2]

        share_id = self.crypto.get_random_bytes(16)
        share_ekey = self.crypto.get_random_bytes(16)
        share_mkey = self.crypto.get_random_bytes(16)
        toStore = e_and_m(self.crypto, share_ekey, share_mkey,
                          file_id + e_key + m_key)
        self.storage_server.put(share_id, toStore)

        # Store this sharing information into our sharing directory
        d = sdirectory[name]
        d[user] = (share_id, share_ekey, share_mkey)
        sdirectory[name] = d

        # Update this sharing directory back to the storage server
        toStore = e_and_m(self.crypto, enc_key2, mac_key2,
                          to_json_string(sdirectory))
        self.storage_server.put(path_join(self.username, "sdir"), toStore)

        dst_pk = self.pks.get_public_key(user)
        msg = self.crypto.asymmetric_encrypt(
            share_id + share_ekey + share_mkey, dst_pk)
        sig = self.crypto.asymmetric_sign(msg, self.private_key)

        return msg + sig