def decode(self, plain): """Decodes a plaintext polynomial and returns the integer. Mathematically this amounts to evaluating the input polynomial at x=2. Args: plain: The plaintext to be decoded. Returns: An integer value. """ result = 0 bit_index = get_significant_count(plain.data) while bit_index > 0: bit_index -= 1 coeff = plain.data[bit_index] # Left shift result. next_result = result << 1 if (next_result < 0) != (result < 0): # Check for overflow. raise OverflowError("output out of range") if coeff >= self.plain_modulus: # Coefficient is bigger than plaintext modulus raise ValueError("plain does not represent a valid plaintext polynomial") coeff_is_negative = coeff >= self.coeff_neg_threshold pos_value = coeff if coeff_is_negative: pos_value = self.plain_modulus - pos_value coeff_value = pos_value if coeff_is_negative: coeff_value = -coeff_value next_result_was_negative = next_result < 0 next_result += coeff_value next_result_is_negative = next_result < 0 if ( next_result_was_negative == coeff_is_negative and next_result_was_negative != next_result_is_negative ): # Accumulation and coefficient had same signs, but accumulator changed signs # after addition, so must be overflow. raise OverflowError("output out of range") result = next_result return result
def decrypt(self, encrypted): """Decrypts the encrypted ciphertext objects. Args: encrypted: A ciphertext object which has to be decrypted. Returns: A PlainText object containing the decrypted result. """ # Calculate [c0 + c1 * sk + c2 * sk^2 ...]_q temp_product_modq = self._mul_ct_sk(copy.deepcopy(encrypted.data)) # Divide scaling variant using BEHZ FullRNS techniques result = self._context.rns_tool.decrypt_scale_and_round(temp_product_modq) # removing leading zeroes in plaintext representation. plain_coeff_count = get_significant_count(result) return PlainText(result[:plain_coeff_count])
def test_get_significant_count(ptr, result): assert result == get_significant_count(ptr)