diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..d7568504da65e57eb219720716ef0fed1c7ac80a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "complex": "cpp" + } +} \ No newline at end of file diff --git a/src/cipher.cpp b/src/cipher.cpp deleted file mode 100644 index fe73379a646f8dc43eafe0e898d9ea325917f10c..0000000000000000000000000000000000000000 --- a/src/cipher.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include <complex> -#include <cmath> -#include <random> \ No newline at end of file diff --git a/src/ciphertext.cpp b/src/ciphertext.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80945f068d05cd9c2d3b10c712d84fd0ae13e336 --- /dev/null +++ b/src/ciphertext.cpp @@ -0,0 +1,18 @@ +#include <complex> +#include <cmath> +#include <random> +#include <polynomial.h> +#include <ciphertext.h> + + +Ciphertext::Ciphertext(Polynomial _c0, Polynomial _c1){ + c0 = Polynomial(4, _c0.coeffs); + c1 = Polynomial(4, _c1.coeffs); +} + +Ciphertext Ciphertext:: operator + (Ciphertext const &obj){ + Polynomial out1 = c0 + obj.c0; + Polynomial out2 = c1 + obj.c1; + Ciphertext out(out1, out2); + return out; +} diff --git a/src/ciphertext.h b/src/ciphertext.h new file mode 100644 index 0000000000000000000000000000000000000000..8c9745c43e9657fb5baa330874c0fb9f3c6a21ff --- /dev/null +++ b/src/ciphertext.h @@ -0,0 +1,15 @@ +#include <polynomial.h> + +#ifndef CIPHERTEXT_H +#define CIPHERTEXT_H + +class Ciphertext { + public: + Polynomial c0; + Polynomial c1; + + Ciphertext(Polynomial _c0, Polynomial _c1); + Ciphertext operator + (Ciphertext const &obj); +}; + +#endif \ No newline at end of file diff --git a/src/ckks.cpp b/src/ckks.cpp index d78c0a7998dd3dd5a0ec5cafed905ac2cb4d3acd..ddb9881631e70e90d87b873794fc0c7138a92e1e 100644 --- a/src/ckks.cpp +++ b/src/ckks.cpp @@ -2,6 +2,8 @@ #include <complex> #include <cmath> #include <random> +#include <polynomial.h> +#include <pubkey.h> #include <eigen3/Eigen/Dense> #define J dcomplex(0.0,1.0) @@ -46,67 +48,6 @@ dcomparr matMult(dcomplex mat[SIZE][SIZE], coeffarr in, int m){ return out; } - -class Polynomial { - public: - int degree; - double coeffs[10]; - - Polynomial(int deg){ - degree = deg; - } - - Polynomial(int deg, double coeff[]){ - degree = deg; - for(int i=0; i<degree; i++){ - coeffs[i] = coeff[i]; - } - } - - void setDegree(int N){ - degree = N; - } - - void setCoeffs(double coeff[]){ - for(int i=0; i<degree; i++){ - coeffs[i] = coeff[i]; - } - } - - Polynomial scaleCoeff(double scale){ - Polynomial out(degree); - for (int i=0; i<degree; i++){ - out.coeffs[i] = coeffs[i] * scale; - } - return out; - } - - Polynomial operator + (Polynomial const &obj){ - - double coeff[degree]; - for(int i=0; i<degree; i++){ - coeff[i] = coeffs[i] + obj.coeffs[i]; - } - - Polynomial out(degree, coeff); - return out; - } - - Polynomial operator * (Polynomial const &obj){ - int deg = degree + obj.degree - 1; - double coeff[deg] = {0.0}; - - for(int i=0; i<degree; i++){ - for(int j=0; j<obj.degree; j++){ - coeff[i+j] += coeffs[i] * obj.coeffs[j]; - } - } - - Polynomial out(deg, coeff); - return out; - } -}; - Polynomial genError(int degree, double var){ double errCoeffs[degree]; @@ -122,62 +63,7 @@ Polynomial genError(int degree, double var){ return err; } -class PubKey{ - public: - Polynomial a = Polynomial(4); - Polynomial b = Polynomial(4); - - PubKey(){ - double test[4] = {1.0,-1.0,1.0,-2.0}; - generateA(4, 4); - b.setCoeffs(test); - } - - void generateA(int degree, int q){ - int half_q = q/2; - random_device rd; - mt19937 gen(rd()); - uniform_int_distribution<int> dis(-half_q, half_q); - double a_coeffs[degree]; - - for (int i=0; i<degree; i++){ - a_coeffs[i] = (double) dis(gen); - } - a.setCoeffs(a_coeffs); - } - - void computeB(){ - - } -}; - -class SecKey{ - public: - Polynomial s = Polynomial(4); - - SecKey(){ - double test[4] = {1.0,-1.0,1.0,0.0}; - s.setCoeffs(test); - } -}; - -class Ciphertext { - public: - Polynomial c0 = Polynomial(4); - Polynomial c1 = Polynomial(4); - - Ciphertext(Polynomial _c0, Polynomial _c1){ - c0.setCoeffs(_c0.coeffs); - c1.setCoeffs(_c1.coeffs); - } - Ciphertext operator + (Ciphertext const &obj){ - Polynomial out1 = c0 + obj.c0; - Polynomial out2 = c1 + obj.c1; - Ciphertext out(out1, out2); - return out; - } -}; class CKKS { private: @@ -228,137 +114,7 @@ class CKKS { }; -class Encoder { - public: - int M; - double scale; - dcomplex root; - dcomplex vandermonde[10][10]; - dcomplex sigmaRBasis[10][10]; - Matrix4dc vand; - - Encoder(int in, double inScale){ - M = in; - scale = inScale; - root = exp((2*M_PI/M) * J); - initVandermonde(root); - initSigmaRBasis(); - } - - void initVandermonde(dcomplex xi){ - int N = M/2; - 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; - - } - } - } - - void 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]; - } - } - } - - dcomparr piInv(dcomparr input){ - int N = M/4; - dcomparr out; - for (int i=0; i<N; i++){ - out.arr[i] = input.arr[i]; - out.arr[2*N-i-1] = conj(input.arr[i]); - } - - return out; - } - - dcomparr sigma(Polynomial pol){ - int N = M/4; - dcomparr out; - for(int i=0; i<N; i++){ - for (int j=0; j<M/2; j++){ - out.arr[i] += pol.coeffs[j] * vandermonde[i][j]; - } - } - return out; - } - - dcomparr decode(Polynomial pol){ - Polynomial unscaled = pol.scaleCoeff(1.0/scale); - return sigma(unscaled); - } - - dcomparr 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]); - out.arr[i] = real(zi); - } - - return out; - } - - coeffarr coordinateWRR(dcomparr coordinates){ - double r; - double f; - - coeffarr roundedCoor; - - for (int i=0; i<10; i++){ - r = real(coordinates.arr[i]) - floor(real(coordinates.arr[i])); - f = randomChoice(r); - roundedCoor.arr[i] = round(real(coordinates.arr[i])-f); - } - - return roundedCoor; - } - - dcomparr discretization(dcomparr z){ - dcomparr coor = computeCoordinate(z); - coeffarr roundedCoor = coordinateWRR(coor); - dcomparr out = matMult(vandermonde, roundedCoor, M/2); - return out; - } - - Polynomial 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)); - } - return out; - } - - Polynomial encode(dcomparr input){ - dcomparr zPi = piInv(input); - - int N = M/4; - for (int i=0; i<N; i++){ - zPi.arr[i] *= scale; - zPi.arr[i+N] *= scale; - } - - dcomparr roundZ = discretization(zPi); - Polynomial out = sigmaInv(roundZ); - - return out; - } -}; int main(){ diff --git a/src/encoder.cpp b/src/encoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb30b0ea88bb26370a2ed9decfa6326cc34834f4 --- /dev/null +++ b/src/encoder.cpp @@ -0,0 +1,155 @@ +#include<iostream> +#include <complex> +#include <cmath> +#include <random> +#include <polynomial.h> +#include <eigen3/Eigen/Dense> + +#define J dcomplex(0.0,1.0) +#define SIZE 10 + +using namespace std; + +typedef complex<double> dcomplex; +typedef Eigen::Matrix<dcomplex, 4, 4> Matrix4dc; +typedef Eigen::Matrix<dcomplex, 4, 1> Matrix1dc; + +struct dcomparr { + dcomplex arr[10]; +}; + +struct coeffarr { + int arr[10]; +}; + +class Encoder { + public: + int M; + double scale; + dcomplex root; + dcomplex vandermonde[10][10]; + dcomplex sigmaRBasis[10][10]; + Matrix4dc vand; + + Encoder(int in, double inScale){ + M = in; + scale = inScale; + root = exp((2*M_PI/M) * J); + initVandermonde(root); + initSigmaRBasis(); + } + + void initVandermonde(dcomplex xi){ + int N = M/2; + 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; + + } + } + } + + void 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]; + } + } + } + + dcomparr piInv(dcomparr input){ + int N = M/4; + dcomparr out; + for (int i=0; i<N; i++){ + out.arr[i] = input.arr[i]; + out.arr[2*N-i-1] = conj(input.arr[i]); + } + + return out; + } + + dcomparr sigma(Polynomial pol){ + int N = M/4; + dcomparr out; + for(int i=0; i<N; i++){ + for (int j=0; j<M/2; j++){ + out.arr[i] += pol.coeffs[j] * vandermonde[i][j]; + } + } + + return out; + } + + dcomparr decode(Polynomial pol){ + Polynomial unscaled = pol.scaleCoeff(1.0/scale); + return sigma(unscaled); + } + + dcomparr 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]); + out.arr[i] = real(zi); + } + + return out; + } + + coeffarr coordinateWRR(dcomparr coordinates){ + double r; + double f; + + coeffarr roundedCoor; + + for (int i=0; i<10; i++){ + r = real(coordinates.arr[i]) - floor(real(coordinates.arr[i])); + f = randomChoice(r); + roundedCoor.arr[i] = round(real(coordinates.arr[i])-f); + } + + return roundedCoor; + } + + dcomparr discretization(dcomparr z){ + dcomparr coor = computeCoordinate(z); + coeffarr roundedCoor = coordinateWRR(coor); + dcomparr out = matMult(vandermonde, roundedCoor, M/2); + return out; + } + + Polynomial 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)); + } + return out; + } + + Polynomial encode(dcomparr input){ + dcomparr zPi = piInv(input); + + int N = M/4; + for (int i=0; i<N; i++){ + zPi.arr[i] *= scale; + zPi.arr[i+N] *= scale; + } + + dcomparr roundZ = discretization(zPi); + Polynomial out = sigmaInv(roundZ); + + return out; + } +}; \ No newline at end of file diff --git a/src/encoder.h b/src/encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..7876df70a1d10edf60b04a5ed21663b03fcffac8 --- /dev/null +++ b/src/encoder.h @@ -0,0 +1,31 @@ +#include <polynomial.h> +#include <util.h> + +#ifndef ENCODER_H +#define ENCODER_H + +class Encoder { + public: + int M; + double scale; + dcomplex root; + dcomplex vandermonde[10][10]; + dcomplex sigmaRBasis[10][10]; + Matrix4dc vand; + + Encoder(int in, double inScale); + void initVandermonde(dcomplex xi); + void initSigmaRBasis(); + dcomparr piInv(dcomparr input); + dcomparr sigma(Polynomial pol); + dcomparr decode(Polynomial pol); + dcomparr computeCoordinate(dcomparr z); + coeffarr coordinateWRR(dcomparr coordinates); + dcomparr discretization(dcomparr z); + Polynomial sigmaInv(dcomparr z); + Polynomial encode(dcomparr input); + +}; + + +#endif \ No newline at end of file diff --git a/src/polynomial.cpp b/src/polynomial.cpp index fe73379a646f8dc43eafe0e898d9ea325917f10c..2eb705591c06b3a43d0ec2d2935447ca60704d66 100644 --- a/src/polynomial.cpp +++ b/src/polynomial.cpp @@ -1,3 +1,59 @@ #include <complex> #include <cmath> -#include <random> \ No newline at end of file +#include <random> +#include <polynomial.h> + + +Polynomial::Polynomial(int deg){ + degree = deg; +} + +Polynomial::Polynomial(int deg, double coeff[]){ + degree = deg; + for(int i=0; i<degree; i++){ + coeffs[i] = coeff[i]; + } +} + +void Polynomial::setDegree(int N){ + degree = N; +} + +void Polynomial::setCoeffs(double coeff[]){ + for(int i=0; i<degree; i++){ + coeffs[i] = coeff[i]; + } +} + +Polynomial Polynomial::scaleCoeff(double scale){ + Polynomial out(degree); + for (int i=0; i<degree; i++){ + out.coeffs[i] = coeffs[i] * scale; + } + return out; +} + +Polynomial Polynomial::operator + (Polynomial const &obj){ + + double coeff[degree]; + for(int i=0; i<degree; i++){ + coeff[i] = coeffs[i] + obj.coeffs[i]; + } + + Polynomial out(degree, coeff); + return out; +} + +Polynomial Polynomial::operator * (Polynomial const &obj){ + int deg = degree + obj.degree - 1; + double coeff[deg] = {0.0}; + + for(int i=0; i<degree; i++){ + for(int j=0; j<obj.degree; j++){ + coeff[i+j] += coeffs[i] * obj.coeffs[j]; + } + } + + Polynomial out(deg, coeff); + return out; +} diff --git a/src/polynomial.h b/src/polynomial.h new file mode 100644 index 0000000000000000000000000000000000000000..046503a2f12c35a6cdb3fffe791e4b33dc0fcf66 --- /dev/null +++ b/src/polynomial.h @@ -0,0 +1,21 @@ +#ifndef POLYNOMIAL_H +#define POLYNOMIAL_H + +class Polynomial { + public: + int degree; + double coeffs[10]; + + Polynomial() = default; + Polynomial(int deg); + Polynomial(int deg, double coeff[]); + + void setDegree(int N); + void setCoeffs(double coeff[]); + Polynomial scaleCoeff(double scale); + Polynomial operator + (Polynomial const &obj); + Polynomial operator * (Polynomial const &obj); +}; + + +#endif \ No newline at end of file diff --git a/src/pubkey.cpp b/src/pubkey.cpp index fe73379a646f8dc43eafe0e898d9ea325917f10c..1badba4c447b19e0e8de27e10040eda68d924a63 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -1,3 +1,33 @@ +#include<iostream> #include <complex> #include <cmath> -#include <random> \ No newline at end of file +#include <random> +#include <polynomial.h> +#include <pubkey.h> + +using namespace std; + +PubKey::PubKey(){ + a = Polynomial(4); + b = Polynomial(4); + double test[4] = {1.0,-1.0,1.0,-2.0}; + generateA(4, 4); + b.setCoeffs(test); +} + +void PubKey::generateA(int degree, int q){ + int half_q = q/2; + random_device rd; + mt19937 gen(rd()); + uniform_int_distribution<int> dis(-half_q, half_q); + double a_coeffs[degree]; + + for (int i=0; i<degree; i++){ + a_coeffs[i] = (double) dis(gen); + } + a.setCoeffs(a_coeffs); +} + +void PubKey::computeB(){ + +} diff --git a/src/pubkey.h b/src/pubkey.h new file mode 100644 index 0000000000000000000000000000000000000000..0d44aa94effe5ec697f039da2782c97a921a380b --- /dev/null +++ b/src/pubkey.h @@ -0,0 +1,16 @@ +#include <polynomial.h> + +#ifndef PUBKEY_H +#define PUBKEY_H + +class PubKey{ + public: + Polynomial a; + Polynomial b; + + PubKey(); + void generateA(int degree, int q); + void computeB(); +}; + +#endif \ No newline at end of file diff --git a/src/seckey.cpp b/src/seckey.cpp index fe73379a646f8dc43eafe0e898d9ea325917f10c..44cd8048dadd2b9d318eecd54b6fcd95db56a5c9 100644 --- a/src/seckey.cpp +++ b/src/seckey.cpp @@ -1,3 +1,11 @@ #include <complex> #include <cmath> -#include <random> \ No newline at end of file +#include <random> +#include <polynomial.h> +#include <seckey.h> + +SecKey::SecKey(){ + s = Polynomial(4); + double test[4] = {1.0,-1.0,1.0,0.0}; + s.setCoeffs(test); +} diff --git a/src/seckey.h b/src/seckey.h new file mode 100644 index 0000000000000000000000000000000000000000..6439e256592d12a47bea5850cd43585a3d368115 --- /dev/null +++ b/src/seckey.h @@ -0,0 +1,14 @@ +#include <polynomial.h> + +#ifndef SECKEY_H +#define SECKEY_H + + +class SecKey{ + public: + Polynomial s; + + SecKey(); +}; + +#endif \ No newline at end of file diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000000000000000000000000000000000000..d2ac39910083f8c7e3a993b67372798f3432c5fa --- /dev/null +++ b/src/util.h @@ -0,0 +1,24 @@ +#include <eigen3/Eigen/Dense> +#include <complex> + +#ifndef UTIL_H +#define UTIL_H + +#define J dcomplex(0.0,1.0) +#define SIZE 10 + +using namespace std; + +typedef complex<double> dcomplex; +typedef Eigen::Matrix<dcomplex, 4, 4> Matrix4dc; +typedef Eigen::Matrix<dcomplex, 4, 1> Matrix1dc; + +struct dcomparr { + dcomplex arr[10]; +}; + +struct coeffarr { + int arr[10]; +}; + +#endif \ No newline at end of file