diff --git a/.vscode/settings.json b/.vscode/settings.json index f33cd36653b3a3dbb38cc531d7ee070e3c0ea1fe..c127f3a71e9a53f61e0cb540d59f3ef28f63bb54 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -46,6 +46,7 @@ "stdexcept": "cpp", "streambuf": "cpp", "typeinfo": "cpp", - "bit": "cpp" + "bit": "cpp", + "chrono": "cpp" } } \ No newline at end of file diff --git a/bin/ciphertext.o b/bin/ciphertext.o index 3dfc07a20ecfae7016cfddd6cfaaf91905c010c1..fdf967e0ee407cb913823f950841084e760e809a 100644 Binary files a/bin/ciphertext.o and b/bin/ciphertext.o differ diff --git a/bin/ckks.o b/bin/ckks.o index cc3ed5eeea7736a6881ebc2557bb9970fba809c2..f7177830de07a577c74798d4d92280441eb81259 100644 Binary files a/bin/ckks.o and b/bin/ckks.o differ diff --git a/bin/encoder.o b/bin/encoder.o index 75116dfb0aecb58a6c557ebcb47452b00703178d..bcadbac61ceb3d015445657f76d7aa0c56608d2a 100644 Binary files a/bin/encoder.o and b/bin/encoder.o differ diff --git a/bin/evalkey.o b/bin/evalkey.o index ba063c472fcf2ad902fc40176de3074f2137d63f..3e28b2d00d2d83df7a6298c1d4f7e85939e0ad28 100644 Binary files a/bin/evalkey.o and b/bin/evalkey.o differ diff --git a/bin/ntt.o b/bin/ntt.o index 40679a382429fbc1a6bdbe246ab1e757cb8db3aa..1ade2c809bf9907a892539002ea6f86f45485344 100644 Binary files a/bin/ntt.o and b/bin/ntt.o differ diff --git a/bin/polynomial.o b/bin/polynomial.o index 067b06b876f3d1a978807b1711a82b941dea529f..eab4a4b865234a36882fe3d19864fcbdae6a2188 100644 Binary files a/bin/polynomial.o and b/bin/polynomial.o differ diff --git a/bin/pubkey.o b/bin/pubkey.o index 170bbe8a88baf2f039c780acd6bddf007ee85e6b..9f076c661993fe6eaf71d983bebb8a22280934f6 100644 Binary files a/bin/pubkey.o and b/bin/pubkey.o differ diff --git a/bin/seckey.o b/bin/seckey.o index 257a327b70529a10066ffeb0315e9c7bb497942d..fd6124ac67ea06ef5800f07b7a34639b3b83b710 100644 Binary files a/bin/seckey.o and b/bin/seckey.o differ diff --git a/run b/run index f8a7d286a7d0f4d0e133f53be7216f3c2821f13e..2cfdbf179c1f65eaa41ce8f043fbc8efc5822481 100755 Binary files a/run and b/run differ diff --git a/src/ckks.cpp b/src/ckks.cpp index ec67b53929e96b45d204241282545ff5a06028c1..c11832b5a44511be19eca4088126cc7379ef1b7f 100644 --- a/src/ckks.cpp +++ b/src/ckks.cpp @@ -2,10 +2,54 @@ #include <complex> #include <cmath> #include <random> +#include <vector> #include "ckks.h" +#include "ntt.h" using namespace std; +#define size(c) ((int)(c).size()) + +vector<int64_t> vScale(vector<int64_t> a, double scale){ + int N = size(a); + vector<int64_t> out; + for(int i=0; i<N; i++){ + double temp = (double) a[i] * scale; + out.push_back((int64_t) temp); + } + return out; +} + +vector<int64_t> vAdd(vector<int64_t> a, vector<int64_t> b){ + int N = size(a); + vector<int64_t> out; + for(int i=0; i<N; i++){ + out.push_back(a[i] + b[i]); + } + return out; +} + +vector<int64_t> vMult(vector<int64_t> a, vector<int64_t> b){ + int N = size(a); + vector<int64_t> out; + for(int i=0; i<N; i++){ + out.push_back(a[i] * b[i]); + } + return out; +} + +Polynomial CKKS::fastMult(Polynomial p1, Polynomial p2, int deg, int64_t w){ + vector<int64_t> pol1 = ntt.ntt(p1, deg, w); + vector<int64_t> pol2 = ntt.ntt(p2, deg, w); + + vector<int64_t> mult; + for(int i=0; i<deg; i++){ + mult.push_back(pol1[i] * pol2[i]); + } + + Polynomial out = ntt.intt(mult, w); + return out; +} CKKS::CKKS(int N, PubKey _pk, EvalKey _evk, SecKey _sk){ pk = _pk; @@ -80,6 +124,47 @@ Ciphertext CKKS::mult(Ciphertext ct1, Ciphertext ct2){ Polynomial outC0 = d1.modCoeff(ql) + d3_0.modCoeff(ql); Polynomial outC1 = d2.modCoeff(ql) + d3_1.modCoeff(ql); + + + // Rescale + ql = (double)ql / (double)pl[level-1]; + Polynomial c0 = outC0.scaleRoundCoeff(1.0/(double)pl[level-1]); + Polynomial c1 = outC1.scaleRoundCoeff(1.0/(double)pl[level-1]); + + + + level -= 1; + + Ciphertext out(c0.modCoeff(ql), c1.modCoeff(ql)); + + return out; +} + +int getNextPow(int deg){ + int out = 2; + while(out < deg){ + out <<= 1; + } + return out; +} + +Ciphertext CKKS::multNTT(Ciphertext ct1, Ciphertext ct2){ + int deg = getNextPow(ct1.c0.degree+ct2.c0.degree-1); + cout << deg << endl; + int64_t w = ntt.genNthRoot(ntt.M, deg); + level += 1; + + Polynomial d1 = fastMult(ct1.c0, ct2.c0, deg, w).modCoeff(ql); + Polynomial d2 = (fastMult(ct1.c0, ct2.c1,deg, w) + fastMult(ct2.c0, ct1.c1,deg, w)).modCoeff(ql); + Polynomial d3 = fastMult(ct1.c1, ct2.c1,deg, w).modCoeff(ql); + + // Relin + Polynomial d3_0 = fastMult(d3, evk.b,deg, w).scaleRoundCoeff(1.0/1000.0); + Polynomial d3_1 = fastMult(d3, evk.a,deg, w).scaleRoundCoeff(1.0/1000.0); + + Polynomial outC0 = d1.modCoeff(ql) + d3_0.modCoeff(ql); + Polynomial outC1 = d2.modCoeff(ql) + d3_1.modCoeff(ql); + // Rescale ql = (double)ql / (double)pl[level-1]; Polynomial c0 = outC0.scaleRoundCoeff(1.0/(double)pl[level-1]); @@ -87,7 +172,6 @@ Ciphertext CKKS::mult(Ciphertext ct1, Ciphertext ct2){ level -= 1; - cout << "marker" << endl; Ciphertext out(c0.modCoeff(ql), c1.modCoeff(ql)); return out; } \ No newline at end of file diff --git a/src/ckks.h b/src/ckks.h index 2c1c269268537479e180700f0dd2709b5ddfe84b..fa1f8ed0d75d86c7931a76d214b802f6f1b3109a 100644 --- a/src/ckks.h +++ b/src/ckks.h @@ -3,6 +3,7 @@ #include "seckey.h" #include "evalkey.h" #include "ciphertext.h" +#include "ntt.h" #ifndef CKKS_H @@ -18,15 +19,17 @@ class CKKS { PubKey pk; EvalKey evk; SecKey sk; + NTT ntt; CKKS(int N, PubKey _pk, EvalKey _evk, SecKey _sk); Polynomial genE(int degree, double var); Polynomial genZO(); Ciphertext encrypt(Polynomial pt); Polynomial decrypt(Ciphertext ct); - + Polynomial fastMult(Polynomial p1, Polynomial p2, int deg, int64_t w); Ciphertext add(Ciphertext ct1, Ciphertext ct2); Ciphertext mult(Ciphertext ct1, Ciphertext ct2); + Ciphertext multNTT(Ciphertext ct1, Ciphertext ct2); }; #endif \ No newline at end of file diff --git a/src/encoder.cpp b/src/encoder.cpp index 9fdae21755b749432c37c9ca57fb2c34e8a0625a..f4b7eadb744b6c2f57e305d74fe1eb1d4d5e80e0 100644 --- a/src/encoder.cpp +++ b/src/encoder.cpp @@ -5,12 +5,24 @@ #include <eigen3/Eigen/Dense> #include "encoder.h" +#include <chrono> + + using namespace std; +using namespace std::chrono; + +dcomplex vdot(dcomplex a[], dcomplex* b, int size, int offset){ + dcomplex out (0.0, 0.0); + for(int i=0; i<size; i++){ + out += b[i+offset] * conj(a[i]); + } + return out; +} -dcomplex vdot(dcomplex a[], dcomplex b[]){ +dcomplex vdots(dcomplex* a, dcomplex* b, int size, int offset){ dcomplex out (0.0, 0.0); - for(int i=0; i<10; i++){ - out += b[i] * conj(a[i]); + for(int i=0; i<size; i++){ + out += b[offset+i] * conj(a[offset+i]); } return out; } @@ -22,20 +34,12 @@ double randomChoice(double val){ return ((number == 0) ? val : (val - 1.0)); } -dcomparr matMult(dcomplex mat[SIZE][SIZE], coeffarr in, int m){ - dcomparr out; - for(int i=0; i<m; i++){ - for(int j=0; j<m; j++){ - out.arr[i] += mat[i][j] * (double)in.arr[j]; - } - } - return out; -} - Encoder::Encoder(int in, double inScale){ M = in; scale = inScale; root = exp((2*M_PI/M) * J); + vandermonde = (dcomplex*) malloc(M/2*M/2*sizeof(dcomplex)); + sigmaRBasis = (dcomplex*) malloc(M/2*M/2*sizeof(dcomplex)); initVandermonde(root); initSigmaRBasis(); } @@ -45,9 +49,7 @@ void Encoder::initVandermonde(dcomplex xi){ for(int i=0; i<N; i++){ for(int j=0; j<N; j++){ int power = (2*i+1) * j; - dcomplex temp = pow(xi, power); - vandermonde[i][j] = temp; - vand(i,j) = temp; + vandermonde[i*N+j] = pow(xi, power); } } } @@ -56,7 +58,7 @@ void Encoder::initSigmaRBasis(){ int N = M/2; for(int i=0; i<N; i++){ for(int j=0; j<N; j++){ - sigmaRBasis[j][i] = vandermonde[i][j]; + sigmaRBasis[j*N+i] = vandermonde[i*N+j]; } } } @@ -78,28 +80,29 @@ dcomparr Encoder::sigma(Polynomial pol){ if(pol.degree == 2*N){ for(int i=0; i<N; i++){ for (int j=0; j<M/2; j++){ - out.arr[i] += pol.coeffs[j] * vandermonde[i][j]; + out.arr[i] += pol.coeffs[j] * vandermonde[i*M/2+j]; } } }else{ int R = 2; - dcomplex tempVandermonde[100][100]; while (R < pol.degree){ R <<=2; } + + dcomplex* tempVandermonde = (dcomplex*) malloc(R*R*sizeof(dcomplex)); for(int i=0; i<R; i++){ for(int j=0; j<R; j++){ int power = (2*i+1) * j; dcomplex temp = pow(exp((2*M_PI/M) * J), power); - tempVandermonde[i][j] = temp; + tempVandermonde[i*R+j] = temp; } } for(int i=0; i<R/2; i++){ for (int j=0; j<R; j++){ - out.arr[i] += pol.coeffs[j] * tempVandermonde[i][j]; + out.arr[i] += pol.coeffs[j] * tempVandermonde[i*R+j]; } } } @@ -107,30 +110,37 @@ dcomparr Encoder::sigma(Polynomial pol){ } dcomparr Encoder::decode(Polynomial pol){ + auto start = high_resolution_clock::now(); Polynomial unscaled = pol.scaleCoeff(1.0/scale); - return sigma(unscaled); + dcomparr out = sigma(unscaled); + + auto stop = high_resolution_clock::now(); + auto duration = duration_cast<microseconds>(stop - start); + //cout << "Decoding: " << duration.count() << endl; + + return out; } dcomparr Encoder::computeCoordinate(dcomparr z){ dcomparr out; for (int i=0; i<M/2; i++){ - dcomplex zi = vdot(z.arr, sigmaRBasis[i]) / vdot(sigmaRBasis[i], sigmaRBasis[i]); + dcomplex zi = vdot(z.arr, sigmaRBasis, M/2, i*M/2) / vdots(sigmaRBasis, sigmaRBasis, M/2, i*M/2); out.arr[i] = real(zi); } return out; } -coeffarr Encoder::coordinateWRR(dcomparr coordinates){ +dcomparr Encoder::coordinateWRR(dcomparr coordinates){ double r; double f; - coeffarr roundedCoor; + dcomparr roundedCoor; for (int i=0; i<M/2; i++){ r = real(coordinates.arr[i]) - floor(real(coordinates.arr[i])); f = randomChoice(r); - roundedCoor.arr[i] = round(real(coordinates.arr[i])-f); + roundedCoor.arr[i] = (double) real(coordinates.arr[i])-f; } return roundedCoor; @@ -138,31 +148,24 @@ coeffarr Encoder::coordinateWRR(dcomparr coordinates){ dcomparr Encoder::discretization(dcomparr z){ dcomparr coor = computeCoordinate(z); - coeffarr roundedCoor = coordinateWRR(coor); - dcomparr out = matMult(vandermonde, roundedCoor, M/2); - return out; + dcomparr roundedCoor = coordinateWRR(coor); + return roundedCoor; } Polynomial Encoder::sigmaInv(dcomparr z){ - Matrix1dc zRounded; int N = M/2; Polynomial out(N); - for (int i=0; i<N; i++){ - zRounded(i,0) = z.arr[i]; - } - - Matrix1dc res = vand.lu().solve(zRounded); - for(int i=0; i<N; i++){ - out.coeffs[i] = real(res(i,0)); + out.coeffs[i] = (double) round(real(z.arr[i])); } + return out; } Polynomial Encoder::encode(dcomparr input){ + auto start = high_resolution_clock::now(); dcomparr zPi = piInv(input); - int N = M/4; for (int i=0; i<N; i++){ zPi.arr[i] *= scale; @@ -172,6 +175,10 @@ Polynomial Encoder::encode(dcomparr input){ dcomparr roundZ = discretization(zPi); Polynomial out = sigmaInv(roundZ); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast<microseconds>(stop - start); + //cout << "Encoding: " << duration.count() << endl; + return out; } diff --git a/src/encoder.h b/src/encoder.h index 969e082f3d5e57f393955f44ee577fe54e23fc40..552ac6361a52b46785fabd176abe093120239a38 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -5,19 +5,14 @@ using namespace std; #define J dcomplex(0.0,1.0) -#define SIZE 100 +#define SIZE 1000 typedef complex<double> dcomplex; -typedef Eigen::Matrix<dcomplex, 4, 4> Matrix4dc; -typedef Eigen::Matrix<dcomplex, 4, 1> Matrix1dc; struct dcomparr { - dcomplex arr[SIZE]; + dcomplex arr[200]; }; -struct coeffarr { - int64_t arr[SIZE]; -}; #ifndef ENCODER_H #define ENCODER_H @@ -27,9 +22,8 @@ class Encoder { int M; double scale; dcomplex root; - dcomplex vandermonde[SIZE][SIZE]; - dcomplex sigmaRBasis[SIZE][SIZE]; - Matrix4dc vand; + dcomplex* vandermonde; + dcomplex* sigmaRBasis; Encoder(int in, double inScale); void initVandermonde(dcomplex xi); @@ -38,7 +32,7 @@ class Encoder { dcomparr sigma(Polynomial pol); dcomparr decode(Polynomial pol); dcomparr computeCoordinate(dcomparr z); - coeffarr coordinateWRR(dcomparr coordinates); + dcomparr coordinateWRR(dcomparr coordinates); dcomparr discretization(dcomparr z); Polynomial sigmaInv(dcomparr z); Polynomial encode(dcomparr input); diff --git a/src/evalkey.cpp b/src/evalkey.cpp index 68bce70e247c52e0c0a8f8da75b0b0f0f8c73808..5c53b7fa0772f22abc7400d5f859b3124cfda937 100644 --- a/src/evalkey.cpp +++ b/src/evalkey.cpp @@ -12,7 +12,7 @@ EvalKey::EvalKey(Polynomial _s, int degree, int64_t q){ p = 1000; s = _s; - generateA(4, 1000); + generateA(degree, 100); computeB(q); } @@ -32,10 +32,10 @@ Polynomial EvalKey::genE(int degree, double var){ } void EvalKey::generateA(int degree, int64_t q){ - int64_t half_q = (p*q)/2; + int64_t half_q = (q)/2; random_device rd; mt19937 gen(rd()); - uniform_int_distribution<int64_t> dis(-half_q, half_q); + uniform_int_distribution<int64_t> dis(0, half_q); double a_coeffs[degree]; for (int i=0; i<degree; i++){ diff --git a/src/ntt.cpp b/src/ntt.cpp index 40be4f1d7c70eeed5024da63d00be543bf5578ce..6a5764181dd3f7984e016ae6599f6c2e60e76cd0 100644 --- a/src/ntt.cpp +++ b/src/ntt.cpp @@ -1,9 +1,9 @@ #include "ntt.h" -int NTT::modExp(int base, int power, int mod){ - int res = 1; - int p = power; - int b = base % mod; +int64_t NTT::modExp(int64_t base, int64_t power, int64_t mod){ + int64_t res = 1; + int64_t p = power; + int64_t b = base % mod; while (p > 0){ if (p & 1){ res = (res * b) % mod; @@ -15,16 +15,16 @@ int NTT::modExp(int base, int power, int mod){ return res; } -int NTT::modInv(int x, int mod){ - int t = 0; - int t1 = 1; - int r = mod; - int r1 = x; +int64_t NTT::modInv(int64_t x, int64_t mod){ + int64_t t = 0; + int64_t t1 = 1; + int64_t r = mod; + int64_t r1 = x; while (r1 != 0){ - int quot = (int) (r/r1); - int temp_t = t; - int temp_r = r; + int64_t quot = (int64_t) (r/r1); + int64_t temp_t = t; + int64_t temp_r = r; t = t1; t1 = (temp_t - quot * t1); r = r1; @@ -71,13 +71,13 @@ int64_t NTT::genNthRoot(int mod, int n){ void NTT::reverse(vector<int64_t> &in, int bitLen){ for (int i=0; i<size(in); i++){ - int revN = 0; + int64_t revN = 0; for(int j=0; j<bitLen ; j++){ if ((i >> j) & 1){ revN |= 1 << (bitLen-1-j); } } - int coeff = in[i]; + int64_t coeff = in[i]; if (revN > i){ coeff ^= in[revN]; @@ -99,8 +99,8 @@ void NTT::_ntt(vector<int64_t> &in, int64_t w){ vector<int64_t> p2; for(int j=0; j<N/2; j++){ int shift = nBit - i - 1; - int P = (j >> shift) << shift; - int wP = modExp(w, P, M); + int64_t P = (j >> shift) << shift; + int64_t wP = modExp(w, P, M); int64_t odd = in[2*j+1] * wP; int64_t even = in[2*j]; p1.push_back((even + odd) % M); @@ -129,7 +129,7 @@ void NTT::_ntt(vector<int64_t> &in, int64_t w){ vector<int64_t> NTT::ntt(Polynomial in, int degree, int64_t w){ vector<int64_t> out(degree,0); - for(int i=0; i<degree; i++){ + for(int i=0; i<in.degree; i++){ out[i] = (int64_t) in.coeffs[i]; } _ntt(out, w); @@ -141,11 +141,10 @@ Polynomial NTT::intt(vector<int64_t> &in, int w){ Polynomial pOut(N); double coeff[N]; - int wInv = modInv(w, M); - int nInv = modInv(N, M); + int64_t wInv = modInv(w, M); + int64_t nInv = modInv(N, M); _ntt(in, wInv); - for(int i=0; i<size(in); i++){ coeff[i] = (in[i] * nInv) % M; } diff --git a/src/ntt.h b/src/ntt.h index 74a6110ac3c456c214e46a32ceb1afea44bd1751..5078f1f82c2edb248ad84898dd70fc22fb95d45c 100644 --- a/src/ntt.h +++ b/src/ntt.h @@ -11,10 +11,9 @@ using namespace std; class NTT{ public: - int g = 3; int M = 2013265921; - int modExp(int base, int power, int mod); - int modInv(int x, int mod); + int64_t modExp(int64_t base, int64_t power, int64_t mod); + int64_t modInv(int64_t x, int64_t mod); int bitLength(int x); void reverse(vector<int64_t> &in, int bitLen); bool existSmallerN(int r, int mod, int n); diff --git a/src/polynomial.h b/src/polynomial.h index e1322333c7fc0c48318b7f977c04217ac7fb36c6..81753efca7bacccf792ffd73ca92009060984690 100644 --- a/src/polynomial.h +++ b/src/polynomial.h @@ -5,7 +5,7 @@ class Polynomial { public: int degree; - double coeffs[100]; + double coeffs[200]; Polynomial() = default; Polynomial(int deg); @@ -17,6 +17,7 @@ class Polynomial { Polynomial scaleRoundCoeff(double scale); Polynomial modCoeff(int64_t q); Polynomial dot(Polynomial const &obj); + Polynomial fastMult(Polynomial p1, Polynomial p2); Polynomial operator + (Polynomial const &obj); Polynomial operator * (Polynomial const &obj); diff --git a/src/pubkey.cpp b/src/pubkey.cpp index d9deba0a8c5f02aa667810a84f5e262f83d2c6b7..39602619f45a2f9bf94356c031ba9c895c3a5d8b 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -11,7 +11,7 @@ PubKey::PubKey(Polynomial _s, int degree, int64_t q){ b = Polynomial(degree); s = _s; - generateA(4, 100); + generateA(degree, 100); computeB(q); } @@ -34,7 +34,7 @@ void PubKey::generateA(int degree, int64_t q){ int64_t half_q = q/2; random_device rd; mt19937 gen(rd()); - uniform_int_distribution<int64_t> dis(-half_q, half_q); + uniform_int_distribution<int64_t> dis(0, half_q); double a_coeffs[degree]; for (int i=0; i<degree; i++){ diff --git a/src/seckey.cpp b/src/seckey.cpp index 6eb3b518767677876478f50e680197a0da810d35..0ea43644b6ca3318e915f4ef2c93a654bcd99166 100644 --- a/src/seckey.cpp +++ b/src/seckey.cpp @@ -5,21 +5,24 @@ using namespace std; -SecKey::SecKey(){ - s = Polynomial(4); - double coeff[4]; +SecKey::SecKey(int deg){ + double coeff[deg]; - int h = 2; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> distr(deg/2, deg); + + int h = distr(gen); string ones(h, '1'); - string zeros(2, '0'); + string zeros((deg-h), '0'); string key = ones + zeros; random_shuffle(key.begin(), key.end()); - for(int i=0; i<4; i++){ + for(int i=0; i<deg; i++){ char temp = key.at(i); - coeff[i] = (double) (atoi(&temp)); + coeff[i] = (double) -1 * (atoi(&temp)); } - s.setCoeffs(coeff); + s = Polynomial(deg, coeff); } diff --git a/src/seckey.h b/src/seckey.h index 8671f2908adaf07c1920b56aa0bd256a1161237d..4fa51cc835de9e1d2986b668fdd8ab3b279136de 100644 --- a/src/seckey.h +++ b/src/seckey.h @@ -8,8 +8,8 @@ class SecKey{ public: Polynomial s; - - SecKey(); + SecKey() = default; + SecKey(int deg); }; #endif \ No newline at end of file diff --git a/test.cpp b/test.cpp index ce8fe33fb82f8ad660557f307523923d57e547e6..f2482640688e42c6fa71a7d1e987828970490973 100644 --- a/test.cpp +++ b/test.cpp @@ -1,4 +1,5 @@ #include <iostream> +#include <chrono> #include "src/encoder.h" #include "src/polynomial.h" #include "src/ckks.h" @@ -8,13 +9,23 @@ using namespace std; +using namespace std::chrono; int main(){ Encoder enc(8, 64.0); - dcomplex a1 = 3.0 + 4.0 *J; - dcomplex a2 = 2.0 - 1.0 *J; - dcomparr input = {a1, a2}; + dcomplex a1 = 4.0 + 3.0 *J; + dcomplex a2 = 2.0 - 1.0*J; + dcomparr input = {a1, a2}; + + // dcomparr input; + // dcomplex a = 1.0 + 1.0; + // for(int i=0; i<32; i++){ + // input.arr[i] = a; + // } + Polynomial pt = enc.encode(input); + + // pt.printPol(); int q0 = 67; int pl[6] = {61, 67, 71, 73, 79, 59}; @@ -24,23 +35,42 @@ int main(){ ql *= pl[i]; } - SecKey sk = SecKey(); - PubKey pk(sk.s, 4, ql); - EvalKey evk(sk.s, 4, ql); + + SecKey sk = SecKey(2); + PubKey pk(sk.s, 2, ql); + // cout << "pk: "; + // pk.b.printPol(); + EvalKey evk(sk.s, 2, ql); + // cout << "evk: "; + // evk.b.printPol(); Polynomial pt2 = pt * pt; - pt2.printPol(); + // pt2.printPol(); CKKS ckks(4, pk, evk, sk); Ciphertext ct = ckks.encrypt(pt); + //ct.c0.printPol(); + + + auto start = high_resolution_clock::now(); Ciphertext ctadd = ckks.mult(ct, ct); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast<microseconds>(stop - start); + cout << "Normal Time: " << duration.count() << endl; + Polynomial ptOut = ckks.decrypt(ctadd); + //ptOut.printPol(); - //problem + // //problem + // cout << "decode" << endl; dcomparr output = enc.decode(ptOut); - cout << "test" << endl; - cout << endl; + // for(int i=0; i<4; i++){ + // cout << output.arr[i] << " "; + // } + // cout << endl; + // // cout << "test" << endl; + // cout << endl; cout << "Experiment" << endl; cout << "polynomial: "; @@ -59,22 +89,40 @@ int main(){ } cout << endl; - cout << "NTT test" << endl; - NTT ntt; - int64_t w = 1728404513; - double coeff[] = {2, 1, 0, 0}; - Polynomial n(4, coeff); + // cout << "NTT test" << endl; + + auto start1 = high_resolution_clock::now(); + Ciphertext mult = ckks.multNTT(ct, ct); + auto stop1 = high_resolution_clock::now(); + auto duration1 = duration_cast<microseconds>(stop1 - start1); + cout << "NTT Time: " << duration1.count() << endl; - vector<int64_t> test = ntt.ntt(n, 4, w); - cout <<"test"<<endl; - for(int i=0;i<4;i++){ - cout << test[i] << " "; + Polynomial nttOut = ckks.decrypt(mult); + + dcomparr nttoutput = enc.decode(nttOut); + nttOut.printPol(); + for(int i=0; i<4; i++){ + cout << nttoutput.arr[i]/1.0 << " "; } cout << endl; + + // double in[] = {2.0, 1.0}; + // Polynomial p1(4, in); + + // double in2[] = {3.0, 1.0}; + // Polynomial p2(4, in2); + + // int64_t w = 1934320121; + // vector<int64_t> out = ckks.ntt.ntt(p1, 16, w); + // for(int i=0; i<16; i++){ + // cout << out[i] << " "; + // } + // cout << endl; + // Polynomial test = ckks.ntt.intt(out, w); + // test.printPol(); - cout <<"test"<<endl; - Polynomial testOut = ntt.intt(test, w); - testOut.printPol(); + // Polynomial test = ckks.fastMult(p1, p2, w); + // test.printPol(); return 0; } \ No newline at end of file diff --git a/test.o b/test.o index 4a9916dc459ad9e40041cc478df7c8e32c0585b8..36a54436f8b4b466bd16e43bbb5ccb847efd286c 100644 Binary files a/test.o and b/test.o differ