Example #1
0
def create_leakage_automaton(automaton, observer=0, secret=0):
    """Gets the leakage automaton with respect to a certain observer and secret.

    Parameters
    ----------
    automaton : dict
        The automaton to use for creating the leakage automaton
    observer : int
        The index of the agent which is observing another agent
    secret : int
        The index of the agent's secret we want to consider

    Returns
    -------
    dict
        The leakage automaton
    """
    det = determinize(automaton, observer)

    # We don't want to worry about this agent's marked states; only every other
    # agent's marked states.
    marked = det["states"]["marked"]
    for i in [x for x in range(len(marked)) if x != secret]:
        marked[i] = []  # We're only considering a specific secret!

    acc = get_coaccessible(det)
    return union([automaton, acc])
def check_modular_opacity(automata, heuristic = no_heuristic):
    """Verifies current state opacity for the modular system composed of the
    input automata. Assumes that the shared alphabet of the automata is a
    subset of the attacker's alphabet, and the attacker's alphabet is defined
    by the second (i.e., index 1, when zero indexed) observable alphabet. Only
    one set of secrets (i.e., marked states) will be checked (the 0th set).

    Parameters
    ----------
    automata : list
        The automata for which to check for opacity

    Returns
    -------
    bool
        Whether the set of modules is opaque
    """
    automata = [determinize(x, 1) for x in automata]
    verified = []
    unverified = automata.copy()
    for a in automata:
        if a in unverified:
            unverified.remove(a)

            # Keep a list of all automata we can use to append to current one
            automata_to_add = heuristic(a, unverified, verified)

            verified.append(a)

            # Keep track of the large automaton we're building
            curr = a

            # Keep going until it's opaque
            while check_opacity_already_determinized(curr)[0] == False:
                if len(automata_to_add) == 0:
                    return False
                next = automata_to_add.pop(0)
                if next in unverified:
                    verified.append(next)
                    unverified.remove(next)
                curr = union([curr, next])

    return True
Example #3
0
    def test_determinize(self):
        """
        This ensures that all pre-built test cases work.
        """
        for i in range(len(self.automata)):
            # Get the answer
            ans = None
            with open(self.filenames[i][:-2] + "out") as f:
                ans = json.load(f)

            # Get the determinization of the appropriate automaton
            result = determinize(self.automata[i])

            # Print
            # helper.pretty_print(result)
            # helper.pretty_print(ans)

            # Check answer, making sure it's OK if elements not in order
            self.assertEqual(converter.convert_to_sets(result), converter.convert_to_sets(ans))
Example #4
0
def check_opacity(automaton, observer=0):
    """Verifies current state opacity for the given automaton with respect to
    a certain agent's observability. That is, if every word leading to a bad
    state has another word with the same projection leading to a good state,
    the automaton is opaque.

    Parameters
    ----------
    automaton : dict
        The automaton for which to check for opacity
    observer : int
        The index of the observer which is examining the system

    Returns
    -------
    list of bool
        Whether or not the automaton is opaque with respect to each set of
        secrets. If true, indicates that opacity holds with respect to those
        secrets
    """
    det = determinize(automaton, observer)
    return [len(m) == 0 for m in det["states"]["marked"]]
Example #5
0
def construct_arena(automaton):
    """Constructs an arena from an automaton, as specified in (Ricker, Marchand,
    & Keroglou, 2019). The arena has the same form as a regular automaton,
    except with a few extra features. The "states" section has two extra lists:
    "v1" and "v2", which correspond to the two distinct types of states.
    The "transitions" section has two extra lists as well: "v1" and "v2", which
    are the two transition lists that exit out of the two sets of states,
    respectively.

    Note
    ----
    Any data on bad states or transitions will be not be included in the
    resulting automaton.
    Also, the automaton must have three entries in marked, observable, and
    controllable. The first is the controller's perspective, the second is the
    first agent's perspective, and the third is the second agent's perspective.
    Note that the two agents' events should be subsets of the controller's event
    set.
    TODO: add a verifier to ensure correct input.

    Parameters
    ----------
    automaton : dict
        The automaton for which to create an arena

    Returns
    -------
    dict
        The resulting arena

    Examples
    --------
    >>> arena = construct_arena(automaton)
    >>> print(arena)
    {
        # Dictionary for the arena with the added features specified above
    }
    """
    # Get the three observers
    all_events = automaton["events"]["all"]
    obs_events = automaton["events"]["observable"]
    all_automata = [
        determinize(automaton, i) for i in range(len(obs_events))
    ]
    all_automata.insert(0, automaton)

    bad_states = []

    # Get initial state. Since we determinized, each will only have one element.
    initial = [a["states"]["initial"][0] for a in all_automata]
    initial_str = format_state(initial)

    new_events = set()
    v1_trans = {}
    v2_trans = {}
    # Add initial state to a visited set and a queue
    v1_queue = [initial]
    v1_visited = {initial_str}
    v2_visited = set()
    # Keep track of secrets
    secrets = {}

    # Keep going through our queue of controller states until done
    while len(v1_queue) > 0:
        curr = v1_queue.pop(0)
        curr_str = format_state(curr)

        # Check if we have a bad state
        marked_obs = check_marked_agents(all_automata, curr)
        if len(marked_obs) != 0:
            bad_states.append(curr_str)
            secrets[curr_str] = format_all_observed_secrets(marked_obs)

        # Identify what events are accessible from here
        events = get_valid_control_actions(all_automata[0], curr[0], all_events)

        for event in events:
            # Add this event to the system
            event_str = format_state_set(event)
            new_events.add(event_str)

            # Add the transition from v1 to the state in v2
            trans = format_transition(curr_str, event_str)
            curr_v2_str = format_state([curr_str, event_str])
            v1_trans[trans] = [curr_v2_str]

            # If we haven't already visited this v2 state, start working on it!
            if curr_v2_str not in v2_visited:
                v2_visited.add(curr_v2_str)
                add_v2_transitions(all_automata, curr, event, v2_trans,
                                   v2_visited, v1_visited, v1_queue)

    # The language includes both the new event types we added and the events
    # already visible to the controller
    all_events = list(new_events.union(set(automaton["events"]["all"])))
    obs_events = list(new_events.union(set(obs_events[0])))

    return {
        "events": {
            "all": all_events,  # The events start off identical
            "controllable": [list(new_events)],  # In arena, control just new
            "observable": [obs_events]
        },
        "states": {
            "all": list(v1_visited.union(v2_visited)),
            "v1": list(v1_visited),
            "v2": list(v2_visited),
            "initial": [initial_str],
            "marked": [bad_states],
            "bad": bad_states,
            "secrets": secrets  # Indicates which agent sees what in composition
        },
        "transitions": {
            "all": {**v1_trans, **v2_trans},
            "v1": v1_trans,
            "v2": v2_trans,
            "bad": {}
        }
    }
Example #6
0
def ops_menu(automata, temp_dir):
    """Opens a menu with options for different operations that can be performed.

    Parameters
    ----------
    automata : list
        The list of automata currently open in the program
    temp_dir : str
        The temporary directory for the session

    Returns
    -------
    None
    """
    display_menu(menu_msg)

    inpt = input().lower()

    # Choose which operation to perform
    if inpt in ["d", "determinization"]:
        selected = select_automaton_menu(automata, "Determinization")
        if selected is not None:
            observer = select_observer_menu(selected)
            if observer is not None:
                result = determinize(selected, observer)
                __save(automata, result, temp_dir)
    elif inpt in ["o", "opacity"]:
        selected = select_automaton_menu(automata, "Checking Opacity")
        if selected is not None:
            observer = select_observer_menu(selected)
            if observer is not None:
                result = check_opacity(selected, observer)
                print("With respect to the observer " + str(observer) +
                      ", the system is opaque")
                print("for the following secrets:")
                print([i for i, x in enumerate(result) if x is True])
                print("The system is not opaque for the following secrets:")
                print([i for i, x in enumerate(result) if x is False])
    elif inpt in ["u", "union", "parallel composition"]:
        selected = select_automata_menu(automata, 2, "Parallel Composition")
        if selected is not None:
            result = union(selected)
            __save(automata, result, temp_dir)
    elif inpt in ["p", "product", "intersection"]:
        selected = select_automata_menu(automata, 2, "Intersection")
        if selected is not None:
            result = product(selected)
            __save(automata, result, temp_dir)
    elif inpt in ["a", "accessible"]:
        selected = select_automaton_menu(automata, "Accessibility Operation")
        if selected is not None:
            result = get_accessible(selected)
            __save(automata, result, temp_dir)
    elif inpt in ["c", "controllable"]:
        selected = select_automaton_menu(automata, "Controllability Operation")
        if selected is not None:
            result = get_controllable(selected)
            __save(automata, result, temp_dir)
    elif inpt in ["ca", "coaccessible"]:
        selected = select_automaton_menu(automata, "Coaccessibility Operation")
        if selected is not None:
            result = get_coaccessible(selected)
            __save(automata, result, temp_dir)
    elif inpt in ["l", "leakage"]:
        selected = select_automaton_menu(automata, "Get Leakage Automaton")
        if selected is not None:
            observer = select_observer_menu(selected)
            if observer is not None:
                secret = select_secret_menu(selected)
                if secret is not None:
                    result = create_leakage_automaton(selected, observer,
                                                      secret)
                    __save(automata, result, temp_dir)
    elif inpt in ["ba"]:
        selected = select_automaton_menu(automata, "Constructing Arena")
        if selected is not None:
            result = construct_arena(selected)
            __save(automata, result, temp_dir)
            show_notification("Bad states:\n" + str(result["states"]["bad"]))
    elif inpt in ["bt"]:
        selected = select_automaton_menu(automata, "Constructing Attractor")
        if selected is not None:
            result = construct_attractor(selected)
            __save(automata, result, temp_dir)
            show_notification("Bad states:\n" + str(result["states"]["bad"]))
    elif inpt in ["bp"]:
        selected = select_automaton_menu(automata, "Pruning Arena")
        if selected is not None:
            result = get_controllable(construct_attractor(selected))
            __save(automata, result, temp_dir)
    elif inpt in ["om"]:
        show_notification(
            "With this operation, we assume the\nattacker can see all items in the\nshared alphabet,as per Enforcing\nOpacity in Modular Systems (2020)"
        )
        selected = select_automata_menu(
            automata, 1, "Checking Opacity for Modular Systems")
        if selected is not None:
            heuristic = select_heuristic()
            result = check_modular_opacity(selected, heuristic=heuristic)
            show_notification("The modular system is " +
                              ("opaque" if result else "not opaque"))
    elif inpt in ["bca"]:
        selected = select_automaton_menu(automata,
                                         "Constructing Communication Arena")
        if selected is not None:
            result = construct_communication_arena(selected)
            __save(automata, result, temp_dir)
    elif inpt in ["e", "exit"]:
        pass
    else:
        show_error("Command not recognized")