#include "FHE/Plaintext.h" #include "FHE/Ring_Element.h" #include "FHE/PPData.h" #include "FHE/P2Data.h" #include "FHE/Rq_Element.h" #include "FHE_Keys.h" #include "FHE/AddableVector.hpp" #include "Math/Z2k.hpp" #include "Math/modp.hpp" template<> void Plaintext::from(const Generator& source) const { b.resize(degree); for (auto& x : b) { source.get(bigint::tmp); x = bigint::tmp; } } template<> void Plaintext::from_poly() const { if (type!=Polynomial) { return; } Ring_Element e(*Field_Data,polynomial); e.from(b); e.change_rep(evaluation); a.resize(n_slots); for (unsigned int i=0; i void Plaintext::to_poly() const { if (type!=Evaluation) { return; } Ring_Element e(*Field_Data,evaluation); for (unsigned int i=0; i void Plaintext::from_poly() const { if (type!=Polynomial) { return; } vector aa((*Field_Data).phi_m()); for (unsigned int i=0; i void Plaintext::to_poly() const { if (type!=Evaluation) { return; } cout << "This is VERY inefficient to convert a plaintext to poly representation" << endl; vector bb((*Field_Data).phi_m()); for (unsigned int i=0; i void Plaintext::from_poly() const { if (type!=Polynomial) { return; } a.resize(n_slots); (*Field_Data).backward(a,b); type=Both; } template<> void Plaintext::to_poly() const { if (type!=Evaluation) { return; } (*Field_Data).forward(b,a); type=Both; } template<> void Plaintext::set_sizes() { n_slots = (*Field_Data).phi_m(); degree = n_slots; } template<> void Plaintext::set_sizes() { n_slots = (*Field_Data).phi_m(); degree = n_slots; } template<> void Plaintext::set_sizes() { n_slots = (*Field_Data).num_slots(); degree = (*Field_Data).degree(); } template void Plaintext::allocate(PT_Type type) const { if (type != Evaluation) b.resize(degree); if (type != Polynomial) a.resize(n_slots); this->type = type; } template void Plaintext::allocate_slots(const bigint& value) { b.resize(degree); for (auto& x : b) x.allocate_slots(value); } template<> void Plaintext::allocate_slots(const bigint& value) { // nothing to allocate for int (void)value; } template<> int Plaintext::get_min_alloc() { int res = 1 << 30; for (auto& x : b) res = min(res, x.get_min_alloc()); return res; } void signed_mod(bigint& x, const bigint& mod, const bigint& half_mod, const bigint& dest_mod) { if (x > half_mod) x -= mod; x %= dest_mod; if (x < 0) x += dest_mod; } template void Plaintext::set_poly_mod(const Generator& generator,const bigint& mod) { allocate(Polynomial); bigint half_mod = mod / 2; for (unsigned int i=0; iget_prime()); b[i] = bigint::tmp; } } template<> void Plaintext::set_poly_mod(const vector& vv,const bigint& mod) { vector pol(vv.size()); bigint te; for (unsigned int i=0; imod/2) { te=vv[i]-mod; } else { te=vv[i]; } pol[i]=isOdd(te); } set_poly(pol); } template<> void Plaintext::set_poly_mod(const Generator& generator,const bigint& mod) { allocate(Polynomial); bigint half_mod = mod / 2; bigint te; for (unsigned int i=0; i half_mod) te -= mod; b[i]=isOdd(te); } } template void rand_poly(vector& b,PRNG& G,const bigint& pr,bool positive=true) { for (unsigned int i=0; i void Plaintext::randomize(PRNG& G,condition cond) { switch (cond) { case Full: rand_poly(b,G,(*Field_Data).get_prime()); type=Polynomial; break; case Diagonal: a.resize(n_slots); a[0].randomize(G); for (unsigned int i=1; i void Plaintext::randomize(PRNG& G, int n_bits, bool Diag, PT_Type t) { allocate(t); switch(t) { case Polynomial: if (Diag) { assign_zero(t); b[0].generateUniform(G, n_bits, false); } else for (int i = 0; i < n_slots; i++) b[i].generateUniform(G, n_bits, false); break; default: throw not_implemented(); } } template void Plaintext::assign_zero(PT_Type t) { type=t; allocate(); if (type!=Polynomial) { a.resize(n_slots); for (unsigned int i=0; i void Plaintext::assign_one(PT_Type t) { type=t; allocate(); if (type!=Polynomial) { a.resize(n_slots); for (unsigned int i=0; i void Plaintext::assign_constant(T constant, PT_Type t) { allocate(Evaluation); for (auto& x : a) x = constant; if (t != Evaluation) to_poly(); } template Plaintext& Plaintext::operator+=( const Plaintext& y) { if (Field_Data!=y.Field_Data) { throw field_mismatch(); } to_poly(); y.to_poly(); if (b.size() != y.b.size()) throw length_error("size mismatch"); add(*this, *this, y); return *this; } template<> void add(Plaintext& z,const Plaintext& x, const Plaintext& y) { if (z.Field_Data!=x.Field_Data) { throw field_mismatch(); } if (z.Field_Data!=y.Field_Data) { throw field_mismatch(); } if (x.type==Both && y.type!=Both) { z.type=y.type; } else if (y.type==Both && x.type!=Both) { z.type=x.type; } else if (x.type!=y.type) { throw rep_mismatch(); } else { z.type=x.type; } z.allocate(); if (z.type!=Polynomial) { z.a.resize(z.n_slots); for (unsigned int i=0; i(*z.Field_Data).get_prime()) { z.b[i]-=(*z.Field_Data).get_prime(); } } } } template<> void add(Plaintext& z,const Plaintext& x, const Plaintext& y) { if (z.Field_Data!=x.Field_Data) { throw field_mismatch(); } if (z.Field_Data!=y.Field_Data) { throw field_mismatch(); } if (x.type==Both && y.type!=Both) { z.type=y.type; } else if (y.type==Both && x.type!=Both) { z.type=x.type; } else if (x.type!=y.type) { throw rep_mismatch(); } else { z.type=x.type; } if (z.type!=Polynomial) { z.a.resize(z.n_slots); for (unsigned int i=0; i(*z.Field_Data).get_prime()) { z.b[i]-=(*z.Field_Data).get_prime(); } } } } template<> void add(Plaintext& z,const Plaintext& x, const Plaintext& y) { if (z.Field_Data!=x.Field_Data) { throw field_mismatch(); } if (z.Field_Data!=y.Field_Data) { throw field_mismatch(); } if (x.type==Both && y.type!=Both) { z.type=y.type; } else if (y.type==Both && x.type!=Both) { z.type=x.type; } else if (x.type!=y.type) { throw rep_mismatch(); } else { z.type=x.type; } z.allocate(); if (z.type!=Polynomial) { z.a.resize(z.n_slots); for (unsigned int i=0; i void sub(Plaintext& z,const Plaintext& x, const Plaintext& y) { if (z.Field_Data!=x.Field_Data) { throw field_mismatch(); } if (z.Field_Data!=y.Field_Data) { throw field_mismatch(); } if (x.type==Both && y.type!=Both) { z.type=y.type; } else if (y.type==Both && x.type!=Both) { z.type=x.type; } else if (x.type!=y.type) { throw rep_mismatch(); } else { z.type=x.type; } z.allocate(); if (z.type!=Polynomial) { z.a.resize(z.n_slots); for (unsigned int i=0; i void sub(Plaintext& z,const Plaintext& x, const Plaintext& y) { if (z.Field_Data!=x.Field_Data) { throw field_mismatch(); } if (z.Field_Data!=y.Field_Data) { throw field_mismatch(); } if (x.type==Both && y.type!=Both) { z.type=y.type; } else if (y.type==Both && x.type!=Both) { z.type=x.type; } else if (x.type!=y.type) { throw rep_mismatch(); } else { z.type=x.type; } z.allocate(); if (z.type!=Polynomial) { z.a.resize(z.n_slots); for (unsigned int i=0; i void sub(Plaintext& z,const Plaintext& x, const Plaintext& y) { if (z.Field_Data!=x.Field_Data) { throw field_mismatch(); } if (z.Field_Data!=y.Field_Data) { throw field_mismatch(); } if (x.type==Both && y.type!=Both) { z.type=y.type; } else if (y.type==Both && x.type!=Both) { z.type=x.type; } else if (x.type!=y.type) { throw rep_mismatch(); } else { z.type=x.type; } z.allocate(); if (z.type!=Polynomial) { z.a.resize(z.n_slots); for (unsigned int i=0; i void mul(Plaintext& z,const Plaintext& x,const Plaintext& y) { if (z.Field_Data!=x.Field_Data) { throw field_mismatch(); } if (z.Field_Data!=y.Field_Data) { throw field_mismatch(); } if (y.type==Polynomial) { throw not_implemented(); } if (x.type==Polynomial) { throw not_implemented(); } z.type=Evaluation; z.allocate(); for (unsigned int i=0; i void Plaintext::negate() { if (type!=Polynomial) { a.resize(n_slots); for (unsigned int i=0; i void Plaintext::negate() { if (type!=Polynomial) { a.resize(n_slots); for (unsigned int i=0; i void Plaintext::negate() { return; } template AddableVector Plaintext::mul_by_X_i(int i, const FHE_PK& pk) const { return AddableVector(get_poly()).mul_by_X_i(i, pk); } template bool Plaintext::equals(const Plaintext& x) const { if (Field_Data!=x.Field_Data) { return false; } if (type!=x.type) { if (type==Evaluation) { x.from_poly(); } else { from_poly(); } } if (type!=Polynomial and x.type!=Polynomial) { a.resize(n_slots); for (unsigned int i=0; i bool Plaintext::is_diagonal() const { if (type != Evaluation) { for (size_t i = 1; i < b.size(); i++) if (b[i] != 0) return false; } if (type != Polynomial) { auto first = a[0]; for (auto& x : a) if (x != first) return false; } return true; } template<> bool Plaintext::is_diagonal() const { if (type == Polynomial) from_poly(); auto first = a[0]; for (auto& x : a) if (x != first) return false; return true; } template void Plaintext::pack(octetStream& o) const { to_poly(); o.store((unsigned int)b.size()); for (unsigned int i = 0; i < b.size(); i++) o.store(b[i]); } template void Plaintext::unpack(octetStream& o) { type = Polynomial; unsigned int size; o.get(size); allocate(); if (size != b.size()) throw length_error("unexpected length received"); for (unsigned int i = 0; i < b.size(); i++) b[i] = o.get(); } template <> size_t Plaintext::report_size(ReportType type) { size_t res = 0; if (type != MINIMAL) res += sizeof(gfp) * a.capacity(); for (unsigned int i = 0; i < b.size(); i++) res += b[i].report_size(type); return res; } template <> size_t Plaintext::report_size(ReportType type) { size_t res = 0; if (type != MINIMAL) res += sizeof(gf2n_short) * a.capacity(); res += sizeof(int) * b.size(); return res; } template void Plaintext::print_evaluation(int n_elements, string desc) const { cout << desc; for (int i = 0; i < n_elements; i++) cout << " " << element(i); cout << endl; } template class Plaintext; template void mul(Plaintext& z,const Plaintext& x,const Plaintext& y); template class Plaintext; template void mul(Plaintext& z,const Plaintext& x,const Plaintext& y); template class Plaintext; template void mul(Plaintext& z,const Plaintext& x,const Plaintext& y);