/* with GT-Strong curve, now only check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */ int PAIR_GTmember(FP12 *m) { BIG a,b; FP2 X; FP12 r,w; if (FP12_isunity(m)) return 0; FP12_conj(&r,m); FP12_mul(&r,m); if (!FP12_isunity(&r)) return 0; BIG_rcopy(a,CURVE_Fra); BIG_rcopy(b,CURVE_Frb); FP2_from_BIGs(&X,a,b); FP12_copy(&r,m); FP12_frob(&r,&X); FP12_frob(&r,&X); FP12_copy(&w,&r); FP12_frob(&w,&X); FP12_frob(&w,&X); FP12_mul(&w,m); #ifndef GT_STRONG if (!FP12_equals(&w,&r)) return 0; BIG_rcopy(a,CURVE_Bnx); FP12_copy(&r,m); FP12_pow(&w,&r,a); FP12_pow(&w,&w,a); FP12_sqr(&r,&w); FP12_mul(&r,&w); FP12_sqr(&r,&r); FP12_copy(&w,m); FP12_frob(&w,&X); #endif return FP12_equals(&w,&r); }
/* SU= 8 */ void FP12_conj(FP12 *w,FP12 *x) { FP12_copy(w,x); FP4_conj(&(w->a),&(w->a)); FP4_nconj(&(w->b),&(w->b)); FP4_conj(&(w->c),&(w->c)); }
void FP12_pinpow(FP12 *r,int e,int bts) { int i,b; FP12 R[2]; FP12_one(&R[0]); FP12_copy(&R[1],r); for (i=bts-1;i>=0;i--) { b=(e>>i)&1; FP12_mul(&R[1-b],&R[b]); FP12_usqr(&R[b],&R[b]); } FP12_copy(r,&R[0]); }
/* f=f^e */ void PAIR_GTpow(FP12 *f,BIG e) { #ifdef USE_GS_GT /* Note that this option requires a lot of RAM! Maybe better to use compressed XTR method, see fp4.c */ int i,np,nn; FP12 g[4]; FP2 X; BIG t,q,x,y; BIG u[4]; BIG_rcopy(x,CURVE_Fra); BIG_rcopy(y,CURVE_Frb); FP2_from_BIGs(&X,x,y); BIG_rcopy(q,CURVE_Order); gs(u,e); FP12_copy(&g[0],f); for (i=1; i<4; i++) { FP12_copy(&g[i],&g[i-1]); FP12_frob(&g[i],&X); } for (i=0; i<4; i++) { np=BIG_nbits(u[i]); BIG_modneg(t,u[i],q); nn=BIG_nbits(t); if (nn<np) { BIG_copy(u[i],t); FP12_conj(&g[i],&g[i]); } } FP12_pow4(f,g,u); #else FP12_pow(f,f,e); #endif }
void FP12_pow(FP12 *r,FP12 *a,BIG b) { FP12 w; BIG z,zilch; int bt; BIG_zero(zilch); BIG_norm(b); BIG_copy(z,b); FP12_copy(&w,a); FP12_one(r); while(1) { bt=BIG_parity(z); BIG_shr(z,1); if (bt) FP12_mul(r,&w); if (BIG_comp(z,zilch)==0) break; FP12_usqr(&w,&w); } FP12_reduce(r); }
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ void PAIR_fexp(FP12 *r) { FP2 X; BIG x,a,b; FP12 t0,y0,y1,y2,y3; BIG_rcopy(x,CURVE_Bnx); BIG_rcopy(a,CURVE_Fra); BIG_rcopy(b,CURVE_Frb); FP2_from_BIGs(&X,a,b); /* Easy part of final exp */ FP12_inv(&t0,r); FP12_conj(r,r); FP12_mul(r,&t0); FP12_copy(&t0,r); FP12_frob(r,&X); FP12_frob(r,&X); FP12_mul(r,&t0); /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */ #if CHOICE<BLS_CURVES FP12_pow(&t0,r,x); // t0=f^-u FP12_usqr(&y3,&t0); // y3=t0^2 FP12_copy(&y0,&t0); FP12_mul(&y0,&y3); // y0=t0*y3 FP12_copy(&y2,&y3); FP12_frob(&y2,&X); // y2=y3^p FP12_mul(&y2,&y3); //y2=y2*y3 FP12_usqr(&y2,&y2); //y2=y2^2 FP12_mul(&y2,&y3); // y2=y2*y3 FP12_pow(&t0,&y0,x); //t0=y0^-u FP12_conj(&y0,r); //y0=~r FP12_copy(&y1,&t0); FP12_frob(&y1,&X); FP12_frob(&y1,&X); //y1=t0^p^2 FP12_mul(&y1,&y0); // y1=y0*y1 FP12_conj(&t0,&t0); // t0=~t0 FP12_copy(&y3,&t0); FP12_frob(&y3,&X); //y3=t0^p FP12_mul(&y3,&t0); // y3=t0*y3 FP12_usqr(&t0,&t0); // t0=t0^2 FP12_mul(&y1,&t0); // y1=t0*y1 FP12_pow(&t0,&y3,x); // t0=y3^-u FP12_usqr(&t0,&t0); //t0=t0^2 FP12_conj(&t0,&t0); //t0=~t0 FP12_mul(&y3,&t0); // y3=t0*y3 FP12_frob(r,&X); FP12_copy(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_usqr(r,&y3); //r=y3^2 FP12_mul(r,&y2); //r=y2*r FP12_copy(&y3,r); FP12_mul(&y3,&y0); // y3=r*y0 FP12_mul(r,&y1); // r=r*y1 FP12_usqr(r,r); // r=r^2 FP12_mul(r,&y3); // r=r*y3 FP12_reduce(r); #else // Ghamman & Fouotsa Method FP12_usqr(&y0,r); FP12_pow(&y1,&y0,x); BIG_fshr(x,1); FP12_pow(&y2,&y1,x); BIG_fshl(x,1); // x must be even FP12_conj(&y3,r); FP12_mul(&y1,&y3); FP12_conj(&y1,&y1); FP12_mul(&y1,&y2); FP12_pow(&y2,&y1,x); FP12_pow(&y3,&y2,x); FP12_conj(&y1,&y1); FP12_mul(&y3,&y1); FP12_conj(&y1,&y1); FP12_frob(&y1,&X); FP12_frob(&y1,&X); FP12_frob(&y1,&X); FP12_frob(&y2,&X); FP12_frob(&y2,&X); FP12_mul(&y1,&y2); FP12_pow(&y2,&y3,x); FP12_mul(&y2,&y0); FP12_mul(&y2,r); FP12_mul(&y1,&y2); FP12_copy(&y2,&y3); FP12_frob(&y2,&X); FP12_mul(&y1,&y2); FP12_copy(r,&y1); FP12_reduce(r); // Aranha et al method as described by Ghamman & Fouotsa /* FP12_usqr(&y0,r); // t0=f^2 FP12_conj(&y3,&y0); // t0=f^-2 FP12_pow(&t0,r,x); // t5=f^u FP12_usqr(&y1,&t0); // t1=t5^2 FP12_mul(&y3,&t0); // t3=t0*t5 FP12_pow(&y0,&y3,x); FP12_pow(&y2,&y0,x); FP12_pow(&y4,&y2,x); FP12_mul(&y4,&y1); FP12_pow(&y1,&y4,x); FP12_conj(&y3,&y3); FP12_mul(&y1,&y3); FP12_mul(&y1,r); FP12_conj(&y3,r); FP12_mul(&y0,r); FP12_frob(&y0,&X); FP12_frob(&y0,&X); FP12_frob(&y0,&X); FP12_mul(&y4,&y3); FP12_frob(&y4,&X); FP12_mul(&t0,&y2); FP12_frob(&t0,&X); FP12_frob(&t0,&X); FP12_mul(&t0,&y0); FP12_mul(&t0,&y4); FP12_mul(&t0,&y1); FP12_copy(r,&t0); FP12_reduce(r);*/ //----------------------------------- /* FP12_copy(&y0,r); // y0=r; FP12_copy(&y1,r); // y1=r; FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_conj(&y3,&t0); FP12_mul(&y1,&y3); // y1*=inverse(t0); FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(t0,X,2); FP12_mul(&y1,&t0); // y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); FP12_conj(&y3,r); FP12_mul(&y1,&y3); // y1*=inverse(r); FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_mul(&y0,&t0); // y0*=t0; FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_mul(&y1,&t0); // y1*=t0; FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); FP12_pow(r,r,x); // r=pow(r,x); FP12_mul(&y0,r); // y0*=r; FP12_copy(&t0,r); FP12_frob(&t0,&X); FP12_frob(&t0,&X); // t0=Frobenius(r,X,2); FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_mul(&y1,&t0); // y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); // r^x3 FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_conj(&y3,&t0); FP12_mul(&y0,&y3); // y0*=inverse(t0); FP12_frob(&t0,&X); // t0=Frobenius(t0,X,1); FP12_mul(&y1,&t0); // y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); // r^x4 FP12_conj(&y3,r); FP12_mul(&y0,&y3); // y0*=inverse(r); FP12_copy(&t0,r); FP12_frob(&t0,&X); // t0=Frobenius(r,X,1); FP12_mul(&y1,&t0); //y1*=t0; FP12_pow(r,r,x); // r=pow(r,x); // r^x5 FP12_mul(&y1,r); // y1*=r; FP12_usqr(&y0,&y0); // r=y0*y0*y1; FP12_mul(&y0,&y1); FP12_copy(r,&y0); FP12_reduce(r); */ #endif }
void FP12_pow4(FP12 *p,FP12 *q,BIG u[4]) { int i,j,a[4],nb,m; FP12 g[8],c,s[2]; BIG t[4],mt; sign8 w[NLEN*BASEBITS+1]; for (i=0;i<4;i++) BIG_copy(t[i],u[i]); FP12_copy(&g[0],&q[0]); FP12_conj(&s[0],&q[1]); FP12_mul(&g[0],&s[0]); /* P/Q */ FP12_copy(&g[1],&g[0]); FP12_copy(&g[2],&g[0]); FP12_copy(&g[3],&g[0]); FP12_copy(&g[4],&q[0]); FP12_mul(&g[4],&q[1]); /* P*Q */ FP12_copy(&g[5],&g[4]); FP12_copy(&g[6],&g[4]); FP12_copy(&g[7],&g[4]); FP12_copy(&s[1],&q[2]); FP12_conj(&s[0],&q[3]); FP12_mul(&s[1],&s[0]); /* R/S */ FP12_conj(&s[0],&s[1]); FP12_mul(&g[1],&s[0]); FP12_mul(&g[2],&s[1]); FP12_mul(&g[5],&s[0]); FP12_mul(&g[6],&s[1]); FP12_copy(&s[1],&q[2]); FP12_mul(&s[1],&q[3]); /* R*S */ FP12_conj(&s[0],&s[1]); FP12_mul(&g[0],&s[0]); FP12_mul(&g[3],&s[1]); FP12_mul(&g[4],&s[0]); FP12_mul(&g[7],&s[1]); /* if power is even add 1 to power, and add q to correction */ FP12_one(&c); BIG_zero(mt); for (i=0;i<4;i++) { if (BIG_parity(t[i])==0) { BIG_inc(t[i],1); BIG_norm(t[i]); FP12_mul(&c,&q[i]); } BIG_add(mt,mt,t[i]); BIG_norm(mt); } FP12_conj(&c,&c); nb=1+BIG_nbits(mt); /* convert exponent to signed 1-bit window */ for (j=0;j<nb;j++) { for (i=0;i<4;i++) { a[i]=BIG_lastbits(t[i],2)-2; BIG_dec(t[i],a[i]); BIG_norm(t[i]); BIG_fshr(t[i],1); } w[j]=8*a[0]+4*a[1]+2*a[2]+a[3]; } w[nb]=8*BIG_lastbits(t[0],2)+4*BIG_lastbits(t[1],2)+2*BIG_lastbits(t[2],2)+BIG_lastbits(t[3],2); FP12_copy(p,&g[(w[nb]-1)/2]); for (i=nb-1;i>=0;i--) { m=w[i]>>7; j=(w[i]^m)-m; /* j=abs(w[i]) */ j=(j-1)/2; FP12_copy(&s[0],&g[j]); FP12_conj(&s[1],&g[j]); FP12_usqr(p,p); FP12_mul(p,&s[m&1]); } FP12_mul(p,&c); /* apply correction */ FP12_reduce(p); }
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ void PAIR_fexp(FP12 *r) { FP2 X; BIG x,a,b; FP12 t0,y0,y1,y2,y3; BIG_rcopy(x,CURVE_Bnx); BIG_rcopy(a,CURVE_Fra); BIG_rcopy(b,CURVE_Frb); FP2_from_BIGs(&X,a,b); /* Easy part of final exp */ FP12_inv(&t0,r); FP12_conj(r,r); FP12_mul(r,&t0); FP12_copy(&t0,r); FP12_frob(r,&X); FP12_frob(r,&X); FP12_mul(r,&t0); /* Hard part of final exp - see Duquesne & Ghamman eprint 2015/192.pdf */ FP12_pow(&t0,r,x); // t0=f^-u FP12_usqr(&y3,&t0); // y3=t0^2 FP12_copy(&y0,&t0); FP12_mul(&y0,&y3); // y0=t0*y3 FP12_copy(&y2,&y3); FP12_frob(&y2,&X); // y2=y3^p FP12_mul(&y2,&y3); //y2=y2*y3 FP12_usqr(&y2,&y2); //y2=y2^2 FP12_mul(&y2,&y3); // y2=y2*y3 FP12_pow(&t0,&y0,x); //t0=y0^-u FP12_conj(&y0,r); //y0=~r FP12_copy(&y1,&t0); FP12_frob(&y1,&X); FP12_frob(&y1,&X); //y1=t0^p^2 FP12_mul(&y1,&y0); // y1=y0*y1 FP12_conj(&t0,&t0); // t0=~t0 FP12_copy(&y3,&t0); FP12_frob(&y3,&X); //y3=t0^p FP12_mul(&y3,&t0); // y3=t0*y3 FP12_usqr(&t0,&t0); // t0=t0^2 FP12_mul(&y1,&t0); // y1=t0*y1 FP12_pow(&t0,&y3,x); // t0=y3^-u FP12_usqr(&t0,&t0); //t0=t0^2 FP12_conj(&t0,&t0); //t0=~t0 FP12_mul(&y3,&t0); // y3=t0*y3 FP12_frob(r,&X); FP12_copy(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_frob(r,&X); FP12_mul(&y0,r); FP12_usqr(r,&y3); //r=y3^2 FP12_mul(r,&y2); //r=y2*r FP12_copy(&y3,r); FP12_mul(&y3,&y0); // y3=r*y0 FP12_mul(r,&y1); // r=r*y1 FP12_usqr(r,r); // r=r^2 FP12_mul(r,&y3); // r=r*y3 FP12_reduce(r); /* our way */ /* // FP12 lv,x0,x1,x2,x3,x4,x5; FP12_copy(&lv,r); FP12_frob(&lv,&X); FP12_copy(&x0,&lv); FP12_frob(&x0,&X); FP12_mul(&lv,r); FP12_mul(&x0,&lv); FP12_frob(&x0,&X); FP12_conj(&x1,r); FP12_pow(&x4,r,x); FP12_copy(&x3,&x4); FP12_frob(&x3,&X); FP12_pow(&x2,&x4,x); FP12_conj(&x5,&x2); FP12_pow(&lv,&x2,x); FP12_frob(&x2,&X); FP12_conj(r,&x2); FP12_mul(&x4,r); FP12_frob(&x2,&X); FP12_copy(r,&lv); FP12_frob(r,&X); FP12_mul(&lv,r); FP12_usqr(&lv,&lv); FP12_mul(&lv,&x4); FP12_mul(&lv,&x5); FP12_copy(r,&x3); FP12_mul(r,&x5); FP12_mul(r,&lv); FP12_mul(&lv,&x2); FP12_usqr(r,r); FP12_mul(r,&lv); FP12_usqr(r,r); FP12_copy(&lv,r); FP12_mul(&lv,&x1); FP12_mul(r,&x0); FP12_usqr(&lv,&lv); FP12_mul(r,&lv); FP12_reduce(r); */ }