// Constructor Ctxt::Ctxt(const FHEPubKey& newPubKey, long newPtxtSpace): context(newPubKey.getContext()), pubKey(newPubKey), ptxtSpace(newPtxtSpace), noiseVar(to_xdouble(0.0)) { if (ptxtSpace<=0) ptxtSpace = pubKey.getPtxtSpace(); else assert (GCD(ptxtSpace, pubKey.getPtxtSpace()) > 1); // sanity check primeSet=context.ctxtPrimes; }
// Constructor Ctxt::Ctxt(const FHEPubKey& newPubKey, long newPtxtSpace): context(newPubKey.getContext()), pubKey(newPubKey), ptxtSpace(newPtxtSpace), noiseVar(to_xdouble(0.0)) { if (ptxtSpace != pubKey.getPtxtSpace()) { // plaintext-space mistamtch ptxtSpace = GCD(ptxtSpace, pubKey.getPtxtSpace()); if (ptxtSpace <= 1) Error("Plaintext-space mismatch Ctxt constructor"); } primeSet=context.ctxtPrimes; }
// Compute the number of digits that we need and the esitmated // added noise from switching this ciphertext part. static std::pair<long, NTL::xdouble> keySwitchNoise(const CtxtPart& p, const FHEPubKey& pubKey, long pSpace) { const FHEcontext& context = p.getContext(); long nDigits = 0; xdouble addedNoise = to_xdouble(0.0); double sizeLeft = context.logOfProduct(p.getIndexSet()); for (size_t i=0; i<context.digits.size() && sizeLeft>0.0; i++) { nDigits++; double digitSize = context.logOfProduct(context.digits[i]); if (sizeLeft<digitSize) digitSize=sizeLeft;// need only part of this digit // Added noise due to this digit is phi(m) *sigma^2 *pSpace^2 *|Di|^2/4, // where |Di| is the magnitude of the digit // WARNING: the following line is written just so to prevent overflow addedNoise += to_xdouble(context.zMStar.getPhiM()) * pSpace*pSpace * xexp(2*digitSize) * context.stdev*context.stdev / 4.0; sizeLeft -= digitSize; } // Sanity-check: make sure that the added noise is not more than the special // primes can handle: After dividing the added noise by the product of all // the special primes, it should be smaller than the added noise term due // to modulus switching, i.e., keyWeight * phi(m) * pSpace^2 / 12 long keyWeight = pubKey.getSKeyWeight(p.skHandle.getSecretKeyID()); double phim = context.zMStar.getPhiM(); double logModSwitchNoise = log((double)keyWeight) +2*log((double)pSpace) +log(phim) -log(12.0); double logKeySwitchNoise = log(addedNoise) -2*context.logOfProduct(context.specialPrimes); assert(logKeySwitchNoise < logModSwitchNoise); return std::pair<long, NTL::xdouble>(nDigits,addedNoise); }
void TestIt(long idx, long p, long r, long L, long c, long skHwt, int build_cache=0) { Vec<long> mvec; vector<long> gens; vector<long> ords; long phim = mValues[idx][1]; long m = mValues[idx][2]; assert(GCD(p, m) == 1); append(mvec, mValues[idx][4]); if (mValues[idx][5]>1) append(mvec, mValues[idx][5]); if (mValues[idx][6]>1) append(mvec, mValues[idx][6]); gens.push_back(mValues[idx][7]); if (mValues[idx][8]>1) gens.push_back(mValues[idx][8]); if (mValues[idx][9]>1) gens.push_back(mValues[idx][9]); ords.push_back(mValues[idx][10]); if (abs(mValues[idx][11])>1) ords.push_back(mValues[idx][11]); if (abs(mValues[idx][12])>1) ords.push_back(mValues[idx][12]); if (!noPrint) { cout << "*** TestIt"; if (isDryRun()) cout << " (dry run)"; cout << ": p=" << p << ", r=" << r << ", L=" << L << ", t=" << skHwt << ", c=" << c << ", m=" << m << " (=" << mvec << "), gens="<<gens<<", ords="<<ords << endl; cout << "Computing key-independent tables..." << std::flush; } setTimersOn(); setDryRun(false); // Need to get a "real context" to test bootstrapping double t = -GetTime(); FHEcontext context(m, p, r, gens, ords); if (scale) { context.scale = scale; } context.zMStar.set_cM(mValues[idx][13]/100.0); buildModChain(context, L, c, /*willBeBootstrappable=*/true); if (!noPrint) { std::cout << "security=" << context.securityLevel()<<endl; std::cout << "# small primes = " << context.smallPrimes.card() << "\n"; std::cout << "# ctxt primes = " << context.ctxtPrimes.card() << "\n"; std::cout << "# bits in ctxt primes = " << long(context.logOfProduct(context.ctxtPrimes)/log(2.0) + 0.5) << "\n"; std::cout << "# special primes = " << context.specialPrimes.card() << "\n"; std::cout << "# bits in special primes = " << long(context.logOfProduct(context.specialPrimes)/log(2.0) + 0.5) << "\n"; std::cout << "scale=" << context.scale<<endl; } context.makeBootstrappable(mvec,/*t=*/skHwt,build_cache,/*alsoThick=*/false); // save time...disable some fat boot precomputation t += GetTime(); //if (skHwt>0) context.rcData.skHwt = skHwt; if (!noPrint) { cout << " done in "<<t<<" seconds\n"; cout << " e=" << context.rcData.e << ", e'=" << context.rcData.ePrime << ", a="<< context.rcData.a << ", t=" << context.rcData.skHwt << "\n "; context.zMStar.printout(); } setDryRun(dry); // Now we can set the dry-run flag if desired long p2r = context.alMod.getPPowR(); for (long numkey=0; numkey<OUTER_REP; numkey++) { // test with 3 keys t = -GetTime(); if (!noPrint) cout << "Generating keys, " << std::flush; FHESecKey secretKey(context); secretKey.GenSecKey(64); // A Hamming-weight-64 secret key addSome1DMatrices(secretKey); // compute key-switching matrices that we need addFrbMatrices(secretKey); if (!noPrint) cout << "computing key-dependent tables..." << std::flush; secretKey.genRecryptData(); t += GetTime(); if (!noPrint) cout << " done in "<<t<<" seconds\n"; FHEPubKey publicKey = secretKey; long d = context.zMStar.getOrdP(); long phim = context.zMStar.getPhiM(); long nslots = phim/d; // GG defines the plaintext space Z_p[X]/GG(X) ZZX GG; GG = context.alMod.getFactorsOverZZ()[0]; EncryptedArray ea(context, GG); if (debug) { dbgKey = &secretKey; dbgEa = &ea; } zz_p::init(p2r); Vec<zz_p> val0(INIT_SIZE, nslots); for (auto& x: val0) random(x); vector<ZZX> val1; val1.resize(nslots); for (long i = 0; i < nslots; i++) { val1[i] = conv<ZZX>(conv<ZZ>(rep(val0[i]))); } vector<ZZX> val_const1; val_const1.resize(nslots); for (long i = 0; i < nslots; i++) { val_const1[i] = 1; } Ctxt c1(publicKey); ea.encrypt(c1, publicKey, val1); Ctxt c2(c1); if (!noPrint) CheckCtxt(c2, "before recryption"); publicKey.thinReCrypt(c2); if (!noPrint) CheckCtxt(c2, "after recryption"); vector<ZZX> val2; ea.decrypt(c2, secretKey, val2); if (val1 == val2) cout << "GOOD\n"; else cout << "BAD\n"; } }