microsoft / SEAL

Microsoft SEAL is an easy-to-use and powerful homomorphic encryption library.
https://www.microsoft.com/en-us/research/group/cryptography-research/
MIT License
3.62k stars 709 forks source link

Evaluator error when works with Ciphertext in vectors #678

Closed marvellous987 closed 10 months ago

marvellous987 commented 10 months ago

Hi all,

I encounter the following error, and may I ask for any help/suggestions about this.

First, I tried to generate a series of plaintext and ciphertext and store into a vector, under the BFV scheme.

...
vector<Ciphertext> matrixA(4*t);
for (int i = 0; i < 4*t; i++) {
    Plaintext temp_plain(uint64_to_hex_string(temp));
    Ciphertext temp_encrypted;
    encryptor.encrypt(temp_plain, temp_encrypted);
    matrixA.push_back(temp_encrypted);
}

vector<Ciphertext> matrixB(4*t);
for (int i = 0; i < 4*t; i++) {
    Plaintext temp_plain(uint64_to_hex_string(temp));
    Ciphertext temp_encrypted;
    encryptor.encrypt(temp_plain, temp_encrypted);
    matrixB.push_back(temp_encrypted);
}

Afterwards, I use the evaluator doing substraction:

vector<Ciphertext> matrixC(4*t);
    for (int i = 0; i < 4*t; i++) {
        Ciphertext temp_subtracted;
        evaluator.sub(matrixA[i], matrixB[i], temp_subtracted);
        matrixC.push_back(temp_subtracted);
    }

And then I received the following error:

libc++abi.dylib: terminating with uncaught exception of type std::invalid_argument: encrypted1 is not valid for encryption parameters

which should be come from the function evaluator.sub(..., ..., ...).

Then, I dive into the library and found out that is_metadata_valid_for() return false in the parameter check, and the 4 entries of the parms_id array are all 0 instead of some non-zero values.

I test with the following case (no vectors involved), which works well and no error:

... (initialize temp)
Plaintext temp_plain(uint64_to_hex_string(temp));
Ciphertext temp_encrypted;
encryptor.encrypt(temp_plain, temp_encrypted);

... (initialize tempB)
Plaintext tempB_plain(uint64_to_hex_string(tempB));
Ciphertext tempB_encrypted;
encryptor.encrypt(tempB_plain, tempB_encrypted);

Ciphertext temp_subtracted;
evaluator.sub(temp_encrypted, tempB_encrypted, temp_subtracted);

May I ask for any help/suggestions? Thank you very much!

kimlaine commented 10 months ago

You have a mistake in how you are using std::vector. Namely, the constructor you are using initializes your vector with 4*t empty ciphertexts, but this isn't what you are hoping to do, because now you're appending to that with std::vector<T>::push_back, so you end up calling Evaluator::sub on empty ciphertexts. Hence, it complains the parameters are not valid for this operation.

Instead, for each of the three matrices, use:

vector<Ciphertext> matrix;
matrix.reserve(4*t);