From Pytorch Models to SEAL FHE


Wei Ao

Computer Vision over Homomorphically Encrypted Data

CVPR 2025 Tutorial

June 12, 2025

from PyTorch to SEAL

Microsoft SEAL

easy-to-use open-source C++ homomorphic encryption library

Installing Microsoft SEAL


SEAL Basics


SEAL Basics


    • CKKS Parameters
    •                 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);
       

SEAL Basics


    • Generate Keys
    •                 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);
       

SEAL Basics


    • Operators
    •                 Encryptor encryptor(context, public_key);
      Evaluator evaluator(context);
      Decryptor decryptor(context, secret_key);
      CKKSEncoder encoder(context);
      size_t slot_count = encoder.slot_count();
       

SEAL Basics


    • Encrypt Vectors
    •                 vector< double > input;
      Plaintext x_plain;
      encoder.encode(input, scale, x_plain);
      Ciphertext x1_encrypted;
      encryptor.encrypt(x_plain, x1_encrypted);
       

SEAL Basics


    • Encode Coefficients
    •                 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);
       

SEAL Basics


    • Compute PI*x^3=x^2*(PI*x)
    •                 /* 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);
       

SEAL Basics


    • Compute 0.4*x
    •                 evaluator.multiply_plain_inplace(x1_encrypted, plain_coeff1);
      evaluator.rescale_to_next_inplace(x1_encrypted);
       

SEAL Basics


    • Compute PI*x^3 + 0.4*x
    •                 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);
       

SEAL Basics


    • Decrypt result
    •                 Plaintext plain_result;
      decryptor.decrypt(encrypted_result, plain_result);
      vector< double > result;
      encoder.decode(plain_result, result);
       

Encrypted CNNs with SEAL

ResNets with FHE

MPCNN: Multiplexed Parallel Convolution with FHE


    • Download MPCNN https://github.com/snu-ccl/FHE-MP-CNN
    • Install GMP
    •                     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  

MPCNN: Multiplexed Parallel Convolution with FHE


    • Install NTL
    •                     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
                          
    • Install OpenMP
    •                     sudo apt-get update
      sudo apt-get install libomp-dev 

MPCNN: Multiplexed Parallel Convolution with FHE


    • Compile SEAL with Bootstrapping
    •                     cd cnn_ckks/cpu-ckks/single-key/seal-modified-3.6.6
      cmake -S . -B build
      cmake --build build
      sudo cmake --install build
                          
    • Compile MPCNN
    •                     cd cnn_ckks
      cmake -S . -B build
      cd build
      make 

MPCNN: Multiplexed Parallel Convolution with FHE


    • Encrypt Images infer_seal.cpp
    •                     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);
       
    • MPCNN Layers infer_seal.cpp
    •                     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);
      
                          

Convolutional Neural Networks on SEAL

Demo of CNNs on SEAL


    • Implementation of ResNets (high-degree and mixed-degree) on SEAL