Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
// Encoder enc(128, 128.0);
// dcomplex a = 1.0 + 1.0 *J;
// dcomparr input;
int q0 = 67;
int pl[6] = {61, 67, 71, 73, 79, 61};
int64_t ql = q0;
for (int i=0; i<5; i++){
ql *= pl[i];
}
int N = pow(2,1);
double scale = 64.0;
Encoder enc(4*N, scale);
dcomplex a1 = 3.0 + 4.0 *J;
dcomplex a2 = 2.0 - 1.0 *J;
dcomparr input(N);
input.arr[0] = a1;
input.arr[1] = a2;
dcomparr input2(N);
input2.arr[0] = 1.0 + 1.0*J;
input2.arr[1] = 1.0 + 2.0*J;
Polynomial pt1 = enc.encode(input2);
// pt1.printPol();
auto start = high_resolution_clock::now();
Polynomial pt = enc.encode(input);
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
pt.printPol();
// dcomparr output = enc.decode(pt);
// for(int i=0; i<N; i++){
// cout << output.arr[i] << " ";
// }
// cout << endl;
// double realN = 0;
// double imagN = 0;
// for(int i=0; i<N; i++){
// realN += pow(abs(real(output.arr[i]) - real(input.arr[i])), 2);
// imagN += pow(abs(imag(output.arr[i]) - imag(input.arr[i])), 2);
// }
// double average = (realN+imagN)/N;
// average = pow(average, 0.5);
// cout << average << endl;
// dcomparr output = enc.decode(pt);
SecKey sk(N);
auto start2 = high_resolution_clock::now();
PubKey pk(sk.s, (N/2)+1, ql);
auto stop2 = high_resolution_clock::now();
auto duration2 = duration_cast<microseconds>(stop2 - start2);
// cout << "public key: " << duration2.count() << endl;
auto start3 = high_resolution_clock::now();
EvalKey evk(sk.s, (N/2)+1, ql);
auto stop3 = high_resolution_clock::now();
auto duration3 = duration_cast<microseconds>(stop3 - start3);
// cout << "eval key: " << 2*duration2.count() << endl;
CKKS ckks(evk);
auto start4 = high_resolution_clock::now();
Ciphertext ct = ckks.encrypt(pt, pk);
auto stop4 = high_resolution_clock::now();
auto duration4 = duration_cast<microseconds>(stop4 - start4);
cout << "encrypt: " << duration4.count() << endl;
// Ciphertext ct1 = ckks.encrypt(pt1, pk);
// auto start5 = high_resolution_clock::now();
// Polynomial ptOut = ckks.decrypt(ct, sk);
// auto stop5 = high_resolution_clock::now();
// auto duration5 = duration_cast<microseconds>(stop5 - start5);
// cout << "decrypt: " << duration5.count() << endl;
// ct.c0.printPol();
// auto start6 = high_resolution_clock::now();
// Ciphertext ctadd = ckks.add(ct, ct1);
// auto stop6 = high_resolution_clock::now();
// auto duration6 = duration_cast<microseconds>(stop6 - start6);
// cout << "add: " << duration6.count() << endl;
// ctadd.c0.printPol();
// Polynomial ptOut = ckks.decrypt(ctadd, sk);
// ptOut.printPol();
// auto start7 = high_resolution_clock::now();
// Ciphertext ctmult = ckks.multNTT(ct, ct);
Ciphertext ctmultNorm = ckks.mult(ct, ct);
// auto stop7 = high_resolution_clock::now();
// auto duration7 = duration_cast<microseconds>(stop7 - start7);
// cout << "mult: " << duration7.count() << endl;
Polynomial multOut = ckks.decrypt(ctmultNorm, sk);
multOut.printPol();
dcomparr multOutput = enc.decode(pt);
for(int i=0; i<2; i++){
cout << multOutput.arr[i] << endl;
}
// NTT ntt;
// int64_t w = ntt.genNthRoot(ntt.M, N);
// auto start7 = high_resolution_clock::now();
// vector<int64_t> nttRes = ntt.ntt(pt, N*2, w);
// auto stop7 = high_resolution_clock::now();
// auto duration7 = duration_cast<microseconds>(stop7 - start7);
// cout << "full ntt: " << duration7.count() << endl;
// auto start8 = high_resolution_clock::now();
// Ciphertext ct1 = ckks.multNTT(ct,ct);
// auto stop8 = high_resolution_clock::now();
// auto duration8 = duration_cast<microseconds>(stop8 - start8);
// cout << "mult ntt: " << duration8.count() << endl;
// auto start9 = high_resolution_clock::now();
// Polynomial nttOut = ntt.intt(nttRes1, w);
// Ciphertext ctmult = ckks.multNTT(ct, ct);
// auto stop9 = high_resolution_clock::now();
// auto duration9 = duration_cast<microseconds>(stop9 - start9);
// cout << "intt: " << duration9.count() << endl;
// int q0 = 67;
// int pl[6] = {61, 67, 71, 73, 79, 59};
// int64_t ql = q0;
// for (int i=0; i<3; i++){
// ql *= pl[i];
// }
// SecKey sk = SecKey(2);
// PubKey pk(sk.s, 3, ql);
// EvalKey evk(sk.s, 3, ql);
// CKKS ckks(4, pk, evk, sk);
// Ciphertext ct = ckks.encrypt(pt);
// ct.c0.printPol();
// ct.c1.printPol();
// cout << endl;
// Polynomial ptout = ckks.decrypt(ct);
// ptout.printPol();
// cout << endl;
// Ciphertext ctadd = ckks.add(ct, ct);
// ctadd.c0.printPol();
// ctadd.c1.printPol();
// cout << endl;
// Polynomial ptadd = ckks.decrypt(ctadd);
// ptadd.printPol();
// cout << endl;
// Ciphertext ctmult = ckks.mult(ct, ct);
// ctmult.c0.printPol();
// ctmult.c1.printPol();
// cout << endl;
// Polynomial ptmult = ckks.decrypt(ctmult);
// ptmult.printPol();
// Encoder enc2(16, 64.0);
// dcomparr outputMult = enc2.decode(ptmult);
// for(int i=0; i<4; i++){
// cout << outputMult.arr[i] << " ";
// }
// cout << endl;
bool error = false;
// for(int i=1; i<5; i++){
// cout << i << endl;
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// dcomparr out = enc.decode(test);
// for(int j=0; j<N; j++){
// if (abs(in.arr[i]-out.arr[i]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// for(int i=1; i<5; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Polynomial testOut = ckks.decrypt(ct);
// dcomparr out = enc.decode(testOut);
// for(int j=0; j<N; j++){
// if (abs(in.arr[j]-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// for(int i=1; i<5; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Ciphertext ctadd = ckks.add(ct,ct);
// Polynomial testOut = ckks.decrypt(ctadd);
// dcomparr out = enc.decode(testOut);
// dcomplex scale(2.0, 0.0);
// for(int j=0; j<N; j++){
// if (abs((scale*in.arr[j])-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// for(int i=1; i<5; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Ciphertext ctadd = ckks.mult(ct,ct);
// Polynomial testOut = ckks.decrypt(ctadd);
// Polynomial control = (test * test).scaleRoundCoeff(1.0/64.0);
// dcomparr out = enc.decode(testOut);
// dcomparr check = enc.decode(control);
// for(int j=0; j<N*2; j++){
// if (abs(check.arr[j]-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// double input[] = {2.0, 1.0};
// Polynomial in(2, input);
// NTT ntt;
// vector<int64_t> out = ntt.ntt(in, 8, 1801542727);
// for(int i=0; i<8; i++){
// cout << out[i] << " ";
// }
// cout << endl;
// Polynomial test = ntt.intt(out, 1801542727);
// test.printPol();
// if(error) {
// cout << "Error" << endl;
// } else {
// cout << "Finish" << endl;
// }
\ No newline at end of file
...@@ -14,171 +14,99 @@ using namespace std; ...@@ -14,171 +14,99 @@ using namespace std;
using namespace std::chrono; using namespace std::chrono;
dcomparr randomFill(int n){
dcomparr out(n);
for(int i=0; i<n; i++){
out.arr[i] = 1.0 + 1.0*J;
}
return out;
}
int main(){ int main(){
// Encoder enc(128, 128.0);
// dcomplex a = 1.0 + 1.0 *J;
// dcomparr input;
// for(int i=0; i<32; i++){
// input.arr[i] = a;
// }
// Encoder enc(8, 64.0);
// dcomplex a1 = 3.0 + 4.0 *J;
// dcomplex a2 = 2.0 - 1.0*J;
// dcomparr input(2);
// input.arr[0] = a1;
// input.arr[1] = a2;
// Polynomial pt = enc.encode(input);
// pt.printPol();
int q0 = 67; int q0 = 67;
int pl[6] = {61, 67, 71, 73, 79, 59}; int pl[6] = {61, 67, 71, 73, 79, 61};
int64_t ql = q0; int64_t ql = q0;
for (int i=0; i<3; i++){ for (int i=0; i<5; i++){
ql *= pl[i]; ql *= pl[i];
} }
// SecKey sk = SecKey(4); Encoder enc(8, 64.0);
// PubKey pk(sk.s, 4, ql); dcomparr input(2);
// EvalKey evk(sk.s, 4, ql); input.arr[0] = (3.0+4.0*J);
input.arr[1] = (2.0-1.0*J);
// cout << "decode" << endl;
// dcomparr out = enc.decode(pt); dcomparr input2(2);
// for(int i=0; i<2; i++){ input2.arr[0] = (1.0+1.0*J);
// cout << out.arr[i] << " "; input2.arr[1] = (1.0+1.0*J);
// }
// cout << endl; cout << "Input: " << endl;
cout << "Input 1: ";
bool error = false; for(int i=0; i<2; i++) cout << input.arr[i] << " ";
// for(int i=1; i<5; i++){ cout << endl;
// cout << i << endl; cout << "Input 2: ";
// int N = pow(2, i); for(int i=0; i<2; i++) cout << input2.arr[i] << " ";
// Encoder enc(N*4, 64.0); cout << endl;
// dcomparr in = randomFill(N); cout << endl;
// Polynomial test = enc.encode(in);
// dcomparr out = enc.decode(test);
// for(int j=0; j<N; j++){ cout << "Encoding: " << endl;
// if (abs(in.arr[i]-out.arr[i]) > 2.0){ cout << "Plaintext 1: ";
// error = true; Polynomial pt1 = enc.encode(input);
// break; pt1.printPol();
// } cout << "Plaintext 2: ";
// } Polynomial pt2 = enc.encode(input2);
// if (error) break; pt2.printPol();
// }
// for(int i=1; i<5; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Polynomial testOut = ckks.decrypt(ct);
// dcomparr out = enc.decode(testOut);
// for(int j=0; j<N; j++){
// if (abs(in.arr[j]-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// for(int i=1; i<5; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Ciphertext ctadd = ckks.add(ct,ct);
// Polynomial testOut = ckks.decrypt(ctadd);
// dcomparr out = enc.decode(testOut);
// dcomplex scale(2.0, 0.0);
// for(int j=0; j<N; j++){
// if (abs((scale*in.arr[j])-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// for(int i=1; i<5; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Ciphertext ctadd = ckks.mult(ct,ct);
// Polynomial testOut = ckks.decrypt(ctadd);
// Polynomial control = (test * test).scaleRoundCoeff(1.0/64.0);
// dcomparr out = enc.decode(testOut);
// dcomparr check = enc.decode(control);
// for(int j=0; j<N*2; j++){
// if (abs(check.arr[j]-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
double input[] = {2.0, 1.0};
Polynomial in(2, input);
NTT ntt;
vector<int64_t> out = ntt.ntt(in, 8, 1801542727);
for(int i=0; i<8; i++){
cout << out[i] << " ";
}
cout << endl; cout << endl;
Polynomial test = ntt.intt(out, 1801542727); SecKey sk(2);
test.printPol(); PubKey pk(sk.s, 3, ql);
EvalKey evk(sk.s, 3, ql);
if(error) { CKKS ckks(evk);
cout << "Error" << endl; Ciphertext ct1 = ckks.encrypt(pt1, pk);
} else { Ciphertext ct2 = ckks.encrypt(pt2, pk);
cout << "Finish" << endl;
}
return 0; cout << "Encryption pt1: " << endl;
cout << "c0: "; ct1.c0.printPol();
cout << "c1: "; ct1.c1.printPol();
cout << endl;
cout << "Ciphertext Addition : (ct1+ct2) " << endl;
Ciphertext ctAdd = ckks.add(ct1, ct2);
Polynomial addOut = ckks.decrypt(ctAdd, sk);
cout << "Pt Addition: "; addOut.printPol();
dcomparr addRes = enc.decode(addOut);
cout << "Addition Result: ";
for(int i=0; i<2; i++) cout << addRes.arr[i] << " ";
cout << endl;
cout << endl;
cout << "Ciphertext Multiplication: (ct1 * ct1) " << endl;
Ciphertext ctMult = ckks.mult(ct1, ct1);
Polynomial multOut = ckks.decrypt(ctMult, sk);
cout << "Pt multiplication: "; multOut.printPol();
dcomparr multRes = enc.decode(multOut);
cout << "Multiplication Result: ";
for(int i=0; i<2; i++) cout << multRes.arr[i] << " ";
cout << endl;
cout << endl;
cout << "Ciphertext Multiplication (NTT): (ct1 * ct1)" << endl;
Ciphertext ctMultNTT = ckks.multNTT(ct1, ct1);
Polynomial multNTTOut = ckks.decrypt(ctMultNTT, sk);
cout << "Pt multiplication (NTT): "; multNTTOut.printPol();
dcomparr multNTTRes = enc.decode(multNTTOut);
cout << "Multiplication Result (NTT): ";
for(int i=0; i<2; i++) cout << multNTTRes.arr[i] << " ";
cout << endl;
cout << endl;
cout << "Decryption ct1: " << endl;
Polynomial decrypted1 = ckks.decrypt(ct1, sk);
cout << "Decryption result: "; decrypted1.printPol();
cout << endl;
cout << "Decoding pt1: " << endl;
dcomparr output = enc.decode(decrypted1);
for(int i=0; i<2; i++){
cout << output.arr[i] << " ";
}
cout << endl;
return 0;
} }
\ No newline at end of file
No preview for this file type
#!/bin/bash
./test.sh > ./res/exp1.txt
./test.sh > ./res/exp2.txt
./test.sh > ./res/exp3.txt
./test.sh > ./res/exp4.txt
./test.sh > ./res/exp5.txt
No preview for this file type
...@@ -103,7 +103,7 @@ Ciphertext CKKS::encrypt(Polynomial pt, PubKey pk){ ...@@ -103,7 +103,7 @@ Ciphertext CKKS::encrypt(Polynomial pt, PubKey pk){
Polynomial CKKS::decrypt(Ciphertext ct, SecKey sk){ Polynomial CKKS::decrypt(Ciphertext ct, SecKey sk){
Polynomial pt = ct.c0 + (ct.c1 * sk.s); Polynomial pt = ct.c0 + (ct.c1 * sk.s);
return pt.modCoeff(ql); return pt;
} }
Ciphertext CKKS::add(Ciphertext ct1, Ciphertext ct2){ Ciphertext CKKS::add(Ciphertext ct1, Ciphertext ct2){
...@@ -145,7 +145,7 @@ int getNextPow(int deg){ ...@@ -145,7 +145,7 @@ int getNextPow(int deg){
Ciphertext CKKS::multNTT(Ciphertext ct1, Ciphertext ct2){ Ciphertext CKKS::multNTT(Ciphertext ct1, Ciphertext ct2){
int deg = getNextPow(ct1.c0.degree+ct2.c0.degree-1); int deg = getNextPow(ct1.c0.degree+ct2.c0.degree-1);
int64_t w = ntt.genNthRoot(ntt.M, deg); //ntt.genNthRoot(ntt.M, deg); int64_t w = 1592366214; //ntt.genNthRoot(ntt.M, deg);
Polynomial d1 = fastMult(ct1.c0, ct2.c0, deg, w).modCoeff(ql); 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 d2 = (fastMult(ct1.c0, ct2.c1,deg, w) + fastMult(ct2.c0, ct1.c1,deg, w)).modCoeff(ql);
......
...@@ -25,11 +25,12 @@ class CKKS { ...@@ -25,11 +25,12 @@ class CKKS {
Ciphertext mult(Ciphertext ct1, Ciphertext ct2); Ciphertext mult(Ciphertext ct1, Ciphertext ct2);
Ciphertext multNTT(Ciphertext ct1, Ciphertext ct2); Ciphertext multNTT(Ciphertext ct1, Ciphertext ct2);
Ciphertext add(Ciphertext ct1, Ciphertext ct2); Ciphertext add(Ciphertext ct1, Ciphertext ct2);
Polynomial fastMult(Polynomial p1, Polynomial p2, int deg, int64_t w);
private: private:
Polynomial genE(int degree, double var); Polynomial genE(int degree, double var);
Polynomial genZO(); Polynomial genZO();
Polynomial fastMult(Polynomial p1, Polynomial p2, int deg, int64_t w);
}; };
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <chrono> #include <chrono>
int counter = 0;
using namespace std; using namespace std;
using namespace std::chrono; using namespace std::chrono;
...@@ -16,6 +18,8 @@ dcomplex vdot(vector<dcomplex> a, vector<dcomplex> b, int size, int offset){ ...@@ -16,6 +18,8 @@ dcomplex vdot(vector<dcomplex> a, vector<dcomplex> b, int size, int offset){
for(int i=0; i<size; i++){ for(int i=0; i<size; i++){
out += b[i+offset] * conj(a[i]); out += b[i+offset] * conj(a[i]);
} }
// counter++;
// cout << counter << endl;
return out; return out;
} }
...@@ -38,10 +42,24 @@ Encoder::Encoder(int in, double inScale){ ...@@ -38,10 +42,24 @@ Encoder::Encoder(int in, double inScale){
M = in; M = in;
scale = inScale; scale = inScale;
root = exp((2*M_PI/M) * J); root = exp((2*M_PI/M) * J);
vandermonde = vector<dcomplex>((M/2)*(M/2)); if(M/4 <= pow(2,12)){
sigmaRBasis = vector<dcomplex>((M/2)*(M/2)); vandermonde = Eigen::MatrixXcd((M/2),(M/2));
initVandermonde(root); sigmaRBasis = Eigen::MatrixXcd((M/2),(M/2));
VandermondeTranspose(); initVandermonde(root);
VandermondeTranspose();
} else {
sigmaBase = Eigen::VectorXcd(M/2);
vanderBase = Eigen::VectorXcd(M/2);
for(int j=0; j<M/2; j++){
int power = (2*j+1);
sigmaBase(j) = pow(root, power);
}
for(int j=0; j<M/2; j++){
vanderBase(j) = pow(root, j);
}
}
} }
void Encoder::initVandermonde(dcomplex xi){ void Encoder::initVandermonde(dcomplex xi){
...@@ -49,7 +67,7 @@ void Encoder::initVandermonde(dcomplex xi){ ...@@ -49,7 +67,7 @@ void Encoder::initVandermonde(dcomplex xi){
for(int i=0; i<N; i++){ for(int i=0; i<N; i++){
for(int j=0; j<N; j++){ for(int j=0; j<N; j++){
int power = (2*i+1) * j; int power = (2*i+1) * j;
vandermonde[i*N+j] = pow(xi, power); vandermonde(i,j) = pow(xi, power);
} }
} }
} }
...@@ -58,7 +76,7 @@ void Encoder::VandermondeTranspose(){ ...@@ -58,7 +76,7 @@ void Encoder::VandermondeTranspose(){
int N = M/2; int N = M/2;
for(int i=0; i<N; i++){ for(int i=0; i<N; i++){
for(int j=0; j<N; j++){ for(int j=0; j<N; j++){
sigmaRBasis[j*N+i] = vandermonde[i*N+j]; sigmaRBasis(j,i) = vandermonde(i,j);
} }
} }
} }
...@@ -81,20 +99,20 @@ dcomparr Encoder::sigma(Polynomial pol){ ...@@ -81,20 +99,20 @@ dcomparr Encoder::sigma(Polynomial pol){
dcomparr out(pol.degree/2); dcomparr out(pol.degree/2);
for(int i=0; i<N; i++){ for(int i=0; i<N; i++){
for (int j=0; j<M/2; j++){ for (int j=0; j<M/2; j++){
out.arr[i] += pol.coeffs[j] * vandermonde[i*M/2+j]; out.arr[i] += pol.coeffs[j] * vandermonde(i, j);
} }
} }
return out; return out;
}else{ }else{
int R = 2; int R = 2;
pol.reduceDeg(); pol.reduceDeg();
while (R < pol.degree){ while (R < pol.degree){
R <<=1; R <<=1;
} }
dcomparr out(M/4);
dcomparr out(R/2);
vector<dcomplex> tempVandermonde = vector<dcomplex>(R*R); vector<dcomplex> tempVandermonde = vector<dcomplex>(R*R);
for(int i=0; i<R; i++){ for(int i=0; i<R; i++){
...@@ -105,7 +123,7 @@ dcomparr Encoder::sigma(Polynomial pol){ ...@@ -105,7 +123,7 @@ dcomparr Encoder::sigma(Polynomial pol){
} }
} }
for(int i=0; i<R/2; i++){ for(int i=0; i<N; i++){
for (int j=0; j<R; j++){ for (int j=0; j<R; j++){
if(j<pol.degree){ if(j<pol.degree){
out.arr[i] += pol.coeffs[j] * tempVandermonde[i*R+j]; out.arr[i] += pol.coeffs[j] * tempVandermonde[i*R+j];
...@@ -118,21 +136,66 @@ dcomparr Encoder::sigma(Polynomial pol){ ...@@ -118,21 +136,66 @@ dcomparr Encoder::sigma(Polynomial pol){
} }
dcomparr Encoder::largeSigma(Polynomial pol){
int N = M/4;
pol.reduceDeg();
int R = 2;
while (R < pol.degree){
R <<=1;
}
dcomparr out(R/2);
for(int i=0; i<R/2; i++){
for (int j=0; j<R; j++){
if(j<pol.degree){
out.arr[i] += pol.coeffs[j] * pow(vanderBase(j), (2*i+1));
}
}
}
return out;
}
dcomparr Encoder::decode(Polynomial pol){ dcomparr Encoder::decode(Polynomial pol){
auto start = high_resolution_clock::now(); auto start = high_resolution_clock::now();
Polynomial unscaled = pol.scaleCoeff(1.0/scale); Polynomial unscaled = pol.scaleCoeff(1.0/scale);
dcomparr out = sigma(unscaled);
if(M/4<=pow(2, 12)){
dcomparr out = sigma(unscaled);
return out;
} else {
dcomparr out = largeSigma(unscaled);
return out;
}
}
dcomparr Encoder::computeCoordinate(dcomparr z){
dcomparr out(M/2);
Eigen::VectorXcd temp = Eigen::Map<Eigen::VectorXcd, Eigen::Unaligned>(z.arr.data(), z.arr.size());
for (int i=0; i<M/2; i++){
Eigen::VectorXcd b = sigmaRBasis.row(i);
dcomplex zi = temp.dot(b) / b.dot(b);
out.arr[i] = real(zi);
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
//cout << "Decoding: " << duration.count() << endl;
return out; return out;
} }
dcomparr Encoder::computeCoordinate(dcomparr z){ Eigen::VectorXcd genB(int i, int N, Eigen::VectorXcd base){
Eigen::VectorXcd b(N);
for(int j=0; j<N; j++){
b(j) = pow(base(j), i);
}
return b;
}
dcomparr Encoder::computeLargeCoordinate(dcomparr z){
dcomparr out(M/2); dcomparr out(M/2);
Eigen::VectorXcd temp = Eigen::Map<Eigen::VectorXcd, Eigen::Unaligned>(z.arr.data(), z.arr.size());
for (int i=0; i<M/2; i++){ for (int i=0; i<M/2; i++){
dcomplex zi = vdot(z.arr, sigmaRBasis, M/2, i*M/2) / vdots(sigmaRBasis, sigmaRBasis, M/2, i*M/2); Eigen::VectorXcd b = genB(i, M/2, sigmaBase);
dcomplex zi = temp.dot(b) / b.dot(b);
out.arr[i] = real(zi); out.arr[i] = real(zi);
} }
...@@ -155,9 +218,15 @@ dcomparr Encoder::coordinateWRR(dcomparr coordinates){ ...@@ -155,9 +218,15 @@ dcomparr Encoder::coordinateWRR(dcomparr coordinates){
} }
dcomparr Encoder::discretization(dcomparr z){ dcomparr Encoder::discretization(dcomparr z){
dcomparr coor = computeCoordinate(z); if(M/4 <= pow(2,12)){
dcomparr roundedCoor = coordinateWRR(coor); dcomparr coor = computeCoordinate(z);
return roundedCoor; dcomparr roundedCoor = coordinateWRR(coor);
return roundedCoor;
} else {
dcomparr coor = computeLargeCoordinate(z);
dcomparr roundedCoor = coordinateWRR(coor);
return roundedCoor;
}
} }
Polynomial Encoder::sigmaInv(dcomparr z){ Polynomial Encoder::sigmaInv(dcomparr z){
...@@ -184,8 +253,6 @@ Polynomial Encoder::encode(dcomparr input){ ...@@ -184,8 +253,6 @@ Polynomial Encoder::encode(dcomparr input){
dcomparr roundZ = discretization(zPi); dcomparr roundZ = discretization(zPi);
Polynomial out = sigmaInv(roundZ); Polynomial out = sigmaInv(roundZ);
// Polynomial out(2);
auto stop = high_resolution_clock::now(); auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start); auto duration = duration_cast<microseconds>(stop - start);
//cout << "Encoding: " << duration.count() << endl; //cout << "Encoding: " << duration.count() << endl;
......
...@@ -22,27 +22,32 @@ struct dcomparr { ...@@ -22,27 +22,32 @@ struct dcomparr {
#define ENCODER_H #define ENCODER_H
class Encoder { class Encoder {
public:
Encoder(int in, double inScale);
Polynomial encode(dcomparr input);
dcomparr decode(Polynomial pol);
private: private:
int M; int M;
double scale; double scale;
dcomplex root; dcomplex root;
vector<dcomplex> vandermonde; Eigen::VectorXcd vanderBase;
vector<dcomplex> sigmaRBasis; Eigen::VectorXcd sigmaBase;
Eigen::MatrixXcd vandermonde;
Eigen::MatrixXcd sigmaRBasis;
void initVandermonde(dcomplex xi); void initVandermonde(dcomplex xi);
void VandermondeTranspose(); void VandermondeTranspose();
dcomparr piInv(dcomparr input); dcomparr piInv(dcomparr input);
dcomparr sigma(Polynomial pol); dcomparr sigma(Polynomial pol);
dcomparr largeSigma(Polynomial pol);
dcomparr computeCoordinate(dcomparr z); dcomparr computeCoordinate(dcomparr z);
dcomparr computeLargeCoordinate(dcomparr z);
dcomparr coordinateWRR(dcomparr coordinates); dcomparr coordinateWRR(dcomparr coordinates);
dcomparr discretization(dcomparr z); dcomparr discretization(dcomparr z);
Polynomial sigmaInv(dcomparr z); Polynomial sigmaInv(dcomparr z);
public:
Encoder(int in, double inScale);
Polynomial encode(dcomparr input);
dcomparr decode(Polynomial pol);
}; };
......
...@@ -44,7 +44,7 @@ void PubKey::generateA(int degree, int64_t q){ ...@@ -44,7 +44,7 @@ void PubKey::generateA(int degree, int64_t q){
void PubKey::computeB(int q, Polynomial s){ void PubKey::computeB(int q, Polynomial s){
Polynomial err = genE(a.degree, 1.0); Polynomial err = genE(a.degree, 1.0);
Polynomial temp = (a.scaleCoeff(-1.0)) * s ; Polynomial temp = (a.scaleCoeff(-1.0)) * s;
Polynomial res = temp.modCoeff(q); Polynomial res = temp.modCoeff(q);
b = Polynomial(res.degree, res.coeffs); b = Polynomial(res.degree, res.coeffs);
......
...@@ -19,205 +19,45 @@ dcomparr randomFill(int n){ ...@@ -19,205 +19,45 @@ dcomparr randomFill(int n){
return out; return out;
} }
int main(){
// Encoder enc(8, 64.0);
// dcomplex a1 = 3.0 + 4.0 *J;
// dcomplex a2 = 2.0 - 1.0*J;
// dcomparr input(2);
// input.arr[0] = a1;
// input.arr[1] = a2;
// // dcomparr input(128);
// // dcomplex a = 1.0 + 1.0*J;
// // for(int i=0; i<128; i++){
// // input.arr[i] = a;
// // }
// Polynomial pt = enc.encode(input);
// pt.printPol();
int main(){
int q0 = 67; int q0 = 67;
int pl[6] = {61, 67, 71, 73, 79, 61}; int pl[6] = {61, 67, 71, 73, 79, 61};
int64_t ql = q0; int64_t ql = q0;
for (int i=0; i<3; i++){ for (int i=0; i<5; i++){
ql *= pl[i]; ql *= pl[i];
} }
// SecKey sk = SecKey(2); int N = pow(2,15);
// // sk.s.printPol(); int scale = pow(2,10);
// PubKey pk(sk.s, 3, ql); Encoder enc(N*4, scale);
// // cout << "pk: "; dcomparr input = randomFill(N);
// // pk.b.printPol();
// EvalKey evk(sk.s, 3, ql);
// cout << "evk: ";
// evk.b.printPol();
// cout << "Control: "; Polynomial pt1 = enc.encode(input);
// Polynomial pt2 = pt * pt;
// pt2.scaleRoundCoeff(1.0/61.0).printPol();
// CKKS ckks(4, pk, evk, sk);
// Ciphertext ct = ckks.encrypt(pt);
// auto start = high_resolution_clock::now();
// Ciphertext ctadd = ckks.multNTT(ct, ct);
// auto stop = high_resolution_clock::now();
// auto duration = duration_cast<microseconds>(stop - start);
//cout << "Normal Time: " << duration.count() << endl;
// cout << "Experiment: ";
// Polynomial ptOut = ckks.decrypt(ctadd);
// ptOut.printPol();
bool error = false;
// for(int i=1; i<5; i++){
// cout << i << endl;
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// dcomparr out = enc.decode(test);
// for(int j=0; j<N; j++){
// if (abs(in.arr[i]-out.arr[i]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// for(int i=1; i<5; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, evk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test, pk);
// Polynomial testOut = ckks.decrypt(ct, sk);
// dcomparr out = enc.decode(testOut);
// for(int j=0; j<N; j++){
// if (abs(in.arr[j]-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
for(int i=7; i<8; i++){
int N = pow(2, i);
Encoder enc(N*4, 64.0);
SecKey sk = SecKey(N);
PubKey pk(sk.s, (N)+1, ql);
EvalKey evk(sk.s, (N)+1, ql);
CKKS ckks(N, evk);
dcomparr in = randomFill(N); SecKey sk(N/2);
PubKey pk(sk.s, N/2, ql);
Polynomial test = enc.encode(in); EvalKey evk(sk.s, N/2, ql);
Ciphertext ct = ckks.encrypt(test, pk);
Ciphertext ctadd = ckks.add(ct,ct);
Polynomial testOut = ckks.decrypt(ctadd, sk);
dcomparr out = enc.decode(testOut); CKKS ckks(4, evk);
dcomplex scale(2.0, 0.0); Ciphertext ct1 = ckks.encrypt(pt1, pk);
for(int j=0; j<N; j++){
if (abs((scale*in.arr[j])-out.arr[j]) > 2.0){
error = true;
break;
}
}
if (error) break;
}
// for(int i=7; i<9; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Ciphertext ctadd = ckks.mult(ct,ct);
// Polynomial testOut = ckks.decrypt(ctadd);
// Polynomial control = (test * test).scaleRoundCoeff(1.0/64.0);
// dcomparr out = enc.decode(testOut);
// dcomparr check = enc.decode(control);
// for(int j=0; j<N*2; j++){
// if (abs(check.arr[j]-out.arr[j]) > 2.0){
// ctadd.c0.printPol();
// ctadd.c1.printPol();
// error = true;
// break;
// }
// }
// if (error) break;
// }
// for(int i=7; i<8; i++){
// int N = pow(2, i);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N); NTT ntt;
// PubKey pk(sk.s, (N)+1, ql); int64_t w = ntt.genNthRoot(ntt.M, N*2);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, evk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test, pk);
// Ciphertext ctadd = ckks.multNTT(ct,ct);
// Polynomial testOut = ckks.decrypt(ctadd, sk);
// Polynomial control = (test * test).scaleRoundCoeff(1.0/64.0);
// dcomparr out = enc.decode(testOut);
// dcomparr check = enc.decode(control);
// for(int j=0; j<N; j++){
// if (abs(check.arr[j]-out.arr[j]) > 2.0){
// error = true;
// break;
// }
// }
// if (error) break;
// }
// int N = pow(2, 3);
// Encoder enc(N*4, 64.0);
// SecKey sk = SecKey(N);
// PubKey pk(sk.s, (N)+1, ql);
// EvalKey evk(sk.s, (N)+1, ql);
// CKKS ckks(N, pk, evk, sk);
// dcomparr in = randomFill(N);
// Polynomial test = enc.encode(in);
// Ciphertext ct = ckks.encrypt(test);
// Ciphertext ctadd = ckks.multNTT(ct,ct);
// Polynomial testOut = ckks.decrypt(ctadd);
if(error) {
cout << "Error" << endl;
} else {
cout << "Finish" << endl;
}
auto start = high_resolution_clock::now();
vector<int64_t> nttOut = ntt.ntt(pt1, N*2, w);
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
cout << "NTT Time: " << duration.count() << endl;
auto start1 = high_resolution_clock::now();
Polynomial output = ntt.intt(nttOut, w);
auto stop1 = high_resolution_clock::now();
auto duration1 = duration_cast<microseconds>(stop1 - start1);
cout << "iNTT Time: " << duration1.count() << endl;
return 0; return 0;
} }
\ No newline at end of file
No preview for this file type