void QGrooveSession::getCommunicationToken() { const QString GS_FUNCTION = "getCommunicationToken"; // Generate secretKey QCryptographicHash secretKey(QCryptographicHash::Md5); secretKey.addData(this->gsSessionId.toUtf8()); QMap<QString, QVariant> parameters; parameters["secretKey"] = secretKey.result().toHex(); // Get header map and generate JSON to complete the request QMap<QString, QVariant> request; request["parameters"] = parameters; request["header"] = this->getHeaderMap(GS_FUNCTION); request["method"] = GS_FUNCTION; gsRequest->postData(this->HOST + this->getEndpoint() + "?" + GS_FUNCTION, QRequest::jsonEncode(request), 2); }
void NTCPSession::CreateAESKey (uint8_t * pubKey, uint8_t * aesKey) { CryptoPP::DH dh (elgp, elgg); CryptoPP::SecByteBlock secretKey(dh.AgreedValueLength()); if (!dh.Agree (secretKey, i2p::context.GetPrivateKey (), pubKey)) { LogPrint ("Couldn't create shared key"); Terminate (); return; }; if (secretKey[0] & 0x80) { aesKey[0] = 0; memcpy (aesKey + 1, secretKey, 31); } else memcpy (aesKey, secretKey, 32); }
int main(int argc, char *argv[]) { if (argc<2) { cout << "\nUsage: " << argv[0] << " L [c=2 w=64 k=80 d=1]" << endl; cout << " L is the number of levels\n"; cout << " optional c is number of columns in the key-switching matrices (default=2)\n"; cout << " optional w is Hamming weight of the secret key (default=64)\n"; cout << " optional k is the security parameter (default=80)\n"; cout << " optional d specifies GF(2^d) arithmetic (default=1, must be <=16)\n"; // cout << " k is the security parameter\n"; // cout << " m determines the ring mod Phi_m(X)" << endl; cout << endl; exit(0); } cout.unsetf(ios::floatfield); cout.precision(4); long L = atoi(argv[1]); long c = 2; long w = 64; long k = 80; long d = 1; if (argc>2) c = atoi(argv[2]); if (argc>3) w = atoi(argv[3]); if (argc>4) k = atoi(argv[4]); if (argc>5) d = atoi(argv[5]); if (d>16) Error("d cannot be larger than 16\n"); cout << "\nTesting FHE with parameters L="<<L << ", c="<<c<<", w="<<w<<", k="<<k<<", d="<<d<< endl; // get a lower-bound on the parameter N=phi(m): // 1. Empirically, we use ~20-bit small primes in the modulus chain (the main // constraints is that 2m must divide p-1 for every prime p). The first // prime is larger, a 40-bit prime. (If this is a 32-bit machine then we // use two 20-bit primes instead.) // 2. With L levels, the largest modulus for "fresh ciphertexts" has size // q0 ~ p0 * p^{L} ~ 2^{40+20L} // 3. We break each ciphertext into upto c digits, do each digit is as large // as D=2^{(40+20L)/c} // 4. The added noise variance term from the key-switching operation is // c*N*sigma^2*D^2, and this must be mod-switched down to w*N (so it is // on part with the added noise from modulus-switching). Hence the ratio // P that we use for mod-switching must satisfy c*N*sigma^2*D^2/P^2<w*N, // or P > sqrt(c/w) * sigma * 2^{(40+20L)/c} // 5. With this extra P factor, the key-switching matrices are defined // relative to a modulus of size // Q0 = q0*P ~ sqrt{c/w} sigma 2^{(40+20L)(1+1/c)} // 6. To get k-bit security we need N>log(Q0/sigma)(k+110)/7.2, i.e. roughly // N > (40+20L)(1+1/c)(k+110) / 7.2 long ptxtSpace = 2; double cc = 1.0+(1.0/(double)c); long N = (long) ceil((pSize*L+p0Size)*cc*(k+110)/7.2); cout << " bounding phi(m) > " << N << endl; #if 0 // A small m for debugging purposes long m = 15; #else // pre-computed values of [phi(m),m,d] long ms[][4] = { //phi(m) m ord(2) c_m*1000 { 1176, 1247, 28, 3736}, { 1936, 2047, 11, 3870}, { 2880, 3133, 24, 3254}, { 4096, 4369, 16, 3422}, { 5292, 5461, 14, 4160}, { 5760, 8435, 24, 8935}, { 8190, 8191, 13, 1273}, {10584, 16383, 14, 8358}, {10752, 11441, 48, 3607}, {12000, 13981, 20, 2467}, {11520, 15665, 24, 14916}, {14112, 18415, 28, 11278}, {15004, 15709, 22, 3867}, {15360, 20485, 24, 12767}, // {16384, 21845, 16, 12798}, {17208 ,21931, 24, 18387}, {18000, 18631, 25, 4208}, {18816, 24295, 28, 16360}, {19200, 21607, 40, 35633}, {21168, 27305, 28, 15407}, {23040, 23377, 48, 5292}, {24576, 24929, 48, 5612}, {27000, 32767, 15, 20021}, {31104, 31609, 71, 5149}, {42336, 42799, 21, 5952}, {46080, 53261, 24, 33409}, {49140, 57337, 39, 2608}, {51840, 59527, 72, 21128}, {61680, 61681, 40, 1273}, {65536, 65537, 32, 1273}, {75264, 82603, 56, 36484}, {84672, 92837, 56, 38520} }; #if 0 for (long i = 0; i < 25; i++) { long m = ms[i][1]; PAlgebra alg(m); alg.printout(); cout << "\n"; // compute phi(m) directly long phim = 0; for (long j = 0; j < m; j++) if (GCD(j, m) == 1) phim++; if (phim != alg.phiM()) cout << "ERROR\n"; } exit(0); #endif // find the first m satisfying phi(m)>=N and d | ord(2) in Z_m^* long m = 0; for (unsigned i=0; i<sizeof(ms)/sizeof(long[3]); i++) if (ms[i][0]>=N && (ms[i][2] % d) == 0) { m = ms[i][1]; c_m = 0.001 * (double) ms[i][3]; break; } if (m==0) Error("Cannot support this L,d combination"); #endif // m = 257; FHEcontext context(m); #if 0 context.stdev = to_xdouble(0.5); // very low error #endif activeContext = &context; // Mark this as the "current" context context.zMstar.printout(); cout << endl; // Set the modulus chain #if 1 // The first 1-2 primes of total p0size bits #if (NTL_SP_NBITS > p0Size) AddPrimesByNumber(context, 1, 1UL<<p0Size); // add a single prime #else AddPrimesByNumber(context, 2, 1UL<<(p0Size/2)); // add two primes #endif #endif // The next L primes, as small as possible AddPrimesByNumber(context, L); ZZ productOfCtxtPrimes = context.productOfPrimes(context.ctxtPrimes); double productSize = context.logOfProduct(context.ctxtPrimes); // might as well test that the answer is roughly correct cout << " context.logOfProduct(...)-log(context.productOfPrimes(...)) = " << productSize-log(productOfCtxtPrimes) << endl; // calculate the size of the digits context.digits.resize(c); IndexSet s1; #if 0 for (long i=0; i<c-1; i++) context.digits[i] = IndexSet(i,i); context.digits[c-1] = context.ctxtPrimes / IndexSet(0,c-2); AddPrimesByNumber(context, 2, 1, true); #else double sizeSoFar = 0.0; double maxDigitSize = 0.0; if (c>1) { // break ciphetext into a few digits double dsize = productSize/c; // initial estimate double target = dsize-(pSize/3.0); long idx = context.ctxtPrimes.first(); for (long i=0; i<c-1; i++) { // compute next digit IndexSet s; while (idx <= context.ctxtPrimes.last() && sizeSoFar < target) { s.insert(idx); sizeSoFar += log((double)context.ithPrime(idx)); idx = context.ctxtPrimes.next(idx); } context.digits[i] = s; s1.insert(s); double thisDigitSize = context.logOfProduct(s); if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize; cout << " digit #"<<i+1<< " " <<s << ": size " << thisDigitSize << endl; target += dsize; } IndexSet s = context.ctxtPrimes / s1; // all the remaining primes context.digits[c-1] = s; double thisDigitSize = context.logOfProduct(s); if (maxDigitSize < thisDigitSize) maxDigitSize = thisDigitSize; cout << " digit #"<<c<< " " <<s << ": size " << thisDigitSize << endl; } else { maxDigitSize = context.logOfProduct(context.ctxtPrimes); context.digits[0] = context.ctxtPrimes; } // Add primes to the chain for the P factor of key-switching double sizeOfSpecialPrimes = maxDigitSize + log(c/(double)w)/2 + log(context.stdev *2); AddPrimesBySize(context, sizeOfSpecialPrimes, true); #endif cout << "* ctxtPrimes: " << context.ctxtPrimes << ", log(q0)=" << context.logOfProduct(context.ctxtPrimes) << endl; cout << "* specialPrimes: " << context.specialPrimes << ", log(P)=" << context.logOfProduct(context.specialPrimes) << endl; for (long i=0; i<context.numPrimes(); i++) { cout << " modulus #" << i << " " << context.ithPrime(i) << endl; } cout << endl; setTimersOn(); const ZZX& PhimX = context.zMstar.PhimX(); // The polynomial Phi_m(X) long phim = context.zMstar.phiM(); // The integer phi(m) FHESecKey secretKey(context); const FHEPubKey& publicKey = secretKey; #if 0 // Debug mode: use sk=1,2 DoubleCRT newSk(to_ZZX(2), context); long id1 = secretKey.ImportSecKey(newSk, 64, ptxtSpace); newSk -= 1; long id2 = secretKey.ImportSecKey(newSk, 64, ptxtSpace); #else long id1 = secretKey.GenSecKey(w,ptxtSpace); // A Hamming-weight-w secret key long id2 = secretKey.GenSecKey(w,ptxtSpace); // A second Hamming-weight-w secret key #endif ZZX zero = to_ZZX(0); // Ctxt zeroCtxt(publicKey); /******************************************************************/ /** TESTS BEGIN HERE ***/ /******************************************************************/ cout << "ptxtSpace = " << ptxtSpace << 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 X; SetX(X); #if 1 // code for rotations... { GF2X::HexOutput = 1; const PAlgebra& al = context.zMstar; const PAlgebraModTwo& al2 = context.modTwo; long ngens = al.numOfGens(); long nslots = al.NSlots(); DoubleCRT tmp(context); vector< vector< DoubleCRT > > maskTable; maskTable.resize(ngens); for (long i = 0; i < ngens; i++) { if (i==0 && al.SameOrd(i)) continue; long ord = al.OrderOf(i); maskTable[i].resize(ord+1, tmp); for (long j = 0; j <= ord; j++) { // initialize the mask that is 1 whenever // the ith coordinate is at least j vector<GF2X> maps, alphas, betas; al2.mapToSlots(maps, G); // Change G to X to get bits in the slots alphas.resize(nslots); for (long k = 0; k < nslots; k++) if (coordinate(al, i, k) >= j) alphas[k] = 1; else alphas[k] = 0; GF2X ptxt; al2.embedInSlots(ptxt, alphas, maps); // Sanity-check, make sure that encode/decode works as expected al2.decodePlaintext(betas, ptxt, G, maps); for (long k = 0; k < nslots; k++) { if (alphas[k] != betas[k]) { cout << " Mask computation failed, i="<<i<<", j="<<j<<"\n"; return 0; } } maskTable[i][j] = to_ZZX(ptxt); } } vector<GF2X> maps; al2.mapToSlots(maps, G); vector<GF2X> alphas(nslots); for (long i=0; i < nslots; i++) random(alphas[i], 8); // random degree-7 polynomial mod 2 for (long amt = 0; amt < 20; amt++) { cout << "."; GF2X ptxt; al2.embedInSlots(ptxt, alphas, maps); DoubleCRT pp(context); pp = to_ZZX(ptxt); rotate(pp, amt, maskTable); GF2X ptxt1 = to_GF2X(to_ZZX(pp)); vector<GF2X> betas; al2.decodePlaintext(betas, ptxt1, G, maps); for (long i = 0; i < nslots; i++) { if (alphas[i] != betas[(i+amt)%nslots]) { cout << " amt="<<amt<<" oops\n"; return 0; } } } cout << "\n"; #if 0 long ord0 = al.OrderOf(0); for (long i = 0; i < nslots; i++) { cout << alphas[i] << " "; if ((i+1) % (nslots/ord0) == 0) cout << "\n"; } cout << "\n\n"; cout << betas.size() << "\n"; for (long i = 0; i < nslots; i++) { cout << betas[i] << " "; if ((i+1) % (nslots/ord0) == 0) cout << "\n"; } #endif return 0; } #endif // an initial sanity check on noise estimates, // comparing the estimated variance to the actual average cout << "pk:"; checkCiphertext(publicKey.pubEncrKey, zero, secretKey); ZZX ptxt[6]; // first four are plaintext, last two are constants std::vector<Ctxt> ctxt(4, Ctxt(publicKey)); // Initialize the plaintext and constants to random 0-1 polynomials for (size_t j=0; j<6; j++) { ptxt[j].rep.SetLength(phim); for (long i = 0; i < phim; i++) ptxt[j].rep[i] = RandomBnd(ptxtSpace); ptxt[j].normalize(); if (j<4) { publicKey.Encrypt(ctxt[j], ptxt[j], ptxtSpace); cout << "c"<<j<<":"; checkCiphertext(ctxt[j], ptxt[j], secretKey); } } // perform upto 2L levels of computation, each level computing: // 1. c0 += c1 // 2. c1 *= c2 // L1' = max(L1,L2)+1 // 3. c1.reLinearlize // 4. c2 *= p4 // 5. c2.automorph(k) // k is the first generator of Zm^* /(2) // 6. c2.reLinearlize // 7. c3 += p5 // 8. c3 *= c0 // L3' = max(L3,L0,L1)+1 // 9. c2 *= c3 // L2' = max(L2,L0+1,L1+1,L3+1)+1 // 10. c0 *= c0 // L0' = max(L0,L1)+1 // 11. c0.reLinearlize // 12. c2.reLinearlize // 13. c3.reLinearlize // // The levels of the four ciphertexts behave as follows: // 0, 0, 0, 0 => 1, 1, 2, 1 => 2, 3, 3, 2 // => 4, 4, 5, 4 => 5, 6, 6, 5 // => 7, 7, 8, 7 => 8,,9, 9, 10 => [...] // // We perform the same operations on the plaintext, and after each operation // we check that decryption still works, and print the curretn modulus and // noise estimate. We stop when we get the first decryption error, or when // we reach 2L levels (which really should not happen). zz_pContext zzpc; zz_p::init(ptxtSpace); zzpc.save(); const zz_pXModulus F = to_zz_pX(PhimX); long g = context.zMstar.ZmStarGen(0); // the first generator in Zm* zz_pX x2g(g, 1); zz_pX p2; // generate a key-switching matrix from s(X^g) to s(X) secretKey.GenKeySWmatrix(/*powerOfS= */ 1, /*powerOfX= */ g, 0, 0, /*ptxtSpace=*/ ptxtSpace); // generate a key-switching matrix from s^2 to s secretKey.GenKeySWmatrix(/*powerOfS= */ 2, /*powerOfX= */ 1, 0, 0, /*ptxtSpace=*/ ptxtSpace); // generate a key-switching matrix from s^3 to s secretKey.GenKeySWmatrix(/*powerOfS= */ 3, /*powerOfX= */ 1, 0, 0, /*ptxtSpace=*/ ptxtSpace); for (long lvl=0; lvl<2*L; lvl++) { cout << "=======================================================\n"; ctxt[0] += ctxt[1]; ptxt[0] += ptxt[1]; PolyRed(ptxt[0], ptxtSpace, true); cout << "c0+=c1: "; checkCiphertext(ctxt[0], ptxt[0], secretKey); ctxt[1].multiplyBy(ctxt[2]); ptxt[1] = (ptxt[1] * ptxt[2]) % PhimX; PolyRed(ptxt[1], ptxtSpace, true); cout << "c1*=c2: "; checkCiphertext(ctxt[1], ptxt[1], secretKey); ctxt[2].multByConstant(ptxt[4]); ptxt[2] = (ptxt[2] * ptxt[4]) % PhimX; PolyRed(ptxt[2], ptxtSpace, true); cout << "c2*=p4: "; checkCiphertext(ctxt[2], ptxt[2], secretKey); ctxt[2] >>= g; zzpc.restore(); p2 = to_zz_pX(ptxt[2]); CompMod(p2, p2, x2g, F); ptxt[2] = to_ZZX(p2); cout << "c2>>="<<g<<":"; checkCiphertext(ctxt[2], ptxt[2], secretKey); ctxt[2].reLinearize(); cout << "c2.relin:"; checkCiphertext(ctxt[2], ptxt[2], secretKey); ctxt[3].addConstant(ptxt[5]); ptxt[3] += ptxt[5]; PolyRed(ptxt[3], ptxtSpace, true); cout << "c3+=p5: "; checkCiphertext(ctxt[3], ptxt[3], secretKey); ctxt[3].multiplyBy(ctxt[0]); ptxt[3] = (ptxt[3] * ptxt[0]) % PhimX; PolyRed(ptxt[3], ptxtSpace, true); cout << "c3*=c0: "; checkCiphertext(ctxt[3], ptxt[3], secretKey); ctxt[0].square(); ptxt[0] = (ptxt[0] * ptxt[0]) % PhimX; PolyRed(ptxt[0], ptxtSpace, true); cout << "c0*=c0: "; checkCiphertext(ctxt[0], ptxt[0], secretKey); ctxt[2].multiplyBy(ctxt[3]); ptxt[2] = (ptxt[2] * ptxt[3]) % PhimX; PolyRed(ptxt[2], ptxtSpace, true); cout << "c2*=c3: "; checkCiphertext(ctxt[2], ptxt[2], secretKey); } /******************************************************************/ /** TESTS END HERE ***/ /******************************************************************/ cout << endl; return 0; }
//Comparison protocol based on "" bool COM(bool disp, long long seed, unsigned p, FHEcontext &context) { ZZ seedZZ; seedZZ = seed; srand48(seed); SetSeed(seedZZ); FHESISecKey secretKey(context); const FHESIPubKey &publicKey(secretKey); long phim = context.zMstar.phiM(); ZZ_pX ptxt1Poly, ptxt2Poly, sum, sumMult, prod, prod2, sumQuad; Plaintext resSum, resSumMult, resProd, resProdSwitch, resProd2, resSumQuad; //gen plaintext ptxt1Poly.rep.SetLength(phim); ptxt2Poly.rep.SetLength(phim); for (long i=0; i < phim; i++) { ptxt1Poly.rep[i] = RandomBnd(p); ptxt2Poly.rep[i] = RandomBnd(p); } //printpoly(ptxt1Poly, phim); ptxt1Poly.normalize(); ptxt2Poly.normalize(); #ifdef DEBUG cout<<"phim:"<<phim<<endl; cout<<"p1:"<<endl; printpoly(ptxt1Poly, phim); cout<<"p2:"<<endl; printpoly(ptxt2Poly, phim); #endif //plaintext operation sum = ptxt1Poly + ptxt2Poly; sumMult = ptxt2Poly * 7; prod = ptxt1Poly * ptxt2Poly; prod2 = prod * prod; sumQuad = prod2 * prod2 * 9; //\sum_((xy)^4) #ifdef DEBUG cout<<"sum:"<<endl; printpoly(sum, phim); cout<<"prod2:"<<endl; printpoly(prod2, phim); #endif rem(prod, prod, to_ZZ_pX(context.zMstar.PhimX())); rem(prod2, prod2, to_ZZ_pX(context.zMstar.PhimX())); rem(sumQuad, sumQuad, to_ZZ_pX(context.zMstar.PhimX())); //encryption start = std::clock(); Plaintext ptxt1(context, ptxt1Poly), ptxt2(context, ptxt2Poly); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; duration = duration/2; cout<<"Encryption:"<< duration <<'\n'; Ciphertext ctxt1(publicKey), ctxt2(publicKey); publicKey.Encrypt(ctxt1, ptxt1); publicKey.Encrypt(ctxt2, ptxt2); Ciphertext cSum = ctxt1; cSum += ctxt2; Ciphertext cSumMult = ctxt2; start = std::clock(); for (int i = 1; i < 7; i++) { cSumMult += ctxt2; } duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC); duration = duration/6; cout<<"Addition:"<< duration <<'\n'; Ciphertext cProd = ctxt1; cProd *= ctxt2; secretKey.Decrypt(resSum, cSum); secretKey.Decrypt(resSumMult, cSumMult); KeySwitchSI keySwitch(secretKey); keySwitch.ApplyKeySwitch(cProd); secretKey.Decrypt(resProd, cProd); cProd *= cProd; Ciphertext tmp = cProd; Ciphertext cSumQuad = cProd; keySwitch.ApplyKeySwitch(cProd); secretKey.Decrypt(resProd2, cProd); for (int i = 0; i < 8; i++) { cSumQuad += tmp; } keySwitch.ApplyKeySwitch(cSumQuad); //apply key switch after summing all prod start = std::clock(); cSumQuad *= cProd; duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC); cout<<"HMult without key switch:"<< duration <<'\n'; keySwitch.ApplyKeySwitch(cSumQuad); duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC); cout<<"HMult with key switch:"<< duration <<'\n'; start = std::clock(); secretKey.Decrypt(resSumQuad, cSumQuad); duration = ( std::clock() - start ) / (double) (CLOCKS_PER_SEC); cout<<"Decryption:"<< duration <<'\n'; //comparison bool success = ((resSum.message == sum) && (resSumMult.message == sumMult) && (resProd.message == prod) && (resProd2.message == prod2) && (resSumQuad == sumQuad)); if (disp || !success) { cout << "Seed: " << seed << endl << endl; if (resSum.message != sum) { cout << "Add failed." << endl; } if (resSumMult.message != sumMult) { cout << "Adding multiple times failed." << endl; } if (resProd.message != prod) { cout << "Multiply failed." << endl; } if (resProd2.message != prod2) { cout << "Squaring failed." << endl; } if (resSumQuad.message != sumQuad) { cout << "Sum and quad failed." << endl; } } if (disp || !success) { cout << "Test " << (success ? "SUCCEEDED" : "FAILED") << endl; } return success; }
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 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[]) { /*************************** 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); }
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(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; }
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; } }
// 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(){ 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[]) { long seed = time(NULL); srand48(seed); SetSeed(to_ZZ(seed)); unsigned p = 2027; unsigned g = 3; unsigned logQ = 120; FHEcontext context(p-1, logQ, p, g); activeContext = &context; context.SetUpSIContext(); FHESISecKey secretKey(context); const FHESIPubKey &publicKey(secretKey); KeySwitchSI keySwitch(secretKey); long phim = context.zMstar.phiM(); long numSlots = context.GetPlaintextSpace().GetTotalSlots(); long rotAmt = rand() % numSlots; long rotDeg = 1; for (int i = 0; i < rotAmt; i++) { rotDeg *= context.Generator(); rotDeg %= context.zMstar.M(); } KeySwitchSI automorphKeySwitch(secretKey, rotDeg); Plaintext p0, p1, p2, p3; randomizePlaintext(p0, phim, p); randomizePlaintext(p1, phim, p); randomizePlaintext(p2, phim, p); randomizePlaintext(p3, phim, p); Plaintext const1, const2; randomizePlaintext(const1, phim, p); randomizePlaintext(const2, phim, p); Ciphertext c0(publicKey); Ciphertext c1(publicKey); Ciphertext c2(publicKey); Ciphertext c3(publicKey); publicKey.Encrypt(c0, p0); publicKey.Encrypt(c1, p1); publicKey.Encrypt(c2, p2); publicKey.Encrypt(c3, p3); p1 *= p2; p0 += const1; p2 *= const2; p3 >>= rotAmt; p1 *= -1; p3 *= p2; p0 -= p3; c1 *= c2; keySwitch.ApplyKeySwitch(c1); c0 += const1.message; c2 *= const2.message; c3 >>= rotDeg; automorphKeySwitch.ApplyKeySwitch(c3); c1 *= -1; c3 *= c2; keySwitch.ApplyKeySwitch(c3); Ciphertext tmp(c3); tmp *= -1; c0 += tmp; Plaintext pp0, pp1, pp2, pp3; secretKey.Decrypt(pp0, c0); secretKey.Decrypt(pp1, c1); secretKey.Decrypt(pp2, c2); secretKey.Decrypt(pp3, c3); if (!(pp0 == p0)) cerr << "oops 0" << endl; if (!(pp1 == p1)) cerr << "oops 1" << endl; if (!(pp2 == p2)) cerr << "oops 2" << endl; if (!(pp3 == p3)) cerr << "oops 3" << endl; cout << "All tests finished." << endl; }
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; }
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"; }