use super::fp::FP;
use super::ecp::ECP;
use super::fp2::FP2;
use super::ecp2::ECP2;
use super::fp4::FP4;
use super::fp12;
use super::fp12::FP12;
use super::big::BIG;
use super::dbig::DBIG;
use super::ecp;
use super::rom;
use types::{SexticTwist, CurvePairingType, SignOfX};
#[allow(non_snake_case)]
fn linedbl(A: &mut ECP2, qx: &FP, qy: &FP) -> FP12 {
let mut a = FP4::new();
let mut b = FP4::new();
let mut c = FP4::new();
let mut xx = FP2::new_copy(&A.getpx()); let mut yy = FP2::new_copy(&A.getpy()); let mut zz = FP2::new_copy(&A.getpz()); let mut yz = FP2::new_copy(&yy); yz.mul(&zz); xx.sqr(); yy.sqr(); zz.sqr();
yz.imul(4);
yz.neg();
yz.norm(); yz.pmul(qy);
xx.imul(6); xx.pmul(qx);
let sb = 3 * rom::CURVE_B_I;
zz.imul(sb);
if ecp::SEXTIC_TWIST == SexticTwist::D_TYPE {
zz.div_ip2();
}
if ecp::SEXTIC_TWIST == SexticTwist::M_TYPE {
zz.mul_ip();
zz.dbl();
yz.mul_ip();
yz.norm();
}
zz.norm();
yy.dbl();
zz.sub(&yy);
zz.norm();
a.copy(&FP4::new_fp2s(&yz, &zz)); if ecp::SEXTIC_TWIST == SexticTwist::D_TYPE {
b.copy(&FP4::new_fp2(&xx)); }
if ecp::SEXTIC_TWIST == SexticTwist::M_TYPE {
c.copy(&FP4::new_fp2(&xx));
c.times_i();
}
A.dbl();
let mut res= FP12::new_fp4s(&a, &b, &c);
res.settype(fp12::SPARSER);
return res;
}
#[allow(non_snake_case)]
fn lineadd(A: &mut ECP2, B: &ECP2, qx: &FP, qy: &FP) -> FP12 {
let mut a = FP4::new();
let mut b = FP4::new();
let mut c = FP4::new();
let mut x1 = FP2::new_copy(&A.getpx()); let mut y1 = FP2::new_copy(&A.getpy()); let mut t1 = FP2::new_copy(&A.getpz()); let mut t2 = FP2::new_copy(&A.getpz());
t1.mul(&B.getpy()); t2.mul(&B.getpx());
x1.sub(&t2);
x1.norm(); y1.sub(&t1);
y1.norm();
t1.copy(&x1); x1.pmul(qy); if ecp::SEXTIC_TWIST == SexticTwist::M_TYPE {
x1.mul_ip();
x1.norm();
}
t1.mul(&B.getpy());
t2.copy(&y1); t2.mul(&B.getpx()); t2.sub(&t1);
t2.norm(); y1.pmul(qx);
y1.neg();
y1.norm();
a.copy(&FP4::new_fp2s(&x1, &t2)); if ecp::SEXTIC_TWIST == SexticTwist::D_TYPE {
b.copy(&FP4::new_fp2(&y1));
}
if ecp::SEXTIC_TWIST == SexticTwist::M_TYPE {
c.copy(&FP4::new_fp2(&y1));
c.times_i();
}
A.add(B);
let mut res= FP12::new_fp4s(&a, &b, &c);
res.settype(fp12::SPARSER);
return res;
}
#[allow(non_snake_case)]
fn lbits(n3: &mut BIG,n: &mut BIG) -> usize {
n.copy(&BIG::new_ints(&rom::CURVE_BNX));
if ecp::CURVE_PAIRING_TYPE==CurvePairingType::BN {
n.pmul(6);
if ecp::SIGN_OF_X==SignOfX::POSITIVEX {
n.inc(2);
} else {
n.dec(2);
}
}
n.norm();
n3.copy(&n);
n3.pmul(3);
n3.norm();
return n3.nbits();
}
pub fn initmp() -> [FP12; rom::ATE_BITS] {
let r: [FP12; rom::ATE_BITS] = [FP12::new_int(1); rom::ATE_BITS];
return r
}
pub fn miller(r:&[FP12]) -> FP12 {
let mut res=FP12::new_int(1);
for i in (1..rom::ATE_BITS).rev() {
res.sqr();
res.ssmul(&r[i]);
}
if ecp::SIGN_OF_X==SignOfX::NEGATIVEX {
res.conj();
}
res.ssmul(&r[0]);
return res;
}
#[allow(non_snake_case)]
pub fn another(r:&mut [FP12],P1: &ECP2,Q1: &ECP) {
let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
let mut n = BIG::new();
let mut n3 = BIG::new();
let mut K = ECP2::new();
if Q1.is_infinity() {
return;
}
let mut P = ECP2::new();
P.copy(P1);
P.affine();
let mut Q = ECP::new();
Q.copy(Q1);
Q.affine();
if ecp::CURVE_PAIRING_TYPE==CurvePairingType::BN {
if ecp::SEXTIC_TWIST==SexticTwist::M_TYPE {
f.inverse();
f.norm();
}
}
let qx = FP::new_copy(&Q.getpx());
let qy = FP::new_copy(&Q.getpy());
let mut A = ECP2::new();
A.copy(&P);
let mut NP = ECP2::new();
NP.copy(&P);
NP.neg();
let nb=lbits(&mut n3,&mut n);
for i in (1..nb-1).rev() {
let mut lv=linedbl(&mut A,&qx,&qy);
let bt=n3.bit(i)-n.bit(i);
if bt==1 {
let lv2=lineadd(&mut A,&P,&qx,&qy);
lv.smul(&lv2);
}
if bt==-1 {
let lv2=lineadd(&mut A,&NP,&qx,&qy);
lv.smul(&lv2);
}
r[i].ssmul(&lv);
}
if ecp::CURVE_PAIRING_TYPE==CurvePairingType::BN {
if ecp::SIGN_OF_X==SignOfX::NEGATIVEX {
A.neg();
}
K.copy(&P);
K.frob(&f);
let mut lv=lineadd(&mut A,&K,&qx,&qy);
K.frob(&f);
K.neg();
let lv2=lineadd(&mut A,&K,&qx,&qy);
lv.smul(&lv2);
r[0].ssmul(&lv);
}
}
#[allow(non_snake_case)]
pub fn ate(P1: &ECP2, Q1: &ECP) -> FP12 {
let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
let mut n = BIG::new();
let mut n3 = BIG::new();
let mut K = ECP2::new();
if Q1.is_infinity() {
return FP12::new_int(1);
}
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
if ecp::SEXTIC_TWIST == SexticTwist::M_TYPE {
f.inverse();
f.norm();
}
}
let mut P = ECP2::new();
P.copy(P1);
P.affine();
let mut Q = ECP::new();
Q.copy(Q1);
Q.affine();
let qx = FP::new_copy(&Q.getpx());
let qy = FP::new_copy(&Q.getpy());
let mut A = ECP2::new();
let mut r = FP12::new_int(1);
A.copy(&P);
let mut NP = ECP2::new();
NP.copy(&P);
NP.neg();
let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
let mut lv = linedbl(&mut A, &qx, &qy);
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
let lv2 = lineadd(&mut A, &P, &qx, &qy);
lv.smul(&lv2);
}
if bt == -1 {
let lv2 = lineadd(&mut A, &NP, &qx, &qy);
lv.smul(&lv2);
}
r.ssmul(&lv);
}
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
r.conj();
}
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
A.neg();
}
K.copy(&P);
K.frob(&f);
let mut lv = lineadd(&mut A, &K, &qx, &qy);
K.frob(&f);
K.neg();
let lv2 = lineadd(&mut A, &K, &qx, &qy);
lv.smul(&lv2);
r.ssmul(&lv);
}
return r;
}
#[allow(non_snake_case)]
pub fn ate2(P1: &ECP2, Q1: &ECP, R1: &ECP2, S1: &ECP) -> FP12 {
let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
let mut n = BIG::new();
let mut n3 = BIG::new();
let mut K = ECP2::new();
if Q1.is_infinity() {
return ate(R1,S1);
}
if S1.is_infinity() {
return ate(P1,Q1);
}
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
if ecp::SEXTIC_TWIST == SexticTwist::M_TYPE {
f.inverse();
f.norm();
}
}
let mut P = ECP2::new();
P.copy(P1);
P.affine();
let mut Q = ECP::new();
Q.copy(Q1);
Q.affine();
let mut R = ECP2::new();
R.copy(R1);
R.affine();
let mut S = ECP::new();
S.copy(S1);
S.affine();
let qx = FP::new_copy(&Q.getpx());
let qy = FP::new_copy(&Q.getpy());
let sx = FP::new_copy(&S.getpx());
let sy = FP::new_copy(&S.getpy());
let mut A = ECP2::new();
let mut B = ECP2::new();
let mut r = FP12::new_int(1);
A.copy(&P);
B.copy(&R);
let mut NP = ECP2::new();
NP.copy(&P);
NP.neg();
let mut NR = ECP2::new();
NR.copy(&R);
NR.neg();
let nb=lbits(&mut n3,&mut n);
for i in (1..nb - 1).rev() {
r.sqr();
let mut lv = linedbl(&mut A, &qx, &qy);
let lv2 = linedbl(&mut B, &sx, &sy);
lv.smul(&lv2);
r.ssmul(&lv);
let bt = n3.bit(i) - n.bit(i);
if bt == 1 {
lv = lineadd(&mut A, &P, &qx, &qy);
let lv2 = lineadd(&mut B, &R, &sx, &sy);
lv.smul(&lv2);
r.ssmul(&lv);
}
if bt == -1 {
lv = lineadd(&mut A, &NP, &qx, &qy);
let lv2 = lineadd(&mut B, &NR, &sx, &sy);
lv.smul(&lv2);
r.ssmul(&lv);
}
}
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
r.conj();
}
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
A.neg();
B.neg();
}
K.copy(&P);
K.frob(&f);
let mut lv = lineadd(&mut A, &K, &qx, &qy);
K.frob(&f);
K.neg();
let mut lv2 = lineadd(&mut A, &K, &qx, &qy);
lv.smul(&lv2);
r.ssmul(&lv);
K.copy(&R);
K.frob(&f);
lv = lineadd(&mut B, &K, &sx, &sy);
K.frob(&f);
K.neg();
lv2 = lineadd(&mut B, &K, &sx, &sy);
lv.smul(&lv2);
r.ssmul(&lv);
}
return r;
}
pub fn fexp(m: &FP12) -> FP12 {
let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
let mut x = BIG::new_ints(&rom::CURVE_BNX);
let mut r = FP12::new_copy(m);
let mut lv = FP12::new_copy(&r);
lv.inverse();
r.conj();
r.mul(&lv);
lv.copy(&r);
r.frob(&f);
r.frob(&f);
r.mul(&lv);
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
lv.copy(&r);
lv.frob(&f);
let mut x0 = FP12::new_copy(&lv);
x0.frob(&f);
lv.mul(&r);
x0.mul(&lv);
x0.frob(&f);
let mut x1 = FP12::new_copy(&r);
x1.conj();
let mut x4 = r.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::POSITIVEX {
x4.conj();
}
let mut x3 = FP12::new_copy(&x4);
x3.frob(&f);
let mut x2 = x4.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::POSITIVEX {
x2.conj();
}
let mut x5 = FP12::new_copy(&x2);
x5.conj();
lv = x2.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::POSITIVEX {
lv.conj();
}
x2.frob(&f);
r.copy(&x2);
r.conj();
x4.mul(&r);
x2.frob(&f);
r.copy(&lv);
r.frob(&f);
lv.mul(&r);
lv.usqr();
lv.mul(&x4);
lv.mul(&x5);
r.copy(&x3);
r.mul(&x5);
r.mul(&lv);
lv.mul(&x2);
r.usqr();
r.mul(&lv);
r.usqr();
lv.copy(&r);
lv.mul(&x1);
r.mul(&x0);
lv.usqr();
r.mul(&lv);
r.reduce();
} else {
let mut y0 = FP12::new_copy(&r);
y0.usqr();
let mut y1 = y0.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
y1.conj();
}
x.fshr(1);
let mut y2 = y1.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
y2.conj();
}
x.fshl(1);
let mut y3 = FP12::new_copy(&r);
y3.conj();
y1.mul(&y3);
y1.conj();
y1.mul(&y2);
y2 = y1.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
y2.conj();
}
y3 = y2.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
y3.conj();
}
y1.conj();
y3.mul(&y1);
y1.conj();
y1.frob(&f);
y1.frob(&f);
y1.frob(&f);
y2.frob(&f);
y2.frob(&f);
y1.mul(&y2);
y2 = y3.pow(&mut x);
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
y2.conj();
}
y2.mul(&y0);
y2.mul(&r);
y1.mul(&y2);
y2.copy(&y3);
y2.frob(&f);
y1.mul(&y2);
r.copy(&y1);
r.reduce();
}
return r;
}
#[allow(non_snake_case)]
fn glv(e: &BIG) -> [BIG; 2] {
let mut u: [BIG; 2] = [BIG::new(), BIG::new()];
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
let mut t = BIG::new();
let q = BIG::new_ints(&rom::CURVE_ORDER);
let mut v: [BIG; 2] = [BIG::new(), BIG::new()];
for i in 0..2 {
t.copy(&BIG::new_ints(&rom::CURVE_W[i])); let mut d: DBIG = BIG::mul(&t, e);
v[i].copy(&d.div(&q));
}
u[0].copy(&e);
for i in 0..2 {
for j in 0..2 {
t = BIG::new_ints(&rom::CURVE_SB[j][i]);
t = BIG::modmul(&mut v[j], &mut t, &q);
u[i].add(&q);
u[i].sub(&t);
u[i].rmod(&q);
}
}
} else {
let q = BIG::new_ints(&rom::CURVE_ORDER);
let x = BIG::new_ints(&rom::CURVE_BNX);
let x2 = BIG::smul(&x, &x);
u[0].copy(&e);
u[0].rmod(&x2);
u[1].copy(&e);
u[1].div(&x2);
u[1].rsub(&q);
}
return u;
}
#[allow(non_snake_case)]
pub fn gs(e: &BIG) -> [BIG; 4] {
let mut u: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()];
if ecp::CURVE_PAIRING_TYPE == CurvePairingType::BN {
let mut t = BIG::new();
let q = BIG::new_ints(&rom::CURVE_ORDER);
let mut v: [BIG; 4] = [BIG::new(), BIG::new(), BIG::new(), BIG::new()];
for i in 0..4 {
t.copy(&BIG::new_ints(&rom::CURVE_WB[i]));
let mut d: DBIG = BIG::mul(&t, e);
v[i].copy(&d.div(&q));
}
u[0].copy(&e);
for i in 0..4 {
for j in 0..4 {
t = BIG::new_ints(&rom::CURVE_BB[j][i]);
t = BIG::modmul(&mut v[j], &mut t, &q);
u[i].add(&q);
u[i].sub(&t);
u[i].rmod(&q);
}
}
} else {
let q = BIG::new_ints(&rom::CURVE_ORDER);
let x = BIG::new_ints(&rom::CURVE_BNX);
let mut w = BIG::new_copy(&e);
for i in 0..3 {
u[i].copy(&w);
u[i].rmod(&x);
w.div(&x);
}
u[3].copy(&w);
if ecp::SIGN_OF_X == SignOfX::NEGATIVEX {
let mut t = BIG::new();
t.copy(&BIG::modneg(&mut u[1], &q));
u[1].copy(&t);
t.copy(&BIG::modneg(&mut u[3], &q));
u[3].copy(&t);
}
}
return u;
}
#[allow(non_snake_case)]
pub fn g1mul(P: &ECP, e: &mut BIG) -> ECP {
let mut R = ECP::new();
if rom::USE_GLV {
R.copy(P);
let mut Q = ECP::new();
Q.copy(P);
Q.affine();
let q = BIG::new_ints(&rom::CURVE_ORDER);
let mut cru = FP::new_big(&BIG::new_ints(&rom::CURVE_CRU));
let mut u = glv(e);
Q.mulx(&mut cru);
let mut np = u[0].nbits();
let mut t: BIG = BIG::modneg(&mut u[0], &q);
let mut nn = t.nbits();
if nn < np {
u[0].copy(&t);
R.neg();
}
np = u[1].nbits();
t = BIG::modneg(&mut u[1], &q);
nn = t.nbits();
if nn < np {
u[1].copy(&t);
Q.neg();
}
u[0].norm();
u[1].norm();
R = R.mul2(&u[0], &mut Q, &u[1]);
} else {
R = P.mul(e);
}
return R;
}
#[allow(non_snake_case)]
pub fn g2mul(P: &ECP2, e: &BIG) -> ECP2 {
let mut R = ECP2::new();
if rom::USE_GS_G2 {
let mut Q: [ECP2; 4] = [ECP2::new(), ECP2::new(), ECP2::new(), ECP2::new()];
let mut f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
let q = BIG::new_ints(&rom::CURVE_ORDER);
let mut u = gs(e);
let mut T = ECP2::new();
if ecp::SEXTIC_TWIST == SexticTwist::M_TYPE {
f.inverse();
f.norm();
}
let mut t = BIG::new();
Q[0].copy(&P);
for i in 1..4 {
T.copy(&Q[i - 1]);
Q[i].copy(&T);
Q[i].frob(&f);
}
for i in 0..4 {
let np = u[i].nbits();
t.copy(&BIG::modneg(&mut u[i], &q));
let nn = t.nbits();
if nn < np {
u[i].copy(&t);
Q[i].neg();
}
u[i].norm();
}
R.copy(&ECP2::mul4(&mut Q, &u));
} else {
R.copy(&P.mul(e));
}
return R;
}
pub fn gtpow(d: &FP12, e: &BIG) -> FP12 {
let mut r = FP12::new();
if rom::USE_GS_GT {
let mut g: [FP12; 4] = [FP12::new(), FP12::new(), FP12::new(), FP12::new()];
let f = FP2::new_bigs(&BIG::new_ints(&rom::FRA), &BIG::new_ints(&rom::FRB));
let q = BIG::new_ints(&rom::CURVE_ORDER);
let mut t = BIG::new();
let mut u = gs(e);
let mut w = FP12::new();
g[0].copy(&d);
for i in 1..4 {
w.copy(&g[i - 1]);
g[i].copy(&w);
g[i].frob(&f);
}
for i in 0..4 {
let np = u[i].nbits();
t.copy(&BIG::modneg(&mut u[i], &q));
let nn = t.nbits();
if nn < np {
u[i].copy(&t);
g[i].conj();
}
u[i].norm();
}
r.copy(&FP12::pow4(&mut g, &u));
} else {
r.copy(&d.pow(e));
}
return r;
}