def _sub_cipher_cipher(self, ct1, ct2): """Subtract two ciphertexts. Args: ct1 (Ciphertext): First polynomial argument (Minuend). ct2 (Ciphertext): Second polynomial argument (Subtrahend). Returns: A Ciphertext object with value equivalent to result of subtraction of two provided arguments. """ ct1, ct2 = copy.deepcopy(ct1.data), copy.deepcopy(ct2.data) result = ct2 if len(ct2) > len(ct1) else ct1 min_size, max_size = min(len(ct1), len(ct2)), max(len(ct1), len(ct2)) for i in range(min_size): for j in range(len(self.coeff_modulus)): result[i][j] = poly_sub_mod(ct1[i][j], ct2[i][j], self.coeff_modulus[j], self.poly_modulus) for i in range(min_size + 1, max_size): for j in range(len(self.coeff_modulus)): result[i][j] = poly_negate_mod(result[i][j], self.coeff_modulus[j]) return CipherText(result)
def encrypt_symmetric(context, secret_key): """Create encryption of zero values with a secret key which can be used in subsequent processes to add a message into it. Args: context (Context): A valid context required for extracting the encryption parameters. secret_key (SecretKey): A secret key generated with same encryption parameters. Returns: A ciphertext object containing encryption of zeroes by symmetric encryption procedure. """ coeff_modulus = context.param.coeff_modulus coeff_mod_size = len(coeff_modulus) # Sample uniformly at random c1 = sample_poly_uniform(context.param) # Sample e <-- chi e = sample_poly_normal(context.param) # calculate -(a*s + e) (mod q) and store in c0 c0 = [0] * coeff_mod_size for i in range(coeff_mod_size): c0[i] = poly_negate_mod( poly_add_mod( poly_mul_mod(c1[i], secret_key[i], coeff_modulus[i]), e[i], coeff_modulus[i] ), coeff_modulus[i], ) return CipherText([c0, c1])
def test_poly_negate_mod(op1, mod, result): assert poly_negate_mod(op1, mod) == result