@@ -101,15 +101,15 @@ namespace seal
101
101
case scheme_type::ckks:
102
102
ckks_decrypt (encrypted, destination, pool_);
103
103
return ;
104
-
104
+
105
105
case scheme_type::bgv:
106
106
bgv_decrypt (encrypted, destination, pool_);
107
107
return ;
108
108
109
109
default :
110
110
throw invalid_argument (" unsupported scheme" );
111
111
}
112
-
112
+
113
113
}
114
114
115
115
void Decryptor::bfv_decrypt (const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool)
@@ -212,7 +212,7 @@ namespace seal
212
212
destination.resize (coeff_count);
213
213
214
214
context_data.rns_tool ()->decrypt_modt (tmp_dest_modq, destination.data (), pool);
215
-
215
+
216
216
// Fix the plaintext after mod-switch operations.
217
217
uint64_t fix = 1 ;
218
218
for (size_t i = context_data.chain_index (); i < first_context_data.chain_index (); i++)
@@ -224,10 +224,10 @@ namespace seal
224
224
{
225
225
multiply_poly_scalar_coeffmod (CoeffIter (destination.data ()), coeff_count, fix, plain_modulus, CoeffIter (destination.data ()));
226
226
}
227
-
227
+
228
228
// How many non-zero coefficients do we really have in the result?
229
229
size_t plain_coeff_count = get_significant_uint64_count_uint (destination.data (), coeff_count);
230
-
230
+
231
231
// Resize destination to appropriate size
232
232
destination.resize (max (plain_coeff_count, size_t (1 )));
233
233
}
@@ -314,39 +314,72 @@ namespace seal
314
314
// Make sure we have enough secret key powers computed
315
315
compute_secret_key_array (encrypted_size - 1 );
316
316
317
- // put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q in destination
318
- // Now do the dot product of encrypted_copy and the secret key array using NTT.
319
- // The secret key powers are already NTT transformed.
320
-
321
- SEAL_ALLOCATE_GET_POLY_ITER (encrypted_copy, encrypted_size - 1 , coeff_count, coeff_modulus_size, pool);
322
- set_poly_array (encrypted.data (1 ), encrypted_size - 1 , coeff_count, coeff_modulus_size, encrypted_copy);
323
-
324
- // Transform c_1, c_2, ... to NTT form unless they already are
325
- if (!is_ntt_form)
317
+ if (encrypted_size == 2 )
326
318
{
327
- ntt_negacyclic_harvey_lazy (encrypted_copy, encrypted_size - 1 , ntt_tables);
328
- }
319
+ ConstRNSIter secret_key_array (secret_key_array_.get (), coeff_count);
320
+ ConstRNSIter c0 (encrypted.data (0 ), coeff_count);
321
+ ConstRNSIter c1 (encrypted.data (1 ), coeff_count);
322
+ if (is_ntt_form)
323
+ {
324
+ SEAL_ITERATE (
325
+ iter (c0, c1, secret_key_array, coeff_modulus, destination), coeff_modulus_size,
326
+ [&](auto I) {
327
+ // put < c_1 * s > mod q in destination
328
+ dyadic_product_coeffmod (get<1 >(I), get<2 >(I), coeff_count, get<3 >(I), get<4 >(I));
329
+ // add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
330
+ add_poly_coeffmod (get<4 >(I), get<0 >(I), coeff_count, get<3 >(I), get<4 >(I));
331
+ });
332
+ }
333
+ else
334
+ {
335
+ SEAL_ITERATE (
336
+ iter (c0, c1, secret_key_array, coeff_modulus, ntt_tables, destination), coeff_modulus_size,
337
+ [&](auto I) {
338
+ set_uint (get<1 >(I), coeff_count, get<5 >(I));
339
+ // Transform c_1 to NTT form
340
+ ntt_negacyclic_harvey_lazy (get<5 >(I), get<4 >(I));
341
+ // put < c_1 * s > mod q in destination
342
+ dyadic_product_coeffmod (get<5 >(I), get<2 >(I), coeff_count, get<3 >(I), get<5 >(I));
343
+ // Transform back
344
+ inverse_ntt_negacyclic_harvey (get<5 >(I), get<4 >(I));
345
+ // add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
346
+ add_poly_coeffmod (get<5 >(I), get<0 >(I), coeff_count, get<3 >(I), get<5 >(I));
347
+ });
348
+ }
349
+ } else {
350
+ // put < (c_1 , c_2, ... , c_{count-1}) , (s,s^2,...,s^{count-1}) > mod q in destination
351
+ // Now do the dot product of encrypted_copy and the secret key array using NTT.
352
+ // The secret key powers are already NTT transformed.
353
+ SEAL_ALLOCATE_GET_POLY_ITER (encrypted_copy, encrypted_size - 1 , coeff_count, coeff_modulus_size, pool);
354
+ set_poly_array (encrypted.data (1 ), encrypted_size - 1 , coeff_count, coeff_modulus_size, encrypted_copy);
355
+
356
+ // Transform c_1, c_2, ... to NTT form unless they already are
357
+ if (!is_ntt_form)
358
+ {
359
+ ntt_negacyclic_harvey_lazy (encrypted_copy, encrypted_size - 1 , ntt_tables);
360
+ }
361
+
362
+ // Compute dyadic product with secret power array
363
+ auto secret_key_array = PolyIter (secret_key_array_.get (), coeff_count, key_coeff_modulus_size);
364
+ SEAL_ITERATE (iter (encrypted_copy, secret_key_array), encrypted_size - 1 , [&](auto I) {
365
+ dyadic_product_coeffmod (get<0 >(I), get<1 >(I), coeff_modulus_size, coeff_modulus, get<0 >(I));
366
+ });
329
367
330
- // Compute dyadic product with secret power array
331
- auto secret_key_array = PolyIter (secret_key_array_. get (), coeff_count, key_coeff_modulus_size );
332
- SEAL_ITERATE (iter ( encrypted_copy, secret_key_array) , encrypted_size - 1 , [&](auto I) {
333
- dyadic_product_coeffmod (get< 0 >(I), get< 1 >(I) , coeff_modulus_size, coeff_modulus, get< 0 >(I) );
334
- });
368
+ // Aggregate all polynomials together to complete the dot product
369
+ set_zero_poly (coeff_count, coeff_modulus_size, destination );
370
+ SEAL_ITERATE (encrypted_copy, encrypted_size - 1 , [&](auto I) {
371
+ add_poly_coeffmod (destination, I , coeff_modulus_size, coeff_modulus, destination );
372
+ });
335
373
336
- // Aggregate all polynomials together to complete the dot product
337
- set_zero_poly (coeff_count, coeff_modulus_size, destination);
338
- SEAL_ITERATE (encrypted_copy, encrypted_size - 1 , [&]( auto I) {
339
- add_poly_coeffmod (destination, I, coeff_modulus_size, coeff_modulus, destination );
340
- });
374
+ if (!is_ntt_form)
375
+ {
376
+ // If the input was not in NTT form, need to transform back
377
+ inverse_ntt_negacyclic_harvey (destination, coeff_modulus_size, ntt_tables );
378
+ }
341
379
342
- if (!is_ntt_form)
343
- {
344
- // If the input was not in NTT form, need to transform back
345
- inverse_ntt_negacyclic_harvey (destination, coeff_modulus_size, ntt_tables);
380
+ // Finally add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
381
+ add_poly_coeffmod (destination, *iter (encrypted), coeff_modulus_size, coeff_modulus, destination);
346
382
}
347
-
348
- // Finally add c_0 to the result; note that destination should be in the same (NTT) form as encrypted
349
- add_poly_coeffmod (destination, *iter (encrypted), coeff_modulus_size, coeff_modulus, destination);
350
383
}
351
384
352
385
int Decryptor::invariant_noise_budget (const Ciphertext &encrypted)
0 commit comments