MastersThesis/TIIGER_TLS/PQ_TIIGER_TLS/sal/miracl-ubuntu22-11-04-24/includes/pair.cpp
2024-04-15 11:53:30 +02:00

1234 lines
27 KiB
C++

/*
* Copyright (c) 2012-2020 MIRACL UK Ltd.
*
* This file is part of MIRACL Core
* (see https://github.com/miracl/core).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* CORE BN Curve pairing functions */
//#define HAS_MAIN
#include "pair_ZZZ.h"
using namespace XXX;
using namespace YYY;
namespace ZZZ {
static void PAIR_line(FP12 *, ECP2 *, ECP2 *, FP *, FP *);
static void PAIR_double(ECP2 *, FP2 *, FP2 *, FP2 *);
static void PAIR_add(ECP2 *, ECP2 *B, FP2 *, FP2 *, FP2 *);
static void PAIR_pack(FP4 *, FP2 *, FP2 *, FP2 *);
static void PAIR_unpack(FP12 *, FP4 *, FP *, FP *);
static void glv(BIG u[2], BIG);
static void gs(BIG u[4], BIG);
}
// Point doubling for pairings
static void ZZZ::PAIR_double(ECP2 *A, FP2 *AA, FP2 *BB, FP2 *CC)
{
FP2 YY;
FP2_copy(CC, &(A->x)); //FP2 XX=new FP2(A.getx()); //X
FP2_copy(&YY, &(A->y)); //FP2 YY=new FP2(A.gety()); //Y
FP2_copy(BB, &(A->z)); //FP2 ZZ=new FP2(A.getz()); //Z
FP2_copy(AA, &YY); //FP2 YZ=new FP2(YY); //Y
FP2_mul(AA, AA, BB); //YZ.mul(ZZ); //YZ
FP2_sqr(CC, CC); //XX.sqr(); //X^2
FP2_sqr(&YY, &YY); //YY.sqr(); //Y^2
FP2_sqr(BB, BB); //ZZ.sqr(); //Z^2
FP2_add(AA, AA, AA);
FP2_neg(AA, AA);
FP2_norm(AA); // -2YZ
FP2_mul_ip(AA);
FP2_norm(AA); // -2YZi
FP2_imul(BB, BB, 3 * CURVE_B_I); //3Bz^2
FP2_imul(CC, CC, 3); //3X^2
#if SEXTIC_TWIST_ZZZ==D_TYPE
FP2_mul_ip(&YY); // Y^2.i
FP2_norm(&YY);
FP2_mul_ip(CC); // 3X^2.i
FP2_norm(CC);
#endif
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_mul_ip(BB); // 3Bz^2.i
FP2_norm(BB);
#endif
FP2_sub(BB, BB, &YY);
FP2_norm(BB);
ECP2_dbl(A); //A.dbl();
}
// Point addition for pairings
static void ZZZ::PAIR_add(ECP2 *A, ECP2 *B, FP2 *AA, FP2 *BB, FP2 *CC)
{
FP2 T1;
FP2_copy(AA, &(A->x)); //FP2 X1=new FP2(A.getx()); // X1
FP2_copy(CC, &(A->y)); //FP2 Y1=new FP2(A.gety()); // Y1
FP2_copy(&T1, &(A->z)); //FP2 T1=new FP2(A.getz()); // Z1
FP2_copy(BB, &T1); //FP2 T2=new FP2(A.getz()); // Z1
FP2_mul(&T1, &T1, &(B->y)); //T1.mul(B.gety()); // T1=Z1.Y2
FP2_mul(BB, BB, &(B->x)); //T2.mul(B.getx()); // T2=Z1.X2
FP2_sub(AA, AA, BB); //X1.sub(T2);
FP2_norm(AA); //X1.norm(); // X1=X1-Z1.X2
FP2_sub(CC, CC, &T1); //Y1.sub(T1);
FP2_norm(CC); //Y1.norm(); // Y1=Y1-Z1.Y2
FP2_copy(&T1, AA); //T1.copy(X1); // T1=X1-Z1.X2
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_mul_ip(AA);
FP2_norm(AA);
#endif
FP2_mul(&T1, &T1, &(B->y)); //T1.mul(B.gety()); // T1=(X1-Z1.X2).Y2
FP2_copy(BB, CC); //T2.copy(Y1); // T2=Y1-Z1.Y2
FP2_mul(BB, BB, &(B->x)); //T2.mul(B.getx()); // T2=(Y1-Z1.Y2).X2
FP2_sub(BB, BB, &T1); //T2.sub(T1);
FP2_norm(BB); //T2.norm(); // T2=(Y1-Z1.Y2).X2 - (X1-Z1.X2).Y2
FP2_neg(CC, CC); //Y1.neg();
FP2_norm(CC); //Y1.norm(); // Y1=-(Y1-Z1.Y2).Xs - ***
ECP2_add(A, B); //A.add(B);
}
/* Line function */
static void ZZZ::PAIR_line(FP12 *v, ECP2 *A, ECP2 *B, FP *Qx, FP *Qy)
{
FP2 AA, BB, CC;
FP4 a, b, c;
if (A == B)
PAIR_double(A, &AA, &BB, &CC);
else
PAIR_add(A, B, &AA, &BB, &CC);
FP2_pmul(&CC, &CC, Qx);
FP2_pmul(&AA, &AA, Qy);
FP4_from_FP2s(&a, &AA, &BB);
#if SEXTIC_TWIST_ZZZ==D_TYPE
FP4_from_FP2(&b, &CC);
FP4_zero(&c);
#endif
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP4_zero(&b);
FP4_from_FP2H(&c, &CC);
#endif
FP12_from_FP4s(v, &a, &b, &c);
v->type = FP_SPARSER;
}
/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
int ZZZ::PAIR_nbits(BIG n3, BIG n)
{
BIG x;
BIG_rcopy(x, CURVE_Bnx);
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
BIG_pmul(n, x, 6);
#if SIGN_OF_X_ZZZ==POSITIVEX
BIG_inc(n, 2);
#else
BIG_dec(n, 2);
#endif
#else
BIG_copy(n, x);
#endif
BIG_norm(n);
BIG_pmul(n3, n, 3);
BIG_norm(n3);
return BIG_nbits(n3);
}
/*
For multi-pairing, product of n pairings
1. Declare FP12 array of length number of bits in Ate parameter
2. Initialise this array by calling PAIR_initmp()
3. Accumulate each pairing by calling PAIR_another() n times
4. Call PAIR_miller()
5. Call final exponentiation PAIR_fexp()
*/
/* prepare for multi-pairing */
void ZZZ::PAIR_initmp(FP12 r[])
{
int i;
for (i = ATE_BITS_ZZZ - 1; i >= 0; i--)
FP12_one(&r[i]);
return;
}
/* basic Miller loop */
void ZZZ::PAIR_miller(FP12 *res, FP12 r[])
{
int i;
FP12_one(res);
for (i = ATE_BITS_ZZZ - 1; i >= 1; i--)
{
FP12_sqr(res, res);
FP12_ssmul(res, &r[i]);
FP12_zero(&r[i]);
}
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(res, res);
#endif
FP12_ssmul(res, &r[0]);
FP12_zero(&r[0]);
return;
}
// Store precomputed line details in an FP4
static void ZZZ::PAIR_pack(FP4 *T, FP2* AA, FP2* BB, FP2 *CC)
{
FP2 I, A, B;
FP2_inv(&I, CC, NULL);
FP2_mul(&A, AA, &I);
FP2_mul(&B, BB, &I);
FP4_from_FP2s(T, &A, &B);
}
// Unpack G2 line function details and include G1
static void ZZZ::PAIR_unpack(FP12 *v, FP4* T, FP *Qx, FP *Qy)
{
FP4 a, b, c;
FP2 t;
FP4_copy(&a, T);
FP2_pmul(&a.a, &a.a, Qy);
FP2_from_FP(&t, Qx);
#if SEXTIC_TWIST_ZZZ==D_TYPE
FP4_from_FP2(&b, &t);
FP4_zero(&c);
#endif
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP4_zero(&b);
FP4_from_FP2H(&c, &t);
#endif
FP12_from_FP4s(v, &a, &b, &c);
v->type = FP_SPARSEST;
}
// Precompute table of line functions for fixed G2 value
void ZZZ::PAIR_precomp(FP4 T[], ECP2* GV)
{
int i, j, nb, bt;
BIG n, n3;
FP2 AA, BB, CC;
ECP2 A, G, NG;
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
ECP2 K;
FP2 X;
FP Qx, Qy;
FP_rcopy(&Qx, Fra);
FP_rcopy(&Qy, Frb);
FP2_from_FPs(&X, &Qx, &Qy);
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_inv(&X, &X, NULL);
FP2_norm(&X);
#endif
#endif
ECP2_copy(&A, GV);
ECP2_copy(&G, GV);
ECP2_copy(&NG, GV);
ECP2_neg(&NG);
nb = PAIR_nbits(n3, n);
j = 0;
for (i = nb - 2; i >= 1; i--)
{
PAIR_double(&A, &AA, &BB, &CC);
PAIR_pack(&T[j++], &AA, &BB, &CC);
bt = BIG_bit(n3, i) - BIG_bit(n, i); // bt=BIG_bit(n,i);
if (bt == 1)
{
PAIR_add(&A, &G, &AA, &BB, &CC);
PAIR_pack(&T[j++], &AA, &BB, &CC);
}
if (bt == -1)
{
PAIR_add(&A, &NG, &AA, &BB, &CC);
PAIR_pack(&T[j++], &AA, &BB, &CC);
}
}
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
#if SIGN_OF_X_ZZZ==NEGATIVEX
ECP2_neg(&A);
#endif
ECP2_copy(&K, &G);
ECP2_frob(&K, &X);
PAIR_add(&A, &K, &AA, &BB, &CC);
PAIR_pack(&T[j++], &AA, &BB, &CC);
ECP2_frob(&K, &X);
ECP2_neg(&K);
PAIR_add(&A, &K, &AA, &BB, &CC);
PAIR_pack(&T[j++], &AA, &BB, &CC);
#endif
}
/* Accumulate another set of line functions for n-pairing, assuming precomputation on G2 */
void ZZZ::PAIR_another_pc(FP12 r[], FP4 T[], ECP *QV)
{
int i, j, nb, bt;
BIG n, n3;
FP12 lv, lv2;
ECP Q;
FP Qx, Qy;
if (ECP_isinf(QV)) return;
nb = PAIR_nbits(n3, n);
ECP_copy(&Q, QV);
ECP_affine(&Q);
FP_copy(&Qx, &(Q.x));
FP_copy(&Qy, &(Q.y));
j = 0;
for (i = nb - 2; i >= 1; i--)
{
PAIR_unpack(&lv, &T[j++], &Qx, &Qy);
bt = BIG_bit(n3, i) - BIG_bit(n, i); // bt=BIG_bit(n,i);
if (bt == 1)
{
PAIR_unpack(&lv2, &T[j++], &Qx, &Qy);
FP12_smul(&lv, &lv2);
}
if (bt == -1)
{
PAIR_unpack(&lv2, &T[j++], &Qx, &Qy);
FP12_smul(&lv, &lv2);
}
FP12_ssmul(&r[i], &lv);
}
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
PAIR_unpack(&lv, &T[j++], &Qx, &Qy);
PAIR_unpack(&lv2, &T[j++], &Qx, &Qy);
FP12_smul(&lv, &lv2);
FP12_ssmul(&r[0], &lv);
#endif
}
/* Accumulate another set of line functions for n-pairing */
void ZZZ::PAIR_another(FP12 r[], ECP2* PV, ECP* QV)
{
int i, nb, bt;
BIG n, n3;
FP12 lv, lv2;
ECP2 A, NP, P;
ECP Q;
FP Qx, Qy;
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
ECP2 K;
FP2 X;
FP_rcopy(&Qx, Fra);
FP_rcopy(&Qy, Frb);
FP2_from_FPs(&X, &Qx, &Qy);
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_inv(&X, &X, NULL);
FP2_norm(&X);
#endif
#endif
if (ECP_isinf(QV)) return;
nb = PAIR_nbits(n3, n);
ECP2_copy(&P, PV);
ECP_copy(&Q, QV);
ECP2_affine(&P);
ECP_affine(&Q);
FP_copy(&Qx, &(Q.x));
FP_copy(&Qy, &(Q.y));
ECP2_copy(&A, &P);
ECP2_copy(&NP, &P); ECP2_neg(&NP);
for (i = nb - 2; i >= 1; i--)
{
PAIR_line(&lv, &A, &A, &Qx, &Qy);
bt = BIG_bit(n3, i) - BIG_bit(n, i); // bt=BIG_bit(n,i);
if (bt == 1)
{
PAIR_line(&lv2, &A, &P, &Qx, &Qy);
FP12_smul(&lv, &lv2);
}
if (bt == -1)
{
PAIR_line(&lv2, &A, &NP, &Qx, &Qy);
FP12_smul(&lv, &lv2);
}
FP12_ssmul(&r[i], &lv);
}
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
#if SIGN_OF_X_ZZZ==NEGATIVEX
ECP2_neg(&A);
#endif
ECP2_copy(&K, &P);
ECP2_frob(&K, &X);
PAIR_line(&lv, &A, &K, &Qx, &Qy);
ECP2_frob(&K, &X);
ECP2_neg(&K);
PAIR_line(&lv2, &A, &K, &Qx, &Qy);
FP12_smul(&lv, &lv2);
FP12_ssmul(&r[0], &lv);
#endif
}
/* Optimal single R-ate pairing r=e(P,Q) */
void ZZZ::PAIR_ate(FP12 *r, ECP2 *P1, ECP *Q1)
{
BIG n, n3;
FP Qx, Qy;
int i, nb, bt;
ECP2 A, NP, P;
ECP Q;
FP12 lv, lv2;
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
ECP2 KA;
FP2 X;
FP_rcopy(&Qx, Fra);
FP_rcopy(&Qy, Frb);
FP2_from_FPs(&X, &Qx, &Qy);
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_inv(&X, &X, NULL);
FP2_norm(&X);
#endif
#endif
FP12_one(r);
if (ECP_isinf(Q1)) return;
nb = PAIR_nbits(n3, n);
ECP2_copy(&P, P1);
ECP_copy(&Q, Q1);
ECP2_affine(&P);
ECP_affine(&Q);
FP_copy(&Qx, &(Q.x));
FP_copy(&Qy, &(Q.y));
ECP2_copy(&A, &P);
ECP2_copy(&NP, &P); ECP2_neg(&NP);
/* Main Miller Loop */
for (i = nb - 2; i >= 1; i--)
{
FP12_sqr(r, r);
PAIR_line(&lv, &A, &A, &Qx, &Qy);
bt = BIG_bit(n3, i) - BIG_bit(n, i); // bt=BIG_bit(n,i);
if (bt == 1)
{
PAIR_line(&lv2, &A, &P, &Qx, &Qy);
FP12_smul(&lv, &lv2);
}
if (bt == -1)
{
PAIR_line(&lv2, &A, &NP, &Qx, &Qy);
FP12_smul(&lv, &lv2);
}
FP12_ssmul(r, &lv);
}
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(r, r);
#endif
/* R-ate fixup required for BN curves */
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
#if SIGN_OF_X_ZZZ==NEGATIVEX
ECP2_neg(&A);
#endif
ECP2_copy(&KA, &P);
ECP2_frob(&KA, &X);
PAIR_line(&lv, &A, &KA, &Qx, &Qy);
ECP2_frob(&KA, &X);
ECP2_neg(&KA);
PAIR_line(&lv2, &A, &KA, &Qx, &Qy);
FP12_smul(&lv, &lv2);
FP12_ssmul(r, &lv);
#endif
}
/* Optimal R-ate double pairing e(P,Q).e(R,S) */
void ZZZ::PAIR_double_ate(FP12 *r, ECP2 *P1, ECP *Q1, ECP2 *R1, ECP *S1)
{
BIG n, n3;
FP Qx, Qy, Sx, Sy;
int i, nb, bt;
ECP2 A, B, NP, NR, P, R;
ECP Q, S;
FP12 lv, lv2;
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
ECP2 K;
FP2 X;
FP_rcopy(&Qx, Fra);
FP_rcopy(&Qy, Frb);
FP2_from_FPs(&X, &Qx, &Qy);
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_inv(&X, &X, NULL);
FP2_norm(&X);
#endif
#endif
if (ECP_isinf(Q1))
{
PAIR_ate(r, R1, S1);
return;
}
if (ECP_isinf(S1))
{
PAIR_ate(r, P1, Q1);
return;
}
nb = PAIR_nbits(n3, n);
ECP2_copy(&P, P1);
ECP_copy(&Q, Q1);
ECP2_affine(&P);
ECP_affine(&Q);
ECP2_copy(&R, R1);
ECP_copy(&S, S1);
ECP2_affine(&R);
ECP_affine(&S);
FP_copy(&Qx, &(Q.x));
FP_copy(&Qy, &(Q.y));
FP_copy(&Sx, &(S.x));
FP_copy(&Sy, &(S.y));
ECP2_copy(&A, &P);
ECP2_copy(&B, &R);
ECP2_copy(&NP, &P); ECP2_neg(&NP);
ECP2_copy(&NR, &R); ECP2_neg(&NR);
FP12_one(r);
/* Main Miller Loop */
for (i = nb - 2; i >= 1; i--)
{
FP12_sqr(r, r);
PAIR_line(&lv, &A, &A, &Qx, &Qy);
PAIR_line(&lv2, &B, &B, &Sx, &Sy);
FP12_smul(&lv, &lv2);
FP12_ssmul(r, &lv);
bt = BIG_bit(n3, i) - BIG_bit(n, i); // bt=BIG_bit(n,i);
if (bt == 1)
{
PAIR_line(&lv, &A, &P, &Qx, &Qy);
PAIR_line(&lv2, &B, &R, &Sx, &Sy);
FP12_smul(&lv, &lv2);
FP12_ssmul(r, &lv);
}
if (bt == -1)
{
PAIR_line(&lv, &A, &NP, &Qx, &Qy);
PAIR_line(&lv2, &B, &NR, &Sx, &Sy);
FP12_smul(&lv, &lv2);
FP12_ssmul(r, &lv);
}
}
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(r, r);
#endif
/* R-ate fixup required for BN curves */
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
#if SIGN_OF_X_ZZZ==NEGATIVEX
ECP2_neg(&A);
ECP2_neg(&B);
#endif
ECP2_copy(&K, &P);
ECP2_frob(&K, &X);
PAIR_line(&lv, &A, &K, &Qx, &Qy);
ECP2_frob(&K, &X);
ECP2_neg(&K);
PAIR_line(&lv2, &A, &K, &Qx, &Qy);
FP12_smul(&lv, &lv2);
FP12_ssmul(r, &lv);
ECP2_copy(&K, &R);
ECP2_frob(&K, &X);
PAIR_line(&lv, &B, &K, &Sx, &Sy);
ECP2_frob(&K, &X);
ECP2_neg(&K);
PAIR_line(&lv2, &B, &K, &Sx, &Sy);
FP12_smul(&lv, &lv2);
FP12_ssmul(r, &lv);
#endif
}
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
void ZZZ::PAIR_fexp(FP12 *r)
{
FP2 X;
BIG x;
FP a, b;
FP12 t0, y0, y1;
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
FP12 y2, y3;
#endif
BIG_rcopy(x, CURVE_Bnx);
FP_rcopy(&a, Fra);
FP_rcopy(&b, Frb);
FP2_from_FPs(&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 PAIRING_FRIENDLY_ZZZ==BN_CURVE
FP12_pow(&t0, r, x); // t0=f^-u
#if SIGN_OF_X_ZZZ==POSITIVEX
FP12_conj(&t0, &t0);
#endif
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
#if SIGN_OF_X_ZZZ==POSITIVEX
FP12_conj(&t0, &t0);
#endif
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
#if SIGN_OF_X_ZZZ==POSITIVEX
FP12_conj(&t0, &t0);
#endif
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
// See https://eprint.iacr.org/2020/875.pdf
FP12_usqr(&y1,r);
FP12_mul(&y1,r); // y1=r^3
FP12_pow(&y0,r,x); // y0=r^x
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(&y0, &y0);
#endif
FP12_conj(&t0,r); // t0=r^-1
FP12_copy(r,&y0);
FP12_mul(r,&t0); // r=r^(x-1)
FP12_pow(&y0,r,x); // y0=r^x
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(&y0, &y0);
#endif
FP12_conj(&t0,r); // t0=r^-1
FP12_copy(r,&y0);
FP12_mul(r,&t0); // r=r^(x-1)
// ^(x+p)
FP12_pow(&y0,r,x); // y0=r^x
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(&y0, &y0);
#endif
FP12_copy(&t0,r);
FP12_frob(&t0,&X); // t0=r^p
FP12_copy(r,&y0);
FP12_mul(r,&t0); // r=r^x.r^p
// ^(x^2+p^2-1)
FP12_pow(&y0,r,x);
FP12_pow(&y0,&y0,x); // y0=r^x^2
FP12_copy(&t0,r);
FP12_frob(&t0,&X);
FP12_frob(&t0,&X); // t0=r^p^2
FP12_mul(&y0,&t0); // y0=r^x^2.r^p^2
FP12_conj(&t0,r); // t0=r^-1
FP12_copy(r,&y0); //
FP12_mul(r,&t0); // r=r^x^2.r^p^2.r^-1
FP12_mul(r,&y1);
FP12_reduce(r);
#endif
}
#ifdef USE_GLV_ZZZ
/* GLV method */
static void ZZZ::glv(BIG u[2], BIG ee)
{
BIG q;
BIG_rcopy(q, CURVE_Order);
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
int i, j;
BIG v[2], t;
DBIG d;
for (i = 0; i < 2; i++)
{
BIG_rcopy(t, CURVE_W[i]);
BIG_mul(d, t, ee);
BIG_ctddiv(v[i],d,q,BIG_nbits(t));
BIG_zero(u[i]);
}
BIG_copy(u[0], ee);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
{
BIG_rcopy(t, CURVE_SB[j][i]);
BIG_modmul(t, v[j], t, q);
BIG_add(u[i], u[i], q);
BIG_sub(u[i], u[i], t);
BIG_ctmod(u[i],q,1);
}
//BIG x, x2;
//BIG_rcopy(x, CURVE_Bnx);
//BIG_smul(x2, x, x);
//BIG_imul(x2,x2,6);
//printf("bits(6x^2) = %d \n",BIG_nbits(x2));
#else
// -(x^2).P = (Beta.x,y)
int bd;
BIG x, x2;
BIG_rcopy(x, CURVE_Bnx);
BIG_smul(x2, x, x);
bd=BIG_nbits(q)-BIG_nbits(x2); // fixed
BIG_copy(u[0], ee);
BIG_ctmod(u[0], x2, bd);
BIG_copy(u[1], ee);
BIG_ctsdiv(u[1], x2, bd);
BIG_sub(u[1], q, u[1]);
#endif
return;
}
#endif // USE_GLV
/* Galbraith & Scott Method */
static void ZZZ::gs(BIG u[4], BIG ee)
{
int i;
BIG q;
BIG_rcopy(q, CURVE_Order);
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
int j;
BIG v[4], t;
DBIG d;
for (i = 0; i < 4; i++)
{
BIG_rcopy(t, CURVE_WB[i]);
BIG_mul(d, t, ee);
BIG_ctddiv(v[i],d,q,BIG_nbits(t));
BIG_zero(u[i]);
}
BIG_copy(u[0], ee);
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
{
BIG_rcopy(t, CURVE_BB[j][i]);
BIG_modmul(t, v[j], t, q);
BIG_add(u[i], u[i], q);
BIG_sub(u[i], u[i], t);
BIG_ctmod(u[i],q,1);
}
//BIG x;
//BIG_rcopy(x, CURVE_Bnx);
//BIG_imul(x,x,3);
//printf("bits(3x) = %d \n",BIG_nbits(x));
#else
int bd;
BIG x, w;
BIG_rcopy(x, CURVE_Bnx);
BIG_copy(w, ee);
bd=BIG_nbits(q)-BIG_nbits(x); // fixed
for (i = 0; i < 3; i++)
{
BIG_copy(u[i], w);
BIG_ctmod(u[i],x,bd);
BIG_ctsdiv(w,x,bd);
}
BIG_copy(u[3], w);
/* */
#if SIGN_OF_X_ZZZ==NEGATIVEX
BIG_modneg(u[1], u[1], q);
BIG_modneg(u[3], u[3], q);
#endif
#endif
return;
}
/* Multiply P by e in group G1 */
void ZZZ::PAIR_G1mul(ECP *P, BIG e)
{
BIG ee,q;
BIG_copy(ee,e);
BIG_rcopy(q, CURVE_Order);
BIG_mod(ee,q);
#ifdef USE_GLV_ZZZ /* Note this method is patented */
int np, nn;
ECP Q;
FP cru;
BIG t;
BIG u[2];
glv(u, ee);
ECP_copy(&Q, P); ECP_affine(&Q);
FP_rcopy(&cru, CRu);
FP_mul(&(Q.x), &(Q.x), &cru);
/* note that -a.B = a.(-B). Use a or -a depending on which is smaller */
np = BIG_nbits(u[0]);
BIG_modneg(t, u[0], q);
nn = BIG_nbits(t);
if (nn < np)
{
BIG_copy(u[0], t);
ECP_neg(P);
}
np = BIG_nbits(u[1]);
BIG_modneg(t, u[1], q);
nn = BIG_nbits(t);
if (nn < np)
{
BIG_copy(u[1], t);
ECP_neg(&Q);
}
BIG_norm(u[0]);
BIG_norm(u[1]);
ECP_mul2(P, &Q, u[0], u[1]);
//printf("nbits(q) = %d\n",BIG_nbits(q));
//printf("nbits(q)/2 = %d\n",BIG_nbits(q)/2);
//printf("u[0] %d = ",BIG_nbits(u[0]));BIG_output(u[0]); printf("\n");
//printf("u[1] %d = ",BIG_nbits(u[1]));BIG_output(u[1]); printf("\n");
#else
ECP_clmul(P, ee, q);
#endif
}
/* Multiply P by e in group G2 */
void ZZZ::PAIR_G2mul(ECP2 *P, BIG e)
{
BIG ee,q;
BIG_copy(ee,e);
BIG_rcopy(q, CURVE_Order);
BIG_mod(ee,q);
#ifdef USE_GS_G2_ZZZ /* Well I didn't patent it :) */
int i, np, nn;
ECP2 Q[4];
FP2 X;
FP fx, fy;
BIG x, u[4];
FP_rcopy(&fx, Fra);
FP_rcopy(&fy, Frb);
FP2_from_FPs(&X, &fx, &fy);
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_inv(&X, &X, NULL);
FP2_norm(&X);
#endif
gs(u, ee);
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], q);
nn = BIG_nbits(x);
if (nn < np)
{
BIG_copy(u[i], x);
ECP2_neg(&Q[i]);
}
BIG_norm(u[i]);
}
ECP2_mul4(P, Q, u);
//printf("nbits(q) = %d\n",BIG_nbits(q));
//printf("nbits(q)/4 = %d\n",BIG_nbits(q)/4);
//printf("u[0] %d = ",BIG_nbits(u[0]));BIG_output(u[0]); printf("\n");
//printf("u[1] %d = ",BIG_nbits(u[1]));BIG_output(u[1]); printf("\n");
//printf("u[2] %d = ",BIG_nbits(u[2]));BIG_output(u[2]); printf("\n");
//printf("u[3] %d = ",BIG_nbits(u[3]));BIG_output(u[3]); printf("\n");
#else
ECP2_mul(P, ee);
#endif
}
/* f=f^e */
void ZZZ::PAIR_GTpow(FP12 *f, BIG e)
{
BIG ee,q;
BIG_copy(ee,e);
BIG_rcopy(q, CURVE_Order);
BIG_mod(ee,q);
#ifdef USE_GS_GT_ZZZ /* 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;
FP fx, fy;
BIG u[4];
FP_rcopy(&fx, Fra);
FP_rcopy(&fy, Frb);
FP2_from_FPs(&X, &fx, &fy);
gs(u, ee);
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]);
}
BIG_norm(u[i]);
}
FP12_pow4(f, g, u);
#else
FP12_pow(f, f, ee);
#endif
}
/* test G1 group membership */
int ZZZ::PAIR_G1member(ECP *P)
{
ECP W,T;
BIG x;
FP cru;
if (ECP_isinf(P)) return 0;
#if PAIRING_FRIENDLY_ZZZ!=BN_CURVE
BIG_rcopy(x, CURVE_Bnx);
ECP_copy(&W,P);
ECP_copy(&T,P);
ECP_mul(&T,x);
if (ECP_equals(P,&T)) return 0; // P is of low order
ECP_mul(&T,x);
ECP_neg(&T);
FP_rcopy(&cru, CRu);
FP_mul(&(W.x), &(W.x), &cru);
if (!ECP_equals(&W,&T)) return 0; // check that Endomorphism works
// Not needed
// ECP_add(&W,P);
// FP_mul(&(T.x), &(T.x), &cru);
// ECP_add(&W,&T);
// if (!ECP_isinf(&W)) return 0; // use it to check order
/*
BIG_rcopy(q, CURVE_Order);
ECP_copy(&W,P);
ECP_mul(&W,q);
if (!ECP_isinf(&W)) return 0; */
#endif
return 1;
}
/* test G2 group membership */
int ZZZ::PAIR_G2member(ECP2 *P)
{
ECP2 W,T;
BIG x;
FP2 X;
FP fx, fy;
if (ECP2_isinf(P)) return 0;
FP_rcopy(&fx, Fra);
FP_rcopy(&fy, Frb);
FP2_from_FPs(&X, &fx, &fy);
#if SEXTIC_TWIST_ZZZ==M_TYPE
FP2_inv(&X, &X, NULL);
FP2_norm(&X);
#endif
BIG_rcopy(x, CURVE_Bnx);
ECP2_copy(&T,P);
ECP2_mul(&T,x);
#if SIGN_OF_X_ZZZ==NEGATIVEX
ECP2_neg(&T);
#endif
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
//https://eprint.iacr.org/2022/348.pdf
ECP2_copy(&W,&T);
ECP2_frob(&W,&X); // W=\psi(xP)
ECP2_add(&T,P); // T=xP+P
ECP2_add(&T,&W); // T=xP+P+\psi(xP)
ECP2_frob(&W,&X); // W=\psi^2(xP)
ECP2_add(&T,&W); // T=xp+P+\psi(xP)+\psi^2(xP)
ECP2_frob(&W,&X); // W=\psi^3(xP)
ECP2_dbl(&W); // W=\psi^3(2xP)
#else
//https://eprint.iacr.org/2021/1130
ECP2_copy(&W,P);
ECP2_frob(&W, &X); // W=\psi(P)
#endif
if (ECP2_equals(&W,&T)) return 1;
return 0;
}
/* Check that m is in cyclotomic sub-group */
/* Check that m!=1, conj(m)*m==1, and m.m^{p^4}=m^{p^2} */
int ZZZ::PAIR_GTcyclotomic(FP12 *m)
{
FP fx,fy;
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;
FP_rcopy(&fx,Fra);
FP_rcopy(&fy,Frb);
FP2_from_FPs(&X,&fx,&fy);
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);
if (!FP12_equals(&w,&r)) return 0;
return 1;
}
/* test for full GT group membership */
int ZZZ::PAIR_GTmember(FP12 *m)
{
BIG x;
FP2 X;
FP fx, fy;
FP12 r,t;
if (!PAIR_GTcyclotomic(m)) return 0;
FP_rcopy(&fx, Fra);
FP_rcopy(&fy, Frb);
FP2_from_FPs(&X, &fx, &fy);
BIG_rcopy(x, CURVE_Bnx);
FP12_pow(&t,m,x);
#if SIGN_OF_X_ZZZ==NEGATIVEX
FP12_conj(&t,&t);
#endif
#if PAIRING_FRIENDLY_ZZZ==BN_CURVE
//https://eprint.iacr.org/2022/348.pdf
FP12_copy(&r,&t);
FP12_frob(&r,&X); // r=(m^x)^p
FP12_mul(&t,m); // t=(m^x).m
FP12_mul(&t,&r); // t=(m^x).m.(m^x)^p
FP12_frob(&r,&X); // r=(m^x)^p^2
FP12_mul(&t,&r); // t=(m^x).m.(m^x)^p.(m^x)^p^2
FP12_frob(&r,&X); // r=(m^x)^p^3
FP12_usqr(&r,&r); // r=(m^2x)^p^3
#else
//https://eprint.iacr.org/2021/1130
FP12_copy(&r,m);
FP12_frob(&r, &X);
#endif
if (FP12_equals(&r,&t)) return 1;
return 0;
}
#ifdef HAS_MAIN
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(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);
}
printf("g= ");
FP12_output(&g);
printf("\n");
}
#endif