Closed jscode017 closed 1 year ago
No. Ring_Element
represents a polynomial modulo a prime and X^{N+1}
whereas Rq_Element
represents a polynomial modulo a prime or product of two prime and X^{N+1}
. There is no documentation on these internals beyond the comments in the source code. This is because the code is limited to a specific kind of homomorphic encryption, that is, BGV with a prime cleartext modulus allowing up to one level of multiplication and such that all primes allow the FFT-based number theory transform. If you're happy with this, I recommend using the high-level interface: https://mp-spdz.readthedocs.io/en/latest/homomorphic-encryption.html
If you're more interested in polynomial arithmetic, NTL might be a better library to use: https://libntl.org/
Thanks for the reply I am looking to build some lattice stuff, so I am looking into the Ring_Element and Rq_Element From what I have seen so far, I may need FFT_Data to init a Ring_Element May I ask how I could init an FFT_Data? In more details, I am finding a some example code to do as follow: It seems to me I need to call the void init(const Ring& Rg,const Zp_Data& PrD); https://github.com/data61/MP-SPDZ/blob/master/FHE/FFT_Data.h#L45
May I ask how could I init it with some variable like bigint than use that bigint to call void init(const Ring& Rg,const Zp_Data& PrD);? Thanks
You should be able to call init(const Ring& Rg, const Zp_Data Prd)
after calling ::init(Rg, m)
for the desired dimension m
and Prd.init(p)
for the desired prime bigint p
. However, you should note that these functions have not been tested outside the parameters that are used in MP-SPDZ.
@mkskeller Thanks again for the reply! May I ask that If I am going to declare a ring element that has value equals 5 Could I do something as follows: Ring ring;
init(ring, 32768);
bigint p;
generate_prime(p, 64, 16384);
Zp_Data prd;
prd.init(bigint(p));
FFT_Data fft;
fft.init(ring, prd);
AddableVector<gfpvar_<0, 5>> a_vec(fft.get_R().phi_m());
a_vec[0]=5;
Or should I assign 5 as some binary form and push to the vector?
And may I ask how could I call the mul function on ring_element correctly, the below code gives me segmentation fault
Ring ring;
init(ring, 32768);
bigint p;
generate_prime(p, 64, 16384);
Zp_Data prd;
prd.init(bigint(p));
FFT_Data fft;
fft.init(ring, prd);
AddableVector<gfpvar_<0, 5>> a_vec(fft.get_R().phi_m());
a_vec[0]=5;
Ring_Element ring_ele(fft, polynomial, a_vec);
AddableVector<gfpvar_<0, 5>> b_vec(fft.get_R().phi_m());
b_vec[0]=7;
Ring_Element ring_ele2(fft, polynomial, b_vec);
Ring_Element ring_ele3(fft, polynomial, b_vec);
mul(ring_ele3, ring_ele2, ring_ele);
Thanks a lot
You need to initialize gfpvar_<0,5>
separately with gfpvar_<0,5>::init_field()
if you want to use it. However, it might be easier to use Ring_Element::from(x)
with vector<bigint> x
.
@mkskeller thanks
Then may I ask what should I pass in the vector
The first is correct.
Then may I also asks that in rq_element Why does it needs to read in two ring element? e.g.: Rq_Element a(Ring_Element(fftd[0], evaluation, a0), Ring_Element(fftd[1], evaluation, a1));
This is for the ciphertext modulus being a composite number (product of two primes). The two Ring_Element
objects then are the representation according to the Chinese Remainder Theorem, which allows calculating the product of polynomials by element-wise product (the ultimate reason for the all infrastructure). The composite modulus is needed for ciphertext multiplication.
Thanks again So do it means that if I would want some Rq_Element of value 5 I could do likewise(based on 5 mod some big prime is also 5)?
bigint p;
bigint p2;
generate_prime(p, 64, 16384);
generate_prime(p2, 128, 32768);
Zp_Data prd;
prd.init(p);
Zp_Data prd2;
prd2.init(p2);
FFT_Data fft;
fft.init(ring, prd);
FFT_Data fft2;
fft2.init(ring2, prd2);
vector<bigint> a_vec(32768);
a_vec[0]=5;
Ring_Element ring_ele(fft, evaluation);
ring_ele.from(a_vec);
Ring_Element ring_ele2(fft2, evaluation);
ring_ele.from(a_vec);
Rq_Element a(ring_ele, ring_ele2);
I think that's right.
However, the Ring
instances need to be the same.
Thanks Then may I ask that if I would like to have a Rq_element that modules n=p*q(where p and q is prime) Do I use different ring instances, or is there other way to do it?
I think there is a misunderstanding. What you want to do is supported, but it doesn't make sense to use two different instances of Ring
because they represent the polynomial X^N+1 for some N, and this has to be same in both instances of Ring_Element
.
Got it, sorry for the stupid question Then may I still ask how to init it with something like gfpvar(as above) does it mean for every element in the addable vector I have to call init_field? e.g.:
AddableVector<gfpvar_<0, 5>> a_vec(fft.get_R().phi_m());
for(auto a: a_vec) a.init_field(with the prime used in ring_element)
No, init_field()
is a static method that only needs to be called once.
But I can only reiterate that using this kind of initialization has no benefit as it's slower.
@mkskeller Thanks again, I would probably stick to bigint then And may I ask how could I write Ring_Element and Rq_Element to file? like: https://github.com/data61/MP-SPDZ/blob/master/Protocols/fake-stuff.h#L91 In the fake offline?
You can use pack
with an octetStream
object and then the output method of said object.
Thanks
And may I ask where the code of != in fft data compare? It seems to me it is here: https://github.com/data61/MP-SPDZ/blob/master/FHE/FFT_Data.cpp#L137 but in https://github.com/data61/MP-SPDZ/blob/master/FHE/Ring_Element.cpp#L152 It seems to trigger another operator
The difference is that the first is called when you the objects as such (via operator overloading) whereas the second compares two pointers, that is, the two objects have the same in memory.
Thanks, so I suppose that if I would want to operate on two ring elements, I probably need to init them by some global fft data, ao they could have the same memory?
Correct. The pointer check is just a way to save time, and there is no reason in the existing implementation to have two different objects with the same content.
Then since I would have to write and read ring elements and rq elements from file, do you recommend maybe I should disable the memory address check in my implementation?(since if read from file they probably do not have the same memory address)
No. Even if you read elements from file, you will have to initialize the FFT_Data pointer in the Ring_Element. If you don't, you will likely encounter an invalid result or a segfault.
Hi @mkskeller May I ask that is the ring_element class only a interger mod prime, and the rq_element class a ring that mods the X^N+1?
If so, I would like to ask that how could I initiate those variables For example: I would like to specify the mod p for the ring elements And also the mod and the N in X^N+1 for the rq_elements
Are there some examples or documents
Thanks :)