/* Copyright (C) 2012,2013 IBM Corp. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PAlgebraMod.cpp - Implementation of the class template PAlgebraModTmpl * * This template implements the structure of the plaintext spaces * A_2 = R[X]/Phi_m(X) with R=(Z/2Z) or R=(Z/2^rZ). * * Phi_m(X) is factored mod 2 as Phi_m(X)=\prod_{t\in T} F_t(X) mod 2, where * the F_t's are irreducible modulo 2. An arbitrarily factor is chosen as F_1, * then for each t \in T we associate with the index t the factor * F_t(X) = GCD(F_1(X^t), Phi_m(X)). * * Note that fixing a representation of the field K=(Z/2Z)[X]/F_1(X) and * letting z be a root of F_1 in K (which is a primitive m-th root of unity * in K), we get that F_t is the minimal polynomial of z^{1/t}. * * The case R=(Z/2^rZ) is implemented by lifting from R=(Z/2Z) */ #include #include #include #include #include #include #include #include #include #include NTL_CLIENT #include // defines count(...), min(...) #include #include #include "NumbTh.h" #include "PAlgebra.h" void PAlgebraModTwo::init(const GF2X& factor) { // Initialization depends on zmStar being initialized if (zmStar.M()<2 || zmStar.NSlots()<=0) { if (PhimXmod != NULL) delete PhimXmod; PhimXmod = NULL; factors.kill(); crtCoeffs.kill(); return; } // Compute the factors Ft of Phi_m(X) mod 2, for all t \in T if (PhimXmod != NULL) delete PhimXmod; PhimXmod = new GF2XModulus(to_GF2X(zmStar.PhimX())); // Phi_m(X) mod 2 // If a factor is specified, use it, else factorize long nSlots = zmStar.NSlots(); if (deg(factor)>0 && IsZero(*PhimXmod % factor)) { factors.SetLength(nSlots); factors[0] = factor; } else if (factors.length() void PAlgebraModTmpl::mapToFt(GF2X& r, const GF2X& G,unsigned long t,const GF2X* rF1) const { long i = zmStar.indexOfRep(t); if (i < 0) { r=GF2X::zero(); return; } if (rF1==NULL) { // Compute the representation "from scratch" GF2E::init(factors[i]); // work with the extension field GF_2[X]/Ft(X) GF2EX Ga=to_GF2EX((GF2X&)G); // G as a polynomial over the extension field r=rep(FindRoot(Ga)); // Find a root of G in this field return; } // if rF1 is set, then use it instead, setting r = rF1(X^t) mod Ft(X) GF2XModulus Ft(factors[i]); // long tInv = InvMod(t,m); GF2X X2t = PowerXMod(t,Ft); // X2t = X^t mod Ft r = CompMod(*rF1,X2t,Ft); // r = F1(X2t) mod Ft /* Debugging sanity-check: G(r)=0 in the extension field (Z/2Z)[X]/Ft(X) GF2E::init(factors[i]); GF2EX Ga=to_GF2EX((GF2X&)G); // G as a polynomial over the extension field GF2E ra =to_GF2E(r); // r is an element in the extension field eval(ra,Ga,ra); // ra = Ga(ra) if (!IsZero(ra)) {// check that Ga(r)=0 in this extension field cout << "rF1(X^t) mod Ft(X) != root of G mod Ft, t=" << t << endl; exit(0); }*******************************************************************/ } template<> void PAlgebraModTmpl::mapToFt(zz_pX& r, const zz_pX& G,unsigned long t,const zz_pX* rF1) const { long i = zmStar.indexOfRep(t); if (i < 0) { r=zz_pX::zero(); return; } if (rF1==NULL) { // Compute the representation "from scratch" zz_pE::init(factors[i]); // work with the extension field GF_2[X]/Ft(X) zz_pEX Ga=to_zz_pEX((zz_pX&)G);// G is polynomial over the extension field r=rep(FindRoot(Ga)); // Find a root of G in this field return; } // if rF1 is set, then use it instead, setting r = rF1(X^t) mod Ft(X) zz_pXModulus Ft(factors[i]); // long tInv = InvMod(t,m); zz_pX X2t = PowerXMod(t,Ft); // X2t = X^t mod Ft r = CompMod(*rF1,X2t,Ft); // r = F1(X2t) mod Ft /* Debugging sanity-check: G(r)=0 in the extension field (Z/2Z)[X]/Ft(X) zz_pE::init(factors[i]); zz_pEX Ga=to_zz_pEX((zz_pX&)G);// G as a polynomial over the extension field zz_pE ra =to_zz_pE(r); // r is an element in the extension field eval(ra,Ga,ra); // ra = Ga(ra) if (!IsZero(ra)) {// check that Ga(r)=0 in this extension field cout << "rF1(X^t) mod Ft(X) != root of G mod Ft, t=" << t << endl; exit(0); }*******************************************************************/ } // return an array such that alphas[i] \in R[X]/G(X) represent the // same element as rt = (p mod Ft) \in R[X]/Ft(X) where t=T[i]. // If the optional map pointer is non-NULL, then (*map)[i] contains // the output of mapToFt(...G,T[i]). template<> void PAlgebraModTmpl::decodePlaintext( vector& alphas, const GF2X& ptxt, const GF2X &G, const vector& maps) const { unsigned long nSlots = zmStar.NSlots(); if (nSlots==0 || maps.size()!= nSlots ||deg(G)<1|| zmStar.OrdTwo()%deg(G)!=0){ alphas.resize(0); return; } // First decompose p into CRT componsnt vector CRTcomps(nSlots); // allocate space for CRT component CRT_decompose(CRTcomps, ptxt); // CRTcomps[i] = p mod facors[i] // Next convert each entry in CRTcomps[] back to base-G representation // (this is roughly the inverse of the embedInSlots operation) // maps contains all the base-G ==> base-Fi maps // SHAI: The code below is supposed to be Nigel's code, borrowed partly // from the constructor Algebra::Algebra(...) and partly from the // function AElement::to_type(2). I don't really unerstand that code, // so hopefully nothing was lost in translation alphas.resize(nSlots); GF2E::init(G); // the extension field R[X]/G(X) for (unsigned long i=0; i void PAlgebraModTmpl::decodePlaintext( vector& alphas, const zz_pX& ptxt, const zz_pX &G, const vector& maps) const { unsigned long nSlots = zmStar.NSlots(); if (nSlots==0 || maps.size()!= nSlots ||deg(G)<1|| zmStar.OrdTwo()%deg(G)!=0){ alphas.resize(0); return; } // First decompose p into CRT componsnt vector CRTcomps(nSlots); // allocate space for CRT component CRT_decompose(CRTcomps, ptxt); // CRTcomps[i] = p mod facors[i] if (IsX(G)) { // if modulus is not prime, this is the only case // that will actually work alphas = CRTcomps; return; } // Next convert each entry in CRTcomps[] back to base-G representation // (this is roughly the inverse of the embedInSlots operation) // maps contains all the base-G ==> base-Fi maps // SHAI: The code below is supposed to be Nigel's code, borrowed partly // from the constructor Algebra::Algebra(...) and partly from the // function AElement::to_type(2). I don't really unerstand that code, // so hopefully nothing was lost in translation alphas.resize(nSlots); zz_pE::init(G); // the extension field R[X]/G(X) for (unsigned long i=0; i