void sampleGaussian(ZZX &poly, long n, double stdev) { static double const Pi=4.0*atan(1.0); // Pi=3.1415.. static long const bignum = 0xfffffff; // THREADS: C++11 guarantees these are initialized only once if (n<=0) n=deg(poly)+1; if (n<=0) return; poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial for (long i=0; i<n; i++) SetCoeff(poly, i, ZZ::zero()); // Uses the Box-Muller method to get two Normal(0,stdev^2) variables for (long i=0; i<n; i+=2) { double r1 = (1+RandomBnd(bignum))/((double)bignum+1); double r2 = (1+RandomBnd(bignum))/((double)bignum+1); double theta=2*Pi*r1; double rr= sqrt(-2.0*log(r2))*stdev; assert(rr < 8*stdev); // sanity-check, no more than 8 standard deviations // Generate two Gaussians RV's, rounded to integers long x = (long) floor(rr*cos(theta) +0.5); SetCoeff(poly, i, x); if (i+1 < n) { x = (long) floor(rr*sin(theta) +0.5); SetCoeff(poly, i+1, x); } } poly.normalize(); // need to call this after we work on the coeffs }
int main() { zz_p::init(2); long i; vec_GF2 v; v.SetLength(5); v[1] = 1; v[0] = v[1]; if (v[0] != v[1]) Error("BitMatTest not OK!!"); for (i=0; i < 8; i++) { mat_zz_p a, x; mat_GF2 A, X, X1; long n = RandomBnd(500) + 1; long m = RandomBnd(500) + 1; cerr << n << " " << m << "\n"; double t; random(a, n, m); t = GetTime(); kernel(x, a); t = GetTime() - t; cerr << t << "\n"; cvt(A, a); t = GetTime(); kernel(X, A); t = GetTime() - t; cerr << t << "\n"; cerr << x.NumRows() << "\n"; cvt(X1, x); if (X1 != X) Error("BitMatTest NOT OK!!"); if (!IsZero(X*A)) Error("BitMatTest NOT OK!!"); cerr << "\n"; } cerr << "BitMatTest OK\n"; }
long PrimeTest(const ZZ& n, long t) { if (n <= 1) return 0; PrimeSeq s; long p; p = s.next(); while (p && p < 2000) { if ((n % p) == 0) return (n == p); p = s.next(); } ZZ x; long i; for (i = 0; i < t; i++) { x = RandomBnd(n); if (witness(n, x)) return 0; } return 1; }
Wallet::Wallet(const ZZ &sk, const ZZ &sIn, const ZZ &tIn, int size, int d, const BankParameters* bp, int st, int l, const hashalg_t &alg, const vector<ZZ> &sig) : sk_u(sk), s(sIn), t(tIn), walletSize(size), coinDenom(d), numCoinsUsed(0), params(bp), stat(st), lx(l), hashAlg(alg), signature(sig) { // generate a list of the indices that haven't yet been added to // the spendOrder vector for(int i = 0; i < walletSize; i++) { //spendOrder[i] = i; spendOrder.push_back(i); } // fill the spendOrder vector // On iteration i, remaining free indices are values // remainingIndices[0], ..., remainingIndices[walletSize - i - 1] for(int i = 0; i < walletSize; i++) { int index = RandomBnd(walletSize); int temp = spendOrder[i]; spendOrder[i] = spendOrder[index]; spendOrder[index] = temp; } #ifdef DEBUG for(int i = 0; i < walletSize; i++) { cout << spendOrder[i] << " "; } #endif //DEBUG }
// choose random curve // if IsZero(Z), then X is non-trivial factor of ZZ_p::modulus() void ECM_random_curve(EC_pCurve& curve, ZZ_p& X, ZZ_p& Z) { ZZ sigma; RandomBnd(sigma,ZZ_p::modulus()-6); sigma+=6; ZZ_p u,v; u = sqr(to_ZZ_p(sigma))-5; v = 4*to_ZZ_p(sigma); ZZ_p C,Cd; C = (v-u)*sqr(v-u)*(3*u+v); Cd = 4*u*sqr(u)*v; // make sure Cd is invertible ZZ Cinv; if (InvModStatus(Cinv,rep(Cd),ZZ_p::modulus())!=0) { conv(X,Cinv); clear(Z); return; } C*=to_ZZ_p(Cinv); C-=2; // random curve ZZ_pX f; SetCoeff(f,3); SetCoeff(f,2,C); SetCoeff(f,1); conv(curve,f); curve.SetRepresentation(curve.MONTGOMERY); // initial point mul(X,u,sqr(u)); mul(Z,v,sqr(v)); }
// Генерация ключей void genkeys ( ZZ &x, ZZ &y, ZZ &p, ZZ &q, ZZ &a) { RandomBnd(x, q-1); // Секретный ключ PowerMod(y, a%p, x%p, p); // Открытый ключ cout << "\nSecret key x = \n"; show_dec_in_hex (x, N); cout << endl; cout << "\nPublic key y = \n"; show_dec_in_hex (y, L); cout << endl; }
ZZX RandPoly(long n,const ZZ& p) { ZZX F; F.SetMaxLength(n); ZZ p2; p2=p>>1; for (long i=0; i<n; i++) { SetCoeff(F,i,RandomBnd(p)-p2); } return F; }
void randomizePlaintext(Plaintext &ptxt, unsigned deg, unsigned p) { ZZ_pX poly; poly.rep.SetLength(deg); for(unsigned i = 0; i < deg; i++) { poly.rep[i] = RandomBnd(p); } poly.normalize(); ptxt.Init(poly); }
NTL_CLIENT int main() { zz_p::init(17); zz_pX P; BuildIrred(P, 10); zz_pE::init(P); zz_pEX f, g, h; random(f, 20); SetCoeff(f, 20); random(h, 20); g = MinPolyMod(h, f); if (deg(g) < 0) Error("bad zz_pEXTest (1)"); if (CompMod(g, h, f) != 0) Error("bad zz_pEXTest (2)"); vec_pair_zz_pEX_long v; long i; for (i = 0; i < 5; i++) { long n = RandomBnd(20)+1; cerr << n << " "; random(f, n); SetCoeff(f, n); v = CanZass(f); g = mul(v); if (f != g) cerr << "oops1\n"; long i; for (i = 0; i < v.length(); i++) if (!DetIrredTest(v[i].a)) Error("bad zz_pEXTest (3)"); } cerr << "\n"; cerr << "zz_pEXTest OK\n"; }
void IndexCalc::IndexCalculus(){ ZZ y; long limit = primeNumbers.length(); ZZ x; for(long i = 0; i < 4*limit; i++){ x = RandomBnd(p) + 1; } }
// Generate a random permutation on [0..n-1] void randomPerm(Permut& perm, long n) { perm.SetLength(n); for (long j = 0; j < n; j++) perm[j] = j; // random shuffle for (long m = n; m > 0; m--) { long p = RandomBnd(m); // swap positions p and m-1 of perm long tmp = perm[p]; perm[p] = perm[m-1]; perm[m-1] = tmp; } }
template <typename T> vec_ZZ RandomPoint(LatticeBasis<T>& B,int seed,int dim=0) { //Generate uniformly random point in the box \prod[-b*i/2,b*i/2] B.updateGSBasis(); vec_ZZ ret; ZZ det = LatticeVolumeZZ(B); if (dim==0) dim = B.dim; ret.SetLength(dim); SetSeed(to_ZZ(seed)); for (int i=0;i<dim;i++) { ret[i] = RandomBnd(det); } ret = NearestPlane(ret,B); return ret; }
// Генерация ЭЦП void gensign ( ZZ &r, ZZ &s, ZZ &H, ZZ &x, ZZ &p, ZZ &q, ZZ &a) { ZZ k; while ( s == 0 ) { RandomBnd(k, q); // Случайное число k r = PowerMod(a%p, k%p, p) % q; if ( r == 0 ) continue; s = (x * r + k * H ) % q; if ( s == 0 ) continue; } cout << "\nGenerate sign\n"; cout << "\nSession key k = \n"; show_dec_in_hex (H, N); cout << endl; cout << "\nr = \n"; show_dec_in_hex (r, N); cout << endl; cout << "\ns = \n"; show_dec_in_hex (s, N); cout << endl; }
// same as ProbPrime(), but with no trial division stage bool ProbPrime_notd(const ZZ& n, long NumTrials=10) { // first try W == 2....the exponentiation // algorithm runs slightly faster in this case ZZ W; W = 2; if (MillerWitness(n, W)) return false; while (--NumTrials>=0) { do { RandomBnd(W,n); } while (IsZero(W)); // W == 0 is not a useful candidate for a witness! if (MillerWitness(n, W)) return false; } return true; }
template <typename T> mat_ZZ RandomPoints(LatticeBasis<T>& B,int seed,int numrows,int dim=0) { B.updateGSBasis(); vec_ZZ r; ZZ det = LatticeVolumeZZ(B); if (dim==0) dim = B.dim; r.SetLength(dim); mat_ZZ ret; ret.SetDims(numrows,dim); SetSeed(to_ZZ(seed)); for (int k=0;k<numrows;k++) { for (int i=0;i<dim;i++) { r[i] = RandomBnd(det); } ret[k] = NearestPlane(r,B); } return ret; }
RandomMatrix(const EncryptedArray& _ea) : ea(_ea) { long n = ea.size(); long d = ea.getDegree(); long bnd = 2*n; // non-zero with probability 1/bnd RBak bak; bak.save(); ea.getContext().alMod.restoreContext(); data.resize(n); for (long i = 0; i < n; i++) { data[i].resize(n); for (long j = 0; j < n; j++) { bool zEntry = (RandomBnd(bnd) > 0); if (zEntry) clear(data[i][j]); else random(data[i][j], d); } } }
void sampleUniform(ZZX& poly, const ZZ& B, long n) { if (n<=0) n=deg(poly)+1; if (n<=0) return; if (B <= 0) { clear(poly); return; } poly.SetMaxLength(n); // allocate space for degree-(n-1) polynomial ZZ UB, tmp; UB = 2*B + 1; for (long i = 0; i < n; i++) { RandomBnd(tmp, UB); tmp -= B; poly.rep[i] = tmp; } poly.normalize(); }
/************** Each round consists of the following: 1. c1.multiplyBy(c0) 2. c0 += random constant 3. c2 *= random constant 4. tmp = c1 5. ea.rotate(tmp, random amount in [-nSlots/2, nSlots/2]) 6. c2 += tmp 7. ea.rotate(c2, random amount in [1-nSlots, nSlots-1]) 8. c1.negate() 9. c3.multiplyBy(c2) 10. c0 -= c3 **************/ void testGeneralOps(const FHEPubKey& publicKey, const FHESecKey& secretKey, const EncryptedArrayCx& ea, double epsilon, long nRounds) { long nslots = ea.size(); char buffer[32]; vector<cx_double> p0, p1, p2, p3; ea.random(p0); ea.random(p1); ea.random(p2); ea.random(p3); Ctxt c0(publicKey), c1(publicKey), c2(publicKey), c3(publicKey); ea.encrypt(c0, publicKey, p0, /*size=*/1.0); ea.encrypt(c1, publicKey, p1, /*size=*/1.0); ea.encrypt(c2, publicKey, p2, /*size=*/1.0); ea.encrypt(c3, publicKey, p3, /*size=*/1.0); resetAllTimers(); FHE_NTIMER_START(Circuit); for (long i = 0; i < nRounds; i++) { if (verbose) std::cout << "*** round " << i << "..."<<endl; long shamt = RandomBnd(2*(nslots/2) + 1) - (nslots/2); // random number in [-nslots/2..nslots/2] long rotamt = RandomBnd(2*nslots - 1) - (nslots - 1); // random number in [-(nslots-1)..nslots-1] // two random constants vector<cx_double> const1, const2; ea.random(const1); ea.random(const2); ZZX const1_poly, const2_poly; ea.encode(const1_poly, const1, /*size=*/1.0); ea.encode(const2_poly, const2, /*size=*/1.0); mul(p1, p0); // c1.multiplyBy(c0) c1.multiplyBy(c0); if (verbose) { CheckCtxt(c1, "c1*=c0"); debugCompare(ea, secretKey, p1, c1, epsilon); } add(p0, const1); // c0 += random constant c0.addConstant(const1_poly); if (verbose) { CheckCtxt(c0, "c0+=k1"); debugCompare(ea, secretKey, p0, c0, epsilon); } mul(p2, const2); // c2 *= random constant c2.multByConstant(const2_poly); if (verbose) { CheckCtxt(c2, "c2*=k2"); debugCompare(ea, secretKey, p2, c2, epsilon); } vector<cx_double> tmp_p(p1); // tmp = c1 Ctxt tmp(c1); sprintf(buffer, "tmp=c1>>=%d", (int)shamt); rotate(tmp_p, shamt); // ea.shift(tmp, random amount in [-nSlots/2,nSlots/2]) ea.rotate(tmp, shamt); if (verbose) { CheckCtxt(tmp, buffer); debugCompare(ea, secretKey, tmp_p, tmp, epsilon); } add(p2, tmp_p); // c2 += tmp c2 += tmp; if (verbose) { CheckCtxt(c2, "c2+=tmp"); debugCompare(ea, secretKey, p2, c2, epsilon); } sprintf(buffer, "c2>>>=%d", (int)rotamt); rotate(p2, rotamt); // ea.rotate(c2, random amount in [1-nSlots, nSlots-1]) ea.rotate(c2, rotamt); if (verbose) { CheckCtxt(c2, buffer); debugCompare(ea, secretKey, p2, c2, epsilon); } negateVec(p1); // c1.negate() c1.negate(); if (verbose) { CheckCtxt(c1, "c1=-c1"); debugCompare(ea, secretKey, p1, c1, epsilon); } mul(p3, p2); // c3.multiplyBy(c2) c3.multiplyBy(c2); if (verbose) { CheckCtxt(c3, "c3*=c2"); debugCompare(ea, secretKey, p3, c3, epsilon); } sub(p0, p3); // c0 -= c3 c0 -= c3; if (verbose) { CheckCtxt(c0, "c0=-c3"); debugCompare(ea, secretKey, p0, c0, epsilon); } } c0.cleanUp(); c1.cleanUp(); c2.cleanUp(); c3.cleanUp(); FHE_NTIMER_STOP(Circuit); vector<cx_double> pp0, pp1, pp2, pp3; ea.decrypt(c0, secretKey, pp0); ea.decrypt(c1, secretKey, pp1); ea.decrypt(c2, secretKey, pp2); ea.decrypt(c3, secretKey, pp3); std::cout << "Test "<<nRounds<<" rounds of mixed operations, "; if (cx_equals(pp0, p0,conv<double>(epsilon*c0.getPtxtMag())) && cx_equals(pp1, p1,conv<double>(epsilon*c1.getPtxtMag())) && cx_equals(pp2, p2,conv<double>(epsilon*c2.getPtxtMag())) && cx_equals(pp3, p3,conv<double>(epsilon*c3.getPtxtMag()))) std::cout << "PASS\n\n"; else { std::cout << "FAIL:\n"; std::cout << " max(p0)="<<largestCoeff(p0) << ", max(pp0)="<<largestCoeff(pp0) << ", maxDiff="<<calcMaxDiff(p0,pp0) << endl; std::cout << " max(p1)="<<largestCoeff(p1) << ", max(pp1)="<<largestCoeff(pp1) << ", maxDiff="<<calcMaxDiff(p1,pp1) << endl; std::cout << " max(p2)="<<largestCoeff(p2) << ", max(pp2)="<<largestCoeff(pp2) << ", maxDiff="<<calcMaxDiff(p2,pp2) << endl; std::cout << " max(p3)="<<largestCoeff(p3) << ", max(pp3)="<<largestCoeff(pp3) << ", maxDiff="<<calcMaxDiff(p3,pp3) << endl<<endl; } if (verbose) { std::cout << endl; printAllTimers(); std::cout << endl; } resetAllTimers(); }
long IsFFTPrime(long n, long& w) { long m, x, y, z; long j, k; if (n <= 1 || n >= NTL_SP_BOUND) return 0; if (n % 2 == 0) return 0; if (n % 3 == 0) return 0; if (n % 5 == 0) return 0; if (n % 7 == 0) return 0; m = n - 1; k = 0; while ((m & 1) == 0) { m = m >> 1; k++; } for (;;) { x = RandomBnd(n); if (x == 0) continue; z = PowerMod(x, m, n); if (z == 1) continue; x = z; j = 0; do { y = z; z = MulMod(y, y, n); j++; } while (j != k && z != 1); if (z != 1 || y != n-1) return 0; if (j == k) break; } /* x^{2^k} = 1 mod n, x^{2^{k-1}} = -1 mod n */ long TrialBound; TrialBound = m >> k; if (TrialBound > 0) { if (!ProbPrime(n, 5)) return 0; /* we have to do trial division by special numbers */ TrialBound = SqrRoot(TrialBound); long a, b; for (a = 1; a <= TrialBound; a++) { b = (a << k) + 1; if (n % b == 0) return 0; } } /* n is an FFT prime */ for (j = NTL_FFTMaxRoot; j < k; j++) x = MulMod(x, x, n); w = x; return 1; }
int main() { #ifdef NTL_LONG_LONG if (sizeof(NTL_LL_TYPE) < 2*sizeof(long)) { printf("999999999999999 "); print_flag(); return 0; } #endif SetSeed(ZZ(0)); long i, k; k = 10*NTL_ZZ_NBITS; for (i = 0; i < 10000; i++) { ZZ a, b, c, d; long da = RandomBnd(k); long db = RandomBnd(k); long dc = RandomBnd(k); long dd = RandomBnd(k); RandomLen(a, da); RandomLen(b, db); RandomLen(c, dc); RandomLen(d, dd); if ((a + b)*(c + d) != c*a + d*a + c*b + d*b) { printf("999999999999999 "); print_flag(); return 0; } } for (i = 0; i < 10000; i++) { ZZ a, b, c; long da = RandomBnd(k); long db = RandomBnd(k); long dc = RandomBnd(k) + 2; RandomLen(a, da); RandomLen(b, db); RandomLen(c, dc); if ( ( a * b ) % c != ((a % c) * (b % c)) % c ) { printf("999999999999999 "); print_flag(); return 0; } } k = 1024; ZZ x1, x2, x3; double t; long j; RandomLen(x1, k); RandomLen(x2, k); long iter; mul(x3, x1, x2); iter = 1; do { t = GetTime(); for (i = 0; i < iter; i++) { for (j = 0; j < 500; j++) mul(x3, x1, x2); } t = GetTime() - t; iter = 2*iter; } while(t < 1); iter = iter/2; iter = long((3/t)*iter) + 1; double tvec[5]; long w; for (w = 0; w < 5; w++) { t = GetTime(); for (i = 0; i < iter; i++) { for (j = 0; j < 500; j++) mul(x3, x1, x2); } t = GetTime() - t; tvec[w] = t; } t = clean_data(tvec); t = floor((t/iter)*1e14); if (t < 0 || t >= 1e15) printf("999999999999999 "); else printf("%015.0f ", t); printf(" [%ld] ", iter); print_flag(); return 0; }
int main() { cerr << "This is NTL version " << NTL_VERSION << "\n"; cerr << "Basic Configuration Options:\n"; #ifdef NTL_STD_CXX cerr << "NTL_STD_CXX\n"; #endif #ifdef NTL_PSTD_NNS cerr << "NTL_PSTD_NNS\n"; #endif #ifdef NTL_PSTD_NHF cerr << "NTL_PSTD_NHF\n"; #endif #ifdef NTL_PSTD_NTN cerr << "NTL_PSTD_NTN\n"; #endif #ifdef NTL_GMP_LIP cerr << "NTL_GMP_LIP\n"; #endif #ifdef NTL_GMP_HACK cerr << "NTL_GMP_HACK\n"; #endif #ifdef NTL_GF2X_LIB cerr << "NTL_GF2X_LIB\n"; #endif #ifdef NTL_LONG_LONG_TYPE cerr << "NTL_LONG_LONG_TYPE: "; cerr << make_string(NTL_LONG_LONG_TYPE) << "\n"; #endif #ifdef NTL_UNSIGNED_LONG_LONG_TYPE cerr << "NTL_UNSIGNED_LONG_LONG_TYPE: "; cerr << make_string(NTL_UNSIGNED_LONG_LONG_TYPE) << "\n"; #endif #ifdef NTL_CXX_ONLY cerr << "NTL_CXX_ONLY\n"; #endif #ifdef NTL_X86_FIX cerr << "NTL_X86_FIX\n"; #endif #ifdef NTL_NO_X86_FIX cerr << "NTL_NO_X86_FIX\n"; #endif #ifdef NTL_NO_INIT_TRANS cerr << "NTL_NO_INIT_TRANS\n"; #endif #ifdef NTL_CLEAN_INT cerr << "NTL_CLEAN_INT\n"; #endif #ifdef NTL_CLEAN_PTR cerr << "NTL_CLEAN_PTR\n"; #endif #ifdef NTL_RANGE_CHECK cerr << "NTL_RANGE_CHECK\n"; #endif cerr << "\n"; cerr << "Resolution of double-word types:\n"; cerr << make_string(NTL_LL_TYPE) << "\n"; cerr << make_string(NTL_ULL_TYPE) << "\n"; cerr << "\n"; cerr << "Performance Options:\n"; #ifdef NTL_LONG_LONG cerr << "NTL_LONG_LONG\n"; #endif #ifdef NTL_AVOID_FLOAT cerr << "NTL_AVOID_FLOAT\n"; #endif #ifdef NTL_SPMM_UL cerr << "NTL_SPMM_UL\n"; #endif #ifdef NTL_SPMM_ULL cerr << "NTL_SPMM_ULL\n"; #endif #ifdef NTL_SPMM_ASM cerr << "NTL_SPMM_ASM\n"; #endif #ifdef NTL_AVOID_BRANCHING cerr << "NTL_AVOID_BRANCHING\n"; #endif #ifdef NTL_TBL_REM cerr << "NTL_TBL_REM\n"; #endif #ifdef NTL_GF2X_ALTCODE cerr << "NTL_GF2X_ALTCODE\n"; #endif #ifdef NTL_GF2X_ALTCODE1 cerr << "NTL_GF2X_ALTCODE1\n"; #endif #ifdef NTL_GF2X_NOINLINE cerr << "NTL_GF2X_NOINLINE\n"; #endif cerr << "\n\n"; if (_ntl_gmp_hack) cerr << "using GMP hack\n\n"; cerr << "running tests..."; long n, k; n = 200; k = 10*NTL_ZZ_NBITS; ZZ p; GenPrime(p, k); ZZ_p::init(p); // initialization ZZ_pX f, g, h, r1, r2, r3; random(g, n); // g = random polynomial of degree < n random(h, n); // h = " " random(f, n); // f = " " // SetCoeff(f, n); // Sets coefficient of X^n to 1 ZZ_p lc; do { random(lc); } while (IsZero(lc)); SetCoeff(f, n, lc); // For doing arithmetic mod f quickly, one must pre-compute // some information. ZZ_pXModulus F; build(F, f); PlainMul(r1, g, h); // this uses classical arithmetic PlainRem(r1, r1, f); MulMod(r2, g, h, F); // this uses the FFT MulMod(r3, g, h, f); // uses FFT, but slower // compare the results... if (r1 != r2) { cerr << "r1 != r2!!\n"; return 1; } else if (r1 != r3) { cerr << "r1 != r3!!\n"; return 1; } // small prime tests...I've made some changes in v5.3 // that should be checked on various platforms, so // we might as well check them here. if (SmallModulusTest(17, 1000)) { cerr << "first SmallModulusTest failed!!\n"; return 1; } if (SmallModulusTest((1L << (NTL_SP_NBITS))-1, 1000)) { cerr << "second SmallModulusTest failed!!\n"; return 1; } // Test gf2x code.... if (GF2X_test()) { cerr << "GF2X test failed!\n"; return 1; } cerr << "OK\n"; ZZ x1, x2, x3, x4; double t; long i; RandomLen(x1, 1024); RandomBnd(x2, x1); RandomBnd(x3, x1); mul(x4, x2, x3); t = GetTime(); for (i = 0; i < 100000; i++) mul(x4, x2, x3); t = GetTime()-t; cerr << "time for 1024-bit mul: " << t*10 << "us"; if (_ntl_gmp_hack) { _ntl_gmp_hack = 0; mul(x4, x2, x3); t = GetTime(); for (i = 0; i < 100000; i++) mul(x4, x2, x3); t = GetTime()-t; cerr << " (" << (t*10) << "us without GMP)"; _ntl_gmp_hack = 1; } cerr << "\n"; rem(x2, x4, x1); t = GetTime(); for (i = 0; i < 100000; i++) rem(x2, x4, x1); t = GetTime()-t; cerr << "time for 2048/1024-bit rem: " << t*10 << "us"; if (_ntl_gmp_hack) { _ntl_gmp_hack = 0; rem(x2, x4, x1); t = GetTime(); for (i = 0; i < 100000; i++) rem(x2, x4, x1); t = GetTime()-t; cerr << " (" << (t*10) << "us without GMP)"; _ntl_gmp_hack = 1; } cerr << "\n"; GenPrime(p, 1024); RandomBnd(x1, p); if (IsZero(x1)) set(x1); InvMod(x2, x1, p); t = GetTime(); for (i = 0; i < 1000; i++) InvMod(x2, x1, p); t = GetTime()-t; cerr << "time for 1024-bit modular inverse: " << t*1000 << "us"; if (_ntl_gmp_hack) { _ntl_gmp_hack = 0; InvMod(x2, x1, p); t = GetTime(); for (i = 0; i < 1000; i++) InvMod(x2, x1, p); t = GetTime()-t; cerr << " (" << (t*1000) << "us without GMP)"; _ntl_gmp_hack = 1; } cerr << "\n"; // test modulus switching n = 1024; k = 1024; RandomLen(p, k); ZZ_p::init(p); ZZ_pInfo->check(); ZZ_pX j1, j2, j3; random(j1, n); random(j2, n); t = GetTime(); for (i = 0; i < 20; i++) mul(j3, j1, j2); t = GetTime()-t; cerr << "time to multiply degree 1023 polynomials\n modulo a 1024-bit number: "; cerr << (t/20) << "s"; if (_ntl_gmp_hack) { _ntl_gmp_hack = 0; ZZ_p::init(p); ZZ_pInfo->check(); t = GetTime(); for (i = 0; i < 20; i++) mul(j3, j1, j2); t = GetTime()-t; cerr << " (" << (t/20) << "s without GMP)"; _ntl_gmp_hack = 1; } cerr << "\n"; GF2X_time(); return 0; }
int main() { #ifdef NTL_SPMM_ULL if (sizeof(NTL_ULL_TYPE) < 2*sizeof(long)) { printf("999999999999999 "); print_flag(); return 0; } #endif long n, k; n = 200; k = 10*NTL_ZZ_NBITS; ZZ p; RandomLen(p, k); ZZ_p::init(p); // initialization ZZ_pX f, g, h, r1, r2, r3; random(g, n); // g = random polynomial of degree < n random(h, n); // h = " " random(f, n); // f = " " SetCoeff(f, n); // Sets coefficient of X^n to 1 // For doing arithmetic mod f quickly, one must pre-compute // some information. ZZ_pXModulus F; build(F, f); PlainMul(r1, g, h); // this uses classical arithmetic PlainRem(r1, r1, f); MulMod(r2, g, h, F); // this uses the FFT MulMod(r3, g, h, f); // uses FFT, but slower // compare the results... if (r1 != r2) { printf("999999999999999 "); print_flag(); return 0; } else if (r1 != r3) { printf("999999999999999 "); print_flag(); return 0; } double t; long i, j; long iter; const int nprimes = 30; const long L = 12; const long N = 1L << L; long r; for (r = 0; r < nprimes; r++) UseFFTPrime(r); vec_long aa[nprimes], AA[nprimes]; for (r = 0; r < nprimes; r++) { aa[r].SetLength(N); AA[r].SetLength(N); for (i = 0; i < N; i++) aa[r][i] = RandomBnd(GetFFTPrime(r)); FFTFwd(AA[r].elts(), aa[r].elts(), L, r); FFTRev1(AA[r].elts(), AA[r].elts(), L, r); } iter = 1; do { t = GetTime(); for (j = 0; j < iter; j++) { for (r = 0; r < nprimes; r++) { long *AAp = AA[r].elts(); long *aap = aa[r].elts(); long q = GetFFTPrime(r); mulmod_t qinv = GetFFTPrimeInv(r); FFTFwd(AAp, aap, L, r); FFTRev1(AAp, aap, L, r); for (i = 0; i < N; i++) AAp[i] = NormalizedMulMod(AAp[i], aap[i], q, qinv); } } t = GetTime() - t; iter = 2*iter; } while(t < 1); iter = iter/2; iter = long((1.5/t)*iter) + 1; double tvec[5]; long w; for (w = 0; w < 5; w++) { t = GetTime(); for (j = 0; j < iter; j++) { for (r = 0; r < nprimes; r++) { long *AAp = AA[r].elts(); long *aap = aa[r].elts(); long q = GetFFTPrime(r); mulmod_t qinv = GetFFTPrimeInv(r); FFTFwd(AAp, aap, L, r); FFTRev1(AAp, aap, L, r); for (i = 0; i < N; i++) AAp[i] = NormalizedMulMod(AAp[i], aap[i], q, qinv); } } t = GetTime() - t; tvec[w] = t; } t = clean_data(tvec); t = floor((t/iter)*1e13); if (t < 0 || t >= 1e15) printf("999999999999999 "); else printf("%015.0f ", t); printf(" [%ld] ", iter); print_flag(); return 0; }
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; }
int main() { long n, i, j, iter, s, k; double t; for (i = 0; i < 10000; i++) { GF2X a, b, c, d; long da = RandomBnd(5*NTL_BITS_PER_LONG); long db = RandomBnd(5*NTL_BITS_PER_LONG); long dc = RandomBnd(5*NTL_BITS_PER_LONG); long dd = RandomBnd(5*NTL_BITS_PER_LONG); random(a, da); random(b, db); random(c, dc); random(d, dd); if ((a + b)*(c + d) != c*a + d*a + c*b + d*b) { printf("999999999999999 "); print_flag(); return 0; } } n = 16; s = 56; GF2X *a = new GF2X[s]; GF2X *b = new GF2X[s]; GF2X c; for (k = 0; k < s; k++) { random(a[k], (n + (k % 7))*NTL_BITS_PER_LONG); random(b[k], (n + (k % 8))*NTL_BITS_PER_LONG); } for (k = 0; k < s; k++) mul(c, a[k], b[k]); iter = 1; do { t = GetTime(); for (i = 0; i < iter; i++) { for (j = 0; j < 1; j++) for (k = 0; k < s; k++) mul(c, a[k], b[k]); } t = GetTime() - t; iter = 2*iter; } while(t < 1); iter = iter/2; iter = long((2/t)*iter) + 1; double tvec[5]; long w; for (w = 0; w < 5; w++) { t = GetTime(); for (i = 0; i < iter; i++) { for (j = 0; j < 1; j++) for (k = 0; k < s; k++) mul(c, a[k], b[k]); } t = GetTime() - t; tvec[w] = t; } t = clean_data(tvec); t = floor((t/iter)*1e14); if (t < 0 || t >= 1e15) printf("999999999999999 "); else printf("%015.0f ", t); printf(" [%ld] ", iter); print_flag(); return 0; }
/************************** //Goldwasser-Micali HE system //len: length of params p,q **************************/ void GM(int len=512){ ZZ N, p, q, x; long m1, m2; ZZ BSm, HEm; //baseline and HE result ZZ c, c1, c2, cm1, cm2, r; //key gen start = std::clock(); GenPrime(p, len); GenPrime(q, len); mul(N, p, q); do{ RandomBnd(x, N); } while( (Jacobi(x,p)==1) || (Jacobi(x,q)==1)); cout<<"Jac:"<<Jacobi(x,p)<<Jacobi(x,q)<<endl; duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"GM Setup:"<< duration <<'\n'; //Enc RandomBnd(m1,2); RandomBnd(m2,2); start = std::clock(); RandomBnd(r, N); MulMod(cm1,r,r,N); if(m1==1) MulMod(cm1,cm1,x,N); RandomBnd(r, N); MulMod(cm2,r,r,N); if(m2==1) MulMod(cm2,cm2,x,N); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"GM Enc:"<< duration <<'\n'; //Evaluation start = std::clock(); MulMod(c,cm1,cm2,N); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"GM Eval:"<< duration <<'\n'; //Dec start = std::clock(); HEm=Jacobi(c,p); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"GM Dec:"<< duration <<'\n'; if(HEm==1) HEm=0; else HEm=1; //baseline BSm=m1^m2; //xor //cout<<"plaintext:"<<m1<<m2<<BSm<<endl; assert(BSm==HEm); }
/************************** //Paillier HE system //len: length of params p,q **************************/ void Paillier(int len=512){ ZZ n, n2, p, q, g, lamda; ZZ p1, q1, p1q1; ZZ miu; ZZ m1, m2; ZZ BSm, HEm; //baseline and HE result ZZ c, c1, c2, cm1, cm2, r; //key gen start = std::clock(); GenPrime(p, len); GenPrime(q, len); mul(n, p, q); mul(n2, n, n); sub(p1,p,1); sub(q1,q,1); GCD(lamda,p1,q1); mul(p1q1,p1,q1); div(lamda, p1q1, lamda); RandomBnd(g, n2); PowerMod(miu,g,lamda,n2); sub(miu, miu, 1); div(miu,miu,n); //should add 1? InvMod(miu, miu, n); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Setup:"<< duration <<'\n'; //Enc start = std::clock(); RandomBnd(m1,n); RandomBnd(m2,n); RandomBnd(r,n); //enc m1 PowerMod(c1, g,m1,n2); PowerMod(c2, r,n,n2); MulMod(cm1, c1,c2, n2); RandomBnd(r,n); //enc m2 PowerMod(c1, g,m2,n2); PowerMod(c2, r,n,n2); MulMod(cm2, c1,c2, n2); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Enc:"<< duration/2 <<'\n'; //Evaluation start = std::clock(); c=cm1; for(int i=0; i<TIMES; i++) MulMod(c,c,cm2,n2); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Eval:"<< duration <<'\n'; //c=cm2; //Dec start = std::clock(); PowerMod(c,c,lamda,n2); sub(c,c,1); div(c,c,n); //should add 1? MulMod(HEm, c, miu, n); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"Pailler Dec:"<< duration <<'\n'; //baseline BSm=m1; for(int i=0; i<TIMES; i++) AddMod(BSm,BSm,m2,n); assert(BSm==HEm); }
//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() { SetSeed(ZZ(0)); cerr << "This is NTL version " << NTL_VERSION << "\n"; cerr << "Hardware charactersitics:\n"; cerr << "NTL_BITS_PER_LONG = " << NTL_BITS_PER_LONG << "\n"; cerr << "NTL_ZZ_NBITS = " << NTL_ZZ_NBITS << "\n"; cerr << "NTL_SP_NBITS = " << NTL_SP_NBITS << "\n"; #ifdef NTL_HAVE_LL_TYPE cerr << "NTL_HAVE_LL_TYPE\n"; #endif #ifdef NTL_LONGDOUBLE_SP_MULMOD cerr << "NTL_LONGDOUBLE_SP_MULMOD\n"; #endif #ifdef NTL_LONGLONG_SP_MULMOD cerr << "NTL_LONGLONG_SP_MULMOD\n"; #endif cerr << "\n"; cerr << "Basic Configuration Options:\n"; #ifdef NTL_LEGACY_NO_NAMESPACE cerr << "NTL_LEGACY_NO_NAMESPACE\n"; #endif #ifdef NTL_LEGACY_INPUT_ERROR cerr << "NTL_LEGACY_INPUT_ERROR\n"; #endif #ifdef NTL_THREADS cerr << "NTL_THREADS\n"; #endif #ifdef NTL_EXCEPTIONS cerr << "NTL_EXCEPTIONS\n"; #endif #ifdef NTL_THREAD_BOOST cerr << "NTL_THREAD_BOOST\n"; #endif #ifdef NTL_LEGACY_SP_MULMOD cout << "NTL_LEGACY_SP_MULMOD\n"; #endif #ifdef NTL_DISABLE_LONGDOUBLE cout << "NTL_DISABLE_LONGDOUBLE\n"; #endif #ifdef NTL_DISABLE_LONGLONG cout << "NTL_DISABLE_LONGLONG\n"; #endif #ifdef NTL_MAXIMIZE_SP_NBITS cout << "NTL_MAXIMIZE_SP_NBITS\n"; #endif #ifdef NTL_GMP_LIP cerr << "NTL_GMP_LIP\n"; #endif #ifdef NTL_GF2X_LIB cerr << "NTL_GF2X_LIB\n"; #endif #ifdef NTL_PCLMUL cerr << "NTL_PCLMUL\n"; #endif #ifdef NTL_LONG_LONG_TYPE cerr << "NTL_LONG_LONG_TYPE: "; cerr << make_string(NTL_LONG_LONG_TYPE) << "\n"; #endif #ifdef NTL_UNSIGNED_LONG_LONG_TYPE cerr << "NTL_UNSIGNED_LONG_LONG_TYPE: "; cerr << make_string(NTL_UNSIGNED_LONG_LONG_TYPE) << "\n"; #endif #ifdef NTL_X86_FIX cerr << "NTL_X86_FIX\n"; #endif #ifdef NTL_NO_X86_FIX cerr << "NTL_NO_X86_FIX\n"; #endif #ifdef NTL_NO_INIT_TRANS cerr << "NTL_NO_INIT_TRANS\n"; #endif #ifdef NTL_CLEAN_INT cerr << "NTL_CLEAN_INT\n"; #endif #ifdef NTL_CLEAN_PTR cerr << "NTL_CLEAN_PTR\n"; #endif #ifdef NTL_RANGE_CHECK cerr << "NTL_RANGE_CHECK\n"; #endif cerr << "\n"; cerr << "Resolution of double-word types:\n"; cerr << make_string(NTL_LL_TYPE) << "\n"; cerr << make_string(NTL_ULL_TYPE) << "\n"; cerr << "\n"; cerr << "Performance Options:\n"; #ifdef NTL_LONG_LONG cerr << "NTL_LONG_LONG\n"; #endif #ifdef NTL_AVOID_FLOAT cerr << "NTL_AVOID_FLOAT\n"; #endif #ifdef NTL_SPMM_ULL cerr << "NTL_SPMM_ULL\n"; #endif #ifdef NTL_SPMM_ASM cerr << "NTL_SPMM_ASM\n"; #endif #ifdef NTL_AVOID_BRANCHING cerr << "NTL_AVOID_BRANCHING\n"; #endif #ifdef NTL_FFT_BIGTAB cout << "NTL_FFT_BIGTAB\n"; #endif #ifdef NTL_FFT_LAZYMUL cout << "NTL_FFT_LAZYMUL\n"; #endif #ifdef NTL_TBL_REM cerr << "NTL_TBL_REM\n"; #endif #ifdef NTL_TBL_REM_LL cerr << "NTL_TBL_REM_LL\n"; #endif #ifdef NTL_CRT_ALTCODE cerr << "NTL_CRT_ALTCODE\n"; #endif #ifdef NTL_CRT_ALTCODE_SMALL cerr << "NTL_CRT_ALTCODE_SMALL\n"; #endif #ifdef NTL_GF2X_ALTCODE cerr << "NTL_GF2X_ALTCODE\n"; #endif #ifdef NTL_GF2X_ALTCODE1 cerr << "NTL_GF2X_ALTCODE1\n"; #endif #ifdef NTL_GF2X_NOINLINE cerr << "NTL_GF2X_NOINLINE\n"; #endif cerr << "\n\n"; cerr << "running tests"; long n, k, i; n = 250; k = 16000; ZZ p; for (i = 0; i < 15; i++) { // cerr << n << "/" << k; cerr << "."; RandomLen(p, k); ZZ_p::init(p); ZZ_pX a, b, c, c1; random(a, n); random(b, n); FFTMul(c, a, b); //cerr << ZZ_pInfo->FFTInfo->NumPrimes; c1 = conv<ZZ_pX>( KarMul( conv<ZZX>(a), conv<ZZX>(b) ) ); if (c1 != c) { cerr << "ZZ_pX mul failed!\n"; return 1; } n = long(n * 1.35); k = long(k / 1.414); } // small prime tests...I've made some changes in v5.3 // that should be checked on various platforms, so // we might as well check them here. if (SmallModulusTest(17, 1000)) { cerr << "first SmallModulusTest failed!!\n"; return 1; } if (SmallModulusTest((1L << (NTL_SP_NBITS))-1, 1000)) { cerr << "second SmallModulusTest failed!!\n"; return 1; } // Test gf2x code.... if (GF2X_test()) { cerr << "GF2X test failed!\n"; return 1; } cerr << "OK\n"; ZZ x1, x2, x3, x4; double t; RandomLen(x1, 1024); RandomBnd(x2, x1); RandomBnd(x3, x1); mul(x4, x2, x3); t = GetTime(); for (i = 0; i < 100000; i++) mul(x4, x2, x3); t = GetTime()-t; cerr << "time for 1024-bit mul: " << t*10 << "us"; cerr << "\n"; rem(x2, x4, x1); t = GetTime(); for (i = 0; i < 100000; i++) rem(x2, x4, x1); t = GetTime()-t; cerr << "time for 2048/1024-bit rem: " << t*10 << "us"; cerr << "\n"; GenPrime(p, 1024); RandomBnd(x1, p); if (IsZero(x1)) set(x1); InvMod(x2, x1, p); t = GetTime(); for (i = 0; i < 1000; i++) InvMod(x2, x1, p); t = GetTime()-t; cerr << "time for 1024-bit modular inverse: " << t*1000 << "us"; cerr << "\n"; // test modulus switching n = 1024; k = 1024; RandomLen(p, k); ZZ_p::init(p); if (!IsOdd(p)) p++; ZZ_pX j1, j2, j3; random(j1, n); random(j2, n); mul(j3, j1, j2); t = GetTime(); for (i = 0; i < 200; i++) mul(j3, j1, j2); t = GetTime()-t; cerr << "time to multiply degree 1023 polynomials\n modulo a 1024-bit number: "; cerr << (t/200) << "s"; cerr << "\n"; GF2X_time(); return 0; }
int main() { RR::SetPrecision(150); long n, b, size; cerr << "n: "; cin >> n; cerr << "b: "; cin >> b; cerr << "size: "; cin >> size; cerr << "prune: "; long prune; cin >> prune; ZZ seed; cerr << "seed: "; cin >> seed; if (seed != 0) SetSeed(seed); char alg; cerr << "alg [fqQxr]: "; cin >> alg; double TotalTime = 0; long TotalSucc = 0; long iter; for (iter = 1; iter <= 20; iter++) { vec_ZZ a; a.SetLength(n); ZZ bound; LeftShift(bound, to_ZZ(1), b); long i; for (i = 1; i <= n; i++) { RandomBnd(a(i), bound); a(i) += 1; } ZZ S; do { RandomLen(S, n+1); } while (weight(S) != n/2+1); ZZ s; clear(s); for (i = 1; i <= n; i++) if (bit(S, i-1)) s += a(i); mat_ZZ B(INIT_SIZE, n+1, n+3); for (i = 1; i <= n; i++) { B(i, i) = 2; B(i, n+1) = a(i) * n; B(i, n+3) = n; } for (i = 1; i <= n; i++) B(n+1, i) = 1; B(n+1, n+1) = s * n; B(n+1, n+2) = 1; B(n+1, n+3) = n; B(n+1, n+3) *= n/2; swap(B(1), B(n+1)); for (i = 2; i <= n; i++) { long j = RandomBnd(n-i+2) + i; swap(B(i), B(j)); } double t; LLLStatusInterval = 10; t = GetTime(); switch (alg) { case 'f': BKZ_FP(B, 0.99, size, prune, SubsetSumSolution); break; case 'q': BKZ_QP(B, 0.99, size, prune, SubsetSumSolution); break; case 'Q': BKZ_QP1(B, 0.99, size, prune, SubsetSumSolution); break; case 'x': BKZ_XD(B, 0.99, size, prune, SubsetSumSolution); break; case 'r': BKZ_RR(B, 0.99, size, prune, SubsetSumSolution); break; default: Error("invalid algorithm"); } t = GetTime()-t; long succ = 0; for (i = 1; i <= n+1; i++) if (SubsetSumSolution(B(i))) succ = 1; TotalTime += t; TotalSucc += succ; if (succ) cerr << "+"; else cerr << "-"; } cerr << "\n"; cerr << "number of success: " << TotalSucc << "\n"; cerr << "average time: " << TotalTime/20 << "\n"; return 0; }
/************************** //ElGamal HE system //len: length of params p,q **************************/ void ElGamal(int len=512){ ZZ n, n2, p, q, g, x, lamda; ZZ p1, q1, p1q1; ZZ bA; ZZ m1, m2, k1, k2; ZZ BSm, HEm; //baseline and HE result ZZ c, r1, r2, t1, t2, cm1, cm2; ZZ r, t; //key gen start = std::clock(); GenPrime(q, len); RandomBnd(g, q); RandomBnd(x, q); PowerMod(bA,g,x, q); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"ElGamal Setup:"<< duration <<'\n'; //Enc RandomBnd(m1, q); RandomBnd(m2, q); start = std::clock(); RandomBnd(k1, q); //B PowerMod(r1,g,k1, q); PowerMod(t1,bA,k1, q); MulMod(t1, t1, m1, q); RandomBnd(k2, q); //B PowerMod(r2,g,k2, q); PowerMod(t2,bA,k2, q); MulMod(t2, t2, m2, q); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"ElGamal Enc:"<< duration/2 <<'\n'; //Evaluation start = std::clock(); MulMod(r,r1,r2,q); MulMod(t,t1,t2,q); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"ElGamal Eval:"<< duration/2 <<'\n'; //Dec start = std::clock(); PowerMod(HEm,r,x,q); InvMod(HEm, HEm, q); MulMod(HEm,HEm,t,q); duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; cout<<"ElGamal Dec:"<< duration/2 <<'\n'; //baseline MulMod(BSm,m1,m2,q); assert(BSm==HEm); }