From Pytorch Models to SEAL FHE
Wei Ao
Computer Vision over Homomorphically Encrypted Data
CVPR 2025 Tutorial
June 12, 2025
cmake -S . -B build
cmake --build build
sudo cmake --install build
#include "examples.h"
using namespace std;
using namespace seal;
EncryptionParameters parms(scheme_type::ckks);
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 60, 40, 40, 60 }));
double scale = pow(2.0, 40);
SEALContext context(parms);
KeyGenerator keygen(context);
auto secret_key = keygen.secret_key();
PublicKey public_key;
keygen.create_public_key(public_key);
RelinKeys relin_keys;
keygen.create_relin_keys(relin_keys);
GaloisKeys gal_keys;
keygen.create_galois_keys(gal_keys);
Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);
CKKSEncoder encoder(context);
size_t slot_count = encoder.slot_count();
vector< double > input;
Plaintext x_plain;
encoder.encode(input, scale, x_plain);
Ciphertext x1_encrypted;
encryptor.encrypt(x_plain, x1_encrypted);
Plaintext plain_coeff3, plain_coeff1, plain_coeff0;
encoder.encode(3.14159265, scale, plain_coeff3);
encoder.encode(0.4, scale, plain_coeff1);
encoder.encode(1.0, scale, plain_coeff0);
/* compute x^2 */
Ciphertext x3_encrypted;
evaluator.square(x1_encrypted, x3_encrypted);
evaluator.relinearize_inplace(x3_encrypted, relin_keys);
evaluator.rescale_to_next_inplace(x3_encrypted);
/* compute PI*x */
Ciphertext x1_encrypted_coeff3;
evaluator.multiply_plain(x1_encrypted, plain_coeff3, x1_encrypted_coeff3);
evaluator.rescale_to_next_inplace(x1_encrypted_coeff3);
/* compute x^2*(PI*x) */
evaluator.multiply_inplace(x3_encrypted, x1_encrypted_coeff3);
evaluator.relinearize_inplace(x3_encrypted, relin_keys);
evaluator.rescale_to_next_inplace(x3_encrypted);
evaluator.multiply_plain_inplace(x1_encrypted, plain_coeff1);
evaluator.rescale_to_next_inplace(x1_encrypted);
x3_encrypted.scale() = pow(2.0, 40);
x1_encrypted.scale() = pow(2.0, 40);
parms_id_type last_parms_id = x3_encrypted.parms_id();
evaluator.mod_switch_to_inplace(x1_encrypted, last_parms_id);
evaluator.mod_switch_to_inplace(plain_coeff0, last_parms_id);
Ciphertext encrypted_result;
evaluator.add(x3_encrypted, x1_encrypted, encrypted_result);
evaluator.add_plain_inplace(encrypted_result, plain_coeff0);
Plaintext plain_result;
decryptor.decrypt(encrypted_result, plain_result);
vector< double > result;
encoder.decode(plain_result, result);
wget https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz
tar xf gmp-6.2.1.tar.xz
cd gmp-6.2.1
./configure
make
make check
sudo make install
wget https://libntl.org/ntl-11.4.3.tar.gz
tar xf ntl-11.4.3.tar.gz
cd ntl-11.4.3/src
./configure
make
make check
sudo make install
sudo apt-get update
sudo apt-get install libomp-dev
cd cnn_ckks/cpu-ckks/single-key/seal-modified-3.6.6
cmake -S . -B build
cmake --build build
sudo cmake --install build
cd cnn_ckks
cmake -S . -B build
cd build
make
in.open("../../../testFile/test_values.txt");
for(long i=0; i< 1 << logn; i++) image.emplace_back(0);
for(long i=0; i < 32*32*3 *image_id; i++) {in>>val;}
for(long i=0; i < 32*32*3; i++) {in>>val; image[i]=val;} in.close();
for(long i=n/init_p; i < n; i++) image[i] = image[i%(n/init_p)];
cnn = TensorCipher(logn, 1, 32, 32, 3, 3, init_p, image, encryptor, encoder, logq);
multiplexed_parallel_convolution_print(cnn, cnn, co, st, fh, fw, conv_weight[stage], bn_running_var[stage], bn_weight[stage], epsilon, encoder, encryptor, evaluator, gal_keys, cipher_pool, output, decryptor, context, stage);
multiplexed_parallel_batch_norm_seal_print(cnn, cnn, bn_bias[stage], bn_running_mean[stage], bn_running_var[stage], bn_weight[stage], epsilon, encoder, encryptor, evaluator, B, output, decryptor, context, stage);
bootstrap_print(cnn, cnn, bootstrapper, output, decryptor, encoder, context, stage);
approx_ReLU_seal_print(cnn, cnn, comp_no, deg, alpha, tree, scaled_val, logp, encryptor, evaluator, decryptor, encoder, public_key, secret_key, relin_keys, B, output, context, gal_keys, stage);