Exemple #1
0
    def prrs_generate_random_share(
        self,
        shape: Union[tuple, torch.Size],
    ) -> Any:
        """Generates a random share using the generators held by a party.

        Args:
            shape (Union[tuple, torch.Size]): Shape for the share.

        Returns:
            Any: ShareTensor or ReplicatedSharedTensor

        """
        from sympc.tensor import ReplicatedSharedTensor
        from sympc.tensor import ShareTensor

        share1, share2 = self._generate_random_share(shape)

        if self.protocol.share_class == ShareTensor:
            # It has encoder_precision = 0 such that the value would not be encoded
            share = ShareTensor(
                data=share1,
                session_uuid=self.uuid,
                config=Config(encoder_precision=0),
            )
        else:
            share = ReplicatedSharedTensor(
                shares=[share1, share2],
                session_uuid=self.uuid,
                config=Config(encoder_precision=0),
            )
        return share
Exemple #2
0
def test_generate_shares() -> None:
    precision = 12
    base = 4

    x_secret = torch.Tensor([5.0])

    # test with default values
    x_share = ShareTensor(data=x_secret)

    shares_from_share_tensor = MPCTensor.generate_shares(x_share, nr_parties=2)
    shares_from_secret = MPCTensor.generate_shares(x_secret,
                                                   nr_parties=2,
                                                   config=Config())

    assert sum(shares_from_share_tensor).tensor == sum(
        shares_from_secret).tensor

    x_share = ShareTensor(data=x_secret,
                          config=Config(encoder_precision=precision,
                                        encoder_base=base))

    shares_from_share_tensor = MPCTensor.generate_shares(x_share, 2)
    shares_from_secret = MPCTensor.generate_shares(
        x_secret,
        2,
        config=Config(encoder_precision=precision, encoder_base=base))

    assert sum(shares_from_share_tensor).tensor == sum(
        shares_from_secret).tensor
def test_different_config() -> None:
    x = torch.tensor([1])
    shares = [x, x]
    session_id = uuid4()
    config1 = Config(encoder_precision=10, encoder_base=2)
    config2 = Config(encoder_precision=12, encoder_base=10)
    x_share = ReplicatedSharedTensor(shares=shares,
                                     session_uuid=session_id,
                                     config=config1)
    y_share = ReplicatedSharedTensor(shares=shares,
                                     session_uuid=session_id,
                                     config=config2)

    # Different fixed point config
    assert x_share != y_share
Exemple #4
0
def protobuf_session_deserializer(proto: MPCSession_PB) -> Session:
    id_session = UUID(bytes=proto.uuid)
    rank = proto.rank
    conf_dict = Dict._proto2object(proto=proto.config)
    _conf_dict = {key: value for key, value in conf_dict.items()}
    conf = Config(**_conf_dict)
    ring_size = int.from_bytes(proto.ring_size, "big")
    nr_parties = int.from_bytes(proto.nr_parties, "big")
    protocol_deserialized = proto.protocol.decode()

    session = Session(
        config=conf,
        uuid=id_session,
        ring_size=ring_size,
        protocol=protocol_deserialized,
    )
    session.rank = rank
    session.crypto_store = CryptoStore()
    session.nr_parties = nr_parties

    if "session" in globals():
        warning("Overwritting session for MPC")
        globals()["session"] = session

    return session
    def __init__(
        self,
        shares: Optional[List[Union[float, int, torch.Tensor]]] = None,
        config: Config = Config(encoder_base=2, encoder_precision=16),
        session_uuid: Optional[UUID] = None,
        ring_size: int = 2**64,
    ):
        """Initialize ReplicatedSharedTensor.

        Args:
            shares (Optional[List[Union[float, int, torch.Tensor]]]): Shares list
                from which RSTensor is created.
            config (Config): The configuration where we keep the encoder precision and base.
            session_uuid (Optional[UUID]): Used to keep track of a share that is associated with a
                remote session
            ring_size (int): field used for the operations applied on the shares
                Defaults to 2**64

        """
        self.session_uuid = session_uuid
        self.ring_size = ring_size

        self.config = config
        self.fp_encoder = FixedPointEncoder(base=config.encoder_base,
                                            precision=config.encoder_precision)

        tensor_type = get_type_from_ring(ring_size)
        self.shares = []
        if shares is not None:
            for i in range(len(shares)):
                self.shares.append(self._encode(shares[i]).to(tensor_type))
Exemple #6
0
    def __init__(
        self,
        data: Optional[Union[float, int, torch.Tensor]] = None,
        config: Config = Config(encoder_base=2, encoder_precision=16),
        session_uuid: Optional[UUID] = None,
        ring_size: int = 2**64,
    ) -> None:
        """Initialize ShareTensor.

        Args:
            data (Optional[Any]): The share a party holds. Defaults to None
            config (Config): The configuration where we keep the encoder precision and base.
            session_uuid (Optional[UUID]): Used to keep track of a share that is associated with a
                remote session
            ring_size (int): field used for the operations applied on the shares
                Defaults to 2**64
        """
        self.session_uuid = session_uuid
        self.ring_size = ring_size

        self.config = config
        self.fp_encoder = FixedPointEncoder(base=config.encoder_base,
                                            precision=config.encoder_precision)

        self.tensor: Optional[torch.Tensor] = None
        if data is not None:
            tensor_type = get_type_from_ring(ring_size)
            self.tensor = self._encode(data).to(tensor_type)
    def bit_extraction(self, pos: int = 0) -> "ReplicatedSharedTensor":
        """Extracts the bit at the specified position.

        Args:
            pos (int): position to extract bit.

        Returns:
            ReplicatedSharedTensor : extracted bits at specific position.

        Raises:
            ValueError: If invalid position is provided.
        """
        ring_bits = get_nr_bits(self.ring_size)
        if pos < 0 or pos > ring_bits - 1:
            raise ValueError(
                f"Invalid position for bit_extraction: {pos}, must be in range:[0,{ring_bits-1}]"
            )
        shares = []
        # logical shift
        bit_mask = torch.ones(self.shares[0].shape,
                              dtype=self.shares[0].dtype) << pos
        shares = [share & bit_mask for share in self.shares]
        rst = ReplicatedSharedTensor(
            shares=shares,
            session_uuid=self.session_uuid,
            config=Config(encoder_base=1, encoder_precision=0),
            ring_size=2,
        )
        return rst
def test_session_ring_xor(get_clients, security, bit) -> None:
    parties = get_clients(3)
    protocol = Falcon(security)
    session = Session(protocol=protocol, parties=parties)
    SessionManager.setup_mpc(session)
    ring_size = session.ring_size
    tensor_type = session.tensor_type
    config = Config(encoder_base=1, encoder_precision=0)
    x_sh1 = torch.tensor([[927021, 3701]], dtype=tensor_type)
    x_sh2 = torch.tensor([[805274, 401]], dtype=tensor_type)
    x_sh3 = torch.tensor([[-1732294, -4102]], dtype=tensor_type)
    bit_sh_1, bit_sh_2, bit_sh_3 = bit
    b_sh1 = torch.tensor([bit_sh_1], dtype=tensor_type)
    b_sh2 = torch.tensor([bit_sh_2], dtype=tensor_type)
    b_sh3 = torch.tensor([bit_sh_3], dtype=tensor_type)
    shares_x = [x_sh1, x_sh2, x_sh3]
    shares_b = [b_sh1, b_sh2, b_sh3]
    rst_list_x = ReplicatedSharedTensor.distribute_shares(shares=shares_x,
                                                          session=session,
                                                          ring_size=ring_size,
                                                          config=config)
    rst_list_b = ReplicatedSharedTensor.distribute_shares(shares=shares_b,
                                                          session=session,
                                                          ring_size=ring_size,
                                                          config=config)
    x = MPCTensor(shares=rst_list_x, session=session, shape=x_sh1.shape)
    b = MPCTensor(shares=rst_list_b, session=session, shape=b_sh1.shape)
    secret_x = ReplicatedSharedTensor.shares_sum(shares_x, ring_size)
    secret_b = ReplicatedSharedTensor.shares_sum(shares_b, ring_size)
    result = operator.xor(x, b)
    expected_res = secret_x ^ secret_b
    assert (result.reconstruct(decode=False) == expected_res).all()
Exemple #9
0
def test_ineq_share_share_local(op_str, precision, base) -> None:
    op = getattr(operator, op_str)

    x = torch.Tensor([[0.125, -1.25], [-4.25, 4]])
    y = torch.Tensor([[4.5, -2.5], [5, 2.25]])

    x_share = ShareTensor(data=x,
                          config=Config(encoder_base=base,
                                        encoder_precision=precision))
    y_share = ShareTensor(data=y,
                          config=Config(encoder_base=base,
                                        encoder_precision=precision))

    expected_res = op(x, y)
    res = op(x_share, y_share)

    assert (res == expected_res).all()
Exemple #10
0
def test_ops_share_share_local(op_str, precision, base) -> None:
    op = getattr(operator, op_str)

    x = torch.Tensor([[0.125, -1.25], [-4.25, 4]])
    y = torch.Tensor([[4.5, -2.5], [5, 2.25]])

    x_share = ShareTensor(data=x,
                          config=Config(encoder_base=base,
                                        encoder_precision=precision))
    y_share = ShareTensor(data=y,
                          config=Config(encoder_base=base,
                                        encoder_precision=precision))

    expected_res = op(x, y)
    res = op(x_share, y_share)
    tensor_decoded = res.fp_encoder.decode(res.tensor)

    assert np.allclose(tensor_decoded, expected_res, rtol=base**-precision)
Exemple #11
0
def test_send_get(get_clients, precision, base) -> None:
    x = torch.Tensor([0.122, 1.342, 4.67])
    x_share = ShareTensor(data=x,
                          config=Config(encoder_precision=precision,
                                        encoder_base=base))
    client = get_clients(1)[0]
    x_ptr = x_share.send(client)

    assert x_share == x_ptr.get()
Exemple #12
0
def test_reconstruct(get_clients) -> None:
    clients = get_clients(2)
    session = Session(parties=clients)
    SessionManager.setup_mpc(session)

    a_rand = 3
    a = ShareTensor(data=a_rand, config=Config(encoder_precision=0))
    MPCTensor.generate_shares(secret=a, nr_parties=2, tensor_type=torch.long)

    MPCTensor.generate_shares(
        secret=a_rand, nr_parties=2, config=Config(), tensor_type=torch.long
    )

    x_secret = torch.Tensor([1, -2, 3.0907, -4.870])
    x = MPCTensor(secret=x_secret, session=session)
    x = x.reconstruct()

    assert np.allclose(x_secret, x)
Exemple #13
0
def test_generate_shares_config(get_clients) -> None:
    x_secret = torch.Tensor([5.0])
    x_share = ShareTensor(data=x_secret)

    shares_from_share_tensor = MPCTensor.generate_shares(x_share, 2)
    shares_from_secret = MPCTensor.generate_shares(
        x_secret, 2, config=Config(encoder_base=2, encoder_precision=16)
    )

    assert sum(shares_from_share_tensor) == sum(shares_from_secret)
Exemple #14
0
    def prrs_generate_random_share(
        self,
        shape: Union[tuple, torch.Size],
        ring_size: Optional[str] = None,
    ) -> Any:
        """Generates a random share using the generators held by a party.

        Args:
            shape (Union[tuple, torch.Size]): Shape for the share.
            ring_size (str): ring size to generate share.

        Returns:
            Any: ShareTensor or ReplicatedSharedTensor

        """
        from sympc.tensor import ReplicatedSharedTensor
        from sympc.tensor import ShareTensor

        if ring_size is None:
            ring_size = self.ring_size
        else:
            ring_size = int(ring_size)  # 2**64 cannot be serialized.

        share1, share2 = self._generate_random_share(shape, ring_size)

        if self.protocol.share_class == ShareTensor:
            # It has encoder_precision = 0 such that the value would not be encoded
            share = ShareTensor(
                data=share1,
                session_uuid=self.uuid,
                config=Config(encoder_precision=0),
                ring_size=ring_size,
            )
        else:
            share = ReplicatedSharedTensor(
                shares=[share1, share2],
                session_uuid=self.uuid,
                config=Config(encoder_precision=0),
                ring_size=ring_size,
            )

        return share
def test_ops_share_private(op_str, precision, base) -> None:
    op = getattr(operator, op_str)

    x = torch.Tensor([[0.125, -1.25], [-4.25, 4]])
    y = torch.Tensor([[4.5, -2.5], [5, 2.25]])

    x_share = ReplicatedSharedTensor(shares=[x],
                                     config=Config(
                                         encoder_base=base,
                                         encoder_precision=precision))
    y_share = ReplicatedSharedTensor(shares=[y],
                                     config=Config(
                                         encoder_base=base,
                                         encoder_precision=precision))

    expected_res = op(x, y)
    res = op(x_share, y_share)
    tensor_decoded = res.fp_encoder.decode(res.shares[0])

    assert np.allclose(tensor_decoded, expected_res, rtol=base**-precision)
Exemple #16
0
def test_log(get_clients) -> None:
    clients = get_clients(2)
    x_secret = torch.Tensor([0.1, 0.5, 2, 5, 10])
    x_secret_log = torch.log(x_secret)

    # with custom precision
    config = Config(encoder_precision=20)
    session = Session(parties=clients, config=config)
    SessionManager.setup_mpc(session)

    x = MPCTensor(secret=x_secret, session=session)
    x_log = log(x)

    assert torch.allclose(x_secret_log, x_log.reconstruct(), atol=1e-1)
Exemple #17
0
    def __init__(
        self,
        parties: Optional[List[Any]] = None,
        ring_size: int = 2**64,
        config: Optional[Config] = None,
        ttp: Optional[Any] = None,
        uuid: Optional[UUID] = None,
    ) -> None:
        """Initializer for the Session."""

        self.uuid = uuid4() if uuid is None else uuid

        # Each worker will have the rank as the index in the list
        # Only the party that is the CC (Control Center) will have access
        # to this

        self.parties: List[Any]
        self.nr_parties: int

        if parties is None:
            self.parties = []
            self.nr_parties = 0
        else:
            self.parties = parties
            self.nr_parties = len(parties)

        # Some protocols require a trusted third party
        # Ex: SPDZ
        self.trusted_third_party = ttp

        # The CryptoStore is initialized at each party when it is unserialized
        self.crypto_store: Optional[Dict[
            Any, Any]] = None  # TODO: this should be CryptoStore

        self.protocol: Optional[str] = None

        self.config = config if config else Config()

        self.przs_generators: List[List[torch.Generator]] = []

        # Those will be populated in the setup_mpc
        self.rank = -1
        self.session_ptrs: List[Session] = []

        # Ring size
        self.tensor_type: Union[torch.dtype] = get_type_from_ring(ring_size)
        self.ring_size = ring_size
        self.min_value = -(ring_size) // 2
        self.max_value = (ring_size - 1) // 2
def test_ops_public_mul_matrix(get_clients, security, base, precision):
    parties = get_clients(3)
    protocol = Falcon(security)
    config = Config(encoder_base=base, encoder_precision=precision)
    session = Session(protocol=protocol, parties=parties, config=config)
    SessionManager.setup_mpc(session)

    secret = torch.Tensor([[0.125, 1001, 4.82, -1.25], [-4.25, 0.217, 3301,
                                                        4]])
    value = torch.Tensor([[4.5, 9.25, 3.47, -2.5], [50, 3.17, 5.82, 2.25]])

    tensor = MPCTensor(secret=secret, session=session)
    result = tensor * value
    expected_res = secret * value
    assert np.allclose(result.reconstruct(), expected_res, atol=1e-3)
def test_bin_public_xor(get_clients, bit) -> None:
    clients = get_clients(3)
    falcon = Protocol.registered_protocols["Falcon"]()
    session = Session(parties=clients, protocol=falcon)
    session.config = Config(encoder_base=1, encoder_precision=0)
    SessionManager.setup_mpc(session)

    x = torch.tensor([[1, 0], [0, 1]], dtype=torch.bool)
    b = torch.tensor([bit], dtype=torch.bool)

    x_share = MPCTensor(secret=x, session=session)
    result = operator.xor(x_share, b)
    expected_res = x ^ b

    assert (result.reconstruct() == expected_res).all()
Exemple #20
0
def test_mul_private(get_clients, security, base, precision):
    parties = get_clients(3)
    protocol = Falcon(security)
    config = Config(encoder_base=base, encoder_precision=precision)
    session = Session(protocol=protocol, parties=parties, config=config)
    SessionManager.setup_mpc(session)

    secret1 = torch.tensor([[-100.25, 0.29, 30.45], [-90.82, 1000, 0.18],
                            [1032.45, -323.18, 15.15]])
    secret2 = 8

    tensor1 = MPCTensor(secret=secret1, session=session)
    tensor2 = MPCTensor(secret=secret2, session=session)

    result = tensor1 * tensor2
    expected_res = secret1 * secret2
    assert np.allclose(result.reconstruct(), expected_res, atol=1e-3)
def test_fixed_point(precision, base) -> None:
    x = torch.tensor([1.25, 3.301])
    shares = [x, x]
    rst = ReplicatedSharedTensor(shares=shares,
                                 config=Config(encoder_precision=precision,
                                               encoder_base=base))
    fp_encoder = FixedPointEncoder(precision=precision, base=base)
    tensor_type = get_type_from_ring(rst.ring_size)
    for i in range(len(shares)):
        shares[i] = fp_encoder.encode(shares[i]).to(tensor_type)

    assert (torch.cat(shares) == torch.cat(rst.shares)).all()

    for i in range(len(shares)):
        shares[i] = fp_encoder.decode(shares[i].type(torch.LongTensor))

    assert (torch.cat(shares) == torch.cat(rst.decode())).all()
Exemple #22
0
def count_wraps_rand(
        nr_parties: int,
        shape: Tuple[int]) -> Tuple[List[ShareTensor], List[ShareTensor]]:
    """Count wraps random.

    The Trusted Third Party (TTP) or Crypto provider should generate:

    - a set of shares for a random number
    - a set of shares for the number of wraparounds for that number

    Those shares are used when doing a public division, such that the
    end result would be the correct one.

    Args:
        nr_parties (int): Number of parties
        shape (Tuple[int]): The shape for the random value

    Returns:
        List[List[List[ShareTensor, ShareTensor]]: a list of instaces with the shares
        for a random integer value and shares for the number of wraparounds that are done when
        reconstructing the random value
    """
    rand_val = torch.empty(size=shape,
                           dtype=torch.long).random_(generator=ttp_generator)

    config = Config(encoder_precision=0)
    r_shares = MPCTensor.generate_shares(secret=rand_val,
                                         nr_parties=nr_parties,
                                         tensor_type=torch.long,
                                         config=config)
    wraps = count_wraps([share.tensor for share in r_shares])

    theta_r_shares = MPCTensor.generate_shares(secret=wraps,
                                               nr_parties=nr_parties,
                                               tensor_type=torch.long,
                                               config=config)

    # We are always creating only an instance
    primitives_sequential = [(r_shares, theta_r_shares)]

    primitives = list(
        map(list,
            zip(*map(lambda x: map(list, zip(*x)), primitives_sequential))))

    return primitives
def test_ops_public_mul_integer_parties(get_clients, parties, security):

    config = Config(encoder_base=1, encoder_precision=0)

    parties = get_clients(parties)
    protocol = Falcon(security)
    session = Session(protocol=protocol, parties=parties, config=config)
    SessionManager.setup_mpc(session)

    secret = torch.tensor([[-100, 20, 30], [-90, 1000, 1], [1032, -323, 15]])
    value = 8

    op = getattr(operator, "mul")
    tensor = MPCTensor(secret=secret, session=session)
    shares = [op(share, value) for share in tensor.share_ptrs]
    result = MPCTensor(shares=shares, session=session)

    assert (result.reconstruct() == (secret * value)).all()
Exemple #24
0
def test_mul_private_matrix(get_clients, security, base, precision):
    parties = get_clients(3)
    protocol = Falcon(security)
    config = Config(encoder_base=base, encoder_precision=precision)
    session = Session(protocol=protocol, parties=parties, config=config)
    SessionManager.setup_mpc(session)

    secret1 = torch.tensor([[-100.25, 20.3, 30.12], [-50.1, 100.217, 1.2],
                            [1032.15, -323.56, 15.15]])

    secret2 = torch.tensor([[-1, 0.28, 3], [-9, 10.18, 1], [32, -23, 5]])

    tensor1 = MPCTensor(secret=secret1, session=session)
    tensor2 = MPCTensor(secret=secret2, session=session)

    result = tensor1 * tensor2
    expected_res = secret1 * secret2
    assert np.allclose(result.reconstruct(), expected_res, atol=1e-3)
Exemple #25
0
    def mul_master(
        x: MPCTensor,
        y: MPCTensor,
        session: Session,
        op_str: str,
        kwargs_: Dict[Any, Any],
    ) -> MPCTensor:
        """Master method for multiplication.

        Args:
            x (MPCTensor): Secret
            y (MPCTensor): Another secret
            session (Session): Session the tensors belong to
            op_str (str): Operation string.
            kwargs_ (Dict[Any, Any]): Kwargs for some operations like conv2d

        Returns:
            result (MPCTensor): Result of the operation.

        Raises:
            ValueError: Raised when number of parties are not three.
            ValueError : Raised when invalid security_type is provided.
        """
        if len(session.parties) != 3:
            raise ValueError("Falcon requires 3 parties")

        result = None

        ring_size = int(x.share_ptrs[0].get_ring_size().get_copy())
        conf_dict = x.share_ptrs[0].get_config().get_copy()
        config = Config(**conf_dict)

        if session.protocol.security_type == "semi-honest":
            result = Falcon.mul_semi_honest(x, y, session, op_str, ring_size,
                                            config, **kwargs_)
        elif session.protocol.security_type == "malicious":
            result = Falcon.mul_malicious(x, y, session, op_str, ring_size,
                                          config, **kwargs_)
        else:
            raise ValueError("Invalid security_type for Falcon multiplication")

        result = ABY3.truncate(result, session, ring_size, config)

        return result
Exemple #26
0
def div_wraps(
    r_share: ShareTensor,
    theta_r: ShareTensor,
    x_share: ShareTensor,
    z_shares: List[torch.Tensor],
    y: Union[torch.Tensor, int],
) -> ShareTensor:
    """From CrypTen Privately computes the number of wraparounds for a set a shares.

    To do so, we note that:
        [theta_x] = theta_z + [beta_xr] - [theta_r] - [eta_xr]

    Where:
        [theta_x] is the wraps for a variable x
        [beta_xr] is the differential wraps for variables x and r
        [eta_xr]  is the plaintext wraps for variables x and r

    Note: Since [eta_xr] = 0 with probability 1 - |x| / Q for modulus Q, we
    can make the assumption that [eta_xr] = 0 with high probability.

    Args:
        r_share (ShareTensor): share for a random variable "r"
        theta_r (ShareTensor): share for the number of wraparounds for "r"
        x_share (ShareTensor): shares for which we want to compute the number of wraparounds
        z_shares (List[torch.Tensor]): list of shares for a random value
        y (Union[torch.Tensor, int]): the number/tensor by which we divide

    Returns:
        ShareTensor representing the number of wraparounds
    """
    session = get_session(str(r_share.session_uuid))

    beta_xr = count_wraps([x_share.tensor, r_share.tensor])
    theta_x = ShareTensor(config=Config(encoder_precision=0))
    theta_x.tensor = beta_xr - theta_r.tensor

    if session.rank == 0:
        theta_z = count_wraps(z_shares)
        theta_x.tensor += theta_z

    x_share.tensor //= y

    return theta_x
Exemple #27
0
def test_session_custom_init() -> None:
    config = Config()
    session = Session(parties=["alice", "bob"],
                      ring_size=2**32,
                      config=config,
                      ttp="TTP")
    assert session.uuid is None
    assert session.parties == ["alice", "bob"]
    assert session.trusted_third_party == "TTP"
    assert session.crypto_store is None
    assert session.protocol is not None
    assert session.config == config
    assert session.przs_generators == []
    assert session.rank == -1
    assert session.session_ptrs == []
    assert session.tensor_type == get_type_from_ring(2**32)
    assert session.ring_size == 2**32
    assert session.min_value == -(2**32) // 2
    assert session.max_value == (2**32 - 1) // 2
Exemple #28
0
def test_truncation_algorithm1(get_clients, base, precision) -> None:
    parties = get_clients(3)
    falcon = Falcon("semi-honest")
    config = Config(encoder_base=base, encoder_precision=precision)
    session = Session(parties=parties, protocol=falcon, config=config)
    SessionManager.setup_mpc(session)

    x = torch.tensor([[1.24, 4.51, 6.87], [7.87, 1301, 541]])

    x_mpc = MPCTensor(secret=x, session=session)

    result = ABY3.truncate(x_mpc, session, session.ring_size, session.config)

    fp_encoder = FixedPointEncoder(base=session.config.encoder_base,
                                   precision=session.config.encoder_precision)
    expected_res = x_mpc.reconstruct(decode=False) // fp_encoder.scale
    expected_res = fp_encoder.decode(expected_res)

    assert np.allclose(result.reconstruct(), expected_res, atol=1e-3)
Exemple #29
0
def proto2object(proto: ShareTensor_PB) -> ShareTensor:
    if proto.session_uuid:
        session = sympc.session.get_session(proto.session_uuid)
        if session is None:
            raise ValueError(
                f"The session {proto.session_uuid} could not be found")

        config = dataclasses.asdict(session.config)
    else:
        config = syft.deserialize(proto.config, from_proto=True)

    data = protobuf_tensor_deserializer(proto.tensor.tensor)
    share = ShareTensor(data=None, config=Config(**config))

    if proto.session_uuid:
        share.session_uuid = UUID(proto.session_uuid)

    # Manually put the tensor since we do not want to re-encode it
    share.tensor = data

    return share
Exemple #30
0
    def bit_decomposition_ttp(x: MPCTensor,
                              session: Session) -> List[MPCTensor]:
        """Perform ABY3 bit decomposition using orchestrator as ttp.

        Args:
            x (MPCTensor): Arithmetic shares of secret.
            session (Session): session the share belongs to.

        Returns:
            b_sh (List[MPCTensor]): Returns binary shares of each bit of the secret.

        TODO: We should modify to use parallel prefix adder, which requires multiprocessing.
        """
        # Decoding is not done as they are shares of PRRS.
        tensor = x.reconstruct(decode=False)
        b_sh: List[MPCTensor] = []  # binary shares of bits
        ring_size = session.ring_size
        shares_sum = ReplicatedSharedTensor.shares_sum
        ring_bits = get_nr_bits(ring_size)

        for idx in range(ring_bits):
            bit_mask = torch.ones(tensor.shape, dtype=tensor.dtype) << idx
            secret = (tensor & bit_mask).type(torch.bool)
            r1 = torch.empty(size=tensor.shape,
                             dtype=torch.bool).random_(generator=gen)
            r2 = torch.empty(size=tensor.shape,
                             dtype=torch.bool).random_(generator=gen)
            r3 = shares_sum([secret, r1, r2], ring_size=2)
            shares = [r1, r2, r3]
            config = Config(encoder_base=1, encoder_precision=0)
            sh_ptr = ReplicatedSharedTensor.distribute_shares(shares=shares,
                                                              session=session,
                                                              ring_size=2,
                                                              config=config)
            b_mpc = MPCTensor(shares=sh_ptr,
                              session=session,
                              shape=tensor.shape)
            b_sh.append(b_mpc)

        return b_sh