Skip to content

Commit e966ba1

Browse files
author
Wei Dai
committed
Merge pull request #363 from fboemer/fboemer/faster-decrypt
1 parent 75ff397 commit e966ba1

File tree

1 file changed

+61
-28
lines changed

1 file changed

+61
-28
lines changed

native/src/seal/decryptor.cpp

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -264,39 +264,72 @@ namespace seal
264264
// Make sure we have enough secret key powers computed
265265
compute_secret_key_array(encrypted_size - 1);
266266

267-
// put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q in destination
268-
// Now do the dot product of encrypted_copy and the secret key array using NTT.
269-
// The secret key powers are already NTT transformed.
270-
271-
SEAL_ALLOCATE_GET_POLY_ITER(encrypted_copy, encrypted_size - 1, coeff_count, coeff_modulus_size, pool);
272-
set_poly_array(encrypted.data(1), encrypted_size - 1, coeff_count, coeff_modulus_size, encrypted_copy);
273-
274-
// Transform c_1, c_2, ... to NTT form unless they already are
275-
if (!is_ntt_form)
267+
if (encrypted_size == 2)
276268
{
277-
ntt_negacyclic_harvey_lazy(encrypted_copy, encrypted_size - 1, ntt_tables);
269+
ConstRNSIter secret_key_array(secret_key_array_.get(), coeff_count);
270+
ConstRNSIter c0(encrypted.data(0), coeff_count);
271+
ConstRNSIter c1(encrypted.data(1), coeff_count);
272+
if (is_ntt_form)
273+
{
274+
SEAL_ITERATE(
275+
iter(c0, c1, secret_key_array, coeff_modulus, destination), coeff_modulus_size, [&](auto I) {
276+
// put < c_1 * s > mod q in destination
277+
dyadic_product_coeffmod(get<1>(I), get<2>(I), coeff_count, get<3>(I), get<4>(I));
278+
// add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
279+
add_poly_coeffmod(get<4>(I), get<0>(I), coeff_count, get<3>(I), get<4>(I));
280+
});
281+
}
282+
else
283+
{
284+
SEAL_ITERATE(
285+
iter(c0, c1, secret_key_array, coeff_modulus, ntt_tables, destination), coeff_modulus_size,
286+
[&](auto I) {
287+
set_uint(get<1>(I), coeff_count, get<5>(I));
288+
// Transform c_1 to NTT form
289+
ntt_negacyclic_harvey_lazy(get<5>(I), get<4>(I));
290+
// put < c_1 * s > mod q in destination
291+
dyadic_product_coeffmod(get<5>(I), get<2>(I), coeff_count, get<3>(I), get<5>(I));
292+
// Transform back
293+
inverse_ntt_negacyclic_harvey(get<5>(I), get<4>(I));
294+
// add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
295+
add_poly_coeffmod(get<5>(I), get<0>(I), coeff_count, get<3>(I), get<5>(I));
296+
});
297+
}
278298
}
299+
else
300+
{
301+
// put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q in destination
302+
// Now do the dot product of encrypted_copy and the secret key array using NTT.
303+
// The secret key powers are already NTT transformed.
304+
SEAL_ALLOCATE_GET_POLY_ITER(encrypted_copy, encrypted_size - 1, coeff_count, coeff_modulus_size, pool);
305+
set_poly_array(encrypted.data(1), encrypted_size - 1, coeff_count, coeff_modulus_size, encrypted_copy);
306+
307+
// Transform c_1, c_2, ... to NTT form unless they already are
308+
if (!is_ntt_form)
309+
{
310+
ntt_negacyclic_harvey_lazy(encrypted_copy, encrypted_size - 1, ntt_tables);
311+
}
312+
313+
// Compute dyadic product with secret power array
314+
auto secret_key_array = PolyIter(secret_key_array_.get(), coeff_count, key_coeff_modulus_size);
315+
SEAL_ITERATE(iter(encrypted_copy, secret_key_array), encrypted_size - 1, [&](auto I) {
316+
dyadic_product_coeffmod(get<0>(I), get<1>(I), coeff_modulus_size, coeff_modulus, get<0>(I));
317+
});
318+
// Aggregate all polynomials together to complete the dot product
319+
set_zero_poly(coeff_count, coeff_modulus_size, destination);
320+
SEAL_ITERATE(encrypted_copy, encrypted_size - 1, [&](auto I) {
321+
add_poly_coeffmod(destination, I, coeff_modulus_size, coeff_modulus, destination);
322+
});
279323

280-
// Compute dyadic product with secret power array
281-
auto secret_key_array = PolyIter(secret_key_array_.get(), coeff_count, key_coeff_modulus_size);
282-
SEAL_ITERATE(iter(encrypted_copy, secret_key_array), encrypted_size - 1, [&](auto I) {
283-
dyadic_product_coeffmod(get<0>(I), get<1>(I), coeff_modulus_size, coeff_modulus, get<0>(I));
284-
});
285-
286-
// Aggregate all polynomials together to complete the dot product
287-
set_zero_poly(coeff_count, coeff_modulus_size, destination);
288-
SEAL_ITERATE(encrypted_copy, encrypted_size - 1, [&](auto I) {
289-
add_poly_coeffmod(destination, I, coeff_modulus_size, coeff_modulus, destination);
290-
});
324+
if (!is_ntt_form)
325+
{
326+
// If the input was not in NTT form, need to transform back
327+
inverse_ntt_negacyclic_harvey(destination, coeff_modulus_size, ntt_tables);
328+
}
291329

292-
if (!is_ntt_form)
293-
{
294-
// If the input was not in NTT form, need to transform back
295-
inverse_ntt_negacyclic_harvey(destination, coeff_modulus_size, ntt_tables);
330+
// Finally add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
331+
add_poly_coeffmod(destination, *iter(encrypted), coeff_modulus_size, coeff_modulus, destination);
296332
}
297-
298-
// Finally add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
299-
add_poly_coeffmod(destination, *iter(encrypted), coeff_modulus_size, coeff_modulus, destination);
300333
}
301334

302335
int Decryptor::invariant_noise_budget(const Ciphertext &encrypted)

0 commit comments

Comments
 (0)