/*************************************************************************** * Copyright 2013 CertiVox UK Ltd. * * This file is part of CertiVox MIRACL Crypto SDK. * * The CertiVox MIRACL Crypto SDK provides developers with an * extensive and efficient set of cryptographic functions. * For further information about its features and functionalities please * refer to http://www.certivox.com * * * The CertiVox MIRACL Crypto SDK is free software: you can * redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * * The CertiVox MIRACL Crypto SDK 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 Affero General Public License for more details. * * * You should have received a copy of the GNU Affero General Public * License along with CertiVox MIRACL Crypto SDK. * If not, see . * * You can be released from the requirements of the license by purchasing * a commercial license. Buying such a license is mandatory as soon as you * develop commercial activities involving the CertiVox MIRACL Crypto SDK * without disclosing the source code of your own applications, or shipping * the CertiVox MIRACL Crypto SDK with a closed source product. * * ***************************************************************************/ /* * MIRACL C++ Implementation file zzn3.cpp * * AUTHOR : M. Scott * * PURPOSE : Implementation of class ZZn3 (Arithmetic over n^3) * * WARNING: This class has been cobbled together for a specific use with * the MIRACL library. It is not complete, and may not work in other * applications * * Assumes p=1 mod 3 and p NOT 1 mod 8 * Irreducible is x^3+cnr (cubic non-residue) * */ #include "zzn3.h" using namespace std; // First find a cubic non-residue cnr, which is also a quadratic non-residue // X is precalculated sixth root of unity (cnr)^(p-1)/6 void ZZn3::get(ZZn& x,ZZn& y,ZZn& z) const {copy(fn.a,x.getzzn()); copy(fn.b,y.getzzn()); copy(fn.c,z.getzzn());} void ZZn3::get(ZZn& x) const {{copy(fn.a,x.getzzn());}} ZZn3& ZZn3::operator/=(const ZZn& x) { ZZn t=(ZZn)1/x; zzn3_smul(&fn,t.getzzn(),&fn); return *this; } ZZn3& ZZn3::operator/=(int i) { if (i==2) {zzn3_div2(&fn); return *this;} ZZn t=one()/i; zzn3_smul(&fn,t.getzzn(),&fn); return *this; } ZZn3& ZZn3::operator/=(const ZZn3& x) { *this*=inverse(x); return *this; } ZZn3 inverse(const ZZn3& w) {ZZn3 i=w; zzn3_inv(&i.fn); return i;} ZZn3 operator+(const ZZn3& x,const ZZn3& y) {ZZn3 w=x; w+=y; return w; } ZZn3 operator+(const ZZn3& x,const ZZn& y) {ZZn3 w=x; w+=y; return w; } ZZn3 operator-(const ZZn3& x,const ZZn3& y) {ZZn3 w=x; w-=y; return w; } ZZn3 operator-(const ZZn3& x,const ZZn& y) {ZZn3 w=x; w-=y; return w; } ZZn3 operator-(const ZZn3& x) {ZZn3 w; zzn3_negate((zzn3 *)&x.fn,&w.fn); return w; } ZZn3 operator*(const ZZn3& x,const ZZn3& y) { ZZn3 w=x; if (&x==&y) w*=w; else w*=y; return w; } ZZn3 operator*(const ZZn3& x,const ZZn& y) {ZZn3 w=x; w*=y; return w;} ZZn3 operator*(const ZZn& y,const ZZn3& x) {ZZn3 w=x; w*=y; return w;} ZZn3 operator*(const ZZn3& x,int y) {ZZn3 w=x; w*=y; return w;} ZZn3 operator*(int y,const ZZn3& x) {ZZn3 w=x; w*=y; return w;} ZZn3 operator/(const ZZn3& x,const ZZn3& y) {ZZn3 w=x; w/=y; return w;} ZZn3 operator/(const ZZn3& x,const ZZn& y) {ZZn3 w=x; w/=y; return w;} ZZn3 operator/(const ZZn3& x,int i) {ZZn3 w=x; w/=i; return w;} #ifndef MR_NO_RAND ZZn3 randn3(void) {ZZn3 w; zzn3_from_zzns(randn().getzzn(),randn().getzzn(),randn().getzzn(),&w.fn); return w;} #endif ZZn3 rhs(const ZZn3& x) { ZZn3 w; miracl *mip=get_mip(); int twist=mip->TWIST; int qnr=mip->cnr; // the cubic non-residue is also a quadratic non-residue w=x*x*x; if (twist) { if (twist==MR_QUARTIC_M) { w+=tx((ZZn3)getA())*x; } if (twist==MR_QUARTIC_D) { w+=txd((ZZn3)getA())*x; } if (twist==MR_SEXTIC_M || twist==MR_CUBIC_M) { w+=tx((ZZn3)getB()); } if (twist==MR_SEXTIC_D || twist==MR_CUBIC_D) { w+=txd((ZZn3)getB()); } if (twist==MR_QUADRATIC) { w+=qnr*qnr*getA()*x+(qnr*qnr*qnr)*getB(); } } else { w+=getA()*x+getB(); } return w; } BOOL is_on_curve(const ZZn3& x) { ZZn3 w; if (qr(rhs(x))) return TRUE; return FALSE; } BOOL qr(const ZZn3& x) { Big p=get_modulus(); ZZn3 r,t; t=r=x; t.powq(); r*=t; t.powq(); r*=t; // check x^[(p^3-1)/2] = 1 if (pow(r,(p-1)/2)==1) return TRUE; else return FALSE; } ZZn3 sqrt(const ZZn3& x) { ZZn3 r,w,t; Big p=get_modulus(); if (!qr(x)) return r; // oh boy this is clever! switch (get_mip()->pmod8) { case 5: r=(x+x); r.powq(); w=r*r; t=w*r; w*=t; r.powq(); r*=(w*(x+x)); r=pow(r,(p-5)/8); r*=t; w=r*r; w*=x; w+=w; r*=x; r*=(w-(ZZn)1); break; case 3: case 7: r=x; r.powq(); t=r*r; w=t*r; r.powq(); r*=(w*x); r=pow(r,(p-3)/4); r*=(t*x); break; default: break; } return r; } ZZn3 tx(const ZZn3& w) { ZZn3 u=w; zzn3_timesi(&u.fn); return u; } ZZn3 tx2(const ZZn3& w) { ZZn3 u=w; zzn3_timesi2(&u.fn); return u; } ZZn3 txd(const ZZn3& w) { ZZn3 u; ZZn wa,wb,wc; w.get(wa,wb,wc); u.set(wb,wc,(wa/get_mip()->cnr)); return u; } // regular ZZn3 powering ZZn3 pow(const ZZn3& x,const Big& k) { int i,j,nb,n,nbw,nzs; ZZn3 u,u2,t[16]; if (k==0) return (ZZn3)1; u=x; if (k==1) return u; // // Prepare table for windowing // u2=(u*u); t[0]=u; for (i=1;i<16;i++) t[i]=u2*t[i-1]; // Left to right method - with windows nb=bits(k); if (nb>1) for (i=nb-2;i>=0;) { n=window(k,i,&nbw,&nzs,5); for (j=0;j0) u*=t[n/2]; i-=nbw; if (nzs) { for (j=0;j