SEAL icon indicating copy to clipboard operation
SEAL copied to clipboard

BFV Encrypting immediately to a lower level modulus

Open abeams opened this issue 4 years ago • 4 comments

Would it be feasible to encrypt a plaintext directly into a lower context data? This would be beneficial in combination with the seeded symmetric encryption, which to my understanding is not possible right now.

abeams avatar Nov 19 '21 01:11 abeams

  • How about call the encrypt (encrypt_symmetric) then drop the modulus.
  • For seeded ciphertext, it might be also work because the seed is used to generate each RNS component in modulus-first order.

fionser avatar Nov 19 '21 04:11 fionser

I don't think this works... Here is a sample program. The output is:

Degree: 8192 Plain Modulus: 1032193 Parameter validation: valid Key Switching enabled: true Batching enabled: true Encrypting 6 as 0x6 0x6 ...... Correct. Size of original seeded ciphertext: 216367 Size of mod switched seeded ciphertext: 323749 Size of original public key ciphertext: 432519 Size of mod switched public key ciphertext: 323809

Note that the size of the mod switched seeded ciphertext is larger than that of the original seeded.

#include "seal/seal.h"
#include <iostream>
#include <sstream>

using namespace std;
using namespace seal;

std::string uint64_to_hex_string(std::uint64_t value)
{
    return seal::util::uint_to_hex_string(&value, std::size_t(1));
}

int main(int argc, char *argv[]){

    srand (time(NULL));

    uint32_t N = 8192;
    uint32_t logt = 20;

    //Initialize parameters
    EncryptionParameters params(scheme_type::bfv);
    params.set_poly_modulus_degree(N);
    params.set_coeff_modulus(CoeffModulus::BFVDefault(N));
    params.set_plain_modulus(PlainModulus::Batching(N, logt));

    uint64_t plain_modulus = params.plain_modulus().value();

    cout << "Degree: "  << N << endl;
    cout << "Plain Modulus: " << plain_modulus << endl;

    //Initialize context
    SEALContext context(params, true);
    cout << "Parameter validation: " << context.parameter_error_message() << endl;
    cout << "Key Switching enabled: " << boolalpha << context.using_keyswitching() << endl;
    cout << "Batching enabled: " << boolalpha << context.first_context_data()->qualifiers().using_batching << endl;

    //Initialize keys
    KeyGenerator keygen(context);
    PublicKey public_key;
    keygen.create_public_key(public_key);
    SecretKey secret_key = keygen.secret_key();

    //Initialize enc/eval/dec
    Encryptor encryptor(context, public_key);
    encryptor.set_secret_key(secret_key);
    Evaluator evaluator(context);
    Decryptor decryptor(context, secret_key);

    stringstream data_stream;

    uint64_t x = 6;
    Plaintext pt(uint64_to_hex_string(x));
    cout << "Encrypting " << x << " as 0x" << pt.to_string() << endl;

    Ciphertext ct;
    Ciphertext ct2;
    encryptor.encrypt_symmetric(pt, ct);
    encryptor.encrypt(pt, ct2);
    uint64_t size1 = encryptor.encrypt_symmetric(pt).save(data_stream);
    uint64_t size3 = encryptor.encrypt(pt).save(data_stream);


    evaluator.mod_switch_to_next_inplace(ct);
    evaluator.mod_switch_to_next_inplace(ct2);
    uint64_t size2 = ct.save(data_stream);
    uint64_t size4 = ct2.save(data_stream);

    Plaintext decrypted;
    decryptor.decrypt(ct, decrypted);
    cout << "0x" << decrypted.to_string() << " ...... Correct." << endl;

    cout << "Size of original seeded ciphertext: " << size1 << endl;
    cout << "Size of mod switched seeded ciphertext: " << size2 << endl;
    cout << "Size of original public key ciphertext: " << size3 << endl;
    cout << "Size of mod switched public key ciphertext: " << size4 << endl;

    return 0;
}

abeams avatar Nov 19 '21 17:11 abeams

Good suggestion! I will add these new APIs to Encryptor in a future release. Let's keep the issue open until then.

At the moment, it has to be done in a hacky way. If you have an urgent need of this, please let me know, I might be able to (with 80% confidence) write a temporary workaround for you.

WeiDaiWD avatar Nov 19 '21 20:11 WeiDaiWD

@abeams A quick solution is to re-use the underlying api

https://github.com/microsoft/SEAL/blob/main/native/src/seal/util/rlwe.cpp#L262

fionser avatar Nov 22 '21 01:11 fionser