def to_paillier(element, public_key): if isinstance(element, torch.Tensor) and isinstance( element.child, PaillierTensor): element.child.pubkey = public_key child = element.child.child if isinstance(child, ndarray): return element elif isinstance(child, EncryptedNumber): element.child.child = array([child]) return element else: raise Exception( "The tensor does not have an EncryptedNumber or a np.ndarray as child" ) elif isinstance(element, PaillierTensor): element.pubkey = public_key return element.wrap() elif isinstance(element, ndarray): tensor = PaillierTensor() tensor.child = element tensor.pubkey = public_key return tensor.wrap() elif isinstance(element, list): tensor = PaillierTensor() tensor.child = array(element) tensor.pubkey = public_key return tensor.wrap() elif isinstance(element, EncryptedNumber): tensor = PaillierTensor() tensor.child = array([element]) tensor.pubkey = public_key return tensor.wrap() else: raise TypeError(type(element))
def deserialize_paillier(struct, pub=None): # Case 1: dict recursion if isinstance(struct, dict): pub = PaillierPublicKey(n=int(struct['n'])) child = [ deserialize_paillier(substruct, pub) for substruct in struct['values'] ] # Building Paillier Tensor tensor = PaillierTensor() tensor.child = array(child) tensor.pubkey = pub return tensor.wrap() # Case 2: list recursion elif isinstance(struct, list): return [deserialize_paillier(substruct, pub) for substruct in struct] # Case 3: Tuple deserialization elif isinstance(struct, tuple): return EncryptedNumber(pub, int(struct[0]), int(struct[1])) # Case 4: Unknown type else: raise TypeError(type(struct))
def encrypt(self, protocol="mpc", **kwargs): """ This method will encrypt each value in the tensor using Multi Party Computation (default) or Paillier Homomorphic Encryption Args: protocol (str): Currently supports 'mpc' for Multi Party Computation and 'paillier' for Paillier Homomorphic Encryption **kwargs: With Respect to MPC accepts: workers (list): Parties involved in the sharing of the Tensor crypto_provider (syft.VirtualWorker): Worker responsible for the generation of the random numbers for encryption requires_grad (bool): If true, whenever the remote value of this tensor will have its gradient updated (for example when calling .backward()), a call will be made to set back the local gradient value. no_wrap (bool): If True, wrap() is called on the created pointer Keyword Args: To be parsed as kwargs for the .fix_prec() method With Respect to Paillier accepts: public_key (phe.paillier.PaillierPublicKey): Can be obtained using ```public_key, private_key = sy.frameworks.torch.he.paillier.keygen()``` Returns: An encrypted version of the Tensor following the protocol specified Raises: NotImplementedError: If protocols other than the ones mentioned above are queried """ if protocol.lower() == "mpc": workers = kwargs.pop("workers") crypto_provider = kwargs.pop("crypto_provider") requires_grad = kwargs.pop("requires_grad", False) no_wrap = kwargs.pop("no_wrap", False) kwargs_fix_prec = kwargs # Rest of kwargs for fix_prec method x_shared = self.fix_prec(**kwargs_fix_prec).share( *workers, crypto_provider=crypto_provider, requires_grad=requires_grad, no_wrap=no_wrap, ) return x_shared elif protocol.lower() == "paillier": public_key = kwargs.get("public_key") x = self.copy() x_encrypted = PaillierTensor().on(x) # Instantiate the class x_encrypted.child.encrypt_( public_key) # Perform Homomorphic Encryption return x_encrypted else: raise NotImplementedError( "Currently the .encrypt() method only supports Paillier Homomorphic " "Encryption and Secure Multi-Party Computation")
def encrypt(self, public_key): """This method will encrypt each value in the tensor using Paillier homomorphic encryption. Args: *public_key a public key created using syft.frameworks.torch.he.paillier.keygen() """ x = self.copy() x2 = PaillierTensor().on(x) x2.child.encrypt_(public_key) return x2
def encrypt(self, protocol="mpc", inplace=False, **kwargs): """ This method will encrypt each value in the tensor using Multi Party Computation (default) or Paillier Homomorphic Encryption Args: protocol (str): Currently supports the following crypto protocols: - 'snn' for SecureNN - 'fss' for Function Secret Sharing (see AriaNN paper) - 'mpc' (Multi Party Computation) defaults to most standard protocol, currently 'snn' - 'paillier' for Paillier Homomorphic Encryption inplace (bool): compute the operation inplace (default is False) **kwargs: With respect to Fixed Precision accepts: precision_fractional (int) dtype (str) With Respect to MPC accepts: workers (list): Parties involved in the sharing of the Tensor crypto_provider (syft.VirtualWorker): Worker responsible for the generation of the random numbers for encryption requires_grad (bool): If true, whenever the remote value of this tensor will have its gradient updated (for example when calling .backward()), a call will be made to set back the local gradient value. no_wrap (bool): If True, wrap() is called on the created pointer Keyword Args: To be parsed as kwargs for the .fix_prec() method With Respect to Paillier accepts: public_key (phe.paillier.PaillierPublicKey): Can be obtained using ```public_key, private_key = sy.frameworks.torch.he.paillier.keygen()``` Returns: An encrypted version of the Tensor following the protocol specified Raises: NotImplementedError: If protocols other than the ones mentioned above are queried """ protocol = protocol.lower() if protocol in {"mpc", "snn", "fss"}: if protocol == "mpc": protocol = "snn" workers = kwargs.pop("workers") crypto_provider = kwargs.pop("crypto_provider") requires_grad = kwargs.pop("requires_grad", False) no_wrap = kwargs.pop("no_wrap", False) dtype = kwargs.get("dtype") kwargs_fix_prec = kwargs # Rest of kwargs for fix_prec method kwargs_share = dict( crypto_provider=crypto_provider, requires_grad=requires_grad, no_wrap=no_wrap, protocol=protocol, dtype=dtype, ) if not inplace: x_shared = self.fix_prec(**kwargs_fix_prec).share( *workers, **kwargs_share) return x_shared else: self.fix_prec_(**kwargs_fix_prec).share_( *workers, **kwargs_share) return self elif protocol == "paillier": public_key = kwargs.get("public_key") x = self.copy() x_encrypted = PaillierTensor().on(x) # Instantiate the class x_encrypted.child.encrypt_( public_key) # Perform Homomorphic Encryption return x_encrypted else: raise NotImplementedError( "Currently the .encrypt() method only supports Paillier Homomorphic " f"Encryption and Secure Multi-Party Computation, but {protocol} was given" )
AutogradTensor: get_child, LoggingTensor: get_child, PaillierTensor: get_child, } backward_func = { TorchTensor: lambda i, **kwargs: i.wrap(**kwargs), torch.Tensor: lambda i, **kwargs: i.wrap(**kwargs), torch.nn.Parameter: lambda i, **kwargs: torch.nn.Parameter(data=i), AutogradTensor: lambda i, **kwargs: AutogradTensor(data=i).on(i, wrap=False), LoggingTensor: lambda i, **kwargs: LoggingTensor().on(i, wrap=False), PaillierTensor: lambda i, **kwargs: PaillierTensor().on(i, wrap=False), } if dependency_check.crypten_available: import crypten type_rule[crypten.mpc.MPCTensor] = one forward_func[crypten.mpc.MPCTensor] = ( lambda i: i.child if hasattr(i, "child") else ().throw(PureFrameworkTensorFoundError)) backward_func[crypten.mpc.MPCTensor] = lambda i, **kwargs: i.wrap(**kwargs) # Methods or functions whose signature changes a lot and that we don't want to "cache", because # they have an arbitrary number of tensors in args which can trigger unexpected behaviour ambiguous_methods = { "__getitem__",
else (_ for _ in ()).throw(PureFrameworkTensorFoundError), torch.nn.Parameter: lambda i: i.child if hasattr(i, "child") else (_ for _ in ()).throw(PureFrameworkTensorFoundError), AutogradTensor: get_child, LoggingTensor: get_child, PaillierTensor: get_child, } backward_func = { TorchTensor: lambda i: i.wrap(), torch.Tensor: lambda i: i.wrap(), torch.nn.Parameter: lambda i: torch.nn.Parameter(data=i), AutogradTensor: lambda i: AutogradTensor(data=i).on(i, wrap=False), LoggingTensor: lambda i: LoggingTensor().on(i, wrap=False), PaillierTensor: lambda i: PaillierTensor().on(i, wrap=False), } ambiguous_methods = { "__getitem__", "_getitem_public", "__setitem__", "view", "permute", "add_", "sub_", "new", "chunk", "reshape", }