void TestIt(long c, long k, long w, long L, long m, long n) { FHEcontext context(m, 2, 1); // p = 2, r = 1 long d = context.zMStar.getOrdP(); buildModChain(context, L, c); context.zMStar.printout(); cerr << endl; #ifdef DEBUG cerr << context << endl; #endif FHESecKey secretKey(context); const FHEPubKey& publicKey = secretKey; secretKey.GenSecKey(w); // A Hamming-weight-w secret key ZZX G; G = makeIrredPoly(2, d); // G = context.alMod.getFactorsOverZZ()[0]; cerr << "generating key-switching matrices... "; addFrbMatrices(secretKey); addSome1DMatrices(secretKey); cerr << "done\n"; cerr << "computing masks and tables for rotation..."; EncryptedArray ea(context, G); cerr << "done\n"; long nslots = ea.size(); if (n <= 0 || n > d) n = d; vector<ZZX> v; v.resize(nslots); for (long i = 0; i < nslots; i++) { GF2X f; random(f, n); conv(v[i], f); } printBits(v, n); Ctxt ctxt(publicKey); ea.encrypt(ctxt, publicKey, v); // ctxt encrypts a vector where each slots is a random // polynomial of degree < n Ctxt* res[n]; for (long j = 0; j < n; j++) res[j] = new Ctxt(publicKey); // allocate resetAllTimers(); incrementalZeroTest(res, ea, ctxt, n); for (long j = 0; j < n; j++) { vector<ZZX> v1; ea.decrypt(*res[j], secretKey, v1); printBits(v1, n); } for (long j = 0; j < n; j++) delete res[j]; // cleanup }
void TestIt(long p, long r, long c, long _k, long w, long L, Vec<long>& mvec, Vec<long>& gens, Vec<long>& ords, long useCache) { if (lsize(mvec)<1) { // use default values mvec.SetLength(3); gens.SetLength(3); ords.SetLength(3); mvec[0] = 7; mvec[1] = 3; mvec[2] = 221; gens[0] = 3979; gens[1] = 3095; gens[2] = 3760; ords[0] = 6; ords[1] = 2; ords[2] = -8; } if (!noPrint) cout << "*** TestIt" << (dry? " (dry run):" : ":") << " p=" << p << ", r=" << r << ", c=" << c << ", k=" << _k << ", w=" << w << ", L=" << L << ", mvec=" << mvec << ", " << ", useCache = " << useCache << endl; setTimersOn(); setDryRun(false); // Need to get a "real context" to test ThinEvalMap // mvec is supposed to include the prime-power factorization of m long nfactors = mvec.length(); for (long i = 0; i < nfactors; i++) for (long j = i+1; j < nfactors; j++) assert(GCD(mvec[i], mvec[j]) == 1); // multiply all the prime powers to get m itself long m = computeProd(mvec); assert(GCD(p, m) == 1); // build a context with these generators and orders vector<long> gens1, ords1; convert(gens1, gens); convert(ords1, ords); FHEcontext context(m, p, r, gens1, ords1); buildModChain(context, L, c); if (!noPrint) { context.zMStar.printout(); // print structure of Zm* /(p) to cout cout << endl; } long d = context.zMStar.getOrdP(); long phim = context.zMStar.getPhiM(); long nslots = phim/d; setDryRun(dry); // Now we can set the dry-run flag if desired FHESecKey secretKey(context); const FHEPubKey& publicKey = secretKey; secretKey.GenSecKey(w); // A Hamming-weight-w secret key addSome1DMatrices(secretKey); // compute key-switching matrices that we need addFrbMatrices(secretKey); // compute key-switching matrices that we need // GG defines the plaintext space Z_p[X]/GG(X) ZZX GG; GG = context.alMod.getFactorsOverZZ()[0]; EncryptedArray ea(context, GG); zz_p::init(context.alMod.getPPowR()); 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]))); } Ctxt ctxt(publicKey); ea.encrypt(ctxt, publicKey, val1); resetAllTimers(); FHE_NTIMER_START(ALL); // Compute homomorphically the transformation that takes the // coefficients packed in the slots and produces the polynomial // corresponding to cube if (!noPrint) CheckCtxt(ctxt, "init"); if (!noPrint) cout << "build ThinEvalMap\n"; ThinEvalMap map(ea, /*minimal=*/false, mvec, /*invert=*/false, /*build_cache=*/false); // compute the transformation to apply if (!noPrint) cout << "apply ThinEvalMap\n"; if (useCache) map.upgrade(); map.apply(ctxt); // apply the transformation to ctxt if (!noPrint) CheckCtxt(ctxt, "ThinEvalMap"); if (!noPrint) cout << "check results\n"; if (!noPrint) cout << "build ThinEvalMap\n"; ThinEvalMap imap(ea, /*minimal=*/false, mvec, /*invert=*/true, /*build_cache=*/false); // compute the transformation to apply if (!noPrint) cout << "apply ThinEvalMap\n"; if (useCache) imap.upgrade(); imap.apply(ctxt); // apply the transformation to ctxt if (!noPrint) { CheckCtxt(ctxt, "ThinEvalMap"); cout << "check results\n"; } #if 1 /* create dirty version of ctxt */ Vec<zz_pX> dirty_val0; dirty_val0.SetLength(nslots); for (long i = 0; i < nslots; i++) { random(dirty_val0[i], d); SetCoeff(dirty_val0[i], 0, val0[i]); } vector<ZZX> dirty_val1; dirty_val1.resize(nslots); for (long i = 0; i < nslots; i++) { dirty_val1[i] = conv<ZZX>(dirty_val0[i]); } Ctxt dirty_ctxt(publicKey); ea.encrypt(dirty_ctxt, publicKey, dirty_val1); EvalMap dirty_map(ea, /*minimal=*/false, mvec, /*invert=*/false, /*build_cache=*/false); dirty_map.apply(dirty_ctxt); imap.apply(dirty_ctxt); #endif vector<ZZX> val2; ea.decrypt(ctxt, secretKey, val2); if (val1 == val2) cout << "ThinEvalMap: GOOD\n"; else cout << "ThinEvalMap: BAD\n"; #if 1 vector<ZZX> dirty_val2; ea.decrypt(dirty_ctxt, secretKey, dirty_val2); if (val1 == dirty_val2) cout << "ThinEvalMap: GOOD\n"; else cout << "ThinEvalMap: BAD\n"; #endif FHE_NTIMER_STOP(ALL); if (!noPrint) { cout << "\n*********\n"; printAllTimers(); cout << endl; } }
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"; } }
int main(int argc, char *argv[]) { ArgMapping amap; long m=53; amap.arg("m", m, "use specified value as modulus"); long p=17; amap.arg("p", p, "plaintext base"); long r=1; amap.arg("r", r, "lifting"); long levels=5; amap.arg("L", levels, "levels"); long nb_coeffs=5; amap.arg("n", nb_coeffs, "nb coefficients to extract"); amap.parse(argc, argv); cout << "\n\n******** generate parameters" << " m=" << m << ", p=" << p << ", r=" << r << ", n=" << nb_coeffs << endl; setTimersOn(); FHEcontext context(m, p, r); buildModChain(context, /*L=*/levels); // cout << context << endl; // context.zMStar.printout(); // cout << endl; cout << "Generating keys and key-switching matrices... " << std::flush; FHESecKey secretKey(context); secretKey.GenSecKey(/*w=*/64);// A Hamming-weight-w secret key addFrbMatrices(secretKey); // compute key-switching matrices that we need add1DMatrices(secretKey); // compute key-switching matrices that we need const FHEPubKey& publicKey = secretKey; cout << "done\n"; resetAllTimers(); EncryptedArray ea = *(context.ea); ea.buildLinPolyMat(false); Ctxt ctxt(publicKey); NewPlaintextArray ptxt(ea); random(ea, ptxt); // ea.encrypt(ctxt, publicKey, ptxt); ea.skEncrypt(ctxt, secretKey, ptxt); cout << "Extracting " << nb_coeffs << " coefficients..."; vector<Ctxt> coeffs; extractCoeffs(ea, coeffs, ctxt, nb_coeffs); cout << "done\n"; vector<ZZX> ptxtDec; ea.decrypt(ctxt, secretKey, ptxtDec); for (long i=0; i<(long)coeffs.size(); i++) { if (!coeffs[i].isCorrect()) { cerr << " potential decryption error for "<<i<<"th coeffs " << endl; CheckCtxt(coeffs[i], ""); exit(0); } vector<ZZX> pCoeffs; ea.decrypt(coeffs[i], secretKey, pCoeffs); assert(pCoeffs.size() == ptxtDec.size()); for (int j = 0; j < pCoeffs.size(); ++j) { if (coeff(pCoeffs[j], 0) != coeff(ptxtDec[j], i)) { cerr << "error: extracted coefficient " << i << " from " "slot " << j << " is " << coeff(pCoeffs[j], 0) << " instead of " << coeff(ptxtDec[j], i) << endl; exit(0); } } } cerr << "Extracted coefficient successfully verified!\n"; }
void TestIt(long R, long p, long r, long d, long c, long k, long w, long L, long m) { cerr << "\n\n******** TestIt: R=" << R << ", p=" << p << ", r=" << r << ", d=" << d << ", c=" << c << ", k=" << k << ", w=" << w << ", L=" << L << ", m=" << m << endl; FHEcontext context(m, p, r); buildModChain(context, L, c); // context.lazy = false; if (context.lazy) cerr << "LAZY REDUCTIONS\n"; else cerr << "NON-LAZY REDUCTIONS\n"; context.zMStar.printout(); cerr << endl; #ifdef DEBUG cerr << context << endl; #endif FHESecKey secretKey(context); const FHEPubKey& publicKey = secretKey; secretKey.GenSecKey(w); // A Hamming-weight-w secret key ZZX G; if (d == 0) { G = context.alMod.getFactorsOverZZ()[0]; d = deg(G); } else G = makeIrredPoly(p, d); cerr << "G = " << G << "\n"; cerr << "generating key-switching matrices... "; addSome1DMatrices(secretKey); // compute key-switching matrices that we need addFrbMatrices(secretKey); // compute key-switching matrices that we need cerr << "done\n"; cerr << "computing masks and tables for rotation..."; EncryptedArray ea(context, G); cerr << "done\n"; long nslots = ea.size(); // L selects even coefficients vector<ZZX> LM(d); for (long j = 0; j < d; j++) if (j % 2 == 0) LM[j] = ZZX(j, 1); vector<ZZX> C; ea.buildLinPolyCoeffs(C, LM); PlaintextArray p0(ea); p0.random(); Ctxt c0(publicKey); ea.encrypt(c0, publicKey, p0); Ctxt res(c0); applyLinPoly1(ea, res, C); PlaintextArray pp0(ea); ea.decrypt(res, secretKey, pp0); p0.print(cout); cout << "\n"; pp0.print(cout); cout << "\n"; }