def test_bit_injection_exception(get_clients) -> None: parties = get_clients(3) falcon = Falcon() session = Session(parties=parties, protocol=falcon) SessionManager.setup_mpc(session) x = MPCTensor(secret=1, session=session) with pytest.raises(ValueError): ABY3.bit_injection(x, session, 2**64)
def private_compare(x: List[MPCTensor], r: torch.Tensor) -> MPCTensor: """Falcon Private Compare functionality which computes(x>r). Args: x (List[MPCTensor]) : shares of bits of x in Zp. r (torch.Tensor) : Public value r. Returns: result (MPCTensor): Returns shares of bits of the operation. Raises: ValueError: If input shares is not a list. ValueError: If input public value is not a tensor. (if (x>=r) returns 1 else returns 0) """ if not isinstance(x, list): raise ValueError( f"Input shares for Private Compare: {x} must be a list") if not isinstance(r, torch.Tensor): raise ValueError( f"Value r:{r} must be a torch tensor for private compare") shape = x[0].shape session = x[0].session ptr_list: List[ReplicatedSharedTensor] = [ session_ptr.prrs_generate_random_share(shape=shape, ring_size="2") for session_ptr in session.session_ptrs ] beta_2 = MPCTensor(shares=ptr_list, session=session, shape=shape) # shares of random bit beta_p = ABY3.bit_injection( beta_2, session, PRIME_NUMBER) # shares of random bit in Zp. m = Falcon._random_prime_group(session, shape) nr_shares = len(x) u = [0] * nr_shares c = [0] * nr_shares w = 0 for i in range(len(x) - 1, -1, -1): r_i = (r >> i) & 1 # bit at ith position u[i] = (1 - 2 * beta_p) * (x[i] - r_i) c[i] = u[i] + 1 + w w += x[i] ^ r_i d = m * math.prod(c) d_val = d.reconstruct(decode=False) # plaintext d. d_val[d_val != 0] = 1 # making all non zero values as 1. beta_prime = d_val return beta_2 + beta_prime
def select_shares(x: MPCTensor, y: MPCTensor, b: MPCTensor) -> MPCTensor: """Returns either x or y based on bit b. Args: x (MPCTensor): input tensor y (MPCTensor): input tensor b (MPCTensor): input tensor which is shares of a bit used as selector bit. Returns: z (MPCTensor):Returns x (if b==0) or y (if b==1). Raises: ValueError: If the selector bit tensor is not of ring size "2". """ ring_size = int(b.share_ptrs[0].get_ring_size().get_copy()) shape = b.shape if ring_size != 2: raise ValueError( f"Invalid {ring_size} for selector bit,must be of ring size 2") if shape is None: raise ValueError( "The selector bit tensor must have a valid shape.") session = x.session # TODO: Should be made to generate with CryptoProvider in Preprocessing stage. c_ptrs: List[ReplicatedSharedTensor] = [] for session_ptr in session.session_ptrs: c_ptrs.append( session_ptr.prrs_generate_random_share( shape=shape, ring_size=str(ring_size))) c = MPCTensor(shares=c_ptrs, session=session, shape=shape) # bit random share c_r = ABY3.bit_injection( c, session, session.ring_size) # bit random share in session ring. tensor_type = get_type_from_ring(session.ring_size) mask = (b ^ c).reconstruct(decode=False).type(tensor_type) d = (mask - (c_r * mask)) + (c_r * (mask ^ 1)) # Order placed carefully to prevent re-encoding,should not be changed. z = x + (d * (y - x)) return z
def test_private_compare(get_clients, security) -> None: parties = get_clients(3) falcon = Falcon(security_type=security) session = Session(parties=parties, protocol=falcon) SessionManager.setup_mpc(session) base = session.config.encoder_base precision = session.config.encoder_precision fp_encoder = FixedPointEncoder(base=base, precision=precision) secret = torch.tensor([[358.85, 79.29], [67.78, 2415.50]]) r = torch.tensor([[357.05, 90], [145.32, 2400.54]]) r = fp_encoder.encode(r) x = MPCTensor(secret=secret, session=session) x_b = ABY3.bit_decomposition_ttp(x, session) # bit shares x_p = [] # prime ring shares for share in x_b: x_p.append(ABY3.bit_injection(share, session, PRIME_NUMBER)) tensor_type = get_type_from_ring(session.ring_size) result = Falcon.private_compare(x_p, r.type(tensor_type)) expected_res = torch.tensor([[1, 0], [0, 1]], dtype=torch.bool) assert (result.reconstruct(decode=False) == expected_res).all()
def test_bit_injection_prime(get_clients, security_type) -> None: parties = get_clients(3) falcon = Falcon(security_type=security_type) session = Session(parties=parties, protocol=falcon) SessionManager.setup_mpc(session) ring_size = PRIME_NUMBER bin_sh = torch.tensor([[1, 1], [0, 0]], dtype=torch.bool) shares = [bin_sh, bin_sh, bin_sh] ptr_lst = ReplicatedSharedTensor.distribute_shares(shares, session, ring_size=2) x = MPCTensor(shares=ptr_lst, session=session, shape=bin_sh.shape) xbit = ABY3.bit_injection(x, session, ring_size) ring0 = int(xbit.share_ptrs[0].get_ring_size().get_copy()) result = xbit.reconstruct(decode=False) exp_res = bin_sh.type(torch.uint8) assert (result == exp_res).all() assert ring_size == ring0