SEAL
SEAL copied to clipboard
Decryption fails after relinearization (CKKS)
I am using the following SealContext:
seal::EncryptionParameters params(seal::scheme_type::ckks);
size_t poly_modulus_degree = 32768;
params.set_poly_modulus_degree(poly_modulus_degree);
std::vector<int> coefs{ 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 40 };
params.set_coeff_modulus(seal::CoeffModulus::Create(poly_modulus_degree, coefs));
seal::SEALContext context(params);
to compute the following set of operations
float a = -0.119982;
float b = -0.119981;
double scale = pow(2, 30);
seal::Plaintext plain_a, plain_b;
seal::Ciphertext enc_a, enc_b;
seal::CKKSEncoder ckks_encoder(context);
seal::Encryptor ckks_encryptor(context, public_key);
ckks_encoder.encode(a, scale, plain_a);
ckks_encoder.encode(b, scale, plain_b);
ckks_encryptor.encrypt(plain_a, enc_a);
ckks_encryptor.encrypt(plain_b, enc_b);
seal::Evaluator evaluator(context);
evaluator.sub_inplace(enc_a, enc_b);
decrypt_print(enc_a, context, secret_key);
evaluator.multiply_inplace(enc_a, enc_a);
decrypt_print(enc_a, context, secret_key);
seal::RelinKeys relin_keys;
keygen_ckks.create_relin_keys(relin_keys);
evaluator.relinearize_inplace(enc_a, relin_keys);
decrypt_print(enc_a, context, secret_key);
where the decrypt_print
function is defined as
void decrypt_print(seal::Ciphertext& encrypted, seal::SEALContext& context, seal::SecretKey& key) {
seal::Decryptor decryptor(context, key);
seal::Plaintext plain;
decryptor.decrypt(encrypted, plain);
std::vector<double> result;
seal::CKKSEncoder encoder(context);
encoder.decode(plain, result);
std::cout << "decrypted value " << result[0] << std::endl;
}
When I run the operations above, I get the following output:
(after sub_inplace) decrypted value 3.77205e-10
(after multiply in place) decrypted value -1.36176e-16
(after relinearize) decrypted value -6.51654e+115
My question is what could be the reason for the failed decryption after relinearization? The scale is stable across the operations above.
Thank you for any insight or comment.
Have you tried decryption right after encoding and encryption? They should give different values from a
or b
. scale
sets an upper-bound on the amount of precision preserved after the decimal point. When scale == pow(2, 30)
, you cannot preserve more than 3 digits.
thanks @WeiDaiWD yes, indeed the values are slightly different even after decryption. Could you please expand on your last statement, regarding the 3 digits (why only 3 digits)? How could one preserve more digits?
Sorry, my bad, I meant to say 9 digits -- 2^30 is close to 10^9. Anyway, precision preserved after decimal point is upper bounded by scale
; it's always equal to or less than scale
because noise exists in ciphertexts. Increasing scale
is the easiest way to preserve more digits.