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; } } } }
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; } } } }
// Build a full permutation network void PermNetwork::buildNetwork(const Permut& pi, const GeneratorTrees& trees) { if (trees.numTrees()==0) { // the identity permutation, nothing to do layers.SetLength(0); return; } Vec<long> dims; trees.getCubeSubDims(dims); // std::cerr << "pi = "<<pi<<endl; // std::cerr << "map2cube ="<<trees.mapToCube()<<endl; // std::cerr << "map2array="<<trees.mapToArray()<<endl; // Compute the permutation on the cube, rho = map2cube o pi o map2array Permut rho; applyPermsToVec(rho, trees.mapToCube(), pi, trees.mapToArray()); // std::cerr << "rho = "<<rho<<endl; // Break rho along the different dimensions CubeSignature sig(dims); // make a cube-signature object vector<ColPerm> perms; breakPermByDim(perms, rho, sig); // for (long i=0; i<(long)perms.size(); i++) { // debugging printouts // Permut tmp; // perms[i].makeExplicit(tmp); // std::cerr << " prems["<<i<<"]="<<tmp<<endl; // } layers.SetLength(trees.numLayers()); // allocate space // Go over the different permutations and build the corresponding layers long dimIdx =0; long frntLyr=0, backLyr=layers.length(); for (long g=0; g<trees.numTrees(); g++) { // go over all the generators/trees const OneGeneratorTree &T = trees[g]; // In each tree, go over all the leaves for (long leaf=T.firstLeaf(); leaf>=0; leaf=T.nextLeaf(leaf)) { const SubDimension& leafData = T[leaf].getData(); // This leaf determines layers frntLyer...frntLey+frst.length()-1, and // if it isn't the middle then also backLyr-scnd.length()...backLyr-1 // handle the first Benes network setLayers4Leaf(/*1st-layer-index=*/frntLyr, /*permutation =*/perms[dimIdx], /*Benes levels =*/leafData.frstBenes, /*generator index=*/T.getAuxKey(), /*(size,good,e) =*/leafData, /*hypercube renaming permutation=*/trees.mapToCube()); frntLyr += leafData.frstBenes.length(); // how many layers were used dimIdx++; if (leafData.scndBenes.length()>0) { // Also a second Benes network long dimIdx2 = perms.size() -dimIdx; // dimIdx was incremented above backLyr -= leafData.scndBenes.length(); setLayers4Leaf(/*1st-layer-index=*/backLyr, /*permutation =*/perms[dimIdx2], /*Benes levels =*/leafData.scndBenes, /*generator index=*/T.getAuxKey(), /*(size,good,e) =*/leafData, /*hypercube renaming permutation=*/trees.mapToCube()); } } } }
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(); } }