mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
making the evaluation keys independant of the OperandQP type
As for the public keys, I think it is better to keep evaluation key types as simple as possible. The "Operand/OperandQP" types are more adapted to the "data" path, i.e. as operands in a circuit. One obvious exemple is that there is no point for keys to have the metadata of a ciphertext.Also, we'll have easier time designing the evaluation logic and evolving the Operand types if the keys do not depend on them.
This commit is contained in:
@@ -229,8 +229,8 @@ func (gkg *GaloisKeyGenProtocol) GenGaloisKey(share *GaloisKeyGenShare, crp Galo
|
||||
BITDecomp := len(m[0])
|
||||
for i := 0; i < RNSDecomp; i++ {
|
||||
for j := 0; j < BITDecomp; j++ {
|
||||
gk.Value[i][j].Value[0].Copy(&m[i][j])
|
||||
gk.Value[i][j].Value[1].Copy(&p[i][j])
|
||||
gk.Value[i][j][0].Copy(&m[i][j])
|
||||
gk.Value[i][j][1].Copy(&p[i][j])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,13 +141,13 @@ func (ekg *RelinKeyGenProtocol) GenShareRoundOne(sk *rlwe.SecretKey, crp RelinKe
|
||||
for j := 0; j < BITDecomp; j++ {
|
||||
for i := 0; i < RNSDecomp; i++ {
|
||||
// h = e
|
||||
ekg.gaussianSamplerQ.Read(shareOut.Value[i][j].Value[0].Q)
|
||||
ekg.gaussianSamplerQ.Read(shareOut.Value[i][j][0].Q)
|
||||
|
||||
if hasModulusP {
|
||||
ringQP.ExtendBasisSmallNormAndCenter(shareOut.Value[i][j].Value[0].Q, levelP, nil, shareOut.Value[i][j].Value[0].P)
|
||||
ringQP.ExtendBasisSmallNormAndCenter(shareOut.Value[i][j][0].Q, levelP, nil, shareOut.Value[i][j][0].P)
|
||||
}
|
||||
|
||||
ringQP.NTT(&shareOut.Value[i][j].Value[0], &shareOut.Value[i][j].Value[0])
|
||||
ringQP.NTT(&shareOut.Value[i][j][0], &shareOut.Value[i][j][0])
|
||||
|
||||
// h = sk*CrtBaseDecompQi + e
|
||||
for k := 0; k < levelP+1; k++ {
|
||||
@@ -161,7 +161,7 @@ func (ekg *RelinKeyGenProtocol) GenShareRoundOne(sk *rlwe.SecretKey, crp RelinKe
|
||||
|
||||
qi := ringQ.SubRings[index].Modulus
|
||||
skP := ekg.buf[0].Q.Coeffs[index]
|
||||
h := shareOut.Value[i][j].Value[0].Q.Coeffs[index]
|
||||
h := shareOut.Value[i][j][0].Q.Coeffs[index]
|
||||
|
||||
for w := 0; w < N; w++ {
|
||||
h[w] = ring.CRed(h[w]+skP[w], qi)
|
||||
@@ -169,19 +169,19 @@ func (ekg *RelinKeyGenProtocol) GenShareRoundOne(sk *rlwe.SecretKey, crp RelinKe
|
||||
}
|
||||
|
||||
// h = sk*CrtBaseDecompQi + -u*a + e
|
||||
ringQP.MulCoeffsMontgomeryThenSub(&ephSkOut.Value, &c[i][j], &shareOut.Value[i][j].Value[0])
|
||||
ringQP.MulCoeffsMontgomeryThenSub(&ephSkOut.Value, &c[i][j], &shareOut.Value[i][j][0])
|
||||
|
||||
// Second Element
|
||||
// e_2i
|
||||
ekg.gaussianSamplerQ.Read(shareOut.Value[i][j].Value[1].Q)
|
||||
ekg.gaussianSamplerQ.Read(shareOut.Value[i][j][1].Q)
|
||||
|
||||
if hasModulusP {
|
||||
ringQP.ExtendBasisSmallNormAndCenter(shareOut.Value[i][j].Value[1].Q, levelP, nil, shareOut.Value[i][j].Value[1].P)
|
||||
ringQP.ExtendBasisSmallNormAndCenter(shareOut.Value[i][j][1].Q, levelP, nil, shareOut.Value[i][j][1].P)
|
||||
}
|
||||
|
||||
ringQP.NTT(&shareOut.Value[i][j].Value[1], &shareOut.Value[i][j].Value[1])
|
||||
ringQP.NTT(&shareOut.Value[i][j][1], &shareOut.Value[i][j][1])
|
||||
// s*a + e_2i
|
||||
ringQP.MulCoeffsMontgomeryThenAdd(&sk.Value, &c[i][j], &shareOut.Value[i][j].Value[1])
|
||||
ringQP.MulCoeffsMontgomeryThenAdd(&sk.Value, &c[i][j], &shareOut.Value[i][j][1])
|
||||
}
|
||||
|
||||
ringQ.MulScalar(ekg.buf[0].Q, 1<<ekg.params.Pow2Base(), ekg.buf[0].Q)
|
||||
@@ -220,7 +220,7 @@ func (ekg *RelinKeyGenProtocol) GenShareRoundTwo(ephSk, sk *rlwe.SecretKey, roun
|
||||
// Computes [(sum samples)*sk + e_1i, sk*a + e_2i]
|
||||
|
||||
// (AggregateShareRoundTwo samples) * sk
|
||||
ringQP.MulCoeffsMontgomeryLazy(&round1.Value[i][j].Value[0], &sk.Value, &shareOut.Value[i][j].Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&round1.Value[i][j][0], &sk.Value, &shareOut.Value[i][j][0])
|
||||
|
||||
// (AggregateShareRoundTwo samples) * sk + e_1i
|
||||
ekg.gaussianSamplerQ.Read(ekg.buf[1].Q)
|
||||
@@ -230,18 +230,18 @@ func (ekg *RelinKeyGenProtocol) GenShareRoundTwo(ephSk, sk *rlwe.SecretKey, roun
|
||||
}
|
||||
|
||||
ringQP.NTT(ekg.buf[1], ekg.buf[1])
|
||||
ringQP.Add(&shareOut.Value[i][j].Value[0], ekg.buf[1], &shareOut.Value[i][j].Value[0])
|
||||
ringQP.Add(&shareOut.Value[i][j][0], ekg.buf[1], &shareOut.Value[i][j][0])
|
||||
|
||||
// second part
|
||||
// (u_i - s_i) * (sum [x][s*a_i + e_2i]) + e3i
|
||||
ekg.gaussianSamplerQ.Read(shareOut.Value[i][j].Value[1].Q)
|
||||
ekg.gaussianSamplerQ.Read(shareOut.Value[i][j][1].Q)
|
||||
|
||||
if levelP > -1 {
|
||||
ringQP.ExtendBasisSmallNormAndCenter(shareOut.Value[i][j].Value[1].Q, levelP, nil, shareOut.Value[i][j].Value[1].P)
|
||||
ringQP.ExtendBasisSmallNormAndCenter(shareOut.Value[i][j][1].Q, levelP, nil, shareOut.Value[i][j][1].P)
|
||||
}
|
||||
|
||||
ringQP.NTT(&shareOut.Value[i][j].Value[1], &shareOut.Value[i][j].Value[1])
|
||||
ringQP.MulCoeffsMontgomeryThenAdd(ekg.buf[0], &round1.Value[i][j].Value[1], &shareOut.Value[i][j].Value[1])
|
||||
ringQP.NTT(&shareOut.Value[i][j][1], &shareOut.Value[i][j][1])
|
||||
ringQP.MulCoeffsMontgomeryThenAdd(ekg.buf[0], &round1.Value[i][j][1], &shareOut.Value[i][j][1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,8 +249,8 @@ func (ekg *RelinKeyGenProtocol) GenShareRoundTwo(ephSk, sk *rlwe.SecretKey, roun
|
||||
// AggregateShares combines two RelinKeyGen shares into a single one.
|
||||
func (ekg *RelinKeyGenProtocol) AggregateShares(share1, share2, shareOut *RelinKeyGenShare) {
|
||||
|
||||
levelQ := share1.Value[0][0].LevelQ()
|
||||
levelP := share1.Value[0][0].LevelP()
|
||||
levelQ := share1.Value[0][0][0].LevelQ()
|
||||
levelP := share1.Value[0][0][0].LevelP()
|
||||
|
||||
ringQP := ekg.params.RingQP().AtLevel(levelQ, levelP)
|
||||
|
||||
@@ -258,8 +258,8 @@ func (ekg *RelinKeyGenProtocol) AggregateShares(share1, share2, shareOut *RelinK
|
||||
BITDecomp := len(shareOut.Value[0])
|
||||
for i := 0; i < RNSDecomp; i++ {
|
||||
for j := 0; j < BITDecomp; j++ {
|
||||
ringQP.Add(&share1.Value[i][j].Value[0], &share2.Value[i][j].Value[0], &shareOut.Value[i][j].Value[0])
|
||||
ringQP.Add(&share1.Value[i][j].Value[1], &share2.Value[i][j].Value[1], &shareOut.Value[i][j].Value[1])
|
||||
ringQP.Add(&share1.Value[i][j][0], &share2.Value[i][j][0], &shareOut.Value[i][j][0])
|
||||
ringQP.Add(&share1.Value[i][j][1], &share2.Value[i][j][1], &shareOut.Value[i][j][1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,8 +277,8 @@ func (ekg *RelinKeyGenProtocol) AggregateShares(share1, share2, shareOut *RelinK
|
||||
// = [s * b + P * s^2 + s*e0 + u*e1 + e2 + e3, b]
|
||||
func (ekg *RelinKeyGenProtocol) GenRelinearizationKey(round1 *RelinKeyGenShare, round2 *RelinKeyGenShare, evalKeyOut *rlwe.RelinearizationKey) {
|
||||
|
||||
levelQ := round1.Value[0][0].LevelQ()
|
||||
levelP := round1.Value[0][0].LevelP()
|
||||
levelQ := round1.Value[0][0][0].LevelQ()
|
||||
levelP := round1.Value[0][0][0].LevelP()
|
||||
|
||||
ringQP := ekg.params.RingQP().AtLevel(levelQ, levelP)
|
||||
|
||||
@@ -286,10 +286,10 @@ func (ekg *RelinKeyGenProtocol) GenRelinearizationKey(round1 *RelinKeyGenShare,
|
||||
BITDecomp := len(round1.Value[0])
|
||||
for i := 0; i < RNSDecomp; i++ {
|
||||
for j := 0; j < BITDecomp; j++ {
|
||||
ringQP.Add(&round2.Value[i][j].Value[0], &round2.Value[i][j].Value[1], &evalKeyOut.Value[i][j].Value[0])
|
||||
evalKeyOut.Value[i][j].Value[1].Copy(&round1.Value[i][j].Value[1])
|
||||
ringQP.MForm(&evalKeyOut.Value[i][j].Value[0], &evalKeyOut.Value[i][j].Value[0])
|
||||
ringQP.MForm(&evalKeyOut.Value[i][j].Value[1], &evalKeyOut.Value[i][j].Value[1])
|
||||
ringQP.Add(&round2.Value[i][j][0], &round2.Value[i][j][1], &evalKeyOut.Value[i][j][0])
|
||||
evalKeyOut.Value[i][j][1].Copy(&round1.Value[i][j][1])
|
||||
ringQP.MForm(&evalKeyOut.Value[i][j][0], &evalKeyOut.Value[i][j][0])
|
||||
ringQP.MForm(&evalKeyOut.Value[i][j][1], &evalKeyOut.Value[i][j][1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +69,8 @@ func (enc *Encryptor) EncryptZero(ct interface{}) {
|
||||
|
||||
for j := 0; j < decompPw2; j++ {
|
||||
for i := 0; i < decompRNS; i++ {
|
||||
enc.EncryptorInterface.EncryptZero(rgswCt.Value[0].Value[i][j])
|
||||
enc.EncryptorInterface.EncryptZero(rgswCt.Value[1].Value[i][j])
|
||||
enc.EncryptorInterface.EncryptZero(&rlwe.OperandQP{MetaData: rlwe.MetaData{IsNTT: true, IsMontgomery: true}, Value: rgswCt.Value[0].Value[i][j][:]})
|
||||
enc.EncryptorInterface.EncryptZero(&rlwe.OperandQP{MetaData: rlwe.MetaData{IsNTT: true, IsMontgomery: true}, Value: rgswCt.Value[1].Value[i][j][:]})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,12 +103,12 @@ func (eval *Evaluator) externalProduct32Bit(ct0 *rlwe.Ciphertext, rgsw *Cipherte
|
||||
ring.MaskVec(eval.BuffInvNTT.Coeffs[0], j*pw2, mask, cw)
|
||||
if j == 0 && i == 0 {
|
||||
subRing.NTTLazy(cw, cwNTT)
|
||||
subRing.MulCoeffsLazy(el.Value[0][j].Value[0].Q.Coeffs[0], cwNTT, acc0)
|
||||
subRing.MulCoeffsLazy(el.Value[0][j].Value[1].Q.Coeffs[0], cwNTT, acc1)
|
||||
subRing.MulCoeffsLazy(el.Value[0][j][0].Q.Coeffs[0], cwNTT, acc0)
|
||||
subRing.MulCoeffsLazy(el.Value[0][j][1].Q.Coeffs[0], cwNTT, acc1)
|
||||
} else {
|
||||
subRing.NTTLazy(cw, cwNTT)
|
||||
subRing.MulCoeffsLazyThenAddLazy(el.Value[0][j].Value[0].Q.Coeffs[0], cwNTT, acc0)
|
||||
subRing.MulCoeffsLazyThenAddLazy(el.Value[0][j].Value[1].Q.Coeffs[0], cwNTT, acc1)
|
||||
subRing.MulCoeffsLazyThenAddLazy(el.Value[0][j][0].Q.Coeffs[0], cwNTT, acc0)
|
||||
subRing.MulCoeffsLazyThenAddLazy(el.Value[0][j][1].Q.Coeffs[0], cwNTT, acc1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,15 +148,15 @@ func (eval *Evaluator) externalProductInPlaceSinglePAndBitDecomp(ct0 *rlwe.Ciphe
|
||||
|
||||
for u, s := range ringQ.SubRings[:levelQ+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomery(el.Value[i][j].Value[0].Q.Coeffs[u], cwNTT, c0QP.Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomery(el.Value[i][j].Value[1].Q.Coeffs[u], cwNTT, c1QP.Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomery(el.Value[i][j][0].Q.Coeffs[u], cwNTT, c0QP.Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomery(el.Value[i][j][1].Q.Coeffs[u], cwNTT, c1QP.Q.Coeffs[u])
|
||||
}
|
||||
|
||||
if ringP != nil {
|
||||
for u, s := range ringP.SubRings[:levelP+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomery(el.Value[i][j].Value[0].P.Coeffs[u], cwNTT, c0QP.P.Coeffs[u])
|
||||
s.MulCoeffsMontgomery(el.Value[i][j].Value[1].P.Coeffs[u], cwNTT, c1QP.P.Coeffs[u])
|
||||
s.MulCoeffsMontgomery(el.Value[i][j][0].P.Coeffs[u], cwNTT, c0QP.P.Coeffs[u])
|
||||
s.MulCoeffsMontgomery(el.Value[i][j][1].P.Coeffs[u], cwNTT, c1QP.P.Coeffs[u])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,15 +164,15 @@ func (eval *Evaluator) externalProductInPlaceSinglePAndBitDecomp(ct0 *rlwe.Ciphe
|
||||
|
||||
for u, s := range ringQ.SubRings[:levelQ+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j].Value[0].Q.Coeffs[u], cwNTT, c0QP.Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j].Value[1].Q.Coeffs[u], cwNTT, c1QP.Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j][0].Q.Coeffs[u], cwNTT, c0QP.Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j][1].Q.Coeffs[u], cwNTT, c1QP.Q.Coeffs[u])
|
||||
}
|
||||
|
||||
if ringP != nil {
|
||||
for u, s := range ringP.SubRings[:levelP+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j].Value[0].P.Coeffs[u], cwNTT, c0QP.P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j].Value[1].P.Coeffs[u], cwNTT, c1QP.P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j][0].P.Coeffs[u], cwNTT, c0QP.P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryThenAdd(el.Value[i][j][1].P.Coeffs[u], cwNTT, c1QP.P.Coeffs[u])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,11 +218,11 @@ func (eval *Evaluator) externalProductInPlaceMultipleP(levelQ, levelP int, ct0 *
|
||||
eval.DecomposeSingleNTT(levelQ, levelP, levelP+1, i, c2NTT, c2InvNTT, c2QP.Q, c2QP.P)
|
||||
|
||||
if k == 0 && i == 0 {
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el.Value[i][0].Value[0], &c2QP, &c0QP)
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el.Value[i][0].Value[1], &c2QP, &c1QP)
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el.Value[i][0][0], &c2QP, &c0QP)
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el.Value[i][0][1], &c2QP, &c1QP)
|
||||
} else {
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el.Value[i][0].Value[0], &c2QP, &c0QP)
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el.Value[i][0].Value[1], &c2QP, &c1QP)
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el.Value[i][0][0], &c2QP, &c0QP)
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el.Value[i][0][1], &c2QP, &c1QP)
|
||||
}
|
||||
|
||||
if reduce%QiOverF == QiOverF-1 {
|
||||
@@ -271,18 +271,18 @@ func AddLazy(op interface{}, ringQP ringqp.Ring, ctOut *Ciphertext) {
|
||||
end = nQ
|
||||
}
|
||||
for k := start; k < end; k++ {
|
||||
s.AddLazy(ctOut.Value[0].Value[i][j].Value[0].Q.Coeffs[k], el.Value[j].Coeffs[k], ctOut.Value[0].Value[i][j].Value[0].Q.Coeffs[k])
|
||||
s.AddLazy(ctOut.Value[1].Value[i][j].Value[1].Q.Coeffs[k], el.Value[j].Coeffs[k], ctOut.Value[1].Value[i][j].Value[1].Q.Coeffs[k])
|
||||
s.AddLazy(ctOut.Value[0].Value[i][j][0].Q.Coeffs[k], el.Value[j].Coeffs[k], ctOut.Value[0].Value[i][j][0].Q.Coeffs[k])
|
||||
s.AddLazy(ctOut.Value[1].Value[i][j][1].Q.Coeffs[k], el.Value[j].Coeffs[k], ctOut.Value[1].Value[i][j][1].Q.Coeffs[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
case *Ciphertext:
|
||||
for i := range el.Value[0].Value {
|
||||
for j := range el.Value[0].Value[i] {
|
||||
ringQP.AddLazy(&ctOut.Value[0].Value[i][j].Value[0], &el.Value[0].Value[i][j].Value[0], &ctOut.Value[0].Value[i][j].Value[0])
|
||||
ringQP.AddLazy(&ctOut.Value[0].Value[i][j].Value[1], &el.Value[0].Value[i][j].Value[1], &ctOut.Value[0].Value[i][j].Value[1])
|
||||
ringQP.AddLazy(&ctOut.Value[1].Value[i][j].Value[0], &el.Value[1].Value[i][j].Value[0], &ctOut.Value[1].Value[i][j].Value[0])
|
||||
ringQP.AddLazy(&ctOut.Value[1].Value[i][j].Value[1], &el.Value[1].Value[i][j].Value[1], &ctOut.Value[1].Value[i][j].Value[1])
|
||||
ringQP.AddLazy(&ctOut.Value[0].Value[i][j][0], &el.Value[0].Value[i][j][0], &ctOut.Value[0].Value[i][j][0])
|
||||
ringQP.AddLazy(&ctOut.Value[0].Value[i][j][1], &el.Value[0].Value[i][j][1], &ctOut.Value[0].Value[i][j][1])
|
||||
ringQP.AddLazy(&ctOut.Value[1].Value[i][j][0], &el.Value[1].Value[i][j][0], &ctOut.Value[1].Value[i][j][0])
|
||||
ringQP.AddLazy(&ctOut.Value[1].Value[i][j][1], &el.Value[1].Value[i][j][1], &ctOut.Value[1].Value[i][j][1])
|
||||
}
|
||||
}
|
||||
default:
|
||||
@@ -294,10 +294,10 @@ func AddLazy(op interface{}, ringQP ringqp.Ring, ctOut *Ciphertext) {
|
||||
func Reduce(ctIn *Ciphertext, ringQP ringqp.Ring, ctOut *Ciphertext) {
|
||||
for i := range ctIn.Value[0].Value {
|
||||
for j := range ctIn.Value[0].Value[i] {
|
||||
ringQP.Reduce(&ctIn.Value[0].Value[i][j].Value[0], &ctOut.Value[0].Value[i][j].Value[0])
|
||||
ringQP.Reduce(&ctIn.Value[0].Value[i][j].Value[1], &ctOut.Value[0].Value[i][j].Value[1])
|
||||
ringQP.Reduce(&ctIn.Value[1].Value[i][j].Value[0], &ctOut.Value[1].Value[i][j].Value[0])
|
||||
ringQP.Reduce(&ctIn.Value[1].Value[i][j].Value[1], &ctOut.Value[1].Value[i][j].Value[1])
|
||||
ringQP.Reduce(&ctIn.Value[0].Value[i][j][0], &ctOut.Value[0].Value[i][j][0])
|
||||
ringQP.Reduce(&ctIn.Value[0].Value[i][j][1], &ctOut.Value[0].Value[i][j][1])
|
||||
ringQP.Reduce(&ctIn.Value[1].Value[i][j][0], &ctOut.Value[1].Value[i][j][0])
|
||||
ringQP.Reduce(&ctIn.Value[1].Value[i][j][1], &ctOut.Value[1].Value[i][j][1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,10 +306,10 @@ func Reduce(ctIn *Ciphertext, ringQP ringqp.Ring, ctOut *Ciphertext) {
|
||||
func MulByXPowAlphaMinusOneLazy(ctIn *Ciphertext, powXMinusOne ringqp.Poly, ringQP ringqp.Ring, ctOut *Ciphertext) {
|
||||
for i := range ctIn.Value[0].Value {
|
||||
for j := range ctIn.Value[0].Value[i] {
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[0].Value[i][j].Value[0], &powXMinusOne, &ctOut.Value[0].Value[i][j].Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[0].Value[i][j].Value[1], &powXMinusOne, &ctOut.Value[0].Value[i][j].Value[1])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[1].Value[i][j].Value[0], &powXMinusOne, &ctOut.Value[1].Value[i][j].Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[1].Value[i][j].Value[1], &powXMinusOne, &ctOut.Value[1].Value[i][j].Value[1])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[0].Value[i][j][0], &powXMinusOne, &ctOut.Value[0].Value[i][j][0])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[0].Value[i][j][1], &powXMinusOne, &ctOut.Value[0].Value[i][j][1])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[1].Value[i][j][0], &powXMinusOne, &ctOut.Value[1].Value[i][j][0])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&ctIn.Value[1].Value[i][j][1], &powXMinusOne, &ctOut.Value[1].Value[i][j][1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,10 +318,10 @@ func MulByXPowAlphaMinusOneLazy(ctIn *Ciphertext, powXMinusOne ringqp.Poly, ring
|
||||
func MulByXPowAlphaMinusOneThenAddLazy(ctIn *Ciphertext, powXMinusOne ringqp.Poly, ringQP ringqp.Ring, ctOut *Ciphertext) {
|
||||
for i := range ctIn.Value[0].Value {
|
||||
for j := range ctIn.Value[0].Value[i] {
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[0].Value[i][j].Value[0], &powXMinusOne, &ctOut.Value[0].Value[i][j].Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[0].Value[i][j].Value[1], &powXMinusOne, &ctOut.Value[0].Value[i][j].Value[1])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[1].Value[i][j].Value[0], &powXMinusOne, &ctOut.Value[1].Value[i][j].Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[1].Value[i][j].Value[1], &powXMinusOne, &ctOut.Value[1].Value[i][j].Value[1])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[0].Value[i][j][0], &powXMinusOne, &ctOut.Value[0].Value[i][j][0])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[0].Value[i][j][1], &powXMinusOne, &ctOut.Value[0].Value[i][j][1])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[1].Value[i][j][0], &powXMinusOne, &ctOut.Value[1].Value[i][j][0])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&ctIn.Value[1].Value[i][j][1], &powXMinusOne, &ctOut.Value[1].Value[i][j][1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,11 +141,11 @@ func (eval *Evaluator) gadgetProductMultiplePLazy(levelQ int, cx *ring.Poly, gad
|
||||
eval.DecomposeSingleNTT(levelQ, levelP, levelP+1, i, cxNTT, cxInvNTT, c2QP.Q, c2QP.P)
|
||||
|
||||
if i == 0 {
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el[i][0].Value[0], &c2QP, &ct.Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el[i][0].Value[1], &c2QP, &ct.Value[1])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el[i][0][0], &c2QP, &ct.Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazy(&el[i][0][1], &c2QP, &ct.Value[1])
|
||||
} else {
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el[i][0].Value[0], &c2QP, &ct.Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el[i][0].Value[1], &c2QP, &ct.Value[1])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el[i][0][0], &c2QP, &ct.Value[0])
|
||||
ringQP.MulCoeffsMontgomeryLazyThenAddLazy(&el[i][0][1], &c2QP, &ct.Value[1])
|
||||
}
|
||||
|
||||
if reduce%QiOverF == QiOverF-1 {
|
||||
@@ -218,30 +218,30 @@ func (eval *Evaluator) gadgetProductSinglePAndBitDecompLazy(levelQ int, cx *ring
|
||||
if i == 0 && j == 0 {
|
||||
for u, s := range ringQ.SubRings[:levelQ+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j].Value[0].Q.Coeffs[u], cwNTT, ct.Value[0].Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j].Value[1].Q.Coeffs[u], cwNTT, ct.Value[1].Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j][0].Q.Coeffs[u], cwNTT, ct.Value[0].Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j][1].Q.Coeffs[u], cwNTT, ct.Value[1].Q.Coeffs[u])
|
||||
}
|
||||
|
||||
if ringP != nil {
|
||||
for u, s := range ringP.SubRings[:levelP+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j].Value[0].P.Coeffs[u], cwNTT, ct.Value[0].P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j].Value[1].P.Coeffs[u], cwNTT, ct.Value[1].P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j][0].P.Coeffs[u], cwNTT, ct.Value[0].P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazy(el[i][j][1].P.Coeffs[u], cwNTT, ct.Value[1].P.Coeffs[u])
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for u, s := range ringQ.SubRings[:levelQ+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j].Value[0].Q.Coeffs[u], cwNTT, ct.Value[0].Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j].Value[1].Q.Coeffs[u], cwNTT, ct.Value[1].Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j][0].Q.Coeffs[u], cwNTT, ct.Value[0].Q.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j][1].Q.Coeffs[u], cwNTT, ct.Value[1].Q.Coeffs[u])
|
||||
}
|
||||
|
||||
if ringP != nil {
|
||||
for u, s := range ringP.SubRings[:levelP+1] {
|
||||
s.NTTLazy(cw, cwNTT)
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j].Value[0].P.Coeffs[u], cwNTT, ct.Value[0].P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j].Value[1].P.Coeffs[u], cwNTT, ct.Value[1].P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j][0].P.Coeffs[u], cwNTT, ct.Value[0].P.Coeffs[u])
|
||||
s.MulCoeffsMontgomeryLazyThenAddLazy(el[i][j][1].P.Coeffs[u], cwNTT, ct.Value[1].P.Coeffs[u])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,7 +323,7 @@ func (eval *Evaluator) GadgetProductHoistedLazy(levelQ int, BuffQPDecompQP []rin
|
||||
var reduce int
|
||||
for i := 0; i < decompRNS; i++ {
|
||||
|
||||
gct := gadgetCt.Value[i][0].Value
|
||||
gct := gadgetCt.Value[i][0]
|
||||
|
||||
if i == 0 {
|
||||
ringQP.MulCoeffsMontgomeryLazy(&gct[0], &BuffQPDecompQP[i], c0QP)
|
||||
|
||||
@@ -12,24 +12,19 @@ import (
|
||||
// GadgetCiphertext is a struct for storing an encrypted
|
||||
// plaintext times the gadget power matrix.
|
||||
type GadgetCiphertext struct {
|
||||
Value structs.Matrix[OperandQP]
|
||||
Value structs.Matrix[tupleQP]
|
||||
}
|
||||
|
||||
// NewGadgetCiphertext returns a new Ciphertext key with pre-allocated zero-value.
|
||||
// Ciphertext is always in the NTT domain.
|
||||
func NewGadgetCiphertext(params ParametersInterface, levelQ, levelP, decompRNS, decompBIT int) *GadgetCiphertext {
|
||||
|
||||
m := make([][]OperandQP, decompRNS)
|
||||
m := make(structs.Matrix[tupleQP], decompRNS)
|
||||
for i := 0; i < decompRNS; i++ {
|
||||
v := make([]OperandQP, decompBIT)
|
||||
|
||||
for j := range v {
|
||||
v[j] = *NewOperandQP(params, 1, levelQ, levelP)
|
||||
v[j].IsNTT = true
|
||||
v[j].IsMontgomery = true
|
||||
m[i] = make([]tupleQP, decompBIT)
|
||||
for j := range m[i] {
|
||||
m[i][j] = newTupleQPAtLevel(params, levelQ, levelP)
|
||||
}
|
||||
|
||||
m[i] = v
|
||||
}
|
||||
|
||||
return &GadgetCiphertext{Value: m}
|
||||
@@ -37,12 +32,12 @@ func NewGadgetCiphertext(params ParametersInterface, levelQ, levelP, decompRNS,
|
||||
|
||||
// LevelQ returns the level of the modulus Q of the target Ciphertext.
|
||||
func (ct GadgetCiphertext) LevelQ() int {
|
||||
return ct.Value[0][0].LevelQ()
|
||||
return ct.Value[0][0][0].LevelQ()
|
||||
}
|
||||
|
||||
// LevelP returns the level of the modulus P of the target Ciphertext.
|
||||
func (ct GadgetCiphertext) LevelP() int {
|
||||
return ct.Value[0][0].LevelP()
|
||||
return ct.Value[0][0][0].LevelP()
|
||||
}
|
||||
|
||||
// Equal checks two Ciphertexts for equality.
|
||||
@@ -55,11 +50,11 @@ func (ct *GadgetCiphertext) CopyNew() (ctCopy *GadgetCiphertext) {
|
||||
if ct == nil || len(ct.Value) == 0 {
|
||||
return nil
|
||||
}
|
||||
v := make([][]OperandQP, len(ct.Value))
|
||||
v := make(structs.Matrix[tupleQP], len(ct.Value))
|
||||
for i := range ct.Value {
|
||||
v[i] = make([]OperandQP, len(ct.Value[0]))
|
||||
v[i] = make([]tupleQP, len(ct.Value[0]))
|
||||
for j, el := range ct.Value[i] {
|
||||
v[i][j] = *el.CopyNew()
|
||||
v[i][j] = el.CopyNew()
|
||||
}
|
||||
}
|
||||
return &GadgetCiphertext{Value: v}
|
||||
@@ -162,7 +157,7 @@ func AddPolyTimesGadgetVectorToGadgetCiphertext(pt *ring.Poly, cts []GadgetCiphe
|
||||
p0tmp := buff.Coeffs[index]
|
||||
|
||||
for u, ct := range cts {
|
||||
p1tmp := ct.Value[i][j].Value[u].Q.Coeffs[index]
|
||||
p1tmp := ct.Value[i][j][u].Q.Coeffs[index]
|
||||
for w := 0; w < N; w++ {
|
||||
p1tmp[w] = ring.CRed(p1tmp[w]+p0tmp[w], qi)
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ func (kgen *KeyGenerator) genEvaluationKey(skIn *ring.Poly, skOut *SecretKey, ev
|
||||
// Samples an encryption of zero for each element of the EvaluationKey.
|
||||
for i := 0; i < len(evk.Value); i++ {
|
||||
for j := 0; j < len(evk.Value[0]); j++ {
|
||||
enc.EncryptZero(evk.Value[i][j])
|
||||
enc.EncryptZero(&OperandQP{MetaData: MetaData{IsNTT: true, IsMontgomery: true}, Value: evk.Value[i][j][:]})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
126
rlwe/keys.go
126
rlwe/keys.go
@@ -95,29 +95,31 @@ func (sk *SecretKey) UnmarshalBinary(p []byte) (err error) {
|
||||
return sk.Value.UnmarshalBinary(p)
|
||||
}
|
||||
|
||||
// PublicKey is a type for generic RLWE public keys.
|
||||
// The Value field stores the polynomials in NTT and Montgomery form.
|
||||
type PublicKey struct {
|
||||
Value [2]ringqp.Poly
|
||||
type tupleQP [2]ringqp.Poly
|
||||
|
||||
// NewPublicKey returns a new PublicKey with zero values.
|
||||
func newTupleQP(params ParametersInterface) (pk tupleQP) {
|
||||
return [2]ringqp.Poly{*params.RingQP().NewPoly(), *params.RingQP().NewPoly()}
|
||||
}
|
||||
|
||||
// NewPublicKey returns a new PublicKey with zero values.
|
||||
func NewPublicKey(params ParametersInterface) (pk *PublicKey) {
|
||||
return &PublicKey{Value: [2]ringqp.Poly{*params.RingQP().NewPoly(), *params.RingQP().NewPoly()}}
|
||||
func newTupleQPAtLevel(params ParametersInterface, levelQ, levelP int) (pk tupleQP) {
|
||||
rqp := params.RingQP().AtLevel(levelQ, levelP)
|
||||
return [2]ringqp.Poly{*rqp.NewPoly(), *rqp.NewPoly()}
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the target PublicKey and returns it.
|
||||
func (p *PublicKey) CopyNew() *PublicKey {
|
||||
return &PublicKey{Value: [2]ringqp.Poly{*p.Value[0].CopyNew(), *p.Value[1].CopyNew()}}
|
||||
func (p *tupleQP) CopyNew() tupleQP {
|
||||
return [2]ringqp.Poly{*p[0].CopyNew(), *p[1].CopyNew()}
|
||||
}
|
||||
|
||||
// Equal performs a deep equal.
|
||||
func (p *PublicKey) Equal(other *PublicKey) bool {
|
||||
return p.Value[0].Equal(&other.Value[0]) && p.Value[1].Equal(&other.Value[1])
|
||||
func (p *tupleQP) Equal(other tupleQP) bool {
|
||||
return p[0].Equal(&other[0]) && p[1].Equal(&other[1])
|
||||
}
|
||||
|
||||
func (p *PublicKey) BinarySize() int {
|
||||
return structs.Vector[ringqp.Poly](p.Value[:]).BinarySize()
|
||||
func (p *tupleQP) BinarySize() int {
|
||||
return structs.Vector[ringqp.Poly](p[:]).BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
@@ -131,8 +133,8 @@ func (p *PublicKey) BinarySize() int {
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p *PublicKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
v := structs.Vector[ringqp.Poly](p.Value[:])
|
||||
func (p *tupleQP) WriteTo(w io.Writer) (n int64, err error) {
|
||||
v := structs.Vector[ringqp.Poly](p[:])
|
||||
return v.WriteTo(w)
|
||||
}
|
||||
|
||||
@@ -147,8 +149,8 @@ func (p *PublicKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p *PublicKey) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
v := structs.Vector[ringqp.Poly](p.Value[:])
|
||||
func (p *tupleQP) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
v := structs.Vector[ringqp.Poly](p[:])
|
||||
n, err = v.ReadFrom(r)
|
||||
if len(v) != 2 {
|
||||
return n, fmt.Errorf("bad public key format")
|
||||
@@ -157,15 +159,15 @@ func (p *PublicKey) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
}
|
||||
|
||||
// MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes.
|
||||
func (p *PublicKey) MarshalBinary() ([]byte, error) {
|
||||
v := structs.Vector[ringqp.Poly](p.Value[:])
|
||||
func (p *tupleQP) MarshalBinary() ([]byte, error) {
|
||||
v := structs.Vector[ringqp.Poly](p[:])
|
||||
return v.MarshalBinary()
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
func (p *PublicKey) UnmarshalBinary(b []byte) error {
|
||||
v := structs.Vector[ringqp.Poly](p.Value[:])
|
||||
func (p *tupleQP) UnmarshalBinary(b []byte) error {
|
||||
v := structs.Vector[ringqp.Poly](p[:])
|
||||
err := v.UnmarshalBinary(b)
|
||||
if len(v) != 2 {
|
||||
return fmt.Errorf("bad public key format")
|
||||
@@ -173,6 +175,72 @@ func (p *PublicKey) UnmarshalBinary(b []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// PublicKey is a type for generic RLWE public keys.
|
||||
// The Value field stores the polynomials in NTT and Montgomery form.
|
||||
type PublicKey struct {
|
||||
Value tupleQP
|
||||
}
|
||||
|
||||
// NewPublicKey returns a new PublicKey with zero values.
|
||||
func NewPublicKey(params ParametersInterface) (pk *PublicKey) {
|
||||
return &PublicKey{Value: newTupleQP(params)}
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the target PublicKey and returns it.
|
||||
func (p *PublicKey) CopyNew() *PublicKey {
|
||||
return &PublicKey{Value: p.Value.CopyNew()}
|
||||
}
|
||||
|
||||
// Equal performs a deep equal.
|
||||
func (p *PublicKey) Equal(other *PublicKey) bool {
|
||||
return p.Value.Equal(other.Value)
|
||||
}
|
||||
|
||||
func (p *PublicKey) BinarySize() int {
|
||||
return p.Value.BinarySize()
|
||||
}
|
||||
|
||||
// WriteTo writes the object on an io.Writer. It implements the io.WriterTo
|
||||
// interface, and will write exactly object.BinarySize() bytes on w.
|
||||
//
|
||||
// Unless w implements the buffer.Writer interface (see lattigo/utils/buffer/writer.go),
|
||||
// it will be wrapped into a bufio.Writer. Since this requires allocations, it
|
||||
// is preferable to pass a buffer.Writer directly:
|
||||
//
|
||||
// - When writing multiple times to a io.Writer, it is preferable to first wrap the
|
||||
// io.Writer in a pre-allocated bufio.Writer.
|
||||
// - When writing to a pre-allocated var b []byte, it is preferable to pass
|
||||
// buffer.NewBuffer(b) as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p *PublicKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return p.Value.WriteTo(w)
|
||||
}
|
||||
|
||||
// ReadFrom reads on the object from an io.Writer. It implements the
|
||||
// io.ReaderFrom interface.
|
||||
//
|
||||
// Unless r implements the buffer.Reader interface (see see lattigo/utils/buffer/reader.go),
|
||||
// it will be wrapped into a bufio.Reader. Since this requires allocation, it
|
||||
// is preferable to pass a buffer.Reader directly:
|
||||
//
|
||||
// - When reading multiple values from a io.Reader, it is preferable to first
|
||||
// first wrap io.Reader in a pre-allocated bufio.Reader.
|
||||
// - When reading from a var b []byte, it is preferable to pass a buffer.NewBuffer(b)
|
||||
// as w (see lattigo/utils/buffer/buffer.go).
|
||||
func (p *PublicKey) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
return p.Value.ReadFrom(r)
|
||||
}
|
||||
|
||||
// MarshalBinary encodes the object into a binary form on a newly allocated slice of bytes.
|
||||
func (p *PublicKey) MarshalBinary() ([]byte, error) {
|
||||
return p.Value.MarshalBinary()
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a slice of bytes generated by
|
||||
// MarshalBinary or WriteTo on the object.
|
||||
func (p *PublicKey) UnmarshalBinary(b []byte) error {
|
||||
return p.Value.UnmarshalBinary(b)
|
||||
}
|
||||
|
||||
// EvaluationKey is a public key indended to be used during the evaluation phase of a homomorphic circuit.
|
||||
// It provides a one way public and non-interactive re-encryption from a ciphertext encrypted under `skIn`
|
||||
// to a ciphertext encrypted under `skOut`.
|
||||
@@ -192,13 +260,17 @@ type EvaluationKey struct {
|
||||
|
||||
// NewEvaluationKey returns a new EvaluationKey with pre-allocated zero-value
|
||||
func NewEvaluationKey(params ParametersInterface, levelQ, levelP int) *EvaluationKey {
|
||||
return &EvaluationKey{GadgetCiphertext: *NewGadgetCiphertext(
|
||||
params,
|
||||
levelQ,
|
||||
levelP,
|
||||
params.DecompRNS(levelQ, levelP),
|
||||
params.DecompPw2(levelQ, levelP),
|
||||
)}
|
||||
//evk := new(EvaluationKey)
|
||||
// drns := params.DecompRNS(levelQ, levelP)
|
||||
// dpw2 := params.DecompPw2(levelQ, levelP)
|
||||
// evk.Value = make(structs.Matrix[tupleQP], drns)
|
||||
// for i := range evk.Value {
|
||||
// evk.Value[i] = make([][2]ringqp.Poly, dpw2)
|
||||
// for j := range evk.Value[i] {
|
||||
// evk.Value[i][j] = NewPublicKey(params).Value
|
||||
// }
|
||||
// }
|
||||
return &EvaluationKey{GadgetCiphertext: *NewGadgetCiphertext(params, levelQ, levelP, params.DecompRNS(levelQ, levelP), params.DecompPw2(levelQ, levelP))}
|
||||
}
|
||||
|
||||
// CopyNew creates a deep copy of the target EvaluationKey and returns it.
|
||||
|
||||
@@ -74,7 +74,7 @@ func EvaluationKeyIsCorrect(evk *EvaluationKey, skIn, skOut *SecretKey, params P
|
||||
// [-asIn + w*P*sOut + e, a] + [asIn]
|
||||
for i := range evk.Value {
|
||||
for j := range evk.Value[i] {
|
||||
ringQP.MulCoeffsMontgomeryThenAdd(&evk.Value[i][j].Value[1], &skOut.Value, &evk.Value[i][j].Value[0])
|
||||
ringQP.MulCoeffsMontgomeryThenAdd(&evk.Value[i][j][1], &skOut.Value, &evk.Value[i][j][0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func EvaluationKeyIsCorrect(evk *EvaluationKey, skIn, skOut *SecretKey, params P
|
||||
for i := range evk.Value { // RNS decomp
|
||||
if i > 0 {
|
||||
for j := range evk.Value[i] { // PW2 decomp
|
||||
ringQP.Add(&evk.Value[0][j].Value[0], &evk.Value[i][j].Value[0], &evk.Value[0][j].Value[0])
|
||||
ringQP.Add(&evk.Value[0][j][0], &evk.Value[i][j][0], &evk.Value[0][j][0])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,22 +96,22 @@ func EvaluationKeyIsCorrect(evk *EvaluationKey, skIn, skOut *SecretKey, params P
|
||||
for i := 0; i < decompPw2; i++ {
|
||||
|
||||
// P*s^i + sum(e) - P*s^i = sum(e)
|
||||
ringQ.Sub(evk.Value[0][i].Value[0].Q, skIn.Value.Q, evk.Value[0][i].Value[0].Q)
|
||||
ringQ.Sub(evk.Value[0][i][0].Q, skIn.Value.Q, evk.Value[0][i][0].Q)
|
||||
|
||||
// Checks that the error is below the bound
|
||||
// Worst error bound is N * floor(6*sigma) * #Keys
|
||||
ringQP.INTT(&evk.Value[0][i].Value[0], &evk.Value[0][i].Value[0])
|
||||
ringQP.IMForm(&evk.Value[0][i].Value[0], &evk.Value[0][i].Value[0])
|
||||
ringQP.INTT(&evk.Value[0][i][0], &evk.Value[0][i][0])
|
||||
ringQP.IMForm(&evk.Value[0][i][0], &evk.Value[0][i][0])
|
||||
|
||||
// Worst bound of inner sum
|
||||
// N*#Keys*(N * #Parties * floor(sigma*6) + #Parties * floor(sigma*6) + N * #Parties + #Parties * floor(6*sigma))
|
||||
|
||||
if log2Bound < ringQ.Log2OfStandardDeviation(evk.Value[0][i].Value[0].Q) {
|
||||
if log2Bound < ringQ.Log2OfStandardDeviation(evk.Value[0][i][0].Q) {
|
||||
return false
|
||||
}
|
||||
|
||||
if levelP != -1 {
|
||||
if log2Bound < ringP.Log2OfStandardDeviation(evk.Value[0][i].Value[0].P) {
|
||||
if log2Bound < ringP.Log2OfStandardDeviation(evk.Value[0][i][0].P) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user