def delete_participant(tree_root, participant, changed_root_keys=None): # find the node participant_to_be_removed = findall_by_attr(tree_root, participant.participant_id)[0] # find all ancestors of this participant and change keys ancestor_list = participant_to_be_removed.ancestors for ancestor in ancestor_list: if ancestor.is_root and changed_root_keys is not None: ancestor.tree_node.root_node_keys = changed_root_keys.copy() else: ancestor.tree_node.reset_key() # code to add details about the messages to be sent # first construct messages for to-be-deleted participant's siblings message_details_dict_list = [] siblings = participant_to_be_removed.siblings for sibling in siblings: if sibling.leaf_node.participant is not None: message_detail = { # "message_name": str(sibling.parent.tree_node.node_id) + "/" + str(sibling.leaf_node.node_id), "message_name": str(sibling.parent.tree_node.node_id) + "/" + str( sibling.leaf_node.participant.participant_id) + "__changeParent__" + str(sibling.parent.tree_node.node_id), "encryption_key": sibling.leaf_node.participant.pairwise_key, "changed_parent_key": sibling.parent.tree_node.node_key} message_details_dict_list.append(message_detail) # construct messages for ancestors and their siblings for ancestor in range(len(ancestor_list) - 2, -1, -1): children = ancestor_list[ancestor].children for child in children: message_detail = { "message_name": str(child.parent.tree_node.node_id) + "/" + str(child.tree_node.node_id) + "__changeParent__" + str(child.parent.tree_node.node_id), "encryption_key": child.tree_node.node_key} if child.parent.is_root and changed_root_keys is not None: message_detail["changed_parent_key"] = child.parent.tree_node.root_node_keys else: message_detail["changed_parent_key"] = child.parent.tree_node.node_key # "changed_parent_key": child.parent.tree_node.node_key} message_details_dict_list.append(message_detail) # delete the participant and add empty node there # moved this to manager class # participant.delete_topic(topic) new_leaf_node = LeafNode(participant_to_be_removed.leaf_node.node_id) new_leaf_node.participant = None new_empty_node = Node("empty", parent=participant_to_be_removed.parent, leaf_node=new_leaf_node) # dis-allocate the participant node after attaching the new empty node to the tree participant_to_be_removed.parent = None participant_to_be_removed.leaf_node = None return tree_root, new_empty_node, message_details_dict_list
def generate_tree(tree_root, depth, no_of_children, participants=None): # todo -- check how to pass depth and no of children automatically and by arguments # height and depth not fitting number of a participants if not (participants is None): if len(participants) > no_of_children ** (depth - 1): return "error message" # todo -- customize the error message current_parents = [tree_root] node_count = 1 temp_parent = [] for d in range(depth): for parent in current_parents: for k in range(no_of_children): children_node = TreeNode(node_count) children_tree_node = Node(str(node_count), parent=parent, tree_node=children_node) children_tree_node.is_root temp_parent.append(children_tree_node) node_count += 1 current_parents.clear() current_parents = list(temp_parent) temp_parent.clear() if participants is None: return tree_root, current_parents, node_count ################################################################ leaf_nodes = current_parents participant_count = 0 node_id = node_count for leaf in leaf_nodes: if not (participants is None): if participant_count < len(participants): node_id += 1 # adding topic to the participant # does it make sense to do this at key manager level? # participants[participant_count].add_topic(topic) # topic commented leaf_node = LeafNode(node_id, participants[participant_count]) Node(participants[participant_count].participant_id, parent=leaf.parent, leaf_node=leaf_node) leaf.parent = None leaf.tree_node = None participant_count += 1 else: break for p in range(participant_count, len(leaf_nodes)): Node("empty", parent=leaf_nodes[p].parent, leaf_node=LeafNode(leaf_nodes[p].tree_node.node_id)) leaf_nodes[p].parent = None leaf_nodes[p].tree_node = None # leaf_node = leaf[0].tree_node return tree_root
def tree_from_json(json_tree): # write code to construct a tree from json data # create topic topic = None # first loop create all nodes and map ids to nodes id_to_node = {} for node in json_tree["node_details"]: if node["leaf_node"] == "false": if node["parent"] is None: tree_node = TreeNode(node["node_id"]) children_tree_node = Node(json_tree["topic"], tree_node=tree_node) id_to_node[node["node_id"]] = children_tree_node else: tree_node = TreeNode(node["node_id"]) children_tree_node = Node(node["node_id"], tree_node=tree_node) id_to_node[node["node_id"]] = children_tree_node else: if node["participant"] is None: leaf_node = LeafNode(node["node_id"]) children_tree_node = Node("empty", leaf_node=leaf_node) id_to_node[node["node_id"]] = children_tree_node else: participant = Participant( node["participant"]["pairwise_key"], node["participant"]["participant_id"]) leaf_node = LeafNode(node["node_id"], participant=participant) children_tree_node = Node(participant.participant_id, leaf_node=leaf_node) id_to_node[node["node_id"]] = children_tree_node participant.add_topic(json_tree["topic"]) parent_node = None for node in json_tree["node_details"]: if node["parent"] is None: id_to_node[node["node_id"]].parent = None parent_node = id_to_node[node["node_id"]] topic = Topic(json_tree["topic"], json_tree["tree_depth"], json_tree["tree_no_of_children"], root_node=parent_node) else: id_to_node[node["node_id"]].parent = id_to_node[node["parent"]] return parent_node, id_to_node
def add_participant(tree_root, participant, changed_root_keys=None): empty_node = findall_by_attr(tree_root, "empty")[0] # participant.add_topic(topic) # include code for user-permissions # or better move this to top new_leaf_node = LeafNode(empty_node.leaf_node.node_id, participant) added_participant = Node(participant.participant_id, parent=empty_node.parent, leaf_node=new_leaf_node) # dis-allocate the old empty node after attaching the new one to the tree empty_node.parent = None empty_node.leaf_node = None # find ancestors of the added participant and change their keys ancestor_list = added_participant.ancestors for ancestor in ancestor_list: if ancestor.is_root and changed_root_keys is not None: ancestor.tree_node.root_node_keys = changed_root_keys.copy() else: ancestor.tree_node.reset_key() # change the keys of root node here # code to add details about the messages to be sent # first construct messages for participant and its siblings message_details_dict_list = [] # adding message for the newly added participant to be decided based on other implementations # todo """message_detail = {"message_name": str(added_participant.parent.tree_node.node_id) + "/" + str(added_participant.leaf_node.node_id), "encryption_key": added_participant.leaf_node.participant.pairwise_key, "changed_parent_key": added_participant.parent.tree_node.node_key} message_details_dict_list.append(message_detail)""" siblings = added_participant.siblings for sibling in siblings: if sibling.leaf_node.participant is not None: message_detail = {# "message_name": str(sibling.parent.tree_node.node_id) + "/" + str(sibling.leaf_node.node_id), "message_name": str(sibling.parent.tree_node.node_id) + "/" + str(sibling.leaf_node.participant.participant_id) + "__changeParent__" + str(sibling.parent.tree_node.node_id), "encryption_key": sibling.leaf_node.participant.pairwise_key, "changed_parent_key": sibling.parent.tree_node.node_key} message_details_dict_list.append(message_detail) # construct messages for ancestors and their siblings for ancestor in range(len(ancestor_list)-2, -1, -1): children = ancestor_list[ancestor].children for child in children: message_detail = { "message_name": str(child.parent.tree_node.node_id) + "/" + str(child.tree_node.node_id) + "__changeParent__" + str(child.parent.tree_node.node_id), "encryption_key": child.tree_node.node_key} if child.parent.is_root and changed_root_keys is not None: message_detail["changed_parent_key"] = child.parent.tree_node.root_node_keys else: message_detail["changed_parent_key"] = child.parent.tree_node.node_key # "changed_parent_key": child.parent.tree_node.node_key} # if last i.e. root node then encryption keys is the list of changed pub-sub keys # add that condition for the last one. when ancestor = 0 basically. message_details_dict_list.append(message_detail) return tree_root, added_participant, message_details_dict_list
def add_participant(tree_root, participant, changed_root_keys=None): empty_nodes = findall_by_attr(tree_root, "empty") if len(empty_nodes) is 0: # tree structure change -- # get all the leaf nodes and maximum node id leaf_nodes = tree_root.leaves last_node_id = int(leaf_nodes[len(leaf_nodes) - 1].leaf_node.node_id) participant_counter = 0 added_participant = None message_details_dict_list = [] # change tree structure # children_node = TreeNode(node_count) # children_tree_node = Node(str(node_count), parent=parent, tree_node=children_node) for leaf in leaf_nodes: new_parent_tree_node = TreeNode(leaf.leaf_node.node_id) new_parent = Node(leaf.leaf_node.node_id, parent=leaf.parent, tree_node=new_parent_tree_node) # two children for this node -- or todo no of children of this root_tree -- # 1st child has the same participant and the second child is empty last_node_id += 1 leaf.leaf_node.name = str(last_node_id) leaf.parent = new_parent # send the changed structure message only to the participants affected # newly added participant messages will be handled by registration protocol not here message_detail = { "message_name": "change_tree_structure" + "/" + leaf.name, "encryption_key": leaf.leaf_node.participant.pairwise_key, "new_ancestor_key": new_parent.tree_node.node_key } message_details_dict_list.append(message_detail) # first check if the participant is already added if participant_counter is 0: # add new participant here last_node_id += 1 new_leaf_node = LeafNode(str(last_node_id), participant) added_participant = Node(participant.participant_id, parent=new_parent, leaf_node=new_leaf_node) participant_counter = 1 else: # add empty node else # if participant is already added 2nd child empty # Node("empty", parent=leaf_nodes[p].parent, leaf_node=LeafNode(leaf_nodes[p].tree_node.node_id)) last_node_id += 1 Node("empty", parent=new_parent, leaf_node=LeafNode(str(last_node_id))) return tree_root, added_participant, message_details_dict_list else: empty_node = empty_nodes[0] # participant.add_topic(topic) # include code for user-permissions # or better move this to top new_leaf_node = LeafNode(empty_node.leaf_node.node_id, participant) added_participant = Node(participant.participant_id, parent=empty_node.parent, leaf_node=new_leaf_node) # dis-allocate the old empty node after attaching the new one to the tree empty_node.parent = None empty_node.leaf_node = None # find ancestors of the added participant and change their keys ancestor_list = added_participant.ancestors for ancestor in ancestor_list: if ancestor.is_root and changed_root_keys is not None: ancestor.tree_node.root_node_keys = changed_root_keys.copy( ) else: ancestor.tree_node.reset_key() # change the keys of root node here # code to add details about the messages to be sent # first construct messages for participant and its siblings message_details_dict_list = [] # adding message for the newly added participant to be decided based on other implementations # todo """message_detail = {"message_name": str(added_participant.parent.tree_node.node_id) + "/" + str(added_participant.leaf_node.node_id), "encryption_key": added_participant.leaf_node.participant.pairwise_key, "changed_parent_key": added_participant.parent.tree_node.node_key} message_details_dict_list.append(message_detail)""" siblings = added_participant.siblings for sibling in siblings: if sibling.leaf_node.participant is not None: message_detail = { # "message_name": str(sibling.parent.tree_node.node_id) + "/" + str(sibling.leaf_node.node_id), "message_name": str(sibling.parent.tree_node.node_id) + "/" + str(sibling.leaf_node.participant.participant_id) + "__changeParent__" + str(sibling.parent.tree_node.node_id), "encryption_key": sibling.leaf_node.participant.pairwise_key, "changed_parent_key": sibling.parent.tree_node.node_key } message_details_dict_list.append(message_detail) # construct messages for ancestors and their siblings for ancestor in range(len(ancestor_list) - 2, -1, -1): children = ancestor_list[ancestor].children for child in children: message_detail = { "message_name": str(child.parent.tree_node.node_id) + "/" + str(child.tree_node.node_id) + "__changeParent__" + str(child.parent.tree_node.node_id), "encryption_key": child.tree_node.node_key } if child.parent.is_root and changed_root_keys is not None: message_detail[ "changed_parent_key"] = child.parent.tree_node.root_node_keys else: message_detail[ "changed_parent_key"] = child.parent.tree_node.node_key # "changed_parent_key": child.parent.tree_node.node_key} # if last i.e. root node then encryption keys is the list of changed pub-sub keys # add that condition for the last one. when ancestor = 0 basically. message_details_dict_list.append(message_detail) return tree_root, added_participant, message_details_dict_list