Ejemplo n.º 1
0
    def build_a_substitution_from(self, v, eq):
        #Build a substitution from equation eq. The domain is variable v.
        #For example, if v: x, eq: f(y) + a = x + b,
        #then, the result would be: x |-> f(y) + a + b
        #Assume that there are no duplicate terms in eq.

        args = xor_to_list(eq.left_side)

        for arg in args:
            if (v == arg):
                args.remove(arg)
        range = list_to_xor(args)
        sigma = SubstituteTerm()
        sigma.add(v, range)
        return sigma
Ejemplo n.º 2
0
def combine_list_of_substitutions(lst):
    #It takes lst is a list of lists of substitutions,
    #returns a list of substitutions.
    #For example, if lst is: [[{x |-> f(z)}, {x |-> a}], [{x |-> f(b)}]],
    #then the result is [{x |-> f(b)}]
    sigma = SubstituteTerm()
    return combine_list_of_substitutions_helper(lst, [sigma])
Ejemplo n.º 3
0
def combine_two_substitutions(subst1, subst2):
    #Combine two substitutions, and get a list of combined substitutions.
    #For example, if sub1 = {x1 |-> f(x), x2 |-> b}, sub2 = {x1 |-> f(a)},
    #then the result would be [{x1 |-> f(a), x2 |-> b}]
    #print("combining")
    #print(sub1)
    #print("and")
    #print(sub2)
    #print("end")
    sub1 = deepcopy(subst1)
    sub2 = deepcopy(subst2)
    domain1 = list(sub1.domain())
    domain2 = list(sub2.domain())
    #if(sub2 == None):
    if (domain2 == []):
        return [sub1]
    else:
        #domain2 = list(sub2.domain())
        first_var_in_sub2 = domain2[0]
        first_var_maps_to_in_sub2 = first_var_in_sub2 * sub2
        if (first_var_in_sub2 in domain1):
            first_var_maps_to_in_sub1 = first_var_in_sub2 * sub1
            if (first_var_maps_to_in_sub1 == first_var_maps_to_in_sub2):
                #print("duplicate variables map to the same term")
                sub2.remove(first_var_in_sub2)
                return combine_two_substitutions(sub1, sub2)
            else:
                #print("duplicate variables map to different terms")
                eq = Equation(convert_to_xorterm(first_var_maps_to_in_sub1),
                              convert_to_xorterm(first_var_maps_to_in_sub2))
                eqs = Equations([eq])
                unifiers = xor_unification(eqs)

                results = []
                sub2.remove(first_var_in_sub2)
                for unifier in unifiers:
                    result = combine_two_substitutions(sub1 * unifier,
                                                       sub2 * unifier)
                    results = results + result
                return results
        else:
            #print("no duplicate variables found")
            sigma = SubstituteTerm()
            sigma.add(first_var_in_sub2, first_var_maps_to_in_sub2)
            sub1 = sub1 * sigma
            sub2.remove(first_var_in_sub2)
            return combine_two_substitutions(sub1, sub2)
Ejemplo n.º 4
0
def xor_unification(eqs):
    equations = purify_equations(eqs)
    diseqs = Disequations([])
    subst = SubstituteTerm()

    state = XOR_proof_state(equations, diseqs, subst)
    solutions = xor_unification_helper(state)

    return solutions
Ejemplo n.º 5
0
def add_empty_subst_to_dictionary(dict):
    new_dict = {}
    for key in dict.keys():
        old_value = dict[key]
        new_value = []
        for val in old_value:
            new_value.append(ConstrainedTerm(val, SubstituteTerm()))
        new_dict.update({key: new_value})
    return new_dict
Ejemplo n.º 6
0
def coalesce(U2: Set[Equation]):
    #Rule (a)
    Uremove = set()
    for e in list(U2):
        if isinstance(e.right_side, Variable) and isinstance(
                e.left_side, Variable) and e not in Uremove:
            sigma = SubstituteTerm()
            sigma.add(e.left_side, e.right_side)
            for e2 in list(U2):
                if e2 != e:
                    if (isinstance(e2.left_side, FuncTerm)
                            or isinstance(e2.left_side, Variable)):
                        e2.left_side = e2.left_side * sigma
                    if (isinstance(e2.right_side, FuncTerm)
                            or isinstance(e2.right_side, Variable)):
                        e2.right_side = e2.right_side * sigma
            #U2.remove(e)
            Uremove.add(e)
    return U2
Ejemplo n.º 7
0
def solve(U2: Set[Equation]):
    #collect the \Sigma_0 terms
    f_terms = set()
    for e in U2:
        if isinstance(e.right_side, FuncTerm) and str(
                e.right_side.function) == "f":
            f_terms.add(e)
    delta = SubstituteTerm()
    #call ac-unif
    delta = ac_unify(f_terms)
    return (delta)
Ejemplo n.º 8
0
def instantiate_a_constraint(constraint, sigma):
    #Instantiate a constraint using sigma
    #For example, if constraint is {x1: [a, b], x2: [f(x1)]}, and sigma is {x1 |-> a}
    #then the result is {x1: [a, b], x2: [f(a)]}
    new_constraints = {}
    for key in constraint.keys():
        old_constraint = constraint[key]
        new_constraint = []
        for o in old_constraint:
            new_constraint.append(
                ConstrainedTerm(o.term * sigma, SubstituteTerm()))
        new_constraints.update({key: new_constraint})
    return new_constraints
Ejemplo n.º 9
0
def _changeVars(overlaping_vars: List[Variable], term: Term, hypothesis: Term,
                conclusion: Term):
    """Change variable names in hypothesis & conclusion to not overlap with overlapping_vars"""
    hypothesis = deepcopy(hypothesis)
    conclusion = deepcopy(conclusion)
    all_vars = get_vars(term, unique=True) | \
        get_vars(hypothesis, unique=True) | \
        get_vars(conclusion, unique=True)
    new_vars: List[Variable] = []
    # Go through all the variables that share the same symbol between the term and rewrite rule
    # and change the variables in the rewrite rule
    for v in overlaping_vars:
        new_var = v
        # Keep renaming variable in rewrite rule until it is not an already existing variable
        while new_var in all_vars:
            new_var = Variable(new_var.symbol + "_1", new_var.sort)
        new_vars.append(new_var)
    # Create substitution between the old and new variable names and apply them
    s = SubstituteTerm()
    for old_v, new_v in zip(overlaping_vars, new_vars):
        s.add(old_v, new_v)
    return hypothesis * s, conclusion * s
Ejemplo n.º 10
0
def check_security(tag):
    if not check_syntax(tag):
        print(f"{tag} is not a valid tag.")
        return None
    lhs = tag
    rhs = convertToConstantTerm(lhs)
    eq = Equation(lhs, rhs)
    subst = SubstituteTerm()
    state = Unification_state([eq], subst)
    subst = apply_rules(state)
    if (trivial_subst(subst)):
        print("The authenticity property is satisfied.")
    else:
        print("The authenticity property is violated.")
Ejemplo n.º 11
0
    def __init__(self, moo_name: str, schedule_name: str = 'every'):
        chaining_function = MOO.find(moo_name)
        if chaining_function is None:
            raise ValueError(f"Mode of operation {moo_name} is not found.")
        self.chaining_function: Callable = chaining_function

        schedule = MOO_Schedule.find(schedule_name)
        if schedule is None:
            raise ValueError(f"Schedule of name {schedule_name} is not found.")
        self.schedule: Callable = schedule

        self.substitutions: SubstituteTerm = SubstituteTerm()
        self.iteration: int = 0
        # TODO: Maybe consider generating a uuid for the IV, so that
        # it is different across sessions?
        self.nonces: List[Constant] = [Constant("r")]
        self.plain_texts: List[Term] = list()
        self.cipher_texts: List[Term] = list()
        self.stopped = False
Ejemplo n.º 12
0
def fix(sigma, constraint):
    #Fix sigma by instantiating it so that it becomes a P-unifier.
    print("fixing:")
    print(sigma)
    if (contains_original_var_only(sigma)):
        return sigma
    else:
        #Prepare for a list of saturation problem
        problem_list = []
        for var in sigma.domain():
            if (is_original_variable(var)):
                problem = deepcopy(constraint[var])
                problem.append(ConstrainedTerm(var * sigma, SubstituteTerm()))
                problem_list.append(problem)

        #Solve them
        list_of_substitutions = []
        for p in problem_list:
            saturation_result = saturate(p)
            substs = []
            for sat_res in saturation_result:
                if (sat_res.term == Zero()):
                    substs.append(sat_res.constraint)
            list_of_substitutions.append(substs)

        #Combine the resulting substitutions
        results = combine_list_of_substitutions(list_of_substitutions)
        if (results == []):
            return None

        #Find a substitution that can be fixed recursively
        # Use it to instantiate sigma, return the result
        for tau in results:
            result = fix(tau, instantiate_a_constraint(constraint, tau))
            if (result != None):
                return sigma * result
        return None
Ejemplo n.º 13
0
def elim_tk(state):
    #Try applying the "elim_tk" rule

    #This rule applied if an equation is of the form: s_1 xor ... xor s_m = t_1 xor ... xor t_n,
    #where no s_i or t_j is d-rooted or e-rooted, and some s_i is a indexed variable Tk.
    #Tk = tk; id (applicable)
    #Tk xor e(Tk, C1) = tk xor e(tk, c1); id (not applicable)

    #If successful, returns "True" and the new state
    #Otherwise, returns "False" and the original state

    #Example: Tk = tk; id ==> true, ; {Tk |-> tk}
    #Example: Tk xor e(Tk, C1) = tk xor e(tk, c1); id ==> false, Tk xor e(Tk, C1) = tk xor e(tk, c1); id
    eqs = state.equations
    subst = state.substitution

    first = eqs[0]
    remaining_eqs = eqs[1:]

    lhs = first.left_side
    rhs = first.right_side
    lhs_summands = summands(lhs)
    rhs_summands = summands(rhs)
    applicable = (not containsDorE(lhs_summands)) and containsT(lhs_summands)
    new_subst = SubstituteTerm()
    remaining_terms = []
    results = []

    if (applicable):
        (var, remaining_terms) = pickT(lhs_summands)
        remaining_terms += rhs_summands
        if (len(remaining_terms) == 1):
            new_subst.add(var, remaining_terms[0])
        else:
            new_subst.add(var, xor(*remaining_terms))
        for t in remaining_eqs:
            results.append(
                Equation(t.left_side * new_subst, t.right_side * new_subst))

    return (applicable, Unification_state(results, subst * new_subst))
Ejemplo n.º 14
0
def subformulaapply(formula: Formula, sigma: SubstituteTerm):
    """Applies a substitution to a formula."""
    # Can't apply a substitution to a bool or Proposition
    if isinstance(formula, (bool, Proposition)):
        return formula

    if isinstance(formula, Predicate):
        # If the arity is zero, then it's a Proposition
        if formula.relation.arity == 0:
            return formula
        # Otherwise, apply the substitution to all
        # the terms in the predicate
        new_terms = [term * sigma for term in formula.args]
        return formula.relation(*new_terms)

    if isinstance(formula, Connective):
        return formula.__class__(subformulaapply(formula[0], sigma),
                                 subformulaapply(formula[1], sigma))
    if isinstance(formula, Not):
        return Not(subformulaapply(formula.subformula, sigma))

    if isinstance(formula, (ForAll, Exists)):
        # TODO: This is based on how Substitions are
        # currently handled. If we decide that its a bug
        # we'll have to rewrite this logic....
        if formula.bound_variable in sigma.range():
            new_bvar = _fresh_var_in_formula(formula)
            sigma.add(formula.bound_variable, new_bvar)
            return formula.__class__(
                new_bvar, subformulaapply(formula.subformula, sigma))

        if formula.bound_Variable in sigma.domain():
            sigma.remove(formula.bound_variable)

        return formula.__class__(formula.bound_variable,
                                 subformulaapply(new_subform, sigma))

    raise ValueError(f"Unexpected type: {type(formula)}.")
Ejemplo n.º 15
0
 def __call__(self, iteration: int, nonces: List[Constant], P: List[Term],
              C: List[Term]):
     IV = nonces[0]
     i = iteration - 1
     # Create substitution between symbolic plain and cipher texts
     # and the symbolic instantiations of them in MOOProgram
     sigma = SubstituteTerm()
     subterms = get_vars(self.term)
     for subterm in subterms:
         if subterm.symbol[0] == "P":
             if '-' not in subterm.symbol:
                 # Assume we mean current plaintext
                 sigma.add(subterm, P[-1])
             else:
                 j = int(subterm.symbol[4:-1])
                 if j > i:
                     # If we request for a cipher block that doesn't exist yet
                     # due to the current session length
                     # then map the subterm to a different nounce
                     #sigma.add(subterm, Constant(IV.symbol + f"_{j}"))
                     sigma.add(subterm, Constant(IV.symbol))
                 else:
                     sigma.add(subterm, P[-j])
         elif subterm.symbol[0] == "C":
             j = int(subterm.symbol[4:-1])
             if j > i:
                 # If we request for a cipher block that doesn't exist yet
                 # due to the current session length
                 # then map the subterm to a different nounce
                 #sigma.add(subterm, Constant(IV.symbol + f"_{j}"))
                 sigma.add(subterm, Constant(IV.symbol))
             else:
                 sigma.add(subterm, C[-j])
     return self.term * sigma
Ejemplo n.º 16
0
def add_empty_subst_to_initial_list(lst):
    new_list = []
    for item in lst:
        new_list.append(ConstrainedTerm(item, SubstituteTerm()))
    return new_list
Ejemplo n.º 17
0
non_zeros = Sort("non_zeros", reals)
divide = Function("divide", 2, [reals, non_zeros], reals)
one = Constant("1", non_zeros)
zero = Constant("0", reals)
try:
    divide(one, zero)
except Exception:
    print("Cannot divide by zero. Check.")

# Directed Acyclic Graphs
# From page 16
# F(g(x, a), g(x,a))
dag = TermDAG(f(g(x, a), g(x, a)))
dag.show()

## Substitutions
sigma = SubstituteTerm()
# Add the mapping x -> f(y)
sigma.add(x, g(y, c))
print(f(x, b))
print("Substitutions: ", sigma)
# Apply the substitution to the term f(x, b)
print(f(x, b) * sigma)
sigma2 = SubstituteTerm()
sigma2.add(y, a)
print("Another Substitution: ", sigma2)
print(
    "Composing both substitutions and applying it to a term: f(x, b) * sigma * sigma2"
)
print(f(x, b) * sigma * sigma2)