Beispiel #1
0
 BigPoly exponentiate_poly_polymod_coeffmod(const BigPoly &operand, const BigUInt &exponent,
     const BigPoly &poly_modulus, const BigUInt &coeff_modulus, const MemoryPoolHandle &pool)
 {
     BigPoly result(poly_modulus.coeff_count(), coeff_modulus.significant_bit_count());
     exponentiate_poly_polymod_coeffmod(operand, exponent, poly_modulus, coeff_modulus, result, pool);
     return result;
 }
Beispiel #2
0
    void KeyGenerator::generate(const BigPoly &secret_key, uint64_t power)
    {
        // Validate arguments.
        if (secret_key.is_zero())
        {
            throw invalid_argument("secret_key cannot be zero");
        }
        if (power == 0)
        {
            throw invalid_argument("power cannot be zero");
        }

        // Handle test-mode case.
        if (mode_ == TEST_MODE)
        {
            public_key_.set_zero();
            public_key_[0] = 1;
            secret_key_.set_zero();
            secret_key_[0] = 1;
            for (int i = 0; i < evaluation_keys_.count(); ++i)
            {
                evaluation_keys_[i].set_zero();
                evaluation_keys_[i][0] = 1;
            }
            return;
        }

        // Extract encryption parameters.
        int coeff_count = poly_modulus_.coeff_count();
        int coeff_bit_count = poly_modulus_.coeff_bit_count();
        int coeff_uint64_count = divide_round_up(coeff_bit_count, bits_per_uint64);

        // Verify secret key looks valid.
        secret_key_ = secret_key;
        if (secret_key_.coeff_count() != coeff_count || secret_key_.coeff_bit_count() != coeff_bit_count)
        {
            throw invalid_argument("secret_key is not valid for encryption parameters");
        }
#ifdef _DEBUG
        if (secret_key_.significant_coeff_count() == coeff_count || !are_poly_coefficients_less_than(secret_key_, coeff_modulus_))
        {
            throw invalid_argument("secret_key is not valid for encryption parameters");
        }
#endif

        // Raise level of secret key.
        if (power > 1)
        {
            exponentiate_poly_polymod_coeffmod(secret_key_.pointer(), &power, 1, polymod_, mod_, secret_key_.pointer(), pool_);
        }

        // Attempt to invert secret_key.
        Pointer secret_key_inv(allocate_poly(coeff_count, coeff_uint64_count, pool_));
        if (!try_invert_poly_coeffmod(secret_key_.pointer(), poly_modulus_.pointer(), coeff_count, mod_, secret_key_inv.get(), pool_))
        {
            // Secret_key is not invertible, so not valid.
            throw invalid_argument("secret_key is not valid for encryption parameters");
        }

        // Calculate plaintext_modulus * noise * secret_key_inv.
        Pointer noise(allocate_poly(coeff_count, coeff_uint64_count, pool_));
        set_poly_coeffs_zero_one_negone(noise.get());
        uint64_t *public_key = public_key_.pointer();
        multiply_poly_poly_polymod_coeffmod(noise.get(), secret_key_inv.get(), polymod_, mod_, noise.get(), pool_);
        multiply_poly_scalar_coeffmod(noise.get(), coeff_count, plain_modulus_.pointer(), mod_, public_key, pool_);

        // Create evaluation keys.
        Pointer evaluation_factor(allocate_uint(coeff_uint64_count, pool_));
        set_uint(1, coeff_uint64_count, evaluation_factor.get());
        for (int i = 0; i < evaluation_keys_.count(); ++i)
        {
            // Multiply secret_key by evaluation_factor (mod coeff modulus).
            uint64_t *evaluation_key = evaluation_keys_[i].pointer();
            multiply_poly_scalar_coeffmod(secret_key_.pointer(), coeff_count, evaluation_factor.get(), mod_, evaluation_key, pool_);

            // Multiply public_key*normal noise and add into evaluation_key.
            set_poly_coeffs_normal(noise.get());
            multiply_poly_poly_polymod_coeffmod(noise.get(), public_key, polymod_, mod_, noise.get(), pool_);
            add_poly_poly_coeffmod(noise.get(), evaluation_key, coeff_count, coeff_modulus_.pointer(), coeff_uint64_count, evaluation_key);

            // Add-in more normal noise to evaluation_key.
            set_poly_coeffs_normal(noise.get());
            add_poly_poly_coeffmod(noise.get(), evaluation_key, coeff_count, coeff_modulus_.pointer(), coeff_uint64_count, evaluation_key);

            // Left shift evaluation factor.
            left_shift_uint(evaluation_factor.get(), decomposition_bit_count_, coeff_uint64_count, evaluation_factor.get());
        }
    }