/* #if CHOICE==BN254_T const BIG TEST_Gx={0x18AFF11A,0xF2EF406,0xAF68220,0x171F2E27,0x6BA0959,0x124C50E0,0x450BE27,0x7003EA8,0x8A914}; const BIG TEST_Gy={0x6E010F4,0xA71D07E,0x7ECADA8,0x8260E8E,0x1F79C328,0x17A09412,0xBFAE690,0x1C57CBD1,0x17DF54}; const BIG TEST_Pxa={0x1047D566,0xD83CD71,0x10322E9D,0x991FA93,0xA282C48,0x18AEBEC8,0xCB05850,0x13B4F669,0x21794A}; const BIG TEST_Pxb={0x1E305936,0x16885BF1,0x327060,0xE26F794,0x1547D870,0x1963E5B2,0x1BEBB96C,0x988A33C,0x1A9B47}; const BIG TEST_Pya={0x20FF876,0x4427E67,0x18732211,0xE88E45E,0x174D1A7E,0x17D877ED,0x343AB37,0x97EB453,0xB00D5}; const BIG TEST_Pyb={0x1D746B7B,0x732F4C2,0x122A49B0,0x16267985,0x235DF56,0x10B1E4D,0x14D8F210,0x17A05C3E,0x5ECF8}; #endif #if CHOICE==BN254_T2 const BIG TEST_Gx={0x15488765,0x46790D7,0xD9900A,0x1DFB43F,0x9F2D307,0xC4724E8,0x5678E51,0x15C3E3A7,0x1BEC8E}; const BIG TEST_Gy={0x3D3273C,0x1AFA5FF,0x1880A139,0xACD34DF,0x17493067,0x10FA4103,0x1D4C9766,0x1A73F3DB,0x2D148}; const BIG TEST_Pxa={0xF8DC275,0xAC27FA,0x11815151,0x152691C8,0x5CDEBF1,0x7D5A965,0x1BF70CE3,0x679A1C8,0xD62CF}; const BIG TEST_Pxb={0x1D17D7A8,0x6B28DF4,0x174A0389,0xFE67E5F,0x1FA97A3C,0x7F5F473,0xFFB5146,0x4BC19A5,0x227010}; const BIG TEST_Pya={0x16CC1F90,0x5284627,0x171B91AB,0x11F843B9,0x1D468755,0x67E279C,0x19FE0EF8,0x1A0CAA6B,0x1CC6CB}; const BIG TEST_Pyb={0x1FF0CF2A,0xBC83255,0x6DD6EE8,0xB8B752F,0x13E484EC,0x1809BE81,0x1A648AA1,0x8CEF3F3,0x86EE}; #endif #if CHOICE==BN254 const BIG TEST_Gx={0x14BEC4670E4EB7,0xEA2973860F6861,0x35C14B2FC3C28F,0x4402A0B63B9473,0x2074A81D}; const BIG TEST_Gy={0xC284846631CBEB,0x34A6E8D871B3B,0x89FB94A82B2006,0x87B20038771FC,0x6A41108}; const BIG TEST_Pxa={0xE4A00F52183C77,0x554E02DF4F8354,0xB65EB5CF1C2F89,0x8B71A87BFCFC9,0x49EEDB1}; const BIG TEST_Pxb={0xCFB8FA9AA8845D,0x8A9CC76D966697,0x185BA05BF5EC08,0x76140E87D97226,0x1FB93AB6}; const BIG TEST_Pya={0x3644CC1EDF208A,0xA637FB3FF8E257,0x4453DA2BB9E686,0xD14AD3CDF6A1FE,0xCD04A1E}; const BIG TEST_Pyb={0x71BD7630A43C14,0x1CAA9F14EA264E,0x3C3C2DFC765DEF,0xCF59D1A1A7D6EE,0x11FF7795}; #endif */ int main() { int i; char byt[32]; csprng rng; BIG xa,xb,ya,yb,w,a,b,t1,q,u[2],v[4],m,r; ECP2 P,G; ECP Q,R; FP12 g,gp; FP4 t,c,cp,cpm1,cpm2; FP2 x,y,X; BIG_rcopy(a,CURVE_Fra); BIG_rcopy(b,CURVE_Frb); FP2_from_BIGs(&X,a,b); BIG_rcopy(xa,CURVE_Gx); BIG_rcopy(ya,CURVE_Gy); ECP_set(&Q,xa,ya); if (Q.inf) printf("Failed to set - point not on curve\n"); else printf("G1 set success\n"); printf("Q= "); ECP_output(&Q); printf("\n"); // BIG_rcopy(r,CURVE_Order); BIG_dec(r,7); BIG_norm(r); BIG_rcopy(xa,CURVE_Pxa); BIG_rcopy(xb,CURVE_Pxb); BIG_rcopy(ya,CURVE_Pya); BIG_rcopy(yb,CURVE_Pyb); FP2_from_BIGs(&x,xa,xb); FP2_from_BIGs(&y,ya,yb); ECP2_set(&P,&x,&y); if (P.inf) printf("Failed to set - point not on curve\n"); else printf("G2 set success\n"); printf("P= "); ECP2_output(&P); printf("\n"); for (i=0; i<1000; i++ ) { PAIR_ate(&g,&P,&Q); PAIR_fexp(&g); // PAIR_GTpow(&g,xa); } printf("g= "); FP12_output(&g); printf("\n"); }
/* 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); }
/* needed for SOK */ static void mapit2(octet *h,ECP2 *Q) { BIG q,one,Fx,Fy,x,hv; FP2 X; ECP2 T,K; BIG_fromBytes(hv,h->val); BIG_rcopy(q,Modulus); BIG_one(one); BIG_mod(hv,q); for (;;) { FP2_from_BIGs(&X,one,hv); if (ECP2_setx(Q,&X)) break; BIG_inc(hv,1); } /* Fast Hashing to G2 - Fuentes-Castaneda, Knapp and Rodriguez-Henriquez */ BIG_rcopy(Fx,CURVE_Fra); BIG_rcopy(Fy,CURVE_Frb); FP2_from_BIGs(&X,Fx,Fy); BIG_rcopy(x,CURVE_Bnx); ECP2_copy(&T,Q); ECP2_mul(&T,x); ECP2_neg(&T); /* our x is negative */ ECP2_copy(&K,&T); ECP2_dbl(&K); ECP2_add(&K,&T); ECP2_affine(&K); ECP2_frob(&K,&X); ECP2_frob(Q,&X); ECP2_frob(Q,&X); ECP2_frob(Q,&X); ECP2_add(Q,&T); ECP2_add(Q,&K); ECP2_frob(&T,&X); ECP2_frob(&T,&X); ECP2_add(Q,&T); ECP2_affine(Q); }
/* Multiply P by e in group G2 */ void PAIR_G2mul(ECP2 *P,BIG e) { #ifdef USE_GS_G2 /* Well I didn't patent it :) */ int i,np,nn; ECP2 Q[4]; FP2 X; BIG x,y; BIG u[4]; BIG_rcopy(x,CURVE_Fra); BIG_rcopy(y,CURVE_Frb); FP2_from_BIGs(&X,x,y); BIG_rcopy(y,CURVE_Order); gs(u,e); ECP2_affine(P); ECP2_copy(&Q[0],P); for (i=1; i<4; i++) { ECP2_copy(&Q[i],&Q[i-1]); ECP2_frob(&Q[i],&X); } for (i=0; i<4; i++) { np=BIG_nbits(u[i]); BIG_modneg(x,u[i],y); nn=BIG_nbits(x); if (nn<np) { BIG_copy(u[i],x); ECP2_neg(&Q[i]); } } ECP2_mul4(P,Q,u); #else ECP2_mul(P,e); #endif }
/* 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 }
/* Optimal R-ate pairing r=e(P,Q) */ void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q) { FP2 X; BIG x,n,Qx,Qy; int i,nb; ECP2 A; FP12 lv; #if CHOICE<BLS_CURVES ECP2 KA; #endif BIG_rcopy(Qx,CURVE_Fra); BIG_rcopy(Qy,CURVE_Frb); FP2_from_BIGs(&X,Qx,Qy); BIG_rcopy(x,CURVE_Bnx); #if CHOICE<BLS_CURVES BIG_pmul(n,x,6); BIG_dec(n,2); #else BIG_copy(n,x); #endif BIG_norm(n); ECP2_affine(P); ECP_affine(Q); BIG_copy(Qx,Q->x); BIG_copy(Qy,Q->y); ECP2_copy(&A,P); FP12_one(r); nb=BIG_nbits(n); /* Main Miller Loop */ for (i=nb-2; i>=1; i--) { PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); if (BIG_bit(n,i)) { PAIR_line(&lv,&A,P,Qx,Qy); FP12_smul(r,&lv); } FP12_sqr(r,r); } PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); if (BIG_parity(n)) { PAIR_line(&lv,&A,P,Qx,Qy); FP12_smul(r,&lv); } /* R-ate fixup required for BN curves */ #if CHOICE<BLS_CURVES ECP2_copy(&KA,P); ECP2_frob(&KA,&X); ECP2_neg(&A); FP12_conj(r,r); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); ECP2_frob(&KA,&X); ECP2_neg(&KA); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); #endif }
/* 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 }
/* Optimal R-ate pairing r=e(P,Q) */ void PAIR_ate(FP12 *r,ECP2 *P,ECP *Q) { FP2 X; BIG x,n,Qx,Qy; int i,nb; ECP2 A,KA; FP12 lv; BIG_rcopy(Qx,CURVE_Fra); BIG_rcopy(Qy,CURVE_Frb); FP2_from_BIGs(&X,Qx,Qy); BIG_rcopy(x,CURVE_Bnx); BIG_pmul(n,x,6); BIG_dec(n,2); BIG_norm(n); ECP2_affine(P); ECP_affine(Q); BIG_copy(Qx,Q->x); BIG_copy(Qy,Q->y); ECP2_copy(&A,P); FP12_one(r); nb=BIG_nbits(n); /* Main Miller Loop */ for (i=nb-2;i>=1;i--) { PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); if (BIG_bit(n,i)) { PAIR_line(&lv,&A,P,Qx,Qy); FP12_smul(r,&lv); } FP12_sqr(r,r); } PAIR_line(&lv,&A,&A,Qx,Qy); FP12_smul(r,&lv); /* R-ate fixup */ ECP2_copy(&KA,P); ECP2_frob(&KA,&X); ECP2_neg(&A); FP12_conj(r,r); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); ECP2_frob(&KA,&X); ECP2_neg(&KA); PAIR_line(&lv,&A,&KA,Qx,Qy); FP12_smul(r,&lv); }
/* 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); */ }