Exemple #1
0
// recrypt all ctxt at level < belowLvl
void packedRecrypt(const CtPtrs& array,
                   const std::vector<zzX>& unpackConsts,
                   const EncryptedArray& ea, long belowLvl)
{
  std::vector<Ctxt*> v;
  for (long i=0; i<array.size(); i++)
    if ( array.isSet(i) && !array[i]->isEmpty()
         && array[i]->findBaseLevel()<belowLvl )
      v.push_back(array[i]);
  packedRecrypt(CtPtrs_vectorPt(v), unpackConsts, ea);
}
Exemple #2
0
// Use packed bootstrapping, so we can bootstrap all in just one go.
void packedRecrypt(const CtPtrs& cPtrs,
                   const std::vector<zzX>& unpackConsts,
                   const EncryptedArray& ea)
{
  FHEPubKey& pKey = (FHEPubKey&)cPtrs[0]->getPubKey();

  // Allocate temporary ciphertexts for the recryption
  int nPacked = divc(cPtrs.size(), ea.getDegree()); // ceil(totoalNum/d)
  std::vector<Ctxt> cts(nPacked, Ctxt(pKey));

  repack(CtPtrs_vectorCt(cts), cPtrs, ea);  // pack ciphertexts
  //  cout << "@"<< lsize(cts)<<std::flush;
  for (Ctxt& c: cts) {     // then recrypt them
    c.reducePtxtSpace(2);  // we only have recryption data for binary ctxt
#ifdef DEBUG_PRINTOUT
    ZZX ptxt;
    decryptAndPrint((cout<<"  before recryption "), c, *dbgKey, *dbgEa);
    dbgKey->Decrypt(ptxt, c);
    c.DummyEncrypt(ptxt);
    decryptAndPrint((cout<<"  after recryption "), c, *dbgKey, *dbgEa);
#else
    pKey.reCrypt(c);
#endif
  }
  unpack(cPtrs, CtPtrs_vectorCt(cts), ea, unpackConsts);
}
Exemple #3
0
// For an n-size array, compute the 2^n products
//     products[j] = \prod_{i s.t. j_i=1} array[i]
//                   \times \prod_{i s.t. j_i=0}(a-array[i])
void computeAllProducts(/*Output*/CtPtrs& products,
                        /*Index*/const CtPtrs& array,
                       std::vector<zzX>* unpackSlotEncoding)
{
  FHE_TIMER_START;
  long nBits = array.size();
  if (lsize(products)>0) {
    long nBits2 = NTL::NumBits(lsize(products)-1); // ceil(log_2(size))
    if (nBits>nBits2)
      nBits=nBits2;    // ignore extra bits in 'array'
  }
  if (nBits<1) return; // do nothing
  assert(nBits <= 16); // Output cannot be bigger than 2^16

  if (lsize(products)==0) // try to set the output size
    products.resize(1L << nBits, &array);
  for (long i=0; i<lsize(products); i++)
    products[i]->clear();

  // Check that we have enough levels, try to bootstrap otherwise
  assert(array.ptr2nonNull() != nullptr);
  long bpl = array.ptr2nonNull()->getContext().BPL();
  if (findMinBitCapacity(array) < (NTL::NumBits(nBits)+1)*bpl) {
    const Ctxt* ct = array.ptr2nonNull(); // find some non-null Ctxt
    assert(unpackSlotEncoding!=nullptr);
    assert(ct!=nullptr);
    assert(ct->getPubKey().isBootstrappable());
    packedRecrypt(array, *unpackSlotEncoding,
                  *(ct->getContext().ea), /*belowLevel=*/nBits +3);
  }
  if (findMinBitCapacity(array) < (NTL::NumBits(nBits)+1)*bpl)
    throw std::logic_error("not enough levels for table lookup");

  // Call the recursive function that copmutes the products
  recursiveProducts(products, CtPtrs_slice(array,0,nBits));
}
Exemple #4
0
// A counterpart of tableLookup. The input is an encrypted table T[]
// and an array of encrypted bits I[], holding the binary representation
// of an index i into T.  This function increments by one the entry T[i].
void tableWriteIn(const CtPtrs& table, const CtPtrs& idx,
                  std::vector<zzX>* unpackSlotEncoding)
{
  FHE_TIMER_START;
  const Ctxt* ct = table.ptr2nonNull(); // find some non-null Ctxt
  long size = lsize(table);
  if (size==0) return;
  std::vector<Ctxt> products(size, Ctxt(ZeroCtxtLike, *ct));  
  CtPtrs_vectorCt pWrap(products); // A wrapper

  // Compute all products of ecnrypted bits =: b_i
  computeAllProducts(pWrap, idx, unpackSlotEncoding);

  // incrememnt each entry of T[i] by products[i]
  NTL_EXEC_RANGE(lsize(table), first, last)
  for(long i=first; i<last; i++)
    *table[i] += products[i];
  NTL_EXEC_RANGE_END
}