// The main method void ThinRecryptData::init(const FHEcontext& context, const Vec<long>& mvec_, long t, bool consFlag, bool build_cache_, bool minimal) { if (alMod != NULL) { // were we called for a second time? cerr << "@Warning: multiple calls to ThinRecryptData::init\n"; return; } assert(computeProd(mvec_) == (long)context.zMStar.getM()); // sanity check // Record the arguments to this function mvec = mvec_; conservative = consFlag; build_cache = build_cache_; if (t <= 0) t = defSkHwt+1; // recryption key Hwt hwt = t; long p = context.zMStar.getP(); long phim = context.zMStar.getPhiM(); long r = context.alMod.getR(); long p2r = context.alMod.getPPowR(); double logp = log((double)p); double noise = p2r * sqrt((t+1)*phim/3.0); double gamma = 2*(t+noise)/((t+1)*p2r); // ratio between numerators long logT = ceil(log((double)(t+2))/logp); // ceil(log_p(t+2)) double rho = (t+1)/pow(p,logT); if (!conservative) { // try alpha, e with this "aggresive" setting setAlphaE(alpha, e, rho, gamma, noise, logp, p2r, t); ePrime = e -r +1 -logT; // If e is too large, try again with rho/p instead of rho long bound = (1L << (context.bitsPerLevel-1)); // halfSizePrime/2 if (pow(p,e) > bound) { // try the conservative setting instead cerr << "* p^e="<<pow(p,e)<<" is too big (bound="<<bound<<")\n"; conservative = true; } } if (conservative) { // set alpha, e with a "conservative" rho/p setAlphaE(alpha, e, rho/p, gamma, noise, logp, p2r, t); ePrime = e -r -logT; } // Compute highest key-Hamming-weight that still works (not more than 256) double qOver4 = (pow(p,e)+1)/4; for (t-=10; qOver4>=lowerBound2(p,r,ePrime,t,alpha) && qOver4>=lowerBound1(p,r,ePrime,t,alpha,noise) && t<257; t++); skHwt = t-1; // First part of Bootstrapping works wrt plaintext space p^{r'} alMod = new PAlgebraMod(context.zMStar, e-ePrime+r); ea = new EncryptedArray(context, *alMod); // Polynomial defaults to F0, PAlgebraMod explicitly given coeffToSlot = new ThinEvalMap(*ea, minimal, mvec, true, build_cache); slotToCoeff = new ThinEvalMap(*context.ea, minimal, mvec, false, build_cache); }
// The main method void RecryptData::init(const FHEcontext& context, const Vec<long>& mvec_, long t, bool consFlag, bool build_cache_, bool minimal) { if (alMod != NULL) { // were we called for a second time? cerr << "@Warning: multiple calls to RecryptData::init\n"; return; } assert(computeProd(mvec_) == (long)context.zMStar.getM()); // sanity check // Record the arguments to this function mvec = mvec_; conservative = consFlag; build_cache = build_cache_; if (t <= 0) t = defSkHwt+1; // recryption key Hwt hwt = t; long p = context.zMStar.getP(); long phim = context.zMStar.getPhiM(); long r = context.alMod.getR(); long p2r = context.alMod.getPPowR(); double logp = log((double)p); double noise = p2r * sqrt((t+1)*phim/3.0); double gamma = 2*(t+noise)/((t+1)*p2r); // ratio between numerators long logT = ceil(log((double)(t+2))/logp); // ceil(log_p(t+2)) double rho = (t+1)/pow(p,logT); if (!conservative) { // try alpha, e with this "aggresive" setting setAlphaE(alpha, e, rho, gamma, noise, logp, p2r, t); ePrime = e -r +1 -logT; // If e is too large, try again with rho/p instead of rho long bound = (1L << (context.bitsPerLevel-1)); // halfSizePrime/2 if (pow(p,e) > bound) { // try the conservative setting instead cerr << "* p^e="<<pow(p,e)<<" is too big (bound="<<bound<<")\n"; conservative = true; } } if (conservative) { // set alpha, e with a "conservative" rho/p setAlphaE(alpha, e, rho/p, gamma, noise, logp, p2r, t); ePrime = e -r -logT; } // Compute highest key-Hamming-weight that still works (not more than 256) double qOver4 = (pow(p,e)+1)/4; for (t-=10; qOver4>=lowerBound2(p,r,ePrime,t,alpha) && qOver4>=lowerBound1(p,r,ePrime,t,alpha,noise) && t<257; t++); skHwt = t-1; // First part of Bootstrapping works wrt plaintext space p^{r'} alMod = new PAlgebraMod(context.zMStar, e-ePrime+r); ea = new EncryptedArray(context, *alMod); // Polynomial defaults to F0, PAlgebraMod explicitly given p2dConv = new PowerfulDCRT(context, mvec); // Initialize the linear polynomial for unpacking the slots zz_pBak bak; bak.save(); ea->getAlMod().restoreContext(); long nslots = ea->size(); long d = ea->getDegree(); const Mat<zz_p>& CBi=ea->getDerived(PA_zz_p()).getNormalBasisMatrixInverse(); vector<ZZX> LM; LM.resize(d); for (long i = 0; i < d; i++) // prepare the linear polynomial LM[i] = rep(CBi[i][0]); vector<ZZX> C; ea->buildLinPolyCoeffs(C, LM); // "build" the linear polynomial unpackSlotEncoding.resize(d); // encode the coefficients for (long j = 0; j < d; j++) { vector<ZZX> v(nslots); for (long k = 0; k < nslots; k++) v[k] = C[j]; ea->encode(unpackSlotEncoding[j], v); } firstMap = new EvalMap(*ea, minimal, mvec, true, build_cache); secondMap = new EvalMap(*context.ea, minimal, mvec, false, build_cache); }