diff --git a/CHANGES.md b/CHANGES.md index efa43a9d9..7de01b1bf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,10 @@ ## Version 3.5.0 +### Hotfix - 4/30/2020 + +- Fixed a critical bug [(Issue 166)](https://github.com/microsoft/SEAL/issues/166) in `Evaluator::multiply_plain_inplace`. Thanks s0l0ist! + ### Hotfix - 4/29/2020 - Switched to using Microsoft GSL v3.0.1 and fixed minor GSL related issues in `CMakeLists.txt`. diff --git a/native/tests/seal/evaluator.cpp b/native/tests/seal/evaluator.cpp index a5f291877..4e1202c3e 100644 --- a/native/tests/seal/evaluator.cpp +++ b/native/tests/seal/evaluator.cpp @@ -991,6 +991,76 @@ namespace sealtest ASSERT_EQ(static_cast(0x5B05B058), encoder.decode_uint64(plain)); ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(PlainModulus::Batching(64, 20)); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + BatchEncoder batch_encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + vector result; + + batch_encoder.encode(vector(batch_encoder.slot_count(), 7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + batch_encoder.encode(vector(batch_encoder.slot_count(), -7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } + { + EncryptionParameters parms(scheme_type::BFV); + Modulus plain_modulus(PlainModulus::Batching(64, 40)); + parms.set_poly_modulus_degree(64); + parms.set_plain_modulus(plain_modulus); + parms.set_coeff_modulus(CoeffModulus::Create(64, { 30, 30, 30 })); + + auto context = SEALContext::Create(parms, false, sec_level_type::none); + KeyGenerator keygen(context); + + BatchEncoder batch_encoder(context); + Encryptor encryptor(context, keygen.public_key()); + Evaluator evaluator(context); + Decryptor decryptor(context, keygen.secret_key()); + + Ciphertext encrypted; + Plaintext plain; + vector result; + + batch_encoder.encode(vector(batch_encoder.slot_count(), 7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + + batch_encoder.encode(vector(batch_encoder.slot_count(), -7), plain); + encryptor.encrypt(plain, encrypted); + evaluator.multiply_plain_inplace(encrypted, plain); + decryptor.decrypt(encrypted, plain); + batch_encoder.decode(plain, result); + ASSERT_TRUE(vector(batch_encoder.slot_count(), 49) == result); + ASSERT_TRUE(encrypted.parms_id() == context->first_parms_id()); + } } TEST(EvaluatorTest, BFVEncryptMultiplyDecrypt)