SEAL icon indicating copy to clipboard operation
SEAL copied to clipboard

Decryption fails after relinearization (CKKS)

Open andreea-anghel opened this issue 2 years ago • 3 comments

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.

andreea-anghel avatar Sep 27 '22 07:09 andreea-anghel

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.

WeiDaiWD avatar Sep 27 '22 23:09 WeiDaiWD

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?

andreea-anghel avatar Sep 29 '22 08:09 andreea-anghel

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.

WeiDaiWD avatar Oct 06 '22 18:10 WeiDaiWD