void testCube(Vec<GenDescriptor>& vec, long widthBound) { GeneratorTrees trees; long cost = trees.buildOptimalTrees(vec, widthBound); if (!noPrint) { cout << "@TestCube: trees=" << trees << endl; cout << " cost =" << cost << endl; } Vec<long> dims; trees.getCubeDims(dims); CubeSignature sig(dims); for (long cnt=0; cnt<3; cnt++) { Permut pi; randomPerm(pi, trees.getSize()); PermNetwork net; net.buildNetwork(pi, trees); HyperCube<long> cube1(sig), cube2(sig); for (long i=0; i<cube1.getSize(); i++) cube1[i] = i; HyperCube<long> cube3 = cube1; applyPermToVec(cube2.getData(), cube1.getData(), pi); // direct application net.applyToCube(cube3); // applying permutation netwrok if (cube2==cube3) cout << "GOOD\n"; else { cout << "BAD\n"; if (cube1.getSize()<100 && !noPrint) { cout << "in="<<cube1.getData() << endl; cout << "out1="<<cube2.getData()<<", out2=" << cube3.getData()<<endl<<endl; } } } }
// Generate all key-switching matrices for a given permutation network void addMatrices4Network(FHESecKey& sKey, const PermNetwork& net, long keyID) { const FHEcontext &context = sKey.getContext(); long m = context.zMStar.getM(); for (long i=0; i<net.depth(); i++) { long e = net.getLayer(i).getE(); long gIdx = net.getLayer(i).getGenIdx(); long g = context.zMStar.ZmStarGen(gIdx); long g2e = PowerMod(g, e, m); // g^e mod m const Vec<long>&shamts = net.getLayer(i).getShifts(); for (long j=0; j<shamts.length(); j++) { if (shamts[j]==0) continue; long val = PowerMod(g2e, shamts[j], m); sKey.GenKeySWmatrix(1, val, keyID, keyID); } } sKey.setKeySwitchMap(); // re-compute the key-switching map }
void testCube(Vec<GenDescriptor>& vec, long widthBound) { GeneratorTrees trees; long cost = trees.buildOptimalTrees(vec, widthBound); cout << "@TestCube: trees=" << trees << endl; cout << " cost =" << cost << endl; Vec<long> dims; trees.getCubeDims(dims); CubeSignature sig(dims); for (long cnt=0; cnt<3; cnt++) { Permut pi; randomPerm(pi, trees.getSize()); // if (pi.length()<100) cout << "pi="<<pi<<endl; PermNetwork net; net.buildNetwork(pi, trees); // if (pi.length()<100) { // cout << "permutations network {[gIdx,e,isID,shifts]} = " << endl; // cout << net << endl; // } HyperCube<long> cube1(sig), cube2(sig); for (long i=0; i<cube1.getSize(); i++) cube1[i] = i; HyperCube<long> cube3 = cube1; applyPermToVec(cube2.getData(), cube1.getData(), pi); // direct application net.applyToCube(cube3); // applying permutation netwrok if (cube2==cube3) cout << "yay\n"; else { cout << "blech\n"; if (cube1.getSize()<100) { cout << "in="<<cube1.getData() << endl; cout << "out1="<<cube2.getData()<<", out2=" << cube3.getData()<<endl<<endl; } } } }
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(); } }