2、在1的基础上,实现了bootstarpping技术,对应的论文
3、在2的基础上,优化,效率更高!
有三个文件夹:lib、run、src
lib:存放依赖库(静态文件),需要生成静态库,具体安装和生成静态库参考:MAC上安装HEAAN库
run:里面有一个run.cpp文件,为测试文件
src:里面是主要代码文件
下面主要学习测试文件(run.cpp)中的几个方法
测试复数向量的编/解码、加/解密
void TestScheme::testEncodeBatch(long logN, long logQ, long logp, long logSlots) {
/*
* 功能:测试明文的编码和解码时间
* 参数:logN(密文维数)、logQ(最大密文模数)、logp(精度,即小数位数)、logSlots(明文插槽数,即多少个明文数能打包成一个明文多项式)
*/
cout << "!!! START TEST ENCODE BATCH !!!" << endl;
//-----------------------------------------
TimeUtils timeutils;
//初始化参数
Context context(logN, logQ);
//生成私钥
SecretKey secretKey(logN);
//生成公钥、计算密钥
Scheme scheme(secretKey, context);
//-----------------------------------------
SetNumThreads(1);
//-----------------------------------------
srand(time(NULL));
//-----------------------------------------
//随机生成复数向量(含有实部和虚部)
long slots = (1 << logSlots);
complex<double>* mvec = EvaluatorUtils::randomComplexArray(slots);
timeutils.start("Encrypt batch");
//开始加密:将复数向量编码为消息,然后使用公钥将其加密成密文
Ciphertext cipher = scheme.encrypt(mvec, slots, logp, logQ);
timeutils.stop("Encrypt batch");
timeutils.start("Decrypt batch");
//开始解密:先解密,然后解密为复数向量
complex<double>* dvec = scheme.decrypt(secretKey, cipher);
timeutils.stop("Decrypt batch");
//显示结果(成对):mval(复数向量)、dval(解密后的复数向量)、eval(误差)
StringUtils::showcompare(mvec, dvec, slots, "val");
cout << "!!! END TEST ENCODE BATCH !!!" << endl;
}
测试复数向量的编/解码、加/解密、加/乘法
void TestScheme::testBasic(long logN, long logQ, long logp, long logSlots) {
cout << "!!! START TEST BASIC !!!" << endl;
//-----------------------------------------
TimeUtils timeutils;
Context context(logN, logQ);//参数初始化
//密钥生成
SecretKey secretKey(logN);//生成私钥
Scheme scheme(secretKey, context);//生成公钥、计算密钥
//-----------------------------------------
SetNumThreads(1);
//-----------------------------------------
srand(time(NULL));
//-----------------------------------------
long slots = (1 << logSlots);//明文槽数
//生成复数向量
complex<double>* mvec1 = EvaluatorUtils::randomComplexArray(slots);
complex<double>* mvec2 = EvaluatorUtils::randomComplexArray(slots);
complex<double>* cvec = EvaluatorUtils::randomComplexArray(slots);
//定义三个复数向量,用于存计算结果(明文)
complex<double>* mvecAdd = new complex<double>[slots];
complex<double>* mvecMult = new complex<double>[slots];
complex<double>* mvecCMult = new complex<double>[slots];
for(long i = 0; i < slots; i++) {
mvecAdd[i] = mvec1[i] + mvec2[i];
mvecMult[i] = mvec1[i] * mvec2[i];
mvecCMult[i] = mvec1[i] * cvec[i];
}
timeutils.start("Encrypt two batch");
Ciphertext cipher1 = scheme.encrypt(mvec1, slots, logp, logQ);
Ciphertext cipher2 = scheme.encrypt(mvec2, slots, logp, logQ);
timeutils.stop("Encrypt two batch");
timeutils.start("Homomorphic Addition");
Ciphertext addCipher = scheme.add(cipher1, cipher2);
timeutils.stop("Homomorphic Addition");
timeutils.start("Homomorphic Multiplication");//密文*密文呢
Ciphertext multCipher = scheme.mult(cipher1, cipher2);//乘法
scheme.reScaleByAndEqual(multCipher, logp);//重缩放
timeutils.stop("Homomorphic Multiplication");
timeutils.start("Homomorphic Multiplication");//密文*常量
Ciphertext cmultCipher = scheme.multByConstVec(cipher1, cvec, slots, logp);//乘法
scheme.reScaleByAndEqual(cmultCipher, logp);//重缩放
timeutils.stop("Homomorphic Multiplication");
timeutils.start("Decrypt batch");
complex<double>* dvecAdd = scheme.decrypt(secretKey, addCipher);
complex<double>* dvecMult = scheme.decrypt(secretKey, multCipher);
complex<double>* dvecCMult = scheme.decrypt(secretKey, cmultCipher);
timeutils.stop("Decrypt batch");
cout <<"三个复数向量A、B、C:"<<endl;
StringUtils::show(mvec1,slots);
StringUtils::show(mvec2,slots);
StringUtils::show(cvec,slots);
StringUtils::showcompare(mvecAdd, dvecAdd, slots, "add");
StringUtils::showcompare(mvecMult, dvecMult, slots, "mult");
StringUtils::showcompare(mvecCMult, dvecCMult, slots, "mult");
}
logN:N的对数,N是密文的维数
logQ:Q的对数,Q是最大密文模数
sigma:高斯分布的标准差
h:HWT的分布参数
N:是2的次幂,对应于环\(Z\left[ X \right]/\left( X^{N}+1 \right)\)
Nh = N/2,即明文模数
logNh = logN - 1
M = 2N
logQQ:PQ的对数
PQ = Q * Q
rotGroup:预计算的旋转组索引
ksiPows:
qpowvec:预计算2的幂
taylorCoeffsMap:预计算泰勒系数
有两种,一种是逐个赋值,一种是快速赋值
//构造函数
Context::Context(long logN, long logQ, double sigma, long h) : logN(logN), logQ(logQ), sigma(sigma), h(h) {
init(logN, logQ, sigma, h);
}
Context::Context(const Context& o) : logN(o.logN), logQ(o.logQ), sigma(o.sigma), h(o.h) {
init(logN, logQ, sigma, h);
}
//初始化函数
void Context::init(long logN, long logQ, double sigma, long h) {
N = 1 << logN; //求逆对数
Nh = N >> 1; //除2
logNh = logN - 1;
M = N << 1; //乘2
logQQ = logQ << 1; //求对数
Q = power2_ZZ(logQ); //求逆对数
QQ = power2_ZZ(logQQ);//求逆对数
rotGroup = new long[Nh]; //按顺序存储Nh个5的倍数(模 M)
long fivePows = 1;
for (long i = 0; i < Nh; ++i) {
rotGroup[i] = fivePows;
fivePows *= 5;
fivePows %= M;
}
ksiPows = new complex<double>[M + 1];//存放的复数向量
for (long j = 0; j < M; ++j) {
double angle = 2.0 * M_PI * j / M;
ksiPows[j].real(cos(angle));//实数部分
ksiPows[j].imag(sin(angle));//虚数部分
}
ksiPows[M] = ksiPows[0];
qpowvec = new ZZ[logQQ + 1];
qpowvec[0] = ZZ(1);
for (long i = 1; i < logQQ + 1; ++i) {
qpowvec[i] = qpowvec[i - 1] << 1;
}
taylorCoeffsMap.insert(pair<string, double*>(LOGARITHM, new double[11]{0,1,-0.5,1./3,-1./4,1./5,-1./6,1./7,-1./8,1./9,-1./10}));
taylorCoeffsMap.insert(pair<string, double*>(EXPONENT, new double[11]{1,1,0.5,1./6,1./24,1./120,1./720,1./5040, 1./40320,1./362880,1./3628800}));
taylorCoeffsMap.insert(pair<string, double*>(SIGMOID, new double[11]{1./2,1./4,0,-1./48,0,1./480,0,-17./80640,0,31./1451520,0}));
}
// 析构函数
Context::~Context() {
delete[] rotGroup;
delete[] ksiPows;
}
ZZ是什么类型,泰勒系数、如何生成复数向量的?
ZZX Context::encode(complex<double>* vals, long slots, long logp) {
/*
* 功能:将复数向量编码成多项式
* 参数:vals(复数数组)、slots(数组大小)、logp(量化比特)
*/
complex<double>* uvals = new complex<double>[slots]();
long i, jdx, idx;
copy(vals, vals + slots, uvals);
ZZX mx;
mx.SetLength(N);
long gap = Nh / slots;
fftSpecialInv(uvals, slots);
for (i = 0, jdx = Nh, idx = 0; i < slots; ++i, jdx += gap, idx += gap) {
mx.rep[idx] = EvaluatorUtils::scaleUpToZZ(uvals[i].real(), logp);
mx.rep[jdx] = EvaluatorUtils::scaleUpToZZ(uvals[i].imag(), logp);
}
delete[] uvals;
return mx;
}
ZZX Context::encodeSingle(complex<double> val, long logp) {
/*
* 功能:将单个复数编码成多项式
* 参数:vals(复数向量)、logp(量化比特)
*/
ZZX mx;
mx.SetLength(N);
mx.rep[0] = EvaluatorUtils::scaleUpToZZ(val.real(), logp);
mx.rep[Nh] = EvaluatorUtils::scaleUpToZZ(val.imag(), logp);
return mx;
}
ZZX Context::encode(double* vals, long slots, long logp) {
/*
* 功能:将多个数(浮点数组)编码成多项式
* 参数:vals(浮点数组)、slots(数组大小)、logp(量化比特)
*/
complex<double>* uvals = new complex<double>[slots];
long i, jdx, idx;
for (i = 0; i < slots; ++i) {
uvals[i].real(vals[i]);
}
ZZX mx;
mx.SetLength(N);
long gap = Nh / slots;
fftSpecialInv(uvals, slots);
for (i = 0, jdx = Nh, idx = 0; i < slots; ++i, jdx += gap, idx += gap) {
mx.rep[idx] = EvaluatorUtils::scaleUpToZZ(uvals[i].real(), logp);
mx.rep[jdx] = EvaluatorUtils::scaleUpToZZ(uvals[i].imag(), logp);
}
delete[] uvals;
return mx;
}
ZZX Context::encodeSingle(double val, long logp) {
/*
* 功能:将单个数(浮点数)编码成多项式
* 参数:vals(浮点数)、logp(量化比特)
*/
ZZX mx;
mx.SetLength(N);
mx.rep[0] = EvaluatorUtils::scaleUpToZZ(val, logp);
return mx;
}
complex<double>* Context::decode(ZZX& mx, long slots, long logp, long logq) {
/*
* 功能:将一个多项式解码为复数数组
* 参数:mx(一个多项式)、slots(数组大小)、logp(量化比特)、logq(模数比特)
*/
ZZ q = qpowvec[logq];
long gap = Nh / slots;
complex<double>* res = new complex<double>[slots];
ZZ tmp;
for (long i = 0, idx = 0; i < slots; ++i, idx += gap) {
rem(tmp, mx[idx], q);
if(NumBits(tmp) == logq) tmp -= q;
res[i].real(EvaluatorUtils::scaleDownToReal(tmp, logp));
rem(tmp, mx[idx + Nh], q);
if(NumBits(tmp) == logq) tmp -= q;
res[i].imag(EvaluatorUtils::scaleDownToReal(tmp, logp));
}
fftSpecial(res, slots);
return res;
}
complex<double> Context::decodeSingle(ZZX& mx, long logp, long logq, bool isComplex) {
/*
* 功能:将一个多项式解码为单个复数
* 参数:mx(一个多项式)、logp(量化比特)、logq(模数比特)、isComplex(是否解码后是复数,默认是)
*/
ZZ q = qpowvec[logq];
complex<double> res;
ZZ tmp = mx.rep[0] % q;
if(NumBits(tmp) == logq) tmp -= q;
res.real(EvaluatorUtils::scaleDownToReal(tmp, logp));
if(isComplex) {
tmp = mx.rep[Nh] % q;
if(NumBits(tmp) == logq) tmp -= q;
res.imag(EvaluatorUtils::scaleDownToReal(tmp, logp));
}
return res;
}
void Context::bitReverse(complex<double>* vals, const long size) {
/*
* 功能:求FFT的比特置换(非)
* 参数:vals(复数数组)、size(数组大小)
*/
for (long i = 1, j = 0; i < size; ++i) {
long bit = size >> 1;
for (; j >= bit; bit>>=1) {
j -= bit;
}
j += bit;
if(i < j) {
swap(vals[i], vals[j]);
}
}
}
void Context::fft(complex<double>* vals, const long size) {
/*
* 功能:计算FFT在Z_q[X] / (X^N + 1)
* 参数:vals(复数数组)、size(数组大小)
*/
bitReverse(vals, size);
for (long len = 2; len <= size; len <<= 1) {
long MoverLen = M / len;
long lenh = len >> 1;
for (long i = 0; i < size; i += len) {
for (long j = 0; j < lenh; ++j) {
long idx = j * MoverLen;
complex<double> u = vals[i + j];
complex<double> v = vals[i + j + lenh];
v *= ksiPows[idx];
vals[i + j] = u + v;
vals[i + j + lenh] = u - v;
}
}
}
}
void Context::fftInvLazy(complex<double>* vals, const long size) {
/*
* 功能:计算FFT的逆延迟
* 参数:vals(复数数组)、size(数组大小)
*/
bitReverse(vals, size);
for (long len = 2; len <= size; len <<= 1) {
long MoverLen = M / len;
long lenh = len >> 1;
for (long i = 0; i < size; i += len) {
for (long j = 0; j < lenh; ++j) {
long idx = (len - j) * MoverLen;
complex<double> u = vals[i + j];
complex<double> v = vals[i + j + lenh];
v *= ksiPows[idx];
vals[i + j] = u + v;
vals[i + j + lenh] = u - v;
}
}
}
}
void Context::fftInv(complex<double>* vals, const long size) {
/*
* 功能:计算FFT的逆在Z_q[X] / (X^N + 1)
* 参数:vals(复数数组)、size(数组大小)
*/
fftInvLazy(vals, size);
for (long i = 0; i < size; ++i) {
vals[i] /= size;
}
}
void Context::fftSpecial(complex<double>* vals, const long size) {
/*
* 功能:在编码和解密时计算特殊FFT在Z_q[X] / (X^N + 1)
* 参数:vals(复数数组)、size(数组大小)
*/
bitReverse(vals, size);
for (long len = 2; len <= size; len <<= 1) {
for (long i = 0; i < size; i += len) {
long lenh = len >> 1;
long lenq = len << 2;
for (long j = 0; j < lenh; ++j) {
long idx = ((rotGroup[j] % lenq)) * M / lenq;
complex<double> u = vals[i + j];
complex<double> v = vals[i + j + lenh];
v *= ksiPows[idx];
vals[i + j] = u + v;
vals[i + j + lenh] = u - v;
}
}
}
}
void Context::fftSpecialInvLazy(complex<double>* vals, const long size) {
/*
* 功能:在编码和解密时 计算特殊FFT逆的延迟 在Z_q[X] / (X^N + 1)
* 参数:vals(复数数组)、size(数组大小)
*/
for (long len = size; len >= 1; len >>= 1) {
for (long i = 0; i < size; i += len) {
long lenh = len >> 1;
long lenq = len << 2;
for (long j = 0; j < lenh; ++j) {
long idx = (lenq - (rotGroup[j] % lenq)) * M / lenq;
complex<double> u = vals[i + j] + vals[i + j + lenh];
complex<double> v = vals[i + j] - vals[i + j + lenh];
v *= ksiPows[idx];
vals[i + j] = u;
vals[i + j + lenh] = v;
}
}
}
bitReverse(vals, size);
}
void Context::fftSpecialInv(complex<double>* vals, const long size) {
/*
* 功能:在编码和解密时 计算特殊FFT逆 在Z_q[X] / (X^N + 1)
* 参数:vals(复数数组)、size(数组大小)
*/
fftSpecialInvLazy(vals, size);
for (long i = 0; i < size; ++i) {
vals[i] /= size;
}
}
关于FFT相关的知识,需要系统学习,后续整理出一篇文章!
mx:一个多项式 mod X^N + 1
logp:量化比特
logq:模数比特
slots:明文槽
isComplex:是否是复数【option of Message with single real slot ?】
Plaintext(ZZX mx = ZZX::zero(), long logp = 0, long logq = 0, long slots = 1, bool isComplex = true) : mx(mx), logp(logp), logq(logq), slots(slots), isComplex(isComplex) {}
Plaintext(const Plaintext& o) : mx(o.mx), logp(o.logp), logq(o.logq), slots(o.slots), isComplex(o.isComplex) {}
密文是一个RLWE实例(ax, bx = mx + ex - ax * sx) 在环 Z_q[X] / (X^N + 1)
ax和bx:都是多项式,满足(ax, bx = mx + ex - ax * sx) 在环 Z_q[X] / (X^N + 1)
logp:?
logq:密文模数的对数
slots:密文的槽数
isComplex:?
Ciphertext(ZZX ax = ZZX::zero(), ZZX bx = ZZX::zero(), long logp = 0, long logq = 0, long slots = 1, bool isComplex = true) : ax(ax), bx(bx), logp(logp), logq(logq), slots(slots), isComplex(isComplex) {}
Ciphertext(const Ciphertext& o) : ax(o.ax), bx(o.bx), logp(o.logp), logq(o.logq), slots(o.slots), isComplex(o.isComplex) {}
void Ring2Utils::mod(ZZX& res, ZZX& p, ZZ& mod, const long degree) {
/*
* 功能:多项式求模 p,输出
* 参数:res(待求模的多项式)、p(输出结果,在Z_q[X] / (X^N + 1)上的一个多项式)、mod(大整数,模数q)、degree(多项式次数,N)
*/
res.SetLength(degree);
for (long i = 0; i < degree; ++i) {
rem(res.rep[i], p.rep[i], mod);
}
}
void Ring2Utils::modAndEqual(ZZX& p, ZZ& mod, const long degree) {
/*
* 功能:多项式求模 p,自身模
* 参数:p(待求模的多项式)、mod(大整数,模数q)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
rem(p.rep[i], p.rep[i], mod);
}
}
void Ring2Utils::add(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:环Z_q[X] / (X^N + 1)中两个多项式相加,在模数下 【无输出】
* 参数:res(p1 + p2 在 Z_q[X] / (X^N + 1))、p1和p2(两个多项式)、mod(模数,q)、degree(多项式次数,N)
*/
res.SetLength(degree);
for (long i = 0; i < degree; ++i) {
AddMod(res.rep[i], p1.rep[i], p2.rep[i], mod);
}
}
ZZX Ring2Utils::add(ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:环Z_q[X] / (X^N + 1)中两个多项式相加,输出res 【有输出】
* 参数:res(输出 p1 + p2 在 Z_q[X] / (X^N + 1))、p1和p2(两个多项式)、mod(模数,q)、degree(多项式次数,N)
*/
ZZX res;
add(res, p1, p2, mod, degree);
return res;
}
void Ring2Utils::addAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:环Z_q[X] / (X^N + 1)中两个多项式相加,p1 -> p1 + p2 【无输出】
* 参数:、p1和p2(两个多项式)、mod(模数,q)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
AddMod(p1.rep[i], p1.rep[i], p2.rep[i], mod);
}
}
void Ring2Utils::sub(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:环Z_q[X] / (X^N + 1)中两个多项式相减,在模数下 【无输出】
* 参数:res(p1 - p2 在 Z_q[X] / (X^N + 1))、p1和p2(两个多项式)、mod(模数,q)、degree(多项式次数,N)
*/
res.SetLength(degree);
for (long i = 0; i < degree; ++i) {
AddMod(res.rep[i], p1.rep[i], -p2.rep[i], mod);
}
}
ZZX Ring2Utils::sub(ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:环Z_q[X] / (X^N + 1)中两个多项式相减,输出res 【有输出】
* 参数:res(输出 p1 - p2 在 Z_q[X] / (X^N + 1))、p1和p2(两个多项式)、mod(模数,q)、degree(多项式次数,N)
*/
ZZX res;
sub(res, p1, p2, mod, degree);
return res;
}
void Ring2Utils::subAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:环Z_q[X] / (X^N + 1)中两个多项式相减,p1 -> p1 - p2 【无输出】
* 参数:、p1和p2(两个多项式)、mod(模数,q)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
AddMod(p1.rep[i], p1.rep[i], -p2.rep[i], mod);
}
}
void Ring2Utils::subAndEqual2(ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:环Z_q[X] / (X^N + 1)中两个多项式相减,p2 -> p1 - p2 【无输出】
* 参数:、p1和p2(两个多项式)、mod(模数,q)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
AddMod(p2.rep[i], p1.rep[i], -p2.rep[i], mod);
}
}
void Ring2Utils::mult(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:res=p1 * p2 在 Z_q[X] / (X^N + 1)上 【无输出】
* mod(模数,q)、degree(多项式次数,N)
*/
res.SetLength(degree);
ZZX pp;
mul(pp, p1, p2);
pp.SetLength(2 * degree);
for (long i = 0; i < degree; ++i) {
rem(pp.rep[i], pp.rep[i], mod);
rem(pp.rep[i + degree], pp.rep[i + degree], mod);
SubMod(res.rep[i], pp.rep[i], pp.rep[i + degree], mod);
}
}
ZZX Ring2Utils::mult(ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:res=p1 * p2 在 Z_q[X] / (X^N + 1)上 【输出res】
* mod(模数,q)、degree(多项式次数,N)
*/
ZZX res;
mult(res, p1, p2, mod, degree);
return res;
}
void Ring2Utils::multAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long degree) {
/*
* 功能:p1 -> p1 * p2 在 Z_q[X] / (X^N + 1)上 【无输出】
* mod(模数,q)、degree(多项式次数,N)
*/
ZZX pp;
mul(pp, p1, p2);
pp.SetLength(2 * degree);
for (long i = 0; i < degree; ++i) {
rem(pp.rep[i], pp.rep[i], mod);
rem(pp.rep[i + degree], pp.rep[i + degree], mod);
SubMod(p1.rep[i], pp.rep[i], pp.rep[i + degree], mod);
}
}
void Ring2Utils::square(ZZX& res, ZZX& p, ZZ& mod, const long degree) {
/*
* 功能:res=p^2 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:res和p(多项式)、mod(模数,q)、degree(多项式次数,N)
*/
res.SetLength(degree);
ZZX pp;
sqr(pp, p);
pp.SetLength(2 * degree);
for (long i = 0; i < degree; ++i) {
rem(pp.rep[i], pp.rep[i], mod);
rem(pp.rep[i + degree], pp.rep[i + degree], mod);
SubMod(res.rep[i], pp.rep[i], pp.rep[i + degree], mod);
}
}
ZZX Ring2Utils::square(ZZX& p, ZZ& mod, const long degree) {
/*
* 功能:res=p^2 在 Z_q[X] / (X^N + 1) 【输出res】
* 参数:res和p(多项式)、mod(模数,q)、degree(多项式次数,N)
*/
ZZX res;
square(res, p, mod, degree);
return res;
}
void Ring2Utils::squareAndEqual(ZZX& p, ZZ& mod, const long degree) {
/*
* 功能:p=p^2 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:p(多项式)、mod(模数,q)、degree(多项式次数,N)
*/
ZZX pp;
sqr(pp, p);
pp.SetLength(2 * degree);
for (long i = 0; i < degree; ++i) {
rem(pp.rep[i], pp.rep[i], mod);
rem(pp.rep[i + degree], pp.rep[i + degree], mod);
SubMod(p.rep[i], pp.rep[i], pp.rep[i + degree], mod);
}
}
void Ring2Utils::multByMonomial(ZZX& res, ZZX& p, const long monomialDeg, const long degree) {
/*
* 功能:res=p * X^d 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:res和p(多项式)、monomialDeg(单次项,d)、degree(多项式次数,N)
*/
long shift = monomialDeg % (2 * degree);
if(shift == 0) {
res = p;
} else {
ZZX tmpx;
tmpx.SetLength(degree);
tmpx = (shift < degree) ? p : -p;
shift %= degree;
res.SetLength(degree);
for (long i = 0; i < shift; ++i) {
res.rep[i] = -tmpx.rep[degree - shift + i];
}
for (long i = shift; i < degree; ++i) {
res.rep[i] = tmpx.rep[i - shift];
}
}
}
ZZX Ring2Utils::multByMonomial(ZZX& p, const long monomialDeg, const long degree) {
/*
* 功能:res=p * X^d 在 Z_q[X] / (X^N + 1) 【输出res】
* 参数:res和p(多项式)、monomialDeg(单次项,d)、degree(多项式次数,N)
*/
ZZX res;
multByMonomial(res, p, monomialDeg, degree);
return res;
}
void Ring2Utils::multByMonomialAndEqual(ZZX& p, const long monomialDeg, const long degree) {
/*
* 功能:多项式乘次幂,即p -> p * X^d 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:p(多项式)、monomialDeg(单次项,d)、degree(多项式次数,N)
*/
long shift = monomialDeg % (2 * degree);
if(shift == 0) {
return;
}
ZZX tmpx;
tmpx.SetLength(degree);
tmpx = (shift < degree) ? p : -p;
shift %= degree;
for (long i = 0; i < shift; ++i) {
p.rep[i] = -tmpx.rep[degree - shift + i];
}
for (long i = shift; i < degree; ++i) {
p.rep[i] = tmpx.rep[i - shift];
}
}
void Ring2Utils::multByConst(ZZX& res, ZZX& p, const ZZ& cnst, ZZ& mod, const long degree) {
/*
* 功能:多项式乘常数,即res=p * c 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:res和p(多项式)、cnst(大常数,c)、mod(模数,q)、degree(多项式次数,N)
*/
res.SetLength(degree);
for (long i = 0; i < degree; ++i) {
MulMod(res.rep[i], p.rep[i], cnst, mod);
}
}
ZZX Ring2Utils::multByConst(ZZX& p, const ZZ& cnst, ZZ& mod, const long degree) {
/*
* 功能:多项式乘常数,即res=p * c 在 Z_q[X] / (X^N + 1) 【输出res】
* 参数:res和p(多项式)、cnst(大常数,c)、mod(模数,q)、degree(多项式次数,N)
*/
ZZX res;
multByConst(res, p, cnst, mod, degree);
return res;
}
void Ring2Utils::multByConstAndEqual(ZZX& p, const ZZ& cnst, ZZ& mod, const long degree) {
/*
* 功能:多项式乘常数,即p=p * c 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:p(多项式)、cnst(大常数,c)、mod(模数,q)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
MulMod(p.rep[i], p.rep[i], cnst, mod);
}
}
void Ring2Utils::leftShift(ZZX& res, ZZX& p, const long bits, ZZ& mod, const long degree) {
/*
* 功能:多项式乘常数,即res=p * 2^b 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:res和p(多项式)、bits(级数,b)、mod(模数,q)、degree(多项式次数,N)
*/
res.SetLength(degree);
for (long i = 0; i < degree; ++i) {
LeftShift(res.rep[i], p.rep[i], bits);
rem(res.rep[i], res.rep[i], mod);
}
}
void Ring2Utils::leftShiftAndEqual(ZZX& p, const long bits, ZZ& mod, const long degree) {
/*
* 功能:多项式乘常数,即p=p * 2^b 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:p(多项式)、bits(级数,b)、mod(模数,q)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
LeftShift(p.rep[i], p.rep[i], bits);
rem(p.rep[i], p.rep[i], mod);
}
}
void Ring2Utils::doubleAndEqual(ZZX& p, ZZ& mod, const long degree) {
/*
* 功能:多项式乘常数,即p=2p 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:p(多项式)、mod(模数,q)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
LeftShift(p.rep[i], p.rep[i], 1);
rem(p.rep[i], p.rep[i], mod);
}
}
void Ring2Utils::rightShift(ZZX& res, ZZX& p, const long bits, const long degree) {
/*
* 功能:多项式乘常数,res=p / 2^b 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:res和p(多项式)、bits(级数,b)、degree(多项式次数,N)
*/
res.SetLength(degree);
for (long i = 0; i < degree; ++i) {
RightShift(res.rep[i], p.rep[i], bits);
}
}
void Ring2Utils::rightShiftAndEqual(ZZX& p, const long bits, const long degree) {
/*
* 功能:多项式乘常数,p -> p / 2^b 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:p(多项式)、bits(级数,b)、degree(多项式次数,N)
*/
for (long i = 0; i < degree; ++i) {
RightShift(p.rep[i], p.rep[i], bits);
}
}
void Ring2Utils::conjugate(ZZX& res, ZZX& p, const long degree) {
/*
* 功能:求共轭,res=conj(p) 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:res和p(多项式)、degree(多项式次数,N)
*/
res.SetLength(degree);
res.rep[0] = p.rep[0];
for (long i = 1; i < degree; ++i) {
res.rep[i] = -p.rep[degree - i];
}
}
void Ring2Utils::conjugateAndEqual(ZZX& p, const long degree) {
/*
* 功能:求共轭,p=conj(p) 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:p(多项式)、degree(多项式次数,N)
*/
for (long i = 0; i < degree / 2; ++i) {
ZZ tmp = p.rep[i];
p.rep[i] = p.rep[degree - i];
p.rep[degree - i] = tmp;
}
p.rep[degree / 2] = -p.rep[degree / 2];
}
void Ring2Utils::inpower(ZZX& res, ZZX& p, const long pow, ZZ& mod, const long degree) {
/*
* 功能:res=p(X^pow) 在 Z_q[X] / (X^N + 1) 【无输出】
* 参数:res和p(多项式)、pow(次幂)、mod(模数,q)、degree(多项式次数,N)
*/
res.kill();
res.SetLength(degree);
for (long i = 0; i < degree; ++i) {
long ipow = i * pow;
long shift = ipow % (2 * degree);
if(shift < degree) {
AddMod(res.rep[shift % degree], res.rep[shift % degree], p.rep[i], mod);
} else {
AddMod(res.rep[shift % degree], res.rep[shift % degree], -p.rep[i], mod);
}
}
}
ZZX Ring2Utils::inpower(ZZX& p, const long pow, ZZ& mod, const long degree) {
/*
* 功能:res=p(X^pow) 在 Z_q[X] / (X^N + 1) 【输出res】
* 参数:res和p(多项式)、pow(次幂)、mod(模数,q)、degree(多项式次数,N)
*/
ZZX res;
inpower(res, p, pow, mod, degree);
return res;
}
void NumUtils::sampleGauss(ZZX& res, const long size, const double stdev) {
/*
* 功能:在高斯分布中随机采样系数生成多项式
* 参数:res(随机生成的多项式)、size(多项式次数)、stdev(高斯分布的标准差)
*/
static double const Pi = 4.0 * atan(1.0);
static long const bignum = 0xfffffff;
res.SetLength(size);
for (long i = 0; i < size; 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 x1 = (long) floor(rr * cos(theta) + 0.5);
res.rep[i] = x1;
if(i + 1 < size) {
long x2 = (long) floor(rr * sin(theta) + 0.5);
res.rep[i + 1] = x2;
}
}
}
void NumUtils::sampleHWT(ZZX& res, const long size, const long h) {
/*
* 功能:随机从{-1,0,1}系数中采样生成多项式
* 参数:res(随机生成的多项式)、size(多项式次数)、h(非0的个数)
*/
res.SetLength(size);
long idx = 0;
ZZ tmp = RandomBits_ZZ(h);
while(idx < h) {
long i = RandomBnd(size);
if(res.rep[i] == 0) {
res.rep[i] = (bit(tmp, idx) == 0) ? ZZ(1) : ZZ(-1);
idx++;
}
}
}
void NumUtils::sampleZO(ZZX& res, const long size) {
/*
* 功能:随机从{-1,0,1}系数中采样生成多项式 【没有0个数的限制】
* 参数:res(随机生成的多项式)、size(多项式次数)
*/
res.SetLength(size);
ZZ tmp = RandomBits_ZZ(2 * size);
for (long i = 0; i < size; ++i) {
res.rep[i] = (bit(tmp, 2 * i) == 0) ? ZZ(0) : (bit(tmp, 2 * i + 1) == 0) ? ZZ(1) : ZZ(-1);
}
}
void NumUtils::sampleBinary(ZZX& res, const long size, const long h) {
/*
* 功能:随机从{0,1}系数中采样生成多项式
* 参数:res(随机生成的多项式)、size(多项式次数)、h(非0的个数)
*/
res.SetLength(size);
long idx = 0;
while(idx < h) {
long i = RandomBnd(size);
if(res.rep[i] == 0) {
res.rep[i] = ZZ(1);
idx++;
}
}
}
void NumUtils::sampleBinary(ZZX& res, const long size) {
/*
* 功能:随机从{0,1}系数中采样生成多项式 【没有0个数的限制】
* 参数:res(随机生成的多项式)、size(多项式次数)
*/
res.SetLength(size);
ZZ tmp = RandomBits_ZZ(size);
for (long i = 0; i < size; ++i) {
res.rep[i] = (bit(tmp, i) == 0) ? ZZ(0) : ZZ(1);
}
}
void NumUtils::sampleUniform2(ZZX& res, const long size, const long bits) {
/*
* 功能:随机从[0, 2^bits-1]中采样系数生成多项式
* 参数:res(随机生成的多项式)、size(多项式次数)、bits(位数)
*/
res.SetLength(size);
for (long i = 0; i < size; i++) {
res.rep[i] = RandomBits_ZZ(bits);
}
}
Key是RLWE的一个实例(ax, bx = mx + ex - ax * sx) 在环上 Z_q[X] / (X^N + 1);
Key(ZZX ax = ZZX::zero(), ZZX bx = ZZX::zero()) : ax(ax), bx(bx) {}
keyMap:包含用于加密、乘法计算、共轭计算的密钥
leftRotKeyMap:包含做左旋转密钥
Scheme::Scheme(Context& context) : context(context) {
}
Scheme::Scheme(SecretKey& secretKey, Context& context) : context(context) {
//生成公钥
addEncKey(secretKey);
//生成乘法计算密钥
addMultKey(secretKey);
};
void Scheme::addEncKey(SecretKey& secretKey) {
/*
* 功能:生成用于公钥(密钥存储在keyMap中)
* 参数:sx(私钥中)
*/
ZZX ex, ax, bx;
NumUtils::sampleUniform2(ax, context.N, context.logQQ);//ax([0, 2^bits-1]采样)
NumUtils::sampleGauss(ex, context.N, context.sigma);//ex(高斯分布中采样)
Ring2Utils::mult(bx, secretKey.sx, ax, context.QQ, context.N);//bx=sx*ax
Ring2Utils::sub(bx, ex, bx, context.QQ, context.N);//bx=ex-sx*ax
keyMap.insert(pair<long, Key>(ENCRYPTION, Key(ax, bx)));//公钥(ax,bx)
}
void Scheme::addMultKey(SecretKey& secretKey) {
/*
* 功能:生成用于共轭密钥(密钥存储在keyMap中)
*/
ZZX ex, ax, bx, sxsx;
Ring2Utils::mult(sxsx, secretKey.sx, secretKey.sx, context.Q, context.N);//sxsx = sx * sx
Ring2Utils::leftShiftAndEqual(sxsx, context.logQ, context.QQ, context.N);//sxsx = sxsx * 2^logQ
NumUtils::sampleUniform2(ax, context.N, context.logQQ);//ax采样于[0, 2^N-1]
NumUtils::sampleGauss(ex, context.N, context.sigma);//ex采样于高斯分布
Ring2Utils::addAndEqual(ex, sxsx, context.QQ, context.N);//ex = ex + sxsx
Ring2Utils::mult(bx, secretKey.sx, ax, context.QQ, context.N);//bx = sx * ax
Ring2Utils::sub(bx, ex, bx, context.QQ, context.N);//bx = ex - bx
keyMap.insert(pair<long, Key>(MULTIPLICATION, Key(ax, bx)));//共轭密钥(ax,bx)
}
void Scheme::addConjKey(SecretKey& secretKey) {
/*
* 功能:生成用于乘法计算的密钥(密钥存储在keyMap中)
*/
ZZX ex, ax, bx, sxconj;
Ring2Utils::conjugate(sxconj, secretKey.sx, context.N);//sxconj = conj(sx)
Ring2Utils::leftShiftAndEqual(sxconj, context.logQ, context.QQ, context.N);//sxconj = sxconj * 2^logQ
NumUtils::sampleUniform2(ax, context.N, context.logQQ);//ax采样于[0, 2^N-1]
NumUtils::sampleGauss(ex, context.N, context.sigma);//ex采样于高斯分布
Ring2Utils::addAndEqual(ex, sxconj, context.QQ, context.N);//ex = ex + sxconj
Ring2Utils::mult(bx, secretKey.sx, ax, context.QQ, context.N);//bx = sx * ax
Ring2Utils::sub(bx, ex, bx, context.QQ, context.N);//bx = ex - bx
keyMap.insert(pair<long, Key>(CONJUGATION, Key(ax, bx)));//乘法密钥(ax, bx)
}
void Scheme::addLeftRotKey(SecretKey& secretKey, long rot) {
/*
* 功能:为左旋转生成密钥(密钥存储在leftRotKeyMap中)
*/
ZZX ex, ax, bx, sxrot;
Ring2Utils::inpower(sxrot, secretKey.sx, context.rotGroup[rot], context.Q, context.N);//sxrot = sx(X^rotGroup[rot])
Ring2Utils::leftShiftAndEqual(sxrot, context.logQ, context.QQ, context.N);//sxrot = sxrot * 2^logQ
NumUtils::sampleUniform2(ax, context.N, context.logQQ);//ax采样于[0, 2^N-1]
NumUtils::sampleGauss(ex, context.N, context.sigma);//ex采样于高斯分布
Ring2Utils::addAndEqual(ex, sxrot, context.QQ, context.N);//ex = ex + sxrot
Ring2Utils::mult(bx, secretKey.sx, ax, context.QQ, context.N);//bx = sx * ax
Ring2Utils::sub(bx, ex, bx, context.QQ, context.N);//bx = ex - bx
leftRotKeyMap.insert(pair<long, Key>(rot, Key(ax, bx)));//左旋转密钥(ax, bx)
}
void Scheme::addLeftRotKeys(SecretKey& secretKey) {
/*
* 功能:生成多次(两次幂)左旋转的密钥(密钥存储在leftRotKeyMap中)
*/
for (long i = 0; i < context.logNh; ++i) {
long idx = 1 << i;
if(leftRotKeyMap.find(idx) == leftRotKeyMap.end()) {
addLeftRotKey(secretKey, idx);
}
}
}
void Scheme::addRightRotKeys(SecretKey& secretKey) {
/*
* 功能:生成多次(两次幂)右旋转的密钥(密钥存储在leftRotKeyMap中)
*/
for (long i = 0; i < context.logNh; ++i) {
long idx = context.N/2 - (1 << i);
if(leftRotKeyMap.find(idx) == leftRotKeyMap.end()) {
addLeftRotKey(secretKey, idx);
}
}
}
void Scheme::addSortKeys(SecretKey& secretKey, long size) {
/*
* 功能:生成用于排序的密钥(密钥存储在leftRotKeyMap中)
*/
for (long i = 1; i < size; ++i) {
if(leftRotKeyMap.find(i) == leftRotKeyMap.end()) {
addLeftRotKey(secretKey, i);
}
}
}
Plaintext Scheme::encode(double* vals, long slots, long logp, long logq) {
/*
* 功能:使用特殊的fft逆运算将double数组编码为ZZX多项式
* 参数:vals(double数组)、slots(数组大小)、logp(?)、logq(密文模式q的对数值)
*/
ZZX mx = context.encode(vals, slots, logp + context.logQ);
return Plaintext(mx, logp, logq, slots, false);
}
Plaintext Scheme::encode(complex<double>* vals, long slots, long logp, long logq) {
/*
* 功能:使用特殊的fft逆运算将复数数组编码为ZZX多项式
* 参数:vals(复数数组)、slots(数组大小)、logp(?)、logq(密文模式q的对数值)
*/
ZZX mx = context.encode(vals, slots, logp + context.logQ);
return Plaintext(mx, logp, logq, slots, true);
}
Plaintext Scheme::encodeSingle(complex<double> val, long logp, long logq) {
/*
* 功能:使用特殊的fft逆运算将单个复数值编码为ZZX多项式
* 参数:vals(复数数组)、logp(?)、logq(密文模式q的对数值)
*/
ZZX mx = context.encodeSingle(val, logp + context.logQ);
return Plaintext(mx, logp, logq, 1, true);
}
Plaintext Scheme::encodeSingle(double val, long logp, long logq) {
/*
* 功能:使用特殊的fft逆运算将单个double数编码为ZZX多项式
* 参数:vals(复数数组)、logp(?)、logq(密文模式q的对数值)
*/
ZZX mx = context.encodeSingle(val, logp + context.logQ);
return Plaintext(mx, logp, logq, 1, false);
}
complex<double>* Scheme::decode(Plaintext& msg) {
/*
* 功能:使用特殊的fft将ZZX多项式解码为复数数组
* 参数:msg(编码后的明文)
*/
return context.decode(msg.mx, msg.slots, msg.logp, msg.logq);
}
complex<double> Scheme::decodeSingle(Plaintext& msg) {
/*
* 功能:使用特殊的fft将ZZX多项式解码为单个复数
* 参数:msg(编码后的明文)
*/
return context.decodeSingle(msg.mx, msg.logp, msg.logq, msg.isComplex);
}
Ciphertext Scheme::encryptMsg(Plaintext& msg) {
/*
* 功能:使用公钥将编码后的明文加密为密文
* 参数:公钥(ax,bx)
*/
ZZX ax, bx, vx, ex;
Key key = keyMap.at(ENCRYPTION);//key是一个RLWE实例
ZZ qQ = context.qpowvec[msg.logq + context.logQ];//
NumUtils::sampleZO(vx, context.N);//vx从{-1,0,1}采样
Ring2Utils::mult(ax, vx, key.ax, qQ, context.N);//ax = vx * ax
NumUtils::sampleGauss(ex, context.N, context.sigma);//ex从高斯采样
Ring2Utils::addAndEqual(ax, ex, qQ, context.N);//ax = ax + ex
Ring2Utils::mult(bx, vx, key.bx, qQ, context.N);// bx = vx * bx
NumUtils::sampleGauss(ex, context.N, context.sigma);//ex从高斯采样
Ring2Utils::addAndEqual(bx, ex, qQ, context.N);//bx = bx + ex
Ring2Utils::addAndEqual(bx, msg.mx, qQ, context.N);//bx = bx + mx
//为什么进行这一步?进行模?
Ring2Utils::rightShiftAndEqual(ax, context.logQ, context.N);//ax = ax / 2^logQ
Ring2Utils::rightShiftAndEqual(bx, context.logQ, context.N);//bx = bx / 2^logQ
//输出密文:(ax * vx +ex , bx * vx +ex +mx)mod
return Ciphertext(ax, bx, msg.logp, msg.logq, msg.slots, msg.isComplex);
}
Ciphertext Scheme::encrypt(double* vals, long slots, long logp, long logq) {
/*
* 功能:将double数组编码为明文消息,然后使用公钥将其加密为密文
* 参数:vals(double数组)、slots(数组大小)
*/
//先编码
Plaintext msg = encode(vals, slots, logp, logq);
//后加密
return encryptMsg(msg);
}
Ciphertext Scheme::encrypt(complex<double>* vals, long slots, long logp, long logq) {
/*
* 功能:将复数数组编码为明文消息,然后使用公钥将其加密为密文
* 参数:vals(复数数组)、slots(数组大小)
*/
//先编码
Plaintext msg = encode(vals, slots, logp, logq);
//再加密
return encryptMsg(msg);
}
Ciphertext Scheme::encryptSingle(double val, long logp, long logq) {
/*
* 功能:将一个double数编码到消息中,然后使用公钥将其加密为密文
* 参数:val(一个double数)
*/
//先编码
Plaintext msg = encodeSingle(val, logp, logq);
//后加密
return encryptMsg(msg);
}
Ciphertext Scheme::encryptSingle(complex<double> val, long logp, long logq) {
/*
* 功能:将一个复数编码到消息中,然后使用公钥将其加密为密文
* 参数:val(一个复数)
*/
//先编码
Plaintext msg = encodeSingle(val, logp, logq);
//后加密
return encryptMsg(msg);
}
Ciphertext Scheme::encryptZeros(long slots, long logp, long logq) {
/*
* 功能:将一组零编码为消息,然后使用公钥将其加密为密文
* 参数:slots(数组大小)
*/
//生成零明文数组
Ciphertext czeros = encryptSingle(0.0, logp, logq);
czeros.isComplex = true;
czeros.slots = slots;
return czeros;
}
Plaintext Scheme::decryptMsg(SecretKey& secretKey, Ciphertext& cipher) {
/*
* 功能:使用私钥将密文解密为明文消息
* 参数:secretKey(私钥)、cipher(密文)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX mx;
Ring2Utils::mult(mx, cipher.ax, secretKey.sx, q, context.N);//mx = ax * sx
Ring2Utils::addAndEqual(mx, cipher.bx, q, context.N);//mx = ax * sx + bx
return Plaintext(mx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
complex<double>* Scheme::decrypt(SecretKey& secretKey, Ciphertext& cipher) {
/*
* 功能:将密文解密为消息,然后将其解码为复数数组
* 参数:secretKey(私钥)、cipher(一个密文)
*/
//先解密
Plaintext msg = decryptMsg(secretKey, cipher);
//再解码
return decode(msg);
}
complex<double> Scheme::decryptSingle(SecretKey& secretKey, Ciphertext& cipher) {
/*
* 功能:将密文解密为消息,然后将其解码为单复数值
* 参数:secretKey(私钥)、cipher(一个密文)
*/
//先解密
Plaintext msg = decryptMsg(secretKey, cipher);
//再解码
return decodeSingle(msg);
}
Ciphertext Scheme::negate(Ciphertext& cipher) {
/*
* 功能:ciphertext(-m)
* 参数:cipher(密文,ciphertext(m))
*/
return Ciphertext(-cipher.ax, -cipher.bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::negateAndEqual(Ciphertext& cipher) {
/*
* 功能:ciphertext(m) = ciphertext(-m)
*/
cipher.ax = -cipher.ax;
cipher.bx = -cipher.bx;
}
Ciphertext Scheme::add(Ciphertext& cipher1, Ciphertext& cipher2) {
/*
* 功能:ciphertext(m1 + m2)
*/
ZZ q = context.qpowvec[cipher1.logq];
ZZX ax, bx;
Ring2Utils::add(ax, cipher1.ax, cipher2.ax, q, context.N);
Ring2Utils::add(bx, cipher1.bx, cipher2.bx, q, context.N);
return Ciphertext(ax, bx, cipher1.logp, cipher1.logq, cipher1.slots, cipher1.isComplex);
}
void Scheme::addAndEqual(Ciphertext& cipher1, Ciphertext& cipher2) {
/*
* 功能:ciphertext(m1) = ciphertext(m1 + m2)
*/
ZZ q = context.qpowvec[cipher1.logq];
Ring2Utils::addAndEqual(cipher1.ax, cipher2.ax, q, context.N);
Ring2Utils::addAndEqual(cipher1.bx, cipher2.bx, q, context.N);
}
Ciphertext Scheme::addConst(Ciphertext& cipher, double cnst, long logp) {
/*
* 功能:ciphertext(m + cnst * 2^logp)
* 参数:cipher(密文,ciphertext(m))、cnst(一个double型常数)、logp(量化比特?,如果logp<0,则使用cipher.logp,否则logp)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX ax = cipher.ax;
ZZX bx = cipher.bx;
ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);
AddMod(bx.rep[0], cipher.bx.rep[0], cnstZZ, q);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
Ciphertext Scheme::addConst(Ciphertext& cipher, RR& cnst, long logp) {
/*
* 功能:ciphertext(m + cnst * 2^logp)
* 参数:cipher(密文,ciphertext(m))、cnst(一个RR类型常量)、logp(量化比特?,如果logp<0,则使用cipher.logp,否则logp)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX ax = cipher.ax;
ZZX bx = cipher.bx;
ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);
AddMod(bx.rep[0], cipher.bx.rep[0], cnstZZ, q);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
Ciphertext Scheme::addConst(Ciphertext& cipher, complex<double> cnst, long logp) {
/*
* 功能:ciphertext(m + cnst * 2^logp)
* 参数:cipher(密文,ciphertext(m))、cnst(一个复数型常量)、logp(量化比特?,如果logp<0,则使用cipher.logp,否则logp)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX ax = cipher.ax;
ZZX bx = cipher.bx;
ZZ cnstrZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst.real(), cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst.real(), logp);
ZZ cnstiZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst.imag(), cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst.imag(), logp);
AddMod(bx.rep[0], cipher.bx.rep[0], cnstrZZ, q);
AddMod(bx.rep[context.Nh], cipher.bx.rep[context.Nh], cnstiZZ, q);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::addConstAndEqual(Ciphertext& cipher, double cnst, long logp) {
/*
* 功能:ciphertext(m) = ciphertext(m + cnst * 2^logp)
* 参数:cipher(密文,ciphertext(m))、cnst(一个double型常量)、logp(量化比特?,如果logp<0,则使用cipher.logp,否则logp)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);
AddMod(cipher.bx.rep[0], cipher.bx.rep[0], cnstZZ, q);
}
void Scheme::addConstAndEqual(Ciphertext& cipher, RR& cnst, long logp) {
/*
* 功能:ciphertext(m) = ciphertext(m + cnst * 2^logp)
* 参数:cipher(密文,ciphertext(m))、cnst(一个RR型常量)、logp(量化比特?,如果logp<0,则使用cipher.logp,否则logp)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);
AddMod(cipher.bx.rep[0], cipher.bx.rep[0], cnstZZ, q);
}
void Scheme::addConstAndEqual(Ciphertext& cipher, complex<double> cnst, long logp) {
/*
* 功能:ciphertext(m) = ciphertext(m + cnst * 2^logp)
* 参数:cipher(密文,ciphertext(m))、cnst(一个复数型常量)、logp(量化比特?,如果logp<0,则使用cipher.logp,否则logp)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ cnstrZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst.real(), cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst.real(), logp);
ZZ cnstiZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst.imag(), cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst.imag(), logp);
AddMod(cipher.bx.rep[0], cipher.bx.rep[0], cnstrZZ, q);
AddMod(cipher.bx.rep[context.Nh], cipher.bx.rep[context.Nh], cnstiZZ, q);
}
Ciphertext Scheme::sub(Ciphertext& cipher1, Ciphertext& cipher2) {
/*
* 功能:密文减法
* 输出:ciphertext(m1 - m2)
*/
ZZ q = context.qpowvec[cipher1.logq];
ZZX ax, bx;
Ring2Utils::sub(ax, cipher1.ax, cipher2.ax, q, context.N);
Ring2Utils::sub(bx, cipher1.bx, cipher2.bx, q, context.N);
return Ciphertext(ax, bx, cipher1.logp, cipher1.logq, cipher1.slots, cipher1.isComplex);
}
void Scheme::subAndEqual(Ciphertext& cipher1, Ciphertext& cipher2) {
/*
* 功能:密文减法
* 输出:ciphertext(m1) = ciphertext(m1 - m2)
*/
ZZ q = context.qpowvec[cipher1.logq];
Ring2Utils::subAndEqual(cipher1.ax, cipher2.ax, q, context.N);
Ring2Utils::subAndEqual(cipher1.bx, cipher2.bx, q, context.N);
}
void Scheme::subAndEqual2(Ciphertext& cipher1, Ciphertext& cipher2) {
/*
* 功能:密文减法
* 输出:ciphertext(m2) = ciphertext(m1 - m2)
*/
ZZ q = context.qpowvec[cipher1.logq];
Ring2Utils::subAndEqual2(cipher1.ax, cipher2.ax, q, context.N);
Ring2Utils::subAndEqual2(cipher1.bx, cipher2.bx, q, context.N);
}
Ciphertext Scheme::imult(Ciphertext& cipher) {
/*
* 功能:密文乘以i(虚单位)
* 输出:ciphertext(i * m)
*/
ZZX ax, bx;
Ring2Utils::multByMonomial(ax, cipher.ax, context.Nh, context.N);
Ring2Utils::multByMonomial(bx, cipher.bx, context.Nh, context.N);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
Ciphertext Scheme::idiv(Ciphertext& cipher) {
/*
* 功能:密文除于i(虚单位)
* 输出:ciphertext(m / i)
*/
ZZX ax, bx;
Ring2Utils::multByMonomial(ax, cipher.ax, 3 * context.Nh, context.N);
Ring2Utils::multByMonomial(bx, cipher.bx, 3 * context.Nh, context.N);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::imultAndEqual(Ciphertext& cipher) {
/*
* 功能:密文乘以i(虚单位)
* 输出:ciphertext(m) = ciphertext(i * m)
*/
Ring2Utils::multByMonomialAndEqual(cipher.ax, context.Nh, context.N);
Ring2Utils::multByMonomialAndEqual(cipher.bx, context.Nh, context.N);
}
void Scheme::idivAndEqual(Ciphertext& cipher) {
/*
* 功能:密文除于i(虚单位)
* 输出:ciphertext(m) = ciphertext(m / i)
*/
Ring2Utils::multByMonomialAndEqual(cipher.ax, 3 * context.Nh, context.N);
Ring2Utils::multByMonomialAndEqual(cipher.bx, 3 * context.Nh, context.N);
}
Ciphertext Scheme::mult(Ciphertext& cipher1, Ciphertext& cipher2) {
/*
* 功能:密文的乘法。该算法包含重线性化,为了降低噪声,我们通常需要在乘法后使用重缩放方法
* 输出:ciphertext(m1 * m2)
*/
ZZ q = context.qpowvec[cipher1.logq];
ZZ qQ = context.qpowvec[cipher1.logq + context.logQ];
ZZX axbx1, axbx2, axax, bxbx, axmult, bxmult;
Key key = keyMap.at(MULTIPLICATION);
Ring2Utils::add(axbx1, cipher1.ax, cipher1.bx, q, context.N);//axbx1 = ax1 + bx1
Ring2Utils::add(axbx2, cipher2.ax, cipher2.bx, q, context.N);//axbx2 = ax2 + bx2
Ring2Utils::multAndEqual(axbx1, axbx2, q, context.N);//axbx1 = axbx1 * axbx2
Ring2Utils::mult(axax, cipher1.ax, cipher2.ax, q, context.N);//axax = ax1 * ax2
Ring2Utils::mult(bxbx, cipher1.bx, cipher2.bx, q, context.N);//bxbx = bx1 * bx2
Ring2Utils::mult(axmult, axax, key.ax, qQ, context.N);//axmult = axax * ax
Ring2Utils::mult(bxmult, axax, key.bx, qQ, context.N);//bxmult = axax * bx
Ring2Utils::rightShiftAndEqual(axmult, context.logQ, context.N);//axmult = axmult / 2^logQ
Ring2Utils::rightShiftAndEqual(bxmult, context.logQ, context.N);//bxmult = bxmult / 2^logQ
Ring2Utils::addAndEqual(axmult, axbx1, q, context.N);//axmult = axmult + axbx1
Ring2Utils::subAndEqual(axmult, bxbx, q, context.N);//axmult = axmult - bxbx
Ring2Utils::subAndEqual(axmult, axax, q, context.N);//axmult = axmult - axax
Ring2Utils::addAndEqual(bxmult, bxbx, q, context.N);//bxmult = bxmult - bxbx
return Ciphertext(axmult, bxmult, cipher1.logp + cipher2.logp, cipher1.logq, cipher1.slots, cipher1.isComplex);
}
void Scheme::multAndEqual(Ciphertext& cipher1, Ciphertext& cipher2) {
/*
* 功能:密文的乘法。该算法包含重线性化,为了降低噪声,我们通常需要在乘法后使用重缩放方法
* 输出:ciphertext(m1) = ciphertext(m1 * m2)
*/
ZZ q = context.qpowvec[cipher1.logq];
ZZ qQ = context.qpowvec[cipher1.logq + context.logQ];
ZZX axbx1, axbx2, axax, bxbx;
Key key = keyMap.at(MULTIPLICATION);
Ring2Utils::add(axbx1, cipher1.ax, cipher1.bx, q, context.N);
Ring2Utils::add(axbx2, cipher2.ax, cipher2.bx, q, context.N);
Ring2Utils::multAndEqual(axbx1, axbx2, q, context.N);
Ring2Utils::mult(axax, cipher1.ax, cipher2.ax, q, context.N);
Ring2Utils::mult(bxbx, cipher1.bx, cipher2.bx, q, context.N);
Ring2Utils::mult(cipher1.ax, axax, key.ax, qQ, context.N);
Ring2Utils::mult(cipher1.bx, axax, key.bx, qQ, context.N);
Ring2Utils::rightShiftAndEqual(cipher1.ax, context.logQ, context.N);
Ring2Utils::rightShiftAndEqual(cipher1.bx, context.logQ, context.N);
Ring2Utils::addAndEqual(cipher1.ax, axbx1, q, context.N);
Ring2Utils::subAndEqual(cipher1.ax, bxbx, q, context.N);
Ring2Utils::subAndEqual(cipher1.ax, axax, q, context.N);
Ring2Utils::addAndEqual(cipher1.bx, bxbx, q, context.N);
cipher1.logp += cipher2.logp;
}
Ciphertext Scheme::square(Ciphertext& cipher) {
/*
* 功能:对密文进行平方运算。该算法包含重线性化,为了降低噪声,我们通常需要在乘法后使用重缩放方法
* 输出:ciphertext(m^2)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ qQ = context.qpowvec[cipher.logq + context.logQ];
ZZX axax, axbx, bxbx, bxmult, axmult;
Key key = keyMap.at(MULTIPLICATION);
Ring2Utils::square(bxbx, cipher.bx, q, context.N);
Ring2Utils::mult(axbx, cipher.ax, cipher.bx, q, context.N);
Ring2Utils::addAndEqual(axbx, axbx, q, context.N);
Ring2Utils::square(axax, cipher.ax, q, context.N);
Ring2Utils::mult(axmult, axax, key.ax, qQ, context.N);
Ring2Utils::mult(bxmult, axax, key.bx, qQ, context.N);
Ring2Utils::rightShiftAndEqual(axmult, context.logQ, context.N);
Ring2Utils::rightShiftAndEqual(bxmult, context.logQ, context.N);
Ring2Utils::addAndEqual(axmult, axbx, q, context.N);
Ring2Utils::addAndEqual(bxmult, bxbx, q, context.N);
return Ciphertext(axmult, bxmult, cipher.logp * 2, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::squareAndEqual(Ciphertext& cipher) {
/*
* 功能:对密文进行平方运算。该算法包含重线性化,为了降低噪声,我们通常需要在乘法后使用重缩放方法
* 输出:ciphertext(m) = ciphertext(m^2)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ qQ = context.qpowvec[cipher.logq + context.logQ];
ZZX bxbx, axbx, axax;
Key key = keyMap.at(MULTIPLICATION);
Ring2Utils::square(bxbx, cipher.bx, q, context.N);
Ring2Utils::mult(axbx, cipher.bx, cipher.ax, q, context.N);
Ring2Utils::addAndEqual(axbx, axbx, q, context.N);
Ring2Utils::square(axax, cipher.ax, q, context.N);
Ring2Utils::mult(cipher.ax, axax, key.ax, qQ, context.N);
Ring2Utils::mult(cipher.bx, axax, key.bx, qQ, context.N);
Ring2Utils::rightShiftAndEqual(cipher.ax, context.logQ, context.N);
Ring2Utils::rightShiftAndEqual(cipher.bx, context.logQ, context.N);
Ring2Utils::addAndEqual(cipher.ax, axbx, q, context.N);
Ring2Utils::addAndEqual(cipher.bx, bxbx, q, context.N);
cipher.logp *= 2;
}
Ciphertext Scheme::multByConst(Ciphertext& cipher, double cnst, long logp) {
/*
* 功能:密文乘以常数(double型)
* 输出:ciphertext(m * (cnst * 2^logp))
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX ax, bx;
ZZ cnstZZ = EvaluatorUtils::scaleUpToZZ(cnst, logp);
Ring2Utils::multByConst(ax, cipher.ax, cnstZZ, q, context.N);
Ring2Utils::multByConst(bx, cipher.bx, cnstZZ, q, context.N);
return Ciphertext(ax, bx, cipher.logp + logp, cipher.logq, cipher.slots, cipher.isComplex);
}
Ciphertext Scheme::multByConst(Ciphertext& cipher, RR& cnst, long logp) {
/*
* 功能:密文乘以常数(RR型)
* 输出:ciphertext(m * (cnst * 2^logp))
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX ax, bx;
ZZ cnstZZ = EvaluatorUtils::scaleUpToZZ(cnst, logp);
Ring2Utils::multByConst(ax, cipher.ax, cnstZZ, q, context.N);
Ring2Utils::multByConst(bx, cipher.bx, cnstZZ, q, context.N);
return Ciphertext(ax, bx, cipher.logp + logp, cipher.logq, cipher.slots, cipher.isComplex);
}
Ciphertext Scheme::multByConst(Ciphertext& cipher, complex<double> cnst, long logp) {
/*
* 功能:密文乘以常数(复数型)
* 输出:ciphertext(m * (cnst * 2^logp))
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX axr, bxr, axi, bxi;
ZZ cnstrZZ = EvaluatorUtils::scaleUpToZZ(cnst.real(), logp);
ZZ cnstiZZ = EvaluatorUtils::scaleUpToZZ(cnst.imag(), logp);
Ring2Utils::multByMonomial(axi, cipher.ax, context.Nh, context.N);
Ring2Utils::multByMonomial(bxi, cipher.bx, context.Nh, context.N);
Ring2Utils::multByConst(axr, cipher.ax, cnstrZZ, q, context.N);
Ring2Utils::multByConst(bxr, cipher.bx, cnstrZZ, q, context.N);
Ring2Utils::multByConstAndEqual(axi, cnstiZZ, q, context.N);
Ring2Utils::multByConstAndEqual(bxi, cnstiZZ, q, context.N);
Ring2Utils::addAndEqual(axr, axi, q, context.N);
Ring2Utils::addAndEqual(bxr, bxi, q, context.N);
return Ciphertext(axr, bxr, cipher.logp + logp, cipher.logq, cipher.slots, cipher.isComplex);
}
Ciphertext Scheme::multByConstVec(Ciphertext& cipher, complex<double>* cnstVec, long slots, long logp) {
/*
* 功能:密文乘以向量(复数)
* 输出:ciphertext(m * (cnst * 2^logp))
*/
ZZX cmx = context.encode(cnstVec, slots, logp);
return multByPoly(cipher, cmx, logp);
}
Ciphertext Scheme::multByConstVec(Ciphertext& cipher, double* cnstVec, long slots, long logp) {
/*
* 功能:密文乘以向量(double型)
* 输出:ciphertext(m * (cnst * 2^logp))
*/
ZZX cmx = context.encode(cnstVec, slots, logp);
return multByPoly(cipher, cmx, logp);
}
void Scheme::multByConstAndEqual(Ciphertext& cipher, double cnst, long logp) {
/*
* 功能:密文乘以常数(double型)
* 输出:ciphertext(m) = ciphertext(m * (cnst * 2^logp))
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ cnstZZ = EvaluatorUtils::scaleUpToZZ(cnst, logp);
Ring2Utils::multByConstAndEqual(cipher.ax, cnstZZ, q, context.N);
Ring2Utils::multByConstAndEqual(cipher.bx, cnstZZ, q, context.N);
cipher.logp += logp;
}
void Scheme::multByConstAndEqual(Ciphertext& cipher, RR& cnst, long logp) {
/*
* 功能:密文乘以常数(RR型)
* 输出:ciphertext(m) = ciphertext(m * (cnst * 2^logp))
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ cnstZZ = EvaluatorUtils::scaleUpToZZ(cnst, logp);
Ring2Utils::multByConstAndEqual(cipher.ax, cnstZZ, q, context.N);
Ring2Utils::multByConstAndEqual(cipher.bx, cnstZZ, q, context.N);
cipher.logp += logp;
}
void Scheme::multByConstAndEqual(Ciphertext& cipher, complex<double> cnst, long logp) {
/*
* 功能:密文乘以常量(复数)
* 输出:ciphertext(m) = ciphertext(m * (cnst * 2^logp))
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX axi, bxi;
ZZ cnstrZZ = EvaluatorUtils::scaleUpToZZ(cnst.real(), logp);
ZZ cnstiZZ = EvaluatorUtils::scaleUpToZZ(cnst.imag(), logp);
Ring2Utils::multByMonomial(axi, cipher.ax, context.Nh, context.N);
Ring2Utils::multByMonomial(bxi, cipher.bx, context.Nh, context.N);
Ring2Utils::multByConstAndEqual(cipher.ax, cnstrZZ, q, context.N);
Ring2Utils::multByConstAndEqual(cipher.bx, cnstrZZ, q, context.N);
Ring2Utils::multByConstAndEqual(axi, cnstiZZ, q, context.N);
Ring2Utils::multByConstAndEqual(bxi, cnstiZZ, q, context.N);
Ring2Utils::addAndEqual(cipher.ax, axi, q, context.N);
Ring2Utils::addAndEqual(cipher.bx, bxi, q, context.N);
cipher.logp += logp;
}
void Scheme::multByConstVecAndEqual(Ciphertext& cipher, complex<double>* cnstVec, long slots, long logp) {
/*
* 功能:密文乘以向量(复数)
* 输出:ciphertext(m) = ciphertext(m * (cnst * 2^logp))
*/
ZZX cmx = context.encode(cnstVec, slots, logp);
multByPolyAndEqual(cipher, cmx, logp);
}
void Scheme::multByConstVecAndEqual(Ciphertext& cipher, double* cnstVec, long slots, long logp) {
/*
* 功能:密文乘以向量(double型)
* 输出:ciphertext(m) = ciphertext(m * (cnst * 2^logp))
*/
ZZX cmx = context.encode(cnstVec, slots, logp);
multByPolyAndEqual(cipher, cmx, logp);
}
Ciphertext Scheme::multByPoly(Ciphertext& cipher, ZZX& poly, long logp) {
/*
* 功能:密文相乘(多项式),poly编码成多项式
* 输出:ciphertext(m * cnst)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX ax, bx;
Ring2Utils::mult(ax, cipher.ax, poly, q, context.N);
Ring2Utils::mult(bx, cipher.bx, poly, q, context.N);
return Ciphertext(ax, bx, cipher.logp + logp, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::multByPolyAndEqual(Ciphertext& cipher, ZZX& poly, long logp) {
/*
* 功能:密文相乘(多项式),poly编码成多项式
* 输出:ciphertext(m) = ciphertext(m * cnst)
*/
ZZ q = context.qpowvec[cipher.logq];
Ring2Utils::multAndEqual(cipher.ax, poly, q, context.N);
Ring2Utils::multAndEqual(cipher.bx, poly, q, context.N);
cipher.logp += logp;
}
Ciphertext Scheme::multByMonomial(Ciphertext& cipher, const long degree) {
/*
* 功能:密文(多项式)乘单项式,degree(单项式级数)
* 输出:ciphertext(m) * X^degree
*/
ZZX ax, bx;
Ring2Utils::multByMonomial(ax, cipher.ax, degree, context.N);
Ring2Utils::multByMonomial(bx, cipher.bx, degree, context.N);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::multByMonomialAndEqual(Ciphertext& cipher, const long degree) {
/*
* 功能:密文(多项式)乘单项式,degree(单项式级数)
* 输出:ciphertext(m) = ciphertext(m) * X^degree
*/
Ring2Utils::multByMonomialAndEqual(cipher.ax, degree, context.N);
Ring2Utils::multByMonomialAndEqual(cipher.bx, degree, context.N);
}
Ciphertext Scheme::multByPo2(Ciphertext& cipher, long deg) {
/*
* 功能:密文(多项式)乘2的幂,deg(2的幂)
* 输出:ciphertext(m*2^degree)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZX ax, bx;
Ring2Utils::leftShift(ax, cipher.ax, deg, q, context.N);
Ring2Utils::leftShift(bx, cipher.bx, deg, q, context.N);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::multByPo2AndEqual(Ciphertext& cipher, long deg) {
/*
* 功能:密文(多项式)乘2的幂,deg(2的幂)
* 输出:ciphertext(m) -> ciphertext(m*2^degree)
*/
ZZ q = context.qpowvec[cipher.logq];
Ring2Utils::leftShiftAndEqual(cipher.ax, deg, q, context.N);
Ring2Utils::leftShiftAndEqual(cipher.bx, deg, q, context.N);
}
void Scheme::multBy2AndEqual(Ciphertext& cipher) {
/*
* 输出:ciphertext(m) -> ciphertext(2m)
*/
ZZ q = context.qpowvec[cipher.logq];
Ring2Utils::doubleAndEqual(cipher.ax, q, context.N);
Ring2Utils::doubleAndEqual(cipher.bx, q, context.N);
}
Ciphertext Scheme::divByPo2(Ciphertext& cipher, long degree) {
/*
* 功能:密文(多项式)除以2的幂
* 输出:ciphertext(m / 2^degree)
*/
ZZX ax, bx;
Ring2Utils::rightShift(ax, cipher.ax, degree, context.N);
Ring2Utils::rightShift(bx, cipher.bx, degree, context.N);
return Ciphertext(ax, bx, cipher.logp, cipher.logq - degree, cipher.slots, cipher.isComplex);
}
void Scheme::divByPo2AndEqual(Ciphertext& cipher, long degree) {
/*
* 功能:密文(多项式)除以2的幂
* 输出:ciphertext(m) = ciphertext(m / 2^degree)
*/
Ring2Utils::rightShiftAndEqual(cipher.ax, degree, context.N);
Ring2Utils::rightShiftAndEqual(cipher.bx, degree, context.N);
cipher.logq -= degree;
}
Ciphertext Scheme::reScaleBy(Ciphertext& cipher, long bitsDown) {
/*
* 功能:重缩放,bitsDown(缩放因子)
* 输出:ciphertext(m / 2^bitsDown) with new modulus (q / 2^bitsDown)
*/
ZZX ax, bx;
Ring2Utils::rightShift(ax, cipher.ax, bitsDown, context.N);
Ring2Utils::rightShift(bx, cipher.bx, bitsDown, context.N);
return Ciphertext(ax, bx, cipher.logp - bitsDown, cipher.logq - bitsDown, cipher.slots, cipher.isComplex);
}
Ciphertext Scheme::reScaleTo(Ciphertext& cipher, long newlogq) {
/*
* 功能:重缩放,newlogq(新密文模数对数)
* 输出:ciphertext(m / 2^(logq - newlogq)) with new modulus (2^newlogq)
*/
ZZX ax, bx;
long bitsDown = cipher.logq - newlogq;
Ring2Utils::rightShift(ax, cipher.ax, bitsDown, context.N);
Ring2Utils::rightShift(bx, cipher.bx, bitsDown, context.N);
return Ciphertext(ax, bx, cipher.logp - bitsDown, newlogq, cipher.slots, cipher.isComplex);
}
void Scheme::reScaleByAndEqual(Ciphertext& cipher, long bitsDown) {
/*
* 功能:重缩放,bitsDown(缩放因子)
* 输出:ciphertext(m) -> ciphertext(m / 2^bitsDown) with new modulus (q / 2^bitsDown)
*/
Ring2Utils::rightShiftAndEqual(cipher.ax, bitsDown, context.N);
Ring2Utils::rightShiftAndEqual(cipher.bx, bitsDown, context.N);
cipher.logq -= bitsDown;
cipher.logp -= bitsDown;
}
void Scheme::reScaleToAndEqual(Ciphertext& cipher, long logq) {
/*
* 功能:重缩放,newlogq(新密文模数对数)
* 输出:ciphertext(m) -> ciphertext(m / 2^(logq - newlogq)) with new modulus (2^newlogq)
*/
long bitsDown = cipher.logq - logq;
cipher.logq = logq;
cipher.logp -= bitsDown;
Ring2Utils::rightShiftAndEqual(cipher.ax, bitsDown, context.N);
Ring2Utils::rightShiftAndEqual(cipher.bx, bitsDown, context.N);
}
Ciphertext Scheme::modDownBy(Ciphertext& cipher, long bitsDown) {
/*
* 功能:模约减,bitsDown(约减因子)
* 输出:ciphertext(m) with new modulus (q/2^bitsDown)
*/
ZZX bx, ax;
long newlogq = cipher.logq - bitsDown;
ZZ q = context.qpowvec[newlogq];
Ring2Utils::mod(ax, cipher.ax, q, context.N);
Ring2Utils::mod(bx, cipher.bx, q, context.N);
return Ciphertext(ax, bx, cipher.logp, newlogq, cipher.slots, cipher.isComplex);
}
void Scheme::modDownByAndEqual(Ciphertext& cipher, long bitsDown) {
/*
* 功能:模约减,bitsDown(约减因子)
* 输出:ciphertext(m) -> ciphertext(m) with new modulus (q/2^bitsDown)
*/
cipher.logq -= bitsDown;
ZZ q = context.qpowvec[cipher.logq];
Ring2Utils::modAndEqual(cipher.ax, q, context.N);
Ring2Utils::modAndEqual(cipher.bx, q, context.N);
}
Ciphertext Scheme::modDownTo(Ciphertext& cipher, long logq) {
/*
* 功能:模约减,logq(新模数的对数)
* 输出:ciphertext(m) with new modulus (2^newlogq)
*/
ZZX bx, ax;
ZZ q = context.qpowvec[logq];
Ring2Utils::mod(ax, cipher.ax, q, context.N);
Ring2Utils::mod(bx, cipher.bx, q, context.N);
return Ciphertext(ax, bx, cipher.logp, logq, cipher.slots);
}
void Scheme::modDownToAndEqual(Ciphertext& cipher, long logq) {
/*
* 功能:模约减,logq(新模数的对数)
* 输出:ciphertext(m) -> ciphertext(m) with new modulus (2^newlogq)
*/
cipher.logq = logq;
ZZ q = context.qpowvec[logq];
Ring2Utils::modAndEqual(cipher.ax, q, context.N);
Ring2Utils::modAndEqual(cipher.bx, q, context.N);
}
Ciphertext Scheme::conjugate(Ciphertext& cipher) {
/*
* 功能:计算密文的共轭密文,cipher(ciphertext(m = x + iy))
* 输出:ciphertext(x - iy)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ qQ = context.qpowvec[cipher.logq + context.logQ];
ZZX bxconj, ax, bx;
Key key = keyMap.at(CONJUGATION);
Ring2Utils::conjugate(bxconj, cipher.bx, context.N);
Ring2Utils::conjugate(bx, cipher.ax, context.N);
Ring2Utils::mult(ax, bx, key.ax, qQ, context.N);
Ring2Utils::multAndEqual(bx, key.bx, qQ, context.N);
Ring2Utils::rightShiftAndEqual(ax, context.logQ, context.N);
Ring2Utils::rightShiftAndEqual(bx, context.logQ, context.N);
Ring2Utils::addAndEqual(bx, bxconj, q, context.N);
return Ciphertext(ax, bx, cipher.logp, cipher.logq, cipher.slots, cipher.isComplex);
}
void Scheme::conjugateAndEqual(Ciphertext& cipher) {
/*
* 功能:计算密文的共轭密文,cipher(ciphertext(m = x + iy))
* 输出:ciphertext(m = x + iy) -> ciphertext(x - iy)
*/
ZZ q = context.qpowvec[cipher.logq];
ZZ qQ = context.qpowvec[cipher.logq + context.logQ];
ZZX bxconj;
Key key = keyMap.at(CONJUGATION);
Ring2Utils::conjugate(bxconj, cipher.bx, context.N);
Ring2Utils::conjugate(cipher.bx, cipher.ax, context.N);
Ring2Utils::mult(cipher.ax, cipher.bx, key.ax, qQ, context.N);
Ring2Utils::multAndEqual(cipher.bx, key.bx, qQ, context.N);
Ring2Utils::rightShiftAndEqual(cipher.ax, context.logQ, context.N);
Ring2Utils::rightShiftAndEqual(cipher.bx, context.logQ, context.N);
Ring2Utils::addAndEqual(cipher.bx, bxconj, q, context.N);
}
用在编码时生成共轭复数时
序列化,将随机采样的明文、生成的密钥、密文、写入文件以及读取文件
数据采样,包括高斯采样等
sx:私钥
SecretKey::SecretKey(long logN, long h) {
long N = 1 << logN; //求N
NumUtils::sampleHWT(sx, N, h);//sx采样于HWT
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章