2

I hope someone can help me understand an error I get when using Palisades. I want to only use the first 329 slots of a BGV ciphertext, and zero out the rest (which at some point contains some 'rubbish' I don't want to re-enter the first 329 slots when doing rotations). So I have created a Plaintext called mask that I fill with 1's in the first 329 slots, which I multiply on a ciphertext to zero out everything outside these slots. The complete code generating the error is here:

#include <fstream>
#include <iostream>
#include <iterator>
#include <random>

#include "palisade.h"

using namespace std;
using namespace lbcrypto;

Plaintext mask;
CryptoContext<DCRTPoly> cryptoContext;

Ciphertext<DCRTPoly> RotateLeft(Ciphertext<DCRTPoly> ct, int r, int ll){
  /* Rotates the ciphertext ct of length ll with r positions to the right. */
  Ciphertext<DCRTPoly> res, shiftR, shiftL;

  shiftL=cryptoContext->EvalAtIndex(ct, r);
  shiftR=cryptoContext->EvalAtIndex(ct, r-ll);
 
  res=cryptoContext->EvalAdd(shiftR, shiftL);
  res=cryptoContext->EvalMult(res,mask);

  return res;
}

int main(){
  usint plaintextModulus = 65537;
  float sigma = 3.2;
  SecurityLevel securityLevel = HEStd_128_classic;
  uint32_t depth = 6;


  ////////////////////////////////////////////////////////////
  // Parameter generation
  ////////////////////////////////////////////////////////////

  cryptoContext = CryptoContextFactory<DCRTPoly>::genCryptoContextBGVrns(
                               depth,
                               plaintextModulus,
                               securityLevel,
                               sigma,
                               2,
                               OPTIMIZED,
                               BV,
                               0,
                               0,
                               0,
                               0,
                               0,
                               0,
                               AUTO);
                                                 

  // enable features that you wish to use
  cryptoContext->Enable(ENCRYPTION);
  cryptoContext->Enable(SHE);
  cryptoContext->Enable(LEVELEDSHE);
  
  LPKeyPair<DCRTPoly> keyPair;
  
  // Perform Key Generation Operation
  keyPair = cryptoContext->KeyGen();

  if (!keyPair.good()) {
    std::cout << "Key generation failed!" << std::endl;
    exit(1);
  }
  //Keys for multiplication
  cryptoContext->EvalMultKeysGen(keyPair.secretKey);
  //Keys for rotations
  cryptoContext->EvalAtIndexKeyGen(keyPair.secretKey,{1,2,3,-326,-327,-328});
                                           
  vector<int64_t> vecMask;
  for(int i=0; i<329; ++i)
    vecMask.push_back(1);
  mask = cryptoContext->MakePackedPlaintext(vecMask);

  std::vector<int64_t> vectorOfBits1;
  for(int64_t i=0; i<329; ++i)
    vectorOfBits1.push_back((i/2)%2);
  Plaintext p1 = cryptoContext->MakePackedPlaintext(vectorOfBits1);

  Ciphertext<DCRTPoly> c1=cryptoContext->Encrypt(keyPair.publicKey, p1);

  Ciphertext<DCRTPoly> r1=RotateLeft(c1,1,329);
  Ciphertext<DCRTPoly> r2=RotateLeft(c1,2,329);
  Ciphertext<DCRTPoly> chi_res=cryptoContext->EvalMult(r1,r2);

  chi_res=cryptoContext->EvalAdd(chi_res,c1);
}

This results in the error

tower size mismatch; cannot add

If the masking is commented out, everything works fine except c1 will contain the rubbish I want removed. How should I do the masking correctly?

IanQ
  • 1,831
  • 5
  • 20
  • 29

1 Answers1

2

It would be helpful to see a more complete code example, including the cryptocontext generation. I will assume you are using BGVrns, rather than BGV in PALISADE before 1.11. If not, I certainly suggest using BGVrns for efficiency.

BGVrns has two modulus switching modes: MANUAL and AUTO. In the MANUAL mode, the user has to call ModReduce() after each multiplication, while in the AUTO mode the modulus switching is done automatically. Based on the error you are describing, you are probably using the MANUAL mode and not calling ModReduce() after that.

To answer your question more definitively, I would like to see the cryptocontext generation and all prior operations for both C1 and the other ciphertext you are trying to add. Thank you.

  • Thanks for reply. Indeed, I am using BGVrns, but the cryptoContext is generated with AUTO. Edited post to include complete code generating the error. Again, appreciate more help. – Håvard Raddum May 13 '21 at 07:14
  • I copied your code and created an example in the master branch of https://gitlab.com/palisade/palisade-development (v1.11.1). The code runs for me without any exceptions. What version/commit of PALISADE are you using? It seems that the issue might be specific to that version. – Yuriy Polyakov May 13 '21 at 16:20
  • Another unrelated comment. Using BV key switching and rotations at the very beginning may significantly increase the noise (you have to be careful). To avoid any noise potential issues, I recommend using the HYBRID key switching while developing the fully functional initial capability. You might want to consider performance tradeoffs between BV and HYBRID later (at the optimization stage). Also, depth = 6 seems to be an overkill unless you are planning to do more computations before decryption. Just wanted to mention these points. – Yuriy Polyakov May 13 '21 at 16:25
  • Thanks for help, Yuriy. I downloaded v1.10.6, since it was the latest one denoted "stable". Will install v1.11.1 instead then. And thanks for tip about HYBRID, will use that. Depth=6 will be correct for the full application I intend to make. – Håvard Raddum May 13 '21 at 18:05
  • 1
    I was able to recreate this error v1.10.6. But this bug was fixed in v1.11. – Yuriy Polyakov May 17 '21 at 18:15