int main(int argc, char *argv[]) { long m, p, r, L, R; ArgMapping argmap; MDL::Timer timer; argmap.arg("m", m, "m"); argmap.arg("L", L, "L"); argmap.arg("p", p, "p"); argmap.arg("r", r, "r"); argmap.arg("R", R, "R"); argmap.parse(argc, argv); timer.start(); FHEcontext context(m, p, r); buildModChain(context, L); FHESecKey sk(context); sk.GenSecKey(64); addSome1DMatrices(sk); FHEPubKey pk = sk; auto G = context.alMod.getFactorsOverZZ()[0]; EncryptedArray ea(context, G); timer.end(); printf("slots %ld\n", ea.size()); printf("Key Gen %f\n", timer.second()); auto data = load_csv("adult.data", R); benchmark(ea, pk, sk, data); }
void act_server(int socket) { FHEcontext context(gM, gP, gR); buildModChain(context, gL); FHEPubKey pk(context); receive_pk(socket, pk); std::vector<Ctxt> ctxts(gC, pk); for (long i = 0; i < gC; i++) pk.Encrypt(ctxts[i], NTL::to_ZZX(i)); send_ctxts(socket, ctxts); nn_close(socket); }
void act_client(int socket) { FHEcontext context(gM, gP, gR); buildModChain(context, gL); FHESecKey sk(context); sk.GenSecKey(64); FHEPubKey &pk = sk; send_pk(socket, pk); std::vector<Ctxt> ctxts; receive_ctxt(socket, pk, ctxts); nn_close(socket); }
void dump_FHE_setting_to_file(const std::string& file, long k, long m, long p, long r, long L) { FHEcontext context(m, p, r); FindM(k, L, 2, p, 0, 1, m, true); buildModChain(context, L); FHESecKey sk(context); sk.GenSecKey(64); addSome1DMatrices(sk); std::fstream out; out.open(file, std::ios::out); if (!out.is_open()) { std::cerr << "Can not open file: " << file << std::endl; return; } out << context; out << sk; out.close(); }
// Testing the I/O of the important classes of the library // (context, keys, ciphertexts). int main(int argc, char *argv[]) { ArgMapping amap; long r=1; long p=2; long c = 2; long w = 64; long L = 5; long mm=0; amap.arg("p", p, "plaintext base"); amap.arg("r", r, "lifting"); amap.arg("c", c, "number of columns in the key-switching matrices"); amap.arg("m", mm, "cyclotomic index","{31,127,1023}"); amap.parse(argc, argv); bool useTable = (mm==0 && p==2); long ptxtSpace = power_long(p,r); long numTests = useTable? N_TESTS : 1; std::unique_ptr<FHEcontext> contexts[numTests]; std::unique_ptr<FHESecKey> sKeys[numTests]; std::unique_ptr<Ctxt> ctxts[numTests]; std::unique_ptr<EncryptedArray> eas[numTests]; vector<ZZX> ptxts[numTests]; // first loop: generate stuff and write it to cout // open file for writing {fstream keyFile("iotest.txt", fstream::out|fstream::trunc); assert(keyFile.is_open()); for (long i=0; i<numTests; i++) { long m = (mm==0)? ms[i][1] : mm; cout << "Testing IO: m="<<m<<", p^r="<<p<<"^"<<r<<endl; Vec<long> mvec(INIT_SIZE,2); mvec[0] = ms[i][4]; mvec[1] = ms[i][5]; vector<long> gens(2); gens[0] = ms[i][6]; gens[1] = ms[i][7]; vector<long> ords(2); ords[0] = ms[i][8]; ords[1] = ms[i][9]; if (useTable && gens[0]>0) contexts[i].reset(new FHEcontext(m, p, r, gens, ords)); else contexts[i].reset(new FHEcontext(m, p, r)); contexts[i]->zMStar.printout(); buildModChain(*contexts[i], L, c); // Set the modulus chain if (mm==0 && m==1023) contexts[i]->makeBootstrappable(mvec); // Output the FHEcontext to file writeContextBase(keyFile, *contexts[i]); writeContextBase(cout, *contexts[i]); keyFile << *contexts[i] << endl; sKeys[i].reset(new FHESecKey(*contexts[i])); const FHEPubKey& publicKey = *sKeys[i]; sKeys[i]->GenSecKey(w,ptxtSpace); // A Hamming-weight-w secret key addSome1DMatrices(*sKeys[i]);// compute key-switching matrices that we need eas[i].reset(new EncryptedArray(*contexts[i])); long nslots = eas[i]->size(); // Output the secret key to file, twice. Below we will have two copies // of most things. keyFile << *sKeys[i] << endl;; keyFile << *sKeys[i] << endl;; vector<ZZX> b; long p2r = eas[i]->getContext().alMod.getPPowR(); ZZX poly = RandPoly(0,to_ZZ(p2r)); // choose a random constant polynomial eas[i]->decode(ptxts[i], poly); ctxts[i].reset(new Ctxt(publicKey)); eas[i]->encrypt(*ctxts[i], publicKey, ptxts[i]); eas[i]->decrypt(*ctxts[i], *sKeys[i], b); assert(ptxts[i].size() == b.size()); for (long j = 0; j < nslots; j++) assert (ptxts[i][j] == b[j]); // output the plaintext keyFile << "[ "; for (long j = 0; j < nslots; j++) keyFile << ptxts[i][j] << " "; keyFile << "]\n"; eas[i]->encode(poly,ptxts[i]); keyFile << poly << endl; // Output the ciphertext to file keyFile << *ctxts[i] << endl; keyFile << *ctxts[i] << endl; cerr << "okay " << i << endl<< endl; } keyFile.close();} cerr << "so far, so good\n\n"; // second loop: read from input and repeat the computation // open file for read {fstream keyFile("iotest.txt", fstream::in); for (long i=0; i<numTests; i++) { // Read context from file unsigned long m1, p1, r1; vector<long> gens, ords; readContextBase(keyFile, m1, p1, r1, gens, ords); FHEcontext tmpContext(m1, p1, r1, gens, ords); keyFile >> tmpContext; assert (*contexts[i] == tmpContext); cerr << i << ": context matches input\n"; // We define some things below wrt *contexts[i], not tmpContext. // This is because the various operator== methods check equality of // references, not equality of the referenced FHEcontext objects. FHEcontext& context = *contexts[i]; FHESecKey secretKey(context); FHESecKey secretKey2(tmpContext); const FHEPubKey& publicKey = secretKey; const FHEPubKey& publicKey2 = secretKey2; keyFile >> secretKey; keyFile >> secretKey2; assert(secretKey == *sKeys[i]); cerr << " secret key matches input\n"; EncryptedArray ea(context); EncryptedArray ea2(tmpContext); long nslots = ea.size(); // Read the plaintext from file vector<ZZX> a; a.resize(nslots); assert(nslots == (long)ptxts[i].size()); seekPastChar(keyFile, '['); // defined in NumbTh.cpp for (long j = 0; j < nslots; j++) { keyFile >> a[j]; assert(a[j] == ptxts[i][j]); } seekPastChar(keyFile, ']'); cerr << " ptxt matches input\n"; // Read the encoded plaintext from file ZZX poly1, poly2; keyFile >> poly1; eas[i]->encode(poly2,a); assert(poly1 == poly2); cerr << " eas[i].encode(a)==poly1 okay\n"; ea.encode(poly2,a); assert(poly1 == poly2); cerr << " ea.encode(a)==poly1 okay\n"; ea2.encode(poly2,a); assert(poly1 == poly2); cerr << " ea2.encode(a)==poly1 okay\n"; eas[i]->decode(a,poly1); assert(nslots == (long)a.size()); for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]); cerr << " eas[i].decode(poly1)==ptxts[i] okay\n"; ea.decode(a,poly1); assert(nslots == (long)a.size()); for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]); cerr << " ea.decode(poly1)==ptxts[i] okay\n"; ea2.decode(a,poly1); assert(nslots == (long)a.size()); for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]); cerr << " ea2.decode(poly1)==ptxts[i] okay\n"; // Read ciperhtext from file Ctxt ctxt(publicKey); Ctxt ctxt2(publicKey2); keyFile >> ctxt; keyFile >> ctxt2; assert(ctxts[i]->equalsTo(ctxt,/*comparePkeys=*/false)); cerr << " ctxt matches input\n"; sKeys[i]->Decrypt(poly2,*ctxts[i]); assert(poly1 == poly2); cerr << " sKeys[i]->decrypt(*ctxts[i]) == poly1 okay\n"; secretKey.Decrypt(poly2,*ctxts[i]); assert(poly1 == poly2); cerr << " secretKey.decrypt(*ctxts[i]) == poly1 okay\n"; secretKey.Decrypt(poly2,ctxt); assert(poly1 == poly2); cerr << " secretKey.decrypt(ctxt) == poly1 okay\n"; secretKey2.Decrypt(poly2,ctxt2); assert(poly1 == poly2); cerr << " secretKey2.decrypt(ctxt2) == poly1 okay\n"; eas[i]->decrypt(ctxt, *sKeys[i], a); assert(nslots == (long)a.size()); for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]); cerr << " eas[i].decrypt(ctxt, *sKeys[i])==ptxts[i] okay\n"; ea.decrypt(ctxt, secretKey, a); assert(nslots == (long)a.size()); for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]); cerr << " ea.decrypt(ctxt, secretKey)==ptxts[i] okay\n"; ea2.decrypt(ctxt2, secretKey2, a); assert(nslots == (long)a.size()); for (long j = 0; j < nslots; j++) assert(a[j] == ptxts[i][j]); cerr << " ea2.decrypt(ctxt2, secretKey2)==ptxts[i] okay\n"; cerr << "test "<<i<<" okay\n\n"; }} unlink("iotest.txt"); // clean up before exiting }
int main(int argc, char *argv[]) { argmap_t argmap; argmap["m"] = "0"; argmap["p"] = "2"; argmap["r"] = "1"; if (!parseArgs(argc, argv, argmap)) usage(); unsigned long m = atoi(argmap["m"]); if (!m) usage(); unsigned long p = atoi(argmap["p"]); unsigned long r = atoi(argmap["r"]); cout << "m = " << m << ", p = " << p << ", r = " << r << endl; vector<long> f; factorize(f,m); cout << "factoring "<<m<<" gives ["; for (unsigned long i=0; i<f.size(); i++) cout << f[i] << " "; cout << "]\n"; PAlgebra al(m, p); al.printout(); cout << "\n"; PAlgebraMod almod(al, r); almod.genMaskTable(); FHEcontext context(m, p, r); buildModChain(context, 5, 2); stringstream s1; writeContextBase(s1, context); s1 << context; string s2 = s1.str(); cout << s2 << endl; stringstream s3(s2); unsigned long m1, p1, r1; readContextBase(s3, m1, p1, r1); FHEcontext c1(m1, p1, r1); s3 >> c1; if (context == c1) cout << "equal\n"; else cout << "not equal\n"; return 0; #if 0 PAlgebraModTwo al2(al); PAlgebraMod2r al2r(r,al2); if (false) { long nslots = al.NSlots(); long ngens = al.numOfGens(); for (long i = 0; i < nslots; i++) { const int* v = al.dLog(al.ith_rep(i)); cout << i << " "; for (long j = 0; j < ngens; j++) cout << v[j] << " "; cout << "\n"; } return 0; } // GF2X::HexOutput = 1; // compact hexadecimal printout // cout << "Phi_m(X) = " << al.PhimX() << endl; // vec_GF2X Fs = al2.Factors(); // cout << "Factors = " << Fs << endl; // GF2X Q = Fs[0]; // for (long i=1; i<Fs.length(); i++) Q *= Fs[i]; // cout << "mult of factors = " << Q << endl; GF2X G; // G is the AES polynomial, G(X)= X^8 +X^4 +X^3 +X +1 SetCoeff(G,8); SetCoeff(G,4); SetCoeff(G,3); SetCoeff(G,1); SetCoeff(G,0); // GF2X G; SetCoeff(G,4); SetCoeff(G,1); SetCoeff(G,0); // X^4 +X +1 // cout << "G = " << G << ", deg(G)=" << deg(G) << endl; vector<GF2X> maps; al2.mapToSlots(maps, G); // cout << "maps = ["; // for (unsigned long i=0; i<maps.size(); i++) // cout << maps[i] << " "; // cout << "]\n"; GF2X X; SetX(X); // The polynomial X GF2X ptxt; // plaintext has X in all the slots cout << "embedding X in plaintext slots... "; al2.embedInAllSlots(ptxt, X, maps); cout << "done\n"; // cout << "ptxt = " << ptxt << endl; // Debugging printout: p modulo all the factors // vector<GF2X> crt; // al2.CRT_decompose(crt,ptxt); // cout << "ptxt mod factors = ["; // for (unsigned long i=0; i<crt.size(); i++) cout << crt[i] << " "; // cout << "]\n"; // Decode the plaintext back to a vector of elements, // and check that they are all equal to X vector<GF2X> alphas; cout << "decoding plaintext slots... "; al2.decodePlaintext(alphas, ptxt, G, maps); cout << "done\n"; // cout << "alphas = ["; // for (unsigned long i=0; i<alphas.size(); i++) // cout << alphas[i] << " "; // cout << "]\n"; cout << "comparing " << alphas.size() << " plaintext slots to X... "; for (unsigned long i=0; i<alphas.size(); i++) if (alphas[i] != X) { cout << "\n alphas["<<i<<"] = "<<alphas[i]<<" != X\n\n"; exit(0); } cout << "all tests completed successfully\n\n"; // encode and decode random polynomials for (unsigned long i=0; i<alphas.size(); i++) random(alphas[i], 8); // random degree-7 polynomial mod 2 cout << "embedding random GF(2^8) elements in plaintext slots... "; al2.embedInSlots(ptxt, alphas, maps); cout << "done\n"; // Compute p^2 mod Phi_m(X) and also p(X^2) mod Phi_m(X) and // verify that they both decode to a vector of X^2 in all the slots cout << "squaring and decoding plaintext slots... "; X *= X; // X^2 // GF2X ptxt2; // SqrMod(ptxt2,ptxt,al2.PhimXMod()); // ptxt2 = ptxt^2 mod Phi_m(X) CompMod(ptxt, ptxt, X, al2.PhimXMod()); // ptxt = ptxt(X^2) mod Phi_m(X) // // sanity chack: these should be the same mod 2 (but not mod 2^r) // if (ptxt != ptxt2) cout << "ptxt^2 != ptxt(X^2) mod Phi_m(X)\n"; vector<GF2X> betas; al2.decodePlaintext(betas, ptxt, G, maps); cout << "done\n"; if (alphas.size() != betas.size()) Error("wrong number of slots decoded"); cout << "comparing decoded plaintext slots... "; for (unsigned long i=0; i<alphas.size(); i++) { SqrMod(alphas[i],alphas[i],G); // should get alpha[i]^2 mod G if (alphas[i] != betas[i]) { cout << "\n alphas["<<i<<"] = "<<alphas[i] <<" != " << "betas["<<i<<"] = " << betas[i] << "\n\n"; exit(0); } } cout << "all tests completed successfully\n\n"; // return 0; al2r.restoreContext(); vector<zz_pX> maps1; zz_pX X1; SetX(X1); cerr << "HERE1\n"; al2r.mapToSlots(maps1, X1); cerr << "HERE1a\n"; vector<zz_pX> alphas1; alphas1.resize(maps.size()); for (long i = 0; i < lsize(alphas1); i++) random(alphas1[i], 1); zz_pX ptxt1; cerr << "HERE2\n"; al2r.embedInSlots(ptxt1, alphas1, maps1); cerr << "HERE3\n"; vector<zz_pX> betas1; al2r.decodePlaintext(betas1, ptxt1, X1, maps1); assert(alphas1 == betas1); return 0; #endif }
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(){ long m, r, p, L, c, w, s, d, security, enc, dec, encMul, recommended; char tempChar; bool toPrint = false, toSave = false; //Scan parameters cout << "Enter HElib's keys paramter. Enter zero for the recommended values" << endl; while(true){ cout << "Enter the field of the computations (a prime number): "; cin >> p; if(isPrime(p)) break; cout << "Error! p must be a prime number! " << endl; } while(true){ recommended = 1; cout << "Enter r (recommended " << recommended <<"): "; cin >> r; if(r == 0) r = recommended; if(r > 0) break; cout << "Error! r must be a positive number!" << endl; } while(true){ recommended = 16; cout << "Enter L (recommended " << recommended <<"): "; cin >> L; if(L == 0) L = recommended; if(L > 1) break; cout << "Error! L must be a positive number!" << endl; } while(true){ recommended = 3; cout << "Enter c (recommended " << recommended <<"): "; cin >> c; if(c == 0) c = recommended; if(c > 1) break; cout << "Error! c must be a positive number!" << endl; } while(true){ recommended = 64; cout << "Enter w (recommended " << recommended <<"): "; cin >> w; if(w == 0) w = recommended; if(w > 1) break; cout << "Error! w must be a positive number!" << endl; } while(true){ recommended = 0; cout << "Enter d (recommended " << recommended <<"): "; cin >> d; if(d >= 0) break; cout << "Error! d must be a positive or zero!" << endl; } while(true){ recommended = 0; cout << "Enter s (recommended " << recommended <<"): "; cin >> s; if(s >= 0) break; cout << "Error! s must be a positive or zero!" << endl; } while(true){ recommended = 128; cout << "Enter security (recommended " << recommended << "): "; cin >> security; if(security == 0) security = recommended; if(security >= 1) break; cout << "Error! security must be a positive number " << endl; } ZZX G; m = FindM(security,L,c,p, d, s, 0); FHEcontext context(m, p, r); // initialize context buildModChain(context, L, c); // modify the context, adding primes to the modulus chain FHESecKey secretKey(context); // construct a secret key structure const FHEPubKey& publicKey = secretKey; // an "upcast": FHESecKey is a subclass of FHEPubKey //if(0 == d) G = context.alMod.getFactorsOverZZ()[0]; secretKey.GenSecKey(w); // actually generate a secret key with Hamming weight w addSome1DMatrices(secretKey); EncryptedArray ea(context, G); // constuct an Encrypted array object ea that is // associated with the given context and the polynomial G long nslots = ea.size(), field = power(p,r); cout << "nslots: " << nslots << endl ; cout << "Computations will be modulo " << field << endl; cout << "m: " << m << endl; unsigned int sz1, sz2, num; while(true){ cout << "Enter number of rows in the matrix: "; cin >> sz1; if(sz1 > 1 && sz1 <= nslots) break; cout << "Error! the value must be between 1 to " << nslots << "!" << endl; } while(true){ cout << "Enter number of columns in the matrix: "; cin >> sz2; if(sz1 > 2 && sz2 <= nslots) break; cout << "Error! the value must be between 1 to " << nslots << "!" << endl; } cout << "Enter the number you want to multiply the matrix by: "; cin >> num; MatSize sz(sz1, sz2); PTMatrix PTmat(sz,field); //random matrix in size origSize1 while(true){ cout << "Print the matrices?" << endl; cout << "Y for yes, N for no: "; cin >> tempChar; if(tempChar == 'Y' || tempChar == 'y'){ toPrint = true; break; } if(tempChar == 'N' || tempChar == 'n'){ toPrint = false; break; } cout << "Error! invalid input!" << endl; } while(true){ cout << "Save the matrices?" << endl; cout << "Y for yes, N for no: "; cin >> tempChar; if(tempChar == 'Y' || tempChar == 'y'){ toSave = true; break; } if(tempChar == 'N' || tempChar == 'n'){ toSave = false; break; } cout << "Error! invalid input!" << endl; } if(toPrint) PTmat.print(); if(toSave){ ofstream out_mat("mat.txt"); PTmat.save(out_mat); out_mat.close(); } //encryptions cout << "Encrypting the matrix..." << endl; resetTimers(); EncryptedMatrix encMat = PTmat.encrypt(ea, publicKey); enc = stopTimers("to encrypt the first matrix"); //Multiply by constant cout << "Multiplying the matricex by constant..." << endl; resetTimers(); encMat *= num; encMul = stopTimers("to multiply the matrix"); cout << "Decrypting the result..." << endl; resetTimers(); PTMatrix res = encMat.decrypt(ea, secretKey); dec = stopTimers("to decrypt the result"); if(toPrint) res.print("Solution: "); PTMatrix PTres = PTmat; for(unsigned int i=1; i < num; i++){ PTres += PTmat; } PTres %= field; if(toPrint) PTres.print("pt Solution: "); if(toSave){ ofstream out_res("mat_res.txt"), out_ptRes("mat_pt_res.txt"); res.save(out_res); PTres.save(out_ptRes); out_res.close(); out_ptRes.close(); } //PTres.print("pt result: "); cout << "\n\n----------------------------------------Summary------------------------------ " << endl; cout << "p: " << p << ", r: " << r << ", L: " << L << ", c: " << c << ", w: " << w << ", d: " << d << ", s: " << s << ", security: " << security << endl; cout << "nslots: " << nslots << "\nm: " << m << endl; cout << "It took " << enc << " clock ticks to encrypt the matrix" << endl; cout << "It took " << dec << " clock ticks to decrypt the result" << endl; cout << "It took " << encMul << " clock ticks to add the encrypted matrices" << endl; cout << "is correct? " << (res==PTres) << endl; return 0; }
void TestIt(long m, long p, long r, long d, long L, long bnd, long B) { cout << "*** TestIt" << (isDryRun()? "(dry run):" : ":") << " m=" << m << ", p=" << p << ", r=" << r << ", d=" << d << ", L=" << L << ", bnd=" << bnd << ", B=" << B << endl; setTimersOn(); FHEcontext context(m, p, r); buildModChain(context, L, /*c=*/2); context.zMStar.printout(); cout << endl; FHESecKey secretKey(context); const FHEPubKey& publicKey = secretKey; secretKey.GenSecKey(/*w=*/64); // A Hamming-weight-w secret key ZZX G; if (d == 0) G = context.alMod.getFactorsOverZZ()[0]; else G = makeIrredPoly(p, d); cout << "G = " << G << "\n"; cout << "generating key-switching matrices... "; addSome1DMatrices(secretKey); // compute key-switching matrices that we need cout << "done\n"; cout << "computing masks and tables for rotation..."; EncryptedArray ea(context, G); cout << "done\n"; PlaintextArray xp0(ea), xp1(ea); xp0.random(); xp1.random(); Ctxt xc0(publicKey); ea.encrypt(xc0, publicKey, xp0); ZZX poly_xp1; ea.encode(poly_xp1, xp1); cout << "** Testing replicate():\n"; bool error = false; Ctxt xc1 = xc0; CheckCtxt(xc1, "before replicate"); replicate(ea, xc1, ea.size()/2); if (!check_replicate(xc1, xc0, ea.size()/2, secretKey, ea)) error = true; CheckCtxt(xc1, "after replicate"); // Get some timing results for (long i=0; i<20 && i<ea.size(); i++) { xc1 = xc0; FHE_NTIMER_START(replicate); replicate(ea, xc1, i); if (!check_replicate(xc1, xc0, i, secretKey, ea)) error = true; FHE_NTIMER_STOP(replicate); } cout << " Replicate test " << (error? "failed :(\n" : "succeeded :)") << endl<< endl; printAllTimers(); cout << "\n** Testing replicateAll()... " << std::flush; #ifdef DEBUG_PRINTOUT replicateVerboseFlag = true; #else replicateVerboseFlag = false; #endif error = false; ReplicateTester *handler = new ReplicateTester(secretKey, ea, xp0, B); try { FHE_NTIMER_START(replicateAll); replicateAll(ea, xc0, handler, bnd); } catch (StopReplicate) { } cout << (handler->error? "failed :(\n" : "succeeded :)") << ", total time=" << handler->t_total << " (" << ((B>0)? B : ea.size()) << " vectors)\n"; delete handler; }
void testCtxt(long m, long p, long widthBound, long L, long r) { if (!noPrint) cout << "@testCtxt(m="<<m<<",p="<<p<<",depth="<<widthBound<< ",r="<<r<<")"; FHEcontext context(m,p,r); EncryptedArray ea(context); // Use G(X)=X for this ea object // Some arbitrary initial plaintext array vector<long> in(ea.size()); for (long i=0; i<ea.size(); i++) in[i] = i % p; // Setup generator-descriptors for the PAlgebra generators Vec<GenDescriptor> vec(INIT_SIZE, ea.dimension()); for (long i=0; i<ea.dimension(); i++) vec[i] = GenDescriptor(/*order=*/ea.sizeOfDimension(i), /*good=*/ ea.nativeDimension(i), /*genIdx=*/i); // Some default for the width-bound, if not provided if (widthBound<=0) widthBound = 1+log2((double)ea.size()); // Get the generator-tree structures and the corresponding hypercube GeneratorTrees trees; long cost = trees.buildOptimalTrees(vec, widthBound); if (!noPrint) { context.zMStar.printout(); cout << ": trees=" << trees << endl; cout << " cost =" << cost << endl; } // Vec<long> dims; // trees.getCubeDims(dims); // CubeSignature sig(dims); // 1/2 prime per level should be more or less enough, here we use 1 per layer if (L<=0) L = (1+trees.numLayers())*context.BPL(); buildModChain(context, /*nLevels=*/L, /*nDigits=*/3); if (!noPrint) cout << "**Using "<<L<<" and " << context.ctxtPrimes.card() << " Ctxt-primes\n"; // Generate a sk/pk pair FHESecKey secretKey(context); const FHEPubKey& publicKey = secretKey; secretKey.GenSecKey(); // A +-1/0 secret key Ctxt ctxt(publicKey); for (long cnt=0; cnt<3; cnt++) { resetAllTimers(); // Choose a random permutation Permut pi; randomPerm(pi, trees.getSize()); // Build a permutation network for pi PermNetwork net; net.buildNetwork(pi, trees); // make sure we have the key-switching matrices needed for this network addMatrices4Network(secretKey, net); // Apply the permutation pi to the plaintext vector<long> out1(ea.size()); vector<long> out2(ea.size()); applyPermToVec(out1, in, pi); // direct application // Encrypt plaintext array, then apply permutation network to ciphertext ea.encrypt(ctxt, publicKey, in); if (!noPrint) cout << " ** applying permutation network to ciphertext... " << flush; double t = GetTime(); net.applyToCtxt(ctxt, ea); // applying permutation netwrok t = GetTime() -t; if (!noPrint) cout << "done in " << t << " seconds" << endl; ea.decrypt(ctxt, secretKey, out2); if (out1==out2) cout << "GOOD\n"; else { cout << "************ BAD\n"; } // printAllTimers(); } }
int main() { string * tmp_ptr; long LLL, DDD, KKK ; long m; long ccc; FHEcontext * context_ptr; FHESecKey * fhekey_ptr; EncryptedArray * ea_ptr; LLL = 682; DDD=12; KKK=80; /* pair<long, long> m_c = get_m_c(LLL, DDD, KKK); m = m_c.first; ccc = m_c.second; */ m = 15709; ccc = 3; context_ptr = new FHEcontext(m, 2, 1); buildModChain(*context_ptr, DDD, ccc); fhekey_ptr = new FHESecKey(*context_ptr); fhekey_ptr->clear(); fhekey_ptr->GenSecKey(64,2); addSome1DMatrices(*fhekey_ptr); const FHEPubKey & pub_key = *fhekey_ptr; ZZX G; G = ZZX(1,1); ea_ptr = new EncryptedArray(*context_ptr, G); // Test I/O, write context and public key, then try to read them back cout << "KEY\n"; cout <<"L= " <<LLL<< " D= " << DDD<< " K= " << KKK << endl<< flush; { stringstream s1; writeContextBase(s1, *context_ptr); s1 << *context_ptr; string s2 = s1.str(); cout << s2 << endl; // output context also to external cout // Read back context from input stream (s3) unsigned long m1, p1, r1; stringstream s3(s2); readContextBase(s3, m1, p1, r1); FHEcontext c1(m1, p1, r1); s3 >> c1; assert(c1 == *context_ptr); } { stringstream s1; s1 << pub_key; string s2 = s1.str(); cout << s2 <<"\nENDKEY" << endl; // output public key also to external cout // Read back cpublic key from input stream (s3) stringstream s3(s2); FHEPubKey pk1(*context_ptr); s3 >> pk1; assert(pk1 == pub_key); } }
int main(int argc, char **argv) { /* On our trusted system we generate a new key * (or read one in) and encrypt the secret data set. */ long m=0, p=2, r=1; // Native plaintext space // Computations will be 'modulo p' long L=16; // Levels long c=3; // Columns in key switching matrix long w=64; // Hamming weight of secret key long d=0; long security = 128; ZZX G; m = FindM(security,L,c,p, d, 0, 0); FHEcontext context(m, p, r); // initialize context buildModChain(context, L, c); // modify the context, adding primes to the modulus chain FHESecKey secretKey(context); // construct a secret key structure const FHEPubKey& publicKey = secretKey; // an "upcast": FHESecKey is a subclass of FHEPubKey //if(0 == d) G = context.alMod.getFactorsOverZZ()[0]; secretKey.GenSecKey(w); // actually generate a secret key with Hamming weight w addSome1DMatrices(secretKey); cout << "Generated key..." << endl; EncryptedArray ea(context, G); // constuct an Encrypted array object ea that is // associated with the given context and the polynomial G long nslots = ea.size(); cout << "Vector Size " << nslots << endl;; vector<long> v1; for(int i = 0 ; i < nslots; i++) { v1.push_back(1); //v1.push_back(i*2); } Ctxt ct1(publicKey); startFHEtimer("ea.encrypt1"); ea.encrypt(ct1, publicKey, v1); stopFHEtimer("ea.encrypt1"); vector<long> v2; Ctxt ct2(publicKey); for(int i = 0 ; i < nslots; i++) { v2.push_back(1); //v2.push_back(i*3); } startFHEtimer("ea.encrypt2"); ea.encrypt(ct2, publicKey, v2); stopFHEtimer("ea.encrypt2"); // v1.mul(v2); // c3.multiplyBy(c2) // ct2.multiplyBy(ct1); // CheckCtxt(ct2, "c3*=c2"); // debugCompare(ea,secretKey,v1,ct2); // On the public (untrusted) system we // can now perform our computation Ctxt ctSum = ct1; Ctxt ctProd = ct1; startFHEtimer("sum"); ctSum += ct2; stopFHEtimer("sum"); //ctProd *= ct2; startFHEtimer("product"); ctProd *= ct2; //ctProd.multiplyBy(ct2); stopFHEtimer("product"); //ea.mat_mul(ctProd,ct2); vector<long> res; startFHEtimer("decryptsum"); ea.decrypt(ctSum, secretKey, res); stopFHEtimer("decryptsum"); //cout << "All computations are modulo " << p << "." << endl; for (unsigned int i = 0; i<res.size(); i++){ cout<< res[i]; } for(unsigned int i = 0; i < res.size(); i++) { cout << v1[i] << " + " << v2[i] << " = " << res[i] << endl; } startFHEtimer("decryptproduct"); ea.decrypt(ctProd, secretKey, res); stopFHEtimer("decryptproduct"); for (unsigned int i = 0; i<res.size(); i++){ cout<< res[i]; } for(unsigned int i = 0; i < res.size(); i++) { cout << v1[i] << " * " << v2[i] << " = " << res[i] << endl; } printAllTimers(); cout << endl; cout << "All computations are modulo " << p << "." << endl; return 0; }
int main(int argc, char **argv) { string inp = "secrets! very secrets!"; cout << "inp = \"" << inp << "\"" << endl; vector<pt_key32> k = pt_genKey(); pt_expandKey(k); printKey(k); // initialize helib long m=0, p=2, r=1; long L=23; long c=3; long w=64; long d=0; long security = 128; cout << "L=" << L << endl; ZZX G; cout << "Finding m..." << endl; m = FindM(security,L,c,p,d,0,0); cout << "Generating context..." << endl; FHEcontext context(m, p, r); cout << "Building mod-chain..." << endl; buildModChain(context, L, c); cout << "Generating keys..." << endl; FHESecKey seckey(context); const FHEPubKey& pubkey = seckey; G = context.alMod.getFactorsOverZZ()[0]; seckey.GenSecKey(w); addSome1DMatrices(seckey); EncryptedArray ea(context, G); global_nslots = ea.size(); cout << "nslots = " << global_nslots << endl; // set up globals CTvec maxint (ea, pubkey, transpose(uint32ToBits(0xFFFFFFFF))); global_maxint = &maxint; // HEencrypt key timer(true); cout << "Encrypting SIMON key..." << flush; vector<CTvec> encryptedKey = heEncrypt(ea, pubkey, k); timer(); // HEencrypt input cout << "Encrypting inp..." << flush; heblock ct = heEncrypt(ea, pubkey, inp); timer(); cout << "Running protocol..." << endl; for (size_t i = 0; i < T; i++) { cout << "Round " << i+1 << "/" << T << "..." << flush; encRound(encryptedKey[i], ct); timer(); // check intermediate result for noise cout << "decrypting..." << flush; vector<pt_block> bs = heblockToBlocks(seckey, ct); timer(); printf("block0 : 0x%08x 0x%08x\n", bs[0].x, bs[0].y); vector<pt_block> pt_bs = pt_simonEnc(k, inp, i+1); printf("should be : 0x%08x 0x%08x\n", pt_bs[0].x, pt_bs[0].y); cout << "decrypted : \"" << pt_simonDec(k, bs, i+1) << "\" " << endl; } return 0; }
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; } }
int main(int argc, char *argv[]) { ArgMapping amap; amap.arg("noPrint", noPrint, "suppress printouts"); long m=16; amap.arg("m", m, "cyclotomic index"); amap.note("e.g., m=1024, m=2047"); long r=8; amap.arg("r", r, "bit of precision"); amap.parse(argc, argv); if (!noPrint) { vector<long> f; factorize(f,m); cout << "r="<<r<<", factoring "<<m<<" gives ["; for (unsigned long i=0; i<f.size(); i++) cout << f[i] << " "; cout << "]\n"; } FHEcontext context(m, /*p=*/-1, r); buildModChain(context, 5, 2); const EncryptedArrayCx& ea = context.ea->getCx(); if (!noPrint) ea.getPAlgebra().printout(); #ifdef DEBUG_PRINTOUT vector<cx_double> vc1; ea.random(vc1); cout << "random complex vc1="; printVec(cout,vc1,8)<<endl; vector<double> vd; ea.random(vd); cout << "random real vd="; printVec(cout,vd,8)<<endl; #endif vector<double> vl; ea.random(vl); vl[1] = -1; // ensure that this is not the zero vector #ifdef DEBUG_PRINTOUT cout << "random int v="; printVec(cout,vl,8)<<endl; #endif zzX poly; double factor = ea.encode(poly, vl, 1.0); if (!noPrint) { ZZX poly2; convert(poly2, poly); cout << " encoded into a degree-"<<NTL::deg(poly2)<<" polynomial\n"; } vector<double> vd2; ea.decode(vd2, poly, factor); #ifdef DEBUG_PRINTOUT cout << " decoded into vd2="; printVec(cout,vd2,8)<<endl; #endif assert(lsize(vl)==lsize(vd2)); double maxDiff = 0.0; for (long i=0; i<lsize(vl); i++) { double diffAbs = std::abs(vl[i]-vd2[i]); if (diffAbs > maxDiff) maxDiff = diffAbs; } cout << ((maxDiff>0.1)? "BAD?" : "GOOD?") << " max |v-vd2|_{infty}="<<maxDiff << endl; return 0; }
int main(int argc, char *argv[]) { /*************************** INIT ***************************/ /* most of the init code is copied directly from HElibs general test (https://github.com/shaih/HElib/blob/master/src%2FTest_General.cpp) */ cerr << "*************************** INIT ***************************" << "\n"; argmap_t argmap; argmap["R"] = "1"; argmap["p"] = "113"; argmap["r"] = "1"; argmap["d"] = "1"; argmap["c"] = "2"; argmap["k"] = "80"; argmap["L"] = "0"; argmap["s"] = "0"; argmap["m"] = "0"; long R = atoi(argmap["R"]); long p = atoi(argmap["p"]); long r = atoi(argmap["r"]); long d = atoi(argmap["d"]); long c = atoi(argmap["c"]); long k = atoi(argmap["k"]); // long z = atoi(argmap["z"]); long L = atoi(argmap["L"]); if (L==0) { // determine L based on R,r L = 3*R+3; if (p>2 || r>1) { // add some more primes for each round long addPerRound = 2*ceil(log((double)p)*r*3)/(log(2.0)*NTL_SP_NBITS) +1; L += R * addPerRound; } } long s = atoi(argmap["s"]); long chosen_m = atoi(argmap["m"]); long w = 64; // Hamming weight of secret key // long L = z*R; // number of levels long m = FindM(k, L, c, p, d, s, chosen_m, true); cerr << "\n\nR=" << 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.zMStar.printout(); cerr << endl; 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]; else G = makeIrredPoly(p, d); cerr << "G = " << G << "\n"; cerr << "generating key-switching matrices... "; addSome1DMatrices(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(); cerr << "slots = " << nslots << "\n"; // set this to the maximum amount of delegates you want to use int delegateLimit = 10; if(delegateLimit > nslots) { cerr << "delegateLimit must be <= nslots\n"; exit(1); } cerr << "delegateLimit = " << delegateLimit << "\n"; /*************************** INIT ***************************/ cerr << "*************************** INIT ***************************" << "\n\n"; cerr << "Reading delegate votes"; vector<vector <long> > delegateVotes = readDelegateVotes("delegate_votes.txt", nslots, delegateLimit); cerr << "done\n"; cerr << "Encoding delegate votes...\n"; vector<PlaintextArray> delegateVotesEncoded = encodeVotes(delegateVotes, ea); cerr << "Encrypting delegate votes...\n"; vector<Ctxt> delegateVotesEncrypted = encryptVotes(delegateVotesEncoded, ea, publicKey); cerr << "Reading direct votes"; vector<vector <long> > votes = readVotes("direct_votes.txt", nslots); cerr << "done\n"; cerr << "Encoding direct votes...\n"; vector<PlaintextArray> votesEncoded = encodeVotes(votes, ea); cerr << "Encrypting direct votes...\n"; vector<Ctxt> votesEncrypted = encryptVotes(votesEncoded, ea, publicKey); cerr << "Reading delegations"; vector<vector <long> > delegations = readVotes("delegations.txt", nslots); cerr << "done\n"; cerr << "Encoding delegations...\n"; vector<PlaintextArray> delegationsEncoded = encodeVotes(delegations, ea); cerr << "Encrypting delegations...\n"; vector<Ctxt> delegationsEncrypted = encryptVotes(delegationsEncoded, ea, publicKey); cerr << "Tallying delegations (+)...\n"; Ctxt delegateWeights = tallyVotes(delegationsEncrypted); vector<Ctxt> weightFactors = getWeightFactors(delegateWeights, ea, publicKey, delegateLimit); cerr << "Applying weights (x)...\n"; vector<Ctxt> weightedDelegateVotes = applyWeights(weightFactors, delegateVotesEncrypted, ea, secretKey); cerr << "Tallying direct votes (+)...\n"; Ctxt directTally = tallyVotes(votesEncrypted); cerr << "Final tally (+)...\n"; Ctxt tally = liquidTally(directTally, weightedDelegateVotes); cerr << "Decrypting final tally...\n"; PlaintextArray totals = decrypt(tally, ea, secretKey); printTally(totals); }
int main(){ cout << "This experiment check for different values of parameters, how much time it takes to encrypt and decrypt a \"full\" matrix (nslots*nslots), and multply 2 encrypted matrices\nAlso check for what size of matrices, the multiplication in the server on the encrypted data is faster than for the user than do all the work on his machine. Using this formula: N > n(P)*(2*Enc(P)+Dec(P)) when:\nP is the parameters\nn(P) is the nslots value for these values\nEnc(P) and Dec(P) is the time it takes to encrypt and decrypt the matrics in size nslots*nslots\nNOTE: this formula don't take into account the time it takes to send and recieve the data to and from the server, and the time it took to the server to do the actual multiplication\n" << endl; /* long m=0, r=1; // Native plaintext space int p = 65539; // Computations will be 'modulo p' long L=16; // Levels long c=3; // Columns in key switching matrix long w=64; // Hamming weight of secret key long d=0; long s = 0; //minimum number of slots [ default=0 ] long security = 128;*/ long m, r, p, L, c, w, s, d, security, enc1, enc2, dec, encMul, ptMul, recommended; char tempChar; bool toEncMult = false, toPrint = false, debugMul = false, toSave = false; //Scan parameters cout << "Enter HElib's keys paramter. Enter zero for the recommended values" << endl; while(true){ cout << "Enter the field of the computations (a prime number): "; cin >> p; if(isPrime(p)) break; cout << "Error! p must be a prime number! " << endl; } while(true){ recommended = 1; cout << "Enter r (recommended " << recommended <<"): "; cin >> r; if(r == 0) r = recommended; if(r > 0) break; cout << "Error! r must be a positive number!" << endl; } while(true){ recommended = 16; cout << "Enter L (recommended " << recommended <<"): "; cin >> L; if(L == 0) L = recommended; if(L > 1) break; cout << "Error! L must be a positive number!" << endl; } while(true){ recommended = 3; cout << "Enter c (recommended " << recommended <<"): "; cin >> c; if(c == 0) c = recommended; if(c > 1) break; cout << "Error! c must be a positive number!" << endl; } while(true){ recommended = 64; cout << "Enter w (recommended " << recommended <<"): "; cin >> w; if(w == 0) w = recommended; if(w > 1) break; cout << "Error! w must be a positive number!" << endl; } while(true){ recommended = 0; cout << "Enter d (recommended " << recommended <<"): "; cin >> d; if(d >= 0) break; cout << "Error! d must be a positive or zero!" << endl; } while(true){ recommended = 0; cout << "Enter s (recommended " << recommended <<"): "; cin >> s; if(s >= 0) break; cout << "Error! s must be a positive or zero!" << endl; } while(true){ recommended = 128; cout << "Enter security (recommended " << recommended << "): "; cin >> security; if(security == 0) security = recommended; if(security >= 1) break; cout << "Error! security must be a positive number " << endl; } ZZX G; m = FindM(security,L,c,p, d, s, 0); FHEcontext context(m, p, r); // initialize context buildModChain(context, L, c); // modify the context, adding primes to the modulus chain FHESecKey secretKey(context); // construct a secret key structure const FHEPubKey& publicKey = secretKey; // an "upcast": FHESecKey is a subclass of FHEPubKey //if(0 == d) G = context.alMod.getFactorsOverZZ()[0]; secretKey.GenSecKey(w); // actually generate a secret key with Hamming weight w addSome1DMatrices(secretKey); EncryptedArray ea(context, G); // constuct an Encrypted array object ea that is // associated with the given context and the polynomial G long nslots = ea.size(), field = power(p,r); cout << "nslots: " << nslots << endl ; cout << "Computations will be modulo " << field << endl; cout << "m: " << m << endl; unsigned int sz1, sz2, sz3; while(true){ cout << "Enter number of rows in the first matrix: "; cin >> sz1; if(sz1 > 1 && sz1 <= nslots) break; cout << "Error! the value must be between 1 to " << nslots << "!" << endl; } while(true){ cout << "Enter number of rows in the first matrix: "; cin >> sz2; if(sz1 > 2 && sz2 <= nslots) break; cout << "Error! the value must be between 1 to " << nslots << "!" << endl; } while(true){ cout << "Enter number of rows in the first matrix: "; cin >> sz3; if(sz1 > 3 && sz3 <= nslots) break; cout << "Error! the value must be between 1 to " << nslots << "!" << endl; } PTMatrix PTmat1(MatSize(sz1, sz2),field), PTmat2(MatSize(sz2, sz3), field); //random matrix in size origSize1 while(true){ cout << "To multiply the encrypted matrices? Not affecting the formula, just for statistic" << endl; cout << "Y for yes, N for no: "; cin >> tempChar; if(tempChar == 'Y' || tempChar == 'y'){ toEncMult = true; break; } if(tempChar == 'N' || tempChar == 'n'){ toEncMult = false; break; } cout << "Error! invalid input!" << endl; } while(toEncMult){ cout << "Debug the multiplication steps?\nY for yesm N for no :"; cin >> tempChar; if(tempChar == 'Y' || tempChar == 'y'){ debugMul = true; break; } if(tempChar == 'N' || tempChar == 'n'){ debugMul = false; break; } cout << "Error! invalid input!" << endl; } while(true){ cout << "Print the matrices?" << endl; cout << "Y for yes, N for no: "; cin >> tempChar; if(tempChar == 'Y' || tempChar == 'y'){ toPrint = true; break; } if(tempChar == 'N' || tempChar == 'n'){ toPrint = false; break; } cout << "Error! invalid input!" << endl; } while(true){ cout << "Save the matrices?" << endl; cout << "Y for yes, N for no: "; cin >> tempChar; if(tempChar == 'Y' || tempChar == 'y'){ toSave = true; break; } if(tempChar == 'N' || tempChar == 'n'){ toSave = false; break; } cout << "Error! invalid input!" << endl; } if(toPrint){ PTmat1.print(); PTmat2.print(); } if(toSave){ ofstream out_mat1("mat1.txt"), out_mat2("mat2.txt"); PTmat1.save(out_mat1); PTmat2.save(out_mat2); out_mat1.close(); out_mat2.close(); } //encryptions cout << "Encrypting the first matrices..." << endl; resetTimers(); EncryptedMatrix encMat1 = PTmat1.encrypt(ea, publicKey); enc1 = stopTimers("to encrypt the first matrix"); cout << "Encrypting the second matrices..." << endl; resetTimers(); EncryptedMatrix encMat2 = PTmat2.encrypt(ea, publicKey); enc2 = stopTimers("to encrypt the second matrix"); //multiplication if(toEncMult){ cout << "Multiplying the matrices..." << endl; resetTimers(); if(debugMul) encMat1 = encMat1.debugMul(encMat2); //same as encMat1 *= encMat2 but print progress update else encMat1 *= encMat2; encMul = stopTimers("to multiply the matrices"); } cout << "Decrypting the result..." << endl; resetTimers(); PTMatrix res = encMat1.decrypt(ea, secretKey); dec = stopTimers("to decrypt the result"); if(toPrint) res.print("Solution: "); resetTimers(); PTMatrix PTres = PTmat1.mulWithMod(PTmat2,field); //like (PTmat1*PTmat2)%p but do modulu after each multiplication to avoid overflow ptMul = stopTimers("to multiply the regular matrices"); if(toSave){ ofstream out_res("mat_res.txt"), out_ptRes("mat_pt_res.txt"); res.save(out_res); PTres.save(out_ptRes); out_res.close(); out_ptRes.close(); } //PTres.print("pt result: "); cout << "\n\n----------------------------------------Summary------------------------------ " << endl; cout << "p: " << p << ", r: " << r << ", L: " << L << ", c: " << c << ", w: " << w << ", d: " << d << ", s: " << s << ", security: " << security << endl; cout << "nslots: " << nslots << "\nm: " << m << endl; cout << "It took " << enc1 << " clock ticks to encrypt the first matrix" << endl; cout << "It took " << enc2 << " clock ticks to encrypt the second matrix" << endl; cout << "It took " << dec << " clock ticks to decrypt the result" << endl; cout << "It took " << ptMul << " clock ticks to multiply the regular matrices" << endl; if(toEncMult){ cout << "It took " << encMul << " clock ticks to multiply the encrypted matrices" << endl; cout << "is correct? " << (res==PTres) << endl; } long N = nslots*(enc1+enc2+dec)/ptMul; cout << "N should be greater than " << N << endl; return 0; }
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 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 }
int main(int argc, char *argv[]) { // Commandline setup ArgMapping amap; long m=16; long r=8; long L=0; double epsilon=0.01; // Accepted accuracy long R=1; long seed=0; bool debug = false; amap.arg("m", m, "Cyclotomic index"); amap.note("e.g., m=1024, m=2047"); amap.arg("r", r, "Bits of precision"); amap.arg("R", R, "number of rounds"); amap.arg("L", L, "Number of bits in modulus", "heuristic"); amap.arg("ep", epsilon, "Accepted accuracy"); amap.arg("seed", seed, "PRG seed"); amap.arg("verbose", verbose, "more printouts"); amap.arg("debug", debug, "for debugging"); amap.parse(argc, argv); if (seed) NTL::SetSeed(ZZ(seed)); if (R<=0) R=1; if (R<=2) L = 100*R; else L = 220*(R-1); if (verbose) { cout << "** m="<<m<<", #rounds="<<R<<", |q|="<<L << ", epsilon="<<epsilon<<endl; } epsilon /= R; try{ // FHE setup keys, context, SKMs, etc FHEcontext context(m, /*p=*/-1, r); context.scale=4; buildModChain(context, L, /*c=*/2); FHESecKey secretKey(context); secretKey.GenSecKey(); // A +-1/0 secret key addSome1DMatrices(secretKey); // compute key-switching matrices const FHEPubKey publicKey = secretKey; const EncryptedArrayCx& ea = context.ea->getCx(); if (verbose) { ea.getPAlgebra().printout(); cout << "r = " << context.alMod.getR() << endl; cout << "ctxtPrimes="<<context.ctxtPrimes << ", specialPrimes="<<context.specialPrimes<<endl<<endl; } if (debug) { dbgKey = & secretKey; dbgEa = (EncryptedArray*) context.ea; } // Run the tests. testBasicArith(publicKey, secretKey, ea, epsilon); testComplexArith(publicKey, secretKey, ea, epsilon); testRotsNShifts(publicKey, secretKey, ea, epsilon); testGeneralOps(publicKey, secretKey, ea, epsilon*R, R); } catch (exception& e) { cerr << e.what() << endl; cerr << "***Major FAIL***" << endl; } return 0; }
int main(int argc, char *argv[]) { ArgMapping amap; long m=17; amap.arg("m", m, "cyclotomic index"); amap.note("e.g., m=2047"); long p=2; amap.arg("p", p, "plaintext base"); long r=1; amap.arg("r", r, "lifting"); Vec<long> gens0; amap.arg("gens", gens0, "use specified vector of generators", NULL); amap.note("e.g., gens='[562 1871 751]'"); Vec<long> ords0; amap.arg("ords", ords0, "use specified vector of orders", NULL); amap.note("e.g., ords='[4 2 -4]', negative means 'bad'"); amap.parse(argc, argv); cout << "m = " << m << ", p = " << p << ", r = " << r << endl; vector<long> f; factorize(f,m); cout << "factoring "<<m<<" gives ["; for (unsigned long i=0; i<f.size(); i++) cout << f[i] << " "; cout << "]\n"; vector<long> gens1, ords1; convert(gens1, gens0); convert(ords1, ords0); PAlgebra al(m, p, gens1, ords1); al.printout(); cout << "\n"; PAlgebraMod almod(al, r); FHEcontext context(m, p, r); buildModChain(context, 5, 2); stringstream s1; writeContextBase(s1, context); s1 << context; string s2 = s1.str(); cout << s2 << endl; stringstream s3(s2); unsigned long m1, p1, r1; vector<long> gens, ords; readContextBase(s3, m1, p1, r1, gens, ords); FHEcontext c1(m1, p1, r1, gens, ords); s3 >> c1; if (context == c1) cout << "equal\n"; else cout << "not equal\n"; return 0; }
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"; }