Closed Dylan-yxn closed 4 years ago
Hello Dylan,
We are aware that there are yet no examples for DCKKS, we are working on providing some in the near future. However the key establishment are very similar, if not identical, to the DBFV scheme, for which there are examples.
Edit : I forgot to add that the test files can be used as examples.
Could you post your code and the output that you get?
Thanks for your reply.
I am imitating RKG written by DBFV, this is my code:
........
// 2) Collective relinearization key generation
for _, pi := range P {
rkg.GenShareRoundOne(pi.rlkEphemSk, pi.sk.Get(), crp, pi.rkgShareOne)
}
rkgCombined1, rkgCombined2, rkgCombined3 := rkg.AllocateShares()
for _, pi := range P {
rkg.AggregateShareRoundOne(pi.rkgShareOne, rkgCombined1, rkgCombined1)
}
for _, pi := range P {
rkg.GenShareRoundTwo(rkgCombined1, pi.sk.Get(), crp, pi.rkgShareTwo)
}
for _, pi := range P {
rkg.AggregateShareRoundTwo(pi.rkgShareTwo, rkgCombined2, rkgCombined2)
}
for _, pi := range P {
rkg.GenShareRoundThree(rkgCombined2, pi.rlkEphemSk, pi.sk.Get(), pi.rkgShareThree)
}
rlk := ckks.NewRelinKey(params)
for _, pi := range P {
rkg.AggregateShareRoundThree(pi.rkgShareThree, rkgCombined3, rkgCombined3)
}
rkg.GenRelinearizationKey(rkgCombined2, rkgCombined3, rlk)
encoder := ckks.NewEncoder(params)
encInputs := make([]*ckks.Ciphertext, N, N)
encryptor := ckks.NewEncryptorFromPk(params, pk)
for i := range encInputs {
encInputs[i] = ckks.NewCiphertext(params, 1,params.MaxLevel(),params.Scale)
}
pt := ckks.NewPlaintext(params,params.MaxLevel(),params.Scale)
for i, pi := range P {
encoder.Encode(pt,pi.input,slots)
encryptor.Encrypt(pt, encInputs[i])
}
evaluator := ckks.NewEvaluator(params)
resultop := ckks.NewCiphertext(params,1,params.MaxLevel(),params.Scale)
evaluator.MulRelin(encInputs[0],encInputs[1],rlk,resultop)
/*CKS and decrypt*/
My Input is:
......
pi.input = make([]complex128, slots, slots)
if i == 0 {
pi.input[0] = complex(6.02,0)
pi.input[1] = complex(7.23,0)
pi.input[2] = complex(6.72,0)
pi.input[3] = complex(6.02,0)
pi.input[4] = complex(8.44,0)
}else if i == 1 {
pi.input[0] = complex(6.33, 0)
pi.input[1] = complex(7.12, 0)
pi.input[2] = complex(5.03, 0)
pi.input[3] = complex(6.64, 0)
pi.input[4] = complex(9.03, 0)
}
......
The answer I got was:
The answer should be: (38.1066+0i, 51.4776+0i......)
It looks like your problem is about the scaling. Here is why I think it is :
All your complex values are much smaller than your real values with a ratio of about 1e-06 or 1e-07, which is among the expected precision for some set of parameters.
If there was something wrong with the keys, then it would output values which look uniform for both the real and complex part and of a bit size of your current total modulus.
And 38.1066/654657562580 = 51.4776/884376917361 = 5.820e-11, the ratio is the same and 1/5.820e-11 is about 35 bits, which is probably your original scale.
At some point you must have hard-coded the scale of your result to be your original scale of 2^35 instead of correct scale (when you do a multiplication the resulting scale is the multiplication between the scale of the two inputs). I don't see the end of your code, but probably you created a plaintext with a scale of params.Scale instead of a scale of resultop.Scale(). You can also use DecryptNew, and it will return a plaintext with the correct scale.
I tried your method using DecryptNew () but still got the wrong answer, here is my code about decryption:
/*CKS*/
zero := params.NewPolyQ()
cksCombined := cks.AllocateShare()
for _, pi := range P[1:] {
cks.GenShare(pi.sk.Get(), zero, resultop, pi.cksShare)
}
encOut := ckks.NewCiphertext(params, 1,params.MaxLevel(),params.Scale)
for _, pi := range P {
cks.AggregateShares(pi.cksShare, cksCombined, cksCombined)
}
cks.KeySwitch(cksCombined,resultop, encOut)
decryptor := ckks.NewDecryptor(params, P[0].sk)
res := encoder.Decode(decryptor.DecryptNew(encOut), slots)
fmt.Printf(" %6f %6f %6f %6f %6f\n",
round(res[0]), round(res[1]), round(res[2]), round(res[3]), round(res[4]))
I also tried Rescale() but got the same answer.
When I used MultByConst(ciphertxt, float64, ciphertext), the answer is right. So I suspect it was rlk before.
Ok, I see what is going on. It is encOut that you have to set with a scale of resultop.Scale(). The cks.KeySwitch is not setting the output ciphertext scale based on the input ciphertext scale, while you would expect it to do it. I'll add an issue and correct this in the v.1.3.1. Thank you for finding this issue.
Thank you again for your patience with me!😁
No problem, thank you for testing our library and giving us feedbacks :)
Hi, I am new here. I am learning the use of DCKKS,but I got into trouble:
After Collective relinearization key generation to get rlk , use it in
evaluator.MulRelin(ciphertext, ciphertext, rlk, result)
I got the wrong result much bigger than I wanted.
Because there is no example of dckks, can you write me a hint?