Esempio n. 1
0
    def enc(self, plain: Union[int, AddressValue], my_addr: AddressValue, target_addr: AddressValue) -> Tuple[CipherValue, Optional[RandomnessValue]]:
        """
        Encrypt plain for receiver with target_addr.

        :param plain: plain text to encrypt
        :param my_addr: address of the sender who encrypts
        :param target_addr: address of the receiver for whom to encrypt
        :return: if symmetric -> (iv_cipher, None), if asymmetric (cipher, randomness which was used to encrypt plain)
        """
        if isinstance(plain, AddressValue):
            plain = int.from_bytes(plain.val, byteorder='big')
        assert not isinstance(plain, Value), f"Tried to encrypt value of type {type(plain).__name__}"
        assert isinstance(my_addr, AddressValue) and isinstance(target_addr, AddressValue)
        assert int(plain) < bn128_scalar_field, f"Integer overflow, plaintext is >= field prime"
        zk_print(f'Encrypting value {plain} for destination "{target_addr}"', verbosity_level=2)

        sk = self.keystore.sk(my_addr).val
        raw_pk = self.keystore.getPk(target_addr)
        if self.params.is_symmetric_cipher():
            assert len(raw_pk) == 1
            pk = raw_pk[0]
        else:
            pk = self.deserialize_pk(raw_pk[:])
        while True:
            # Retry until cipher text is not 0
            cipher, rnd = self._enc(int(plain), sk, pk)
            cipher = CipherValue(cipher, params=self.params)
            rnd = RandomnessValue(rnd, params=self.params) if rnd is not None else None
            if cipher != CipherValue(params=self.params):
                break

        return cipher, rnd
Esempio n. 2
0
 def test_homomorphic_add_zero(self):
     eg = ElgamalCrypto(None)
     cipher1 = CipherValue([
         17990166387038654353532224054392704246273066434684370089496246721960255371329,
         15866190370882469414665095798958204707796441173247149326160843221134574846694,
         13578016172019942326633412365679613147103709674318008979748420035774874659858,
         15995926508900361671313404296634773295236345482179714831868518062689263430374
     ])
     cipher2 = CipherValue([0, 0, 0, 0])
     res = eg.do_op('+', None, cipher1, cipher2)
     self.assertEqual(CipherValue(res), cipher1)
Esempio n. 3
0
 def __get_decrypted_retval(self, raw_value, is_cipher, crypto_params_name,
                            constructor):
     return self.dec(CipherValue(raw_value,
                                 params=CryptoParams(crypto_params_name)),
                     constructor,
                     crypto_backend=crypto_params_name
                     )[0] if is_cipher else constructor(raw_value)
Esempio n. 4
0
 def do_rerand(self, arg: CipherValue,
               public_key: List[int]) -> Tuple[List[int], List[int]]:
     # homomorphically add encryption of zero to re-randomize
     r = randrange(babyjubjub.CURVE_ORDER)
     enc_zero = CipherValue(self._enc_with_rand(0, r, public_key),
                            params=arg.params)
     return self.do_op('+', public_key, arg, enc_zero), [r]
Esempio n. 5
0
 def do_rerand(self, arg: CipherValue, crypto_backend: str,
               target_addr: AddressValue, data: Dict, rnd_key: str):
     """
     Re-randomizes arg using fresh randomness, which is stored in data[rnd_key] (side-effect!)
     """
     params = CryptoParams(crypto_backend)
     pk = self.__keystore[params.crypto_name].getPk(target_addr)
     crypto_inst = self.__crypto[params.crypto_name]
     assert isinstance(crypto_inst, ZkayHomomorphicCryptoInterface)
     result, rand = crypto_inst.do_rerand(arg, pk[:])
     data[rnd_key] = RandomnessValue(rand,
                                     params=params)  # store randomness
     return CipherValue(result, params=params)
Esempio n. 6
0
 def test_homomorphic_add(self):
     eg = ElgamalCrypto(None)
     cipher1 = CipherValue([
         17990166387038654353532224054392704246273066434684370089496246721960255371329,
         15866190370882469414665095798958204707796441173247149326160843221134574846694,
         13578016172019942326633412365679613147103709674318008979748420035774874659858,
         15995926508900361671313404296634773295236345482179714831868518062689263430374
     ])
     cipher2 = CipherValue([
         20000451794290380375914691798920385097103434955980148521154607378788339649411,
         3379688933589504078077257631396507733503572474143535438012650064116108361323,
         19394553866420759826901398082663942344084257999221733532877406304105119931558,
         20583024216337563044477284173241746163084488704258522180236559083511927239523
     ])
     res = eg.do_op('+', None, cipher1, cipher2)
     expected = [
         18885199402227818148211810144232318738102042906622969713112212912459159846007,
         11125071952177567933017599368067887482603292954302203070407920687516147981132,
         20036470080915178878390944667725801469044803295396841663384258912114611255016,
         18986185709423663075397883577572338596028661172318034324882291197251276265727
     ]
     self.assertEqual(res, expected)
Esempio n. 7
0
 def deserialize(
     operand: Union[CipherValue, int]
 ) -> Union[Tuple[babyjubjub.Point, babyjubjub.Point], int]:
     if isinstance(operand, CipherValue):
         # if ciphertext is 0, return (Point.ZERO, Point.ZERO) == Enc(0, 0)
         if operand == CipherValue([0] * 4, params=operand.params):
             return babyjubjub.Point.ZERO, babyjubjub.Point.ZERO
         else:
             c1 = babyjubjub.Point(babyjubjub.Fq(operand[0]),
                                   babyjubjub.Fq(operand[1]))
             c2 = babyjubjub.Point(babyjubjub.Fq(operand[2]),
                                   babyjubjub.Fq(operand[3]))
             return c1, c2
     else:
         return operand
Esempio n. 8
0
    def do_homomorphic_op(self, op: str, crypto_backend: str,
                          target_addr: AddressValue, *args: Union[CipherValue,
                                                                  int]):
        params = CryptoParams(crypto_backend)
        pk = self.__keystore[params.crypto_name].getPk(target_addr)
        for arg in args:
            if isinstance(arg, CipherValue
                          ) and params.crypto_name != arg.params.crypto_name:
                raise ValueError(
                    'CipherValues from different crypto backends used in homomorphic operation'
                )

        crypto_inst = self.__crypto[params.crypto_name]
        assert isinstance(crypto_inst, ZkayHomomorphicCryptoInterface)
        result = crypto_inst.do_op(op, pk[:], *args)
        return CipherValue(result, params=params)
Esempio n. 9
0
    def dec(self, cipher: CipherValue, my_addr: AddressValue) -> Tuple[int, Optional[RandomnessValue]]:
        """
        Decrypt cipher encrypted for my_addr.

        :param cipher: encrypted value
        :param my_addr: cipher is encrypted for this address
        :return: if symmetric -> (plain, None), if asymmetric (plain, randomness which was used to encrypt plain)
        """
        assert isinstance(cipher, CipherValue), f"Tried to decrypt value of type {type(cipher).__name__}"
        assert isinstance(my_addr, AddressValue)
        zk_print(f'Decrypting value {cipher} for {my_addr}', verbosity_level=2)

        if cipher == CipherValue(params=self.params):
            # Ciphertext is all zeros, i.e. uninitialized -> zero
            return 0, (None if self.params.is_symmetric_cipher() else RandomnessValue(params=self.params))
        else:
            sk = self.keystore.sk(my_addr)
            plain, rnd = self._dec(cipher[:], sk.val)
            return plain, (None if rnd is None else RandomnessValue(rnd, params=self.params))
Esempio n. 10
0
    def __get(self, key: Union[str, Tuple], cache: bool):
        if not isinstance(key, Tuple):
            key = (key, )
        var, indices = key[0], key[1:]
        loc = var + ''.join(f'[{k}]' for k in key[1:])

        # Retrieve from state scope
        if cache and loc in self.__state:
            return self.__state[loc]
        else:
            is_cipher, constr = self.__constructors[var]
            try:
                if is_cipher:
                    val = CipherValue(
                        self.api._req_state_var(var,
                                                *indices,
                                                count=cfg.cipher_len))
                else:
                    val = constr(self.api._req_state_var(var, *indices))
            except BlockChainError:
                raise KeyError(key)
            if cache:
                self.__state[loc] = val
            return val
Esempio n. 11
0
 def __get_decrypted_retval(self, raw_value, is_cipher, constructor):
     return self.dec(
         CipherValue(raw_value),
         constructor)[0] if is_cipher else constructor(raw_value)