Skip to content

Commit 427c55f

Browse files
author
Wei Dai
authored
Merge pull request #363 from fboemer/fboemer/faster-decrypt
Fboemer/faster decrypt
2 parents 051ffd3 + 75e0dda commit 427c55f

File tree

3 files changed

+69
-36
lines changed

3 files changed

+69
-36
lines changed

native/src/seal/decryptor.cpp

Lines changed: 66 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ namespace seal
101101
case scheme_type::ckks:
102102
ckks_decrypt(encrypted, destination, pool_);
103103
return;
104-
104+
105105
case scheme_type::bgv:
106106
bgv_decrypt(encrypted, destination, pool_);
107107
return;
108108

109109
default:
110110
throw invalid_argument("unsupported scheme");
111111
}
112-
112+
113113
}
114114

115115
void Decryptor::bfv_decrypt(const Ciphertext &encrypted, Plaintext &destination, MemoryPoolHandle pool)
@@ -212,7 +212,7 @@ namespace seal
212212
destination.resize(coeff_count);
213213

214214
context_data.rns_tool()->decrypt_modt(tmp_dest_modq, destination.data(), pool);
215-
215+
216216
//Fix the plaintext after mod-switch operations.
217217
uint64_t fix = 1;
218218
for(size_t i = context_data.chain_index(); i < first_context_data.chain_index(); i++)
@@ -224,10 +224,10 @@ namespace seal
224224
{
225225
multiply_poly_scalar_coeffmod(CoeffIter(destination.data()), coeff_count, fix, plain_modulus, CoeffIter(destination.data()));
226226
}
227-
227+
228228
// How many non-zero coefficients do we really have in the result?
229229
size_t plain_coeff_count = get_significant_uint64_count_uint(destination.data(), coeff_count);
230-
230+
231231
// Resize destination to appropriate size
232232
destination.resize(max(plain_coeff_count, size_t(1)));
233233
}
@@ -314,39 +314,72 @@ namespace seal
314314
// Make sure we have enough secret key powers computed
315315
compute_secret_key_array(encrypted_size - 1);
316316

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)
326318
{
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+
});
329367

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+
});
335373

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+
}
341379

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);
346382
}
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);
350383
}
351384

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

native/src/seal/evaluator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ namespace seal
617617
encrypted1.scale() = new_scale;
618618
}
619619

620-
void Evaluator::bgv_multiply(Ciphertext &encrypted1, Ciphertext &encrypted2, MemoryPoolHandle pool)
620+
void Evaluator::bgv_multiply(Ciphertext &encrypted1, Ciphertext &encrypted2, MemoryPoolHandle pool) const
621621
{
622622
if (encrypted1.is_ntt_form() || encrypted2.is_ntt_form())
623623
{

native/src/seal/evaluator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ namespace seal
10171017
*/
10181018
inline void rotate_columns_inplace(
10191019
Ciphertext &encrypted, const GaloisKeys &galois_keys, MemoryPoolHandle pool = MemoryManager::GetPool()) const
1020-
{
1020+
{
10211021
auto scheme = context_.key_context_data()->parms().scheme();
10221022
if (scheme != scheme_type::bfv && scheme != scheme_type::bgv)
10231023
{
@@ -1204,7 +1204,7 @@ namespace seal
12041204

12051205
void ckks_multiply(Ciphertext &encrypted1, const Ciphertext &encrypted2, MemoryPoolHandle pool) const;
12061206

1207-
void bgv_multiply(Ciphertext &encrypted1, Ciphertext &encrypted2, MemoryPoolHandle pool);
1207+
void bgv_multiply(Ciphertext &encrypted1, Ciphertext &encrypted2, MemoryPoolHandle pool) const;
12081208

12091209
void bfv_square(Ciphertext &encrypted, MemoryPoolHandle pool) const;
12101210

0 commit comments

Comments
 (0)