ostream& operator<<(ostream& str, const FHEPubKey& pk) { str << "["; writeContextBase(str, pk.getContext()); // output the public encryption key itself str << pk.pubEncrKey << endl; // output skHwts in the same format as vec_long str << "["; for (long i=0; i<(long)pk.skHwts.size(); i++) str << pk.skHwts[i]<<" "; str << "]\n"; // output the key-switching matrices str << pk.keySwitching.size() << endl; for (long i=0; i<(long)pk.keySwitching.size(); i++) str << pk.keySwitching[i] << endl; // output keySwitchMap in the same format as vec_vec_long str << "["; for (long i=0; i<(long)pk.keySwitchMap.size(); i++) { str << "["; for (long j=0; j<(long)pk.keySwitchMap[i].size(); j++) str << pk.keySwitchMap[i][j] << " "; str << "]\n "; } str << "]\n"; str << pk.KS_strategy << "\n"; // output the bootstrapping key, if any str << pk.recryptKeyID << " "; if (pk.recryptKeyID>=0) str << pk.recryptEkey << endl; return str << "]"; }
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; }
// 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 }
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); } }