def update_output_wire(self, false_label, true_label): """ Updates the output wire's labels and point-and-permute bits. :param false_label: the false label :param true_label: the true label """ self.output_wire.false_label.label = false_label self.output_wire.true_label.label = true_label self.output_wire.false_label.pp_bit = get_last_bit(false_label) self.output_wire.true_label.pp_bit = get_last_bit(true_label)
def modify_pp_bits(self, A0_, B0_, C0_): """ Modifies the point-and-permute bits according to the last bit of the label. """ left, right, out = self.wires() l_pp_bit, r_pp_bit = get_last_bit(A0_), get_last_bit(B0_) out_pp_bit = get_last_bit(C0_) left.false_label.pp_bit = l_pp_bit left.true_label.pp_bit = not l_pp_bit right.false_label.pp_bit = r_pp_bit right.true_label.pp_bit = not r_pp_bit out.false_label.pp_bit = out_pp_bit out.true_label.pp_bit = not out_pp_bit
def half_gates_ungarble(self, garblers_label, evaluators_label): """ Evaluates the gate by decrypting each half gate and XORing the result. :param garblers_label: the chosen label by the garbler :param evaluators_label: the chosen label by the evaluator :return: the correct output label :rtype: :class:`Label` """ if self.gate_type == 'AND': s_a, s_b = garblers_label.pp_bit, evaluators_label.pp_bit entry1, entry2 = self.table gen = hashlib.sha256(garblers_label.label).digest() eva = hashlib.sha256(evaluators_label.label).digest() C_g = xor(gen, entry1) if s_a else gen C_e = xor(eva, xor(entry2, garblers_label.label)) if s_b else eva output_label = Label(0) output_label.represents = None output_label.label = xor(C_g, C_e) output_label.pp_bit = get_last_bit(output_label.label) return output_label else: return self.free_xor_ungarble(garblers_label, evaluators_label)
def grr3_ungarble(self, garblers_label, evaluators_label): """ If the point-and-permute bits are false, then imagine the ciphertext was the all zero ciphertext. Otherwise, proceed as in the point-and-permute optimization. :param garblers_label: the chosen label by the garbler :param evaluators_label: the chosen label by the evaluator :return: the correct output label :rtype: :class:`Label` """ left_pp_bit = garblers_label.pp_bit right_pp_bit = evaluators_label.pp_bit key1 = AESKey(garblers_label.to_base64()) key2 = AESKey(evaluators_label.to_base64()) if not left_pp_bit and not right_pp_bit: zero_ciphertext = bytes(settings.NUM_BYTES) output_label = Label(0) output_label.represents = None output_label.label = key2.decrypt(key1.decrypt(zero_ciphertext, unpad=False), unpad=False) output_label.pp_bit = get_last_bit(output_label.label) else: table_entry = self.table[2 * left_pp_bit + right_pp_bit - 1] output_label = pickle.loads( key2.decrypt(key1.decrypt(table_entry, from_base64=True))) return output_label
def free_xor_garble(self): """ In this optimization *XOR* gates are garbled for free, that is, the table corresponding to this gate is empty. The way this optimization accomplishes this is by setting the true label of each wire as an offset *R* of the false label. This offset is global to the whole circuit, so by the properties of *XOR*, everything works out nicely. For more information see `the paper <http://www.cs.toronto.edu/~vlad/papers/XOR_ICALP08.pdf>`_. Note that FreeXOR is not compatible with GRR2. """ if self.gate_type == 'XOR': A0 = self.left_wire.false_label.label B0 = self.right_wire.false_label.label R = settings.R C0, C1 = xor(A0, B0), xor(xor(A0, B0), R) pp_bit = get_last_bit(C0) f_label = self.output_wire.false_label t_label = self.output_wire.true_label f_label.label = C0 f_label.pp_bit = pp_bit t_label.label = C1 t_label.pp_bit = not pp_bit else: if settings.GRR3: self.grr3_garble() else: self.point_and_permute_garble()
def __init__(self, file): if settings.FREE_XOR or settings.HALF_GATES: while True: settings.R = os.urandom(settings.NUM_BYTES) if get_last_bit(settings.R): break self.tree = self.build_tree(file) self.input_wires = None
def set_zero_ciphertext(self): """ Generates the zero ciphertext by taking the two labels with false point-and-permute bits and setting the output labels accordingly. This function is used for GRR3. """ l, r = self.left_wire, self.right_wire pp_left = l.false_label if not l.false_label.pp_bit else l.true_label pp_right = r.false_label if not r.false_label.pp_bit else r.true_label output_label = generate_zero_ciphertext(pp_left, pp_right) in1, in2 = pp_left.represents, pp_right.represents logic_value = self.evaluate_gate(in1, in2) true_label = self.output_wire.true_label false_label = self.output_wire.false_label if logic_value: true_label.label = output_label pp_bit = get_last_bit(output_label) true_label.pp_bit = pp_bit false_label.pp_bit = not pp_bit else: false_label.label = output_label pp_bit = get_last_bit(output_label) false_label.pp_bit = pp_bit true_label.pp_bit = not pp_bit
def free_xor_ungarble(self, garblers_label, evaluators_label): """ Evaluates *XOR* gates for free by XORing the two labels he receives. :param garblers_label: the chosen label by the garbler :param evaluators_label: the chosen label by the evaluator :return: the correct output label :rtype: :class:`Label` """ if self.gate_type == 'XOR': output_label = Label(0) output_label.represents = None output_label.label = xor(garblers_label.label, evaluators_label.label) output_label.pp_bit = get_last_bit(output_label.label) else: g, e = garblers_label, evaluators_label if settings.GRR3: output_label = self.grr3_ungarble(g, e) else: output_label = self.point_and_permute_ungarble(g, e) return output_label