use crate::bls12381::big;
use crate::bls12381::big::BIG;
use crate::bls12381::dbig::DBIG;
use crate::bls12381::fp::FP;
use crate::bls12381::fp;
use crate::bls12381::rom;
#[derive(Clone)]
pub struct ECP {
x: FP,
y: FP,
z: FP,
}
pub const WEIERSTRASS: usize = 0;
pub const EDWARDS: usize = 1;
pub const MONTGOMERY: usize = 2;
pub const NOT: usize = 0;
pub const BN: usize = 1;
pub const BLS: usize = 2;
pub const D_TYPE: usize = 0;
pub const M_TYPE: usize = 1;
pub const POSITIVEX: usize = 0;
pub const NEGATIVEX: usize = 1;
pub const CURVETYPE:usize=WEIERSTRASS;
pub const CURVE_PAIRING_TYPE:usize=BLS;
pub const SEXTIC_TWIST:usize=M_TYPE;
pub const SIGN_OF_X:usize=NEGATIVEX;
pub const ATE_BITS:usize=65;
pub const G2_TABLE:usize=69;
pub const HASH_TYPE:usize=32;
pub const AESKEY:usize=16;
#[allow(non_snake_case)]
impl ECP {
pub fn pnew() -> ECP {
ECP {
x: FP::new(),
y: FP::new_int(1),
z: FP::new(),
}
}
pub fn new() -> ECP {
let mut E = ECP::pnew();
if CURVETYPE == EDWARDS {
E.z.one();
}
return E;
}
pub fn new_bigs(ix: &BIG, iy: &BIG) -> ECP {
let mut E = ECP::new();
E.x.bcopy(ix);
E.y.bcopy(iy);
E.z.one();
E.x.norm();
let mut rhs = ECP::rhs(&E.x);
if CURVETYPE == MONTGOMERY {
if rhs.qr(None) != 1 {
E.inf();
}
} else {
let mut y2 = FP::new_copy(&E.y);
y2.sqr();
if !y2.equals(&mut rhs) {
E.inf();
}
}
return E;
}
pub fn new_bigint(ix: &BIG, s: isize) -> ECP {
let mut E = ECP::new();
let mut hint = FP::new();
E.x.bcopy(ix);
E.x.norm();
E.z.one();
let mut rhs = ECP::rhs(&E.x);
if rhs.qr(Some(&mut hint)) == 1 {
let mut ny = rhs.sqrt(Some(&hint));
if ny.redc().parity() != s {
ny.neg(); ny.norm()
}
E.y.copy(&ny);
} else {
E.inf()
}
return E;
}
#[allow(non_snake_case)]
pub fn new_big(ix: &BIG) -> ECP {
let mut E = ECP::new();
let mut hint = FP::new();
E.x.bcopy(ix);
E.x.norm();
E.z.one();
let mut rhs = ECP::rhs(&E.x);
if rhs.qr(Some(&mut hint)) == 1 {
if CURVETYPE != MONTGOMERY {
E.y.copy(&rhs.sqrt(Some(&hint)))
}
} else {
E.inf();
}
return E;
}
pub fn inf(&mut self) {
self.x.zero();
if CURVETYPE != MONTGOMERY {
self.y.one();
}
if CURVETYPE != EDWARDS {
self.z.zero();
} else {
self.z.one()
}
}
fn rhs(x: &FP) -> FP {
let mut r = FP::new_copy(x);
r.sqr();
if CURVETYPE == WEIERSTRASS {
let b = FP::new_big(&BIG::new_ints(&rom::CURVE_B));
r.mul(x);
if rom::CURVE_A == -3 {
let mut cx = FP::new_copy(x);
cx.imul(3);
cx.neg();
cx.norm();
r.add(&cx);
}
r.add(&b);
}
if CURVETYPE == EDWARDS {
let mut b = FP::new_big(&BIG::new_ints(&rom::CURVE_B));
let one = FP::new_int(1);
b.mul(&r);
b.sub(&one);
b.norm();
if rom::CURVE_A == -1 {
r.neg()
}
r.sub(&one);
r.norm();
b.inverse();
r.mul(&b);
}
if CURVETYPE == MONTGOMERY {
let mut x3 = FP::new();
x3.copy(&r);
x3.mul(x);
r.imul(rom::CURVE_A);
r.add(&x3);
r.add(&x);
}
r.reduce();
return r;
}
pub fn is_infinity(&self) -> bool {
if CURVETYPE == EDWARDS {
return self.x.iszilch() && self.y.equals(&self.z);
}
if CURVETYPE == WEIERSTRASS {
return self.x.iszilch() && self.z.iszilch();
}
if CURVETYPE == MONTGOMERY {
return self.z.iszilch();
}
return true;
}
pub fn cswap(&mut self, Q: &mut ECP, d: isize) {
self.x.cswap(&mut Q.x, d);
if CURVETYPE != MONTGOMERY {
self.y.cswap(&mut Q.y, d)
}
self.z.cswap(&mut Q.z, d);
}
pub fn cmove(&mut self, Q: &ECP, d: isize) {
self.x.cmove(&Q.x, d);
if CURVETYPE != MONTGOMERY {
self.y.cmove(&Q.y, d)
}
self.z.cmove(&Q.z, d);
}
fn teq(b: i32, c: i32) -> isize {
let mut x = b ^ c;
x -= 1;
return ((x >> 31) & 1) as isize;
}
pub fn copy(&mut self, P: &ECP) {
self.x.copy(&P.x);
if CURVETYPE != MONTGOMERY {
self.y.copy(&P.y)
}
self.z.copy(&P.z);
}
pub fn neg(&mut self) {
if CURVETYPE == WEIERSTRASS {
self.y.neg();
self.y.norm();
}
if CURVETYPE == EDWARDS {
self.x.neg();
self.x.norm();
}
return;
}
pub fn mulx(&mut self, c: &mut FP) {
self.x.mul(c);
}
fn selector(&mut self, W: &[ECP], b: i32) {
let mut MP = ECP::new();
let m = b >> 31;
let mut babs = (b ^ m) - m;
babs = (babs - 1) / 2;
self.cmove(&W[0], ECP::teq(babs, 0));
self.cmove(&W[1], ECP::teq(babs, 1));
self.cmove(&W[2], ECP::teq(babs, 2));
self.cmove(&W[3], ECP::teq(babs, 3));
self.cmove(&W[4], ECP::teq(babs, 4));
self.cmove(&W[5], ECP::teq(babs, 5));
self.cmove(&W[6], ECP::teq(babs, 6));
self.cmove(&W[7], ECP::teq(babs, 7));
MP.copy(self);
MP.neg();
self.cmove(&MP, (m & 1) as isize);
}
pub fn equals(&mut self, Q: &mut ECP) -> bool {
let mut a = FP::new();
let mut b = FP::new();
a.copy(&self.x);
a.mul(&Q.z);
b.copy(&Q.x);
b.mul(&self.z);
if !a.equals(&mut b) {
return false;
}
if CURVETYPE != MONTGOMERY {
a.copy(&self.y);
a.mul(&Q.z);
b.copy(&Q.y);
b.mul(&self.z);
if !a.equals(&mut b) {
return false;
}
}
return true;
}
pub fn affine(&mut self) {
if self.is_infinity() {
return;
}
let mut one = FP::new_int(1);
if self.z.equals(&mut one) {
return;
}
self.z.inverse();
self.x.mul(&self.z);
self.x.reduce();
if CURVETYPE != MONTGOMERY {
self.y.mul(&self.z);
self.y.reduce();
}
self.z.copy(&one);
}
pub fn getx(&self) -> BIG {
let mut W = ECP::new();
W.copy(self);
W.affine();
return W.x.redc();
}
pub fn gety(&self) -> BIG {
let mut W = ECP::new();
W.copy(self);
W.affine();
return W.y.redc();
}
pub fn gets(&self) -> isize {
let y = self.gety();
return y.parity();
}
pub fn getpx(&self) -> FP {
let w = FP::new_copy(&self.x);
return w;
}
pub fn getpy(&self) -> FP {
let w = FP::new_copy(&self.y);
return w;
}
pub fn getpz(&self) -> FP {
let w = FP::new_copy(&self.z);
return w;
}
pub fn tobytes(&self, b: &mut [u8], compress: bool) {
let mb = big::MODBYTES as usize;
let mut t: [u8; big::MODBYTES as usize] = [0; big::MODBYTES as usize];
let mut W = ECP::new();
W.copy(self);
W.affine();
W.x.redc().tobytes(&mut t);
if CURVETYPE == MONTGOMERY {
for i in 0..mb {
b[i] = t[i]
}
return;
}
for i in 0..mb {
b[i + 1] = t[i]
}
if compress {
b[0] = 0x02;
if W.y.redc().parity() == 1 {
b[0] = 0x03
}
return;
}
b[0] = 0x04;
W.y.redc().tobytes(&mut t);
for i in 0..mb {
b[i + mb + 1] = t[i]
}
}
pub fn frombytes(b: &[u8]) -> ECP {
let mut t: [u8; big::MODBYTES as usize] = [0; big::MODBYTES as usize];
let mb = big::MODBYTES as usize;
let p = BIG::new_ints(&rom::MODULUS);
if CURVETYPE == MONTGOMERY {
for i in 0..mb {
t[i] = b[i]
}
let px = BIG::frombytes(&t);
if BIG::comp(&px, &p) >= 0 {
return ECP::new();
}
return ECP::new_big(&px);
}
for i in 0..mb {
t[i] = b[i + 1]
}
let px = BIG::frombytes(&t);
if BIG::comp(&px, &p) >= 0 {
return ECP::new();
}
if b[0] == 0x04 {
for i in 0..mb {
t[i] = b[i + mb + 1]
}
let py = BIG::frombytes(&t);
if BIG::comp(&py, &p) >= 0 {
return ECP::new();
}
return ECP::new_bigs(&px, &py);
}
if b[0] == 0x02 || b[0] == 0x03 {
return ECP::new_bigint(&px, (b[0] & 1) as isize);
}
return ECP::new();
}
pub fn tostring(&self) -> String {
let mut W = ECP::new();
W.copy(self);
W.affine();
if W.is_infinity() {
return String::from("infinity");
}
if CURVETYPE == MONTGOMERY {
return format!("({})", W.x.redc().tostring());
} else {
return format!("({},{})", W.x.redc().tostring(), W.y.redc().tostring());
};
}
pub fn dbl(&mut self) {
if CURVETYPE == WEIERSTRASS {
if rom::CURVE_A == 0 {
let mut t0 = FP::new_copy(&self.y);
t0.sqr();
let mut t1 = FP::new_copy(&self.y);
t1.mul(&self.z);
let mut t2 = FP::new_copy(&self.z);
t2.sqr();
self.z.copy(&t0);
self.z.add(&t0);
self.z.norm();
self.z.dbl();
self.z.dbl();
self.z.norm();
t2.imul(3 * rom::CURVE_B_I);
let mut x3 = FP::new_copy(&t2);
x3.mul(&self.z);
let mut y3 = FP::new_copy(&t0);
y3.add(&t2);
y3.norm();
self.z.mul(&t1);
t1.copy(&t2);
t1.add(&t2);
t2.add(&t1);
t0.sub(&t2);
t0.norm();
y3.mul(&t0);
y3.add(&x3);
t1.copy(&self.x);
t1.mul(&self.y);
self.x.copy(&t0);
self.x.norm();
self.x.mul(&t1);
self.x.dbl();
self.x.norm();
self.y.copy(&y3);
self.y.norm();
} else {
let mut t0 = FP::new_copy(&self.x);
let mut t1 = FP::new_copy(&self.y);
let mut t2 = FP::new_copy(&self.z);
let mut t3 = FP::new_copy(&self.x);
let mut z3 = FP::new_copy(&self.z);
let mut y3 = FP::new();
let mut x3 = FP::new();
let mut b = FP::new();
if rom::CURVE_B_I == 0 {
b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B)));
}
t0.sqr();
t1.sqr();
t2.sqr();
t3.mul(&self.y);
t3.dbl();
t3.norm();
z3.mul(&self.x);
z3.dbl();
z3.norm();
y3.copy(&t2);
if rom::CURVE_B_I == 0 {
y3.mul(&b);
} else {
y3.imul(rom::CURVE_B_I);
}
y3.sub(&z3);
x3.copy(&y3);
x3.add(&y3);
x3.norm();
y3.add(&x3);
x3.copy(&t1);
x3.sub(&y3);
x3.norm();
y3.add(&t1);
y3.norm();
y3.mul(&x3);
x3.mul(&t3);
t3.copy(&t2);
t3.add(&t2);
t2.add(&t3);
if rom::CURVE_B_I == 0 {
z3.mul(&b);
} else {
z3.imul(rom::CURVE_B_I);
}
z3.sub(&t2);
z3.sub(&t0);
z3.norm();
t3.copy(&z3);
t3.add(&z3);
z3.add(&t3);
z3.norm();
t3.copy(&t0);
t3.add(&t0);
t0.add(&t3);
t0.sub(&t2);
t0.norm();
t0.mul(&z3);
y3.add(&t0);
t0.copy(&self.y);
t0.mul(&self.z);
t0.dbl();
t0.norm();
z3.mul(&t0);
x3.sub(&z3);
t0.dbl();
t0.norm();
t1.dbl();
t1.norm();
z3.copy(&t0);
z3.mul(&t1);
self.x.copy(&x3);
self.x.norm();
self.y.copy(&y3);
self.y.norm();
self.z.copy(&z3);
self.z.norm();
}
}
if CURVETYPE == EDWARDS {
let mut c = FP::new_copy(&self.x);
let mut d = FP::new_copy(&self.y);
let mut h = FP::new_copy(&self.z);
let mut j = FP::new();
self.x.mul(&self.y);
self.x.dbl();
self.x.norm();
c.sqr();
d.sqr();
if rom::CURVE_A == -1 {
c.neg()
}
self.y.copy(&c);
self.y.add(&d);
self.y.norm();
h.sqr();
h.dbl();
self.z.copy(&self.y);
j.copy(&self.y);
j.sub(&h);
j.norm();
self.x.mul(&j);
c.sub(&d);
c.norm();
self.y.mul(&c);
self.z.mul(&j);
}
if CURVETYPE == MONTGOMERY {
let mut a = FP::new_copy(&self.x);
let mut b = FP::new_copy(&self.x);
let mut aa = FP::new();
let mut bb = FP::new();
let mut c = FP::new();
a.add(&self.z);
a.norm();
aa.copy(&a);
aa.sqr();
b.sub(&self.z);
b.norm();
bb.copy(&b);
bb.sqr();
c.copy(&aa);
c.sub(&bb);
c.norm();
self.x.copy(&aa);
self.x.mul(&bb);
a.copy(&c);
a.imul((rom::CURVE_A + 2) / 4);
bb.add(&a);
bb.norm();
self.z.copy(&bb);
self.z.mul(&c);
}
return;
}
pub fn add(&mut self, Q: &ECP) {
if CURVETYPE == WEIERSTRASS {
if rom::CURVE_A == 0 {
let b = 3 * rom::CURVE_B_I;
let mut t0 = FP::new_copy(&self.x);
t0.mul(&Q.x);
let mut t1 = FP::new_copy(&self.y);
t1.mul(&Q.y);
let mut t2 = FP::new_copy(&self.z);
t2.mul(&Q.z);
let mut t3 = FP::new_copy(&self.x);
t3.add(&self.y);
t3.norm();
let mut t4 = FP::new_copy(&Q.x);
t4.add(&Q.y);
t4.norm();
t3.mul(&t4);
t4.copy(&t0);
t4.add(&t1);
t3.sub(&t4);
t3.norm();
t4.copy(&self.y);
t4.add(&self.z);
t4.norm();
let mut x3 = FP::new_copy(&Q.y);
x3.add(&Q.z);
x3.norm();
t4.mul(&x3);
x3.copy(&t1);
x3.add(&t2);
t4.sub(&x3);
t4.norm();
x3.copy(&self.x);
x3.add(&self.z);
x3.norm();
let mut y3 = FP::new_copy(&Q.x);
y3.add(&Q.z);
y3.norm();
x3.mul(&y3);
y3.copy(&t0);
y3.add(&t2);
y3.rsub(&x3);
y3.norm();
x3.copy(&t0);
x3.add(&t0);
t0.add(&x3);
t0.norm();
t2.imul(b);
let mut z3 = FP::new_copy(&t1);
z3.add(&t2);
z3.norm();
t1.sub(&t2);
t1.norm();
y3.imul(b);
x3.copy(&y3);
x3.mul(&t4);
t2.copy(&t3);
t2.mul(&t1);
x3.rsub(&t2);
y3.mul(&t0);
t1.mul(&z3);
y3.add(&t1);
t0.mul(&t3);
z3.mul(&t4);
z3.add(&t0);
self.x.copy(&x3);
self.x.norm();
self.y.copy(&y3);
self.y.norm();
self.z.copy(&z3);
self.z.norm();
} else {
let mut t0 = FP::new_copy(&self.x);
let mut t1 = FP::new_copy(&self.y);
let mut t2 = FP::new_copy(&self.z);
let mut t3 = FP::new_copy(&self.x);
let mut t4 = FP::new_copy(&Q.x);
let mut z3 = FP::new();
let mut y3 = FP::new_copy(&Q.x);
let mut x3 = FP::new_copy(&Q.y);
let mut b = FP::new();
if rom::CURVE_B_I == 0 {
b.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B)));
}
t0.mul(&Q.x);
t1.mul(&Q.y);
t2.mul(&Q.z);
t3.add(&self.y);
t3.norm();
t4.add(&Q.y);
t4.norm();
t3.mul(&t4);
t4.copy(&t0);
t4.add(&t1);
t3.sub(&t4);
t3.norm();
t4.copy(&self.y);
t4.add(&self.z);
t4.norm();
x3.add(&Q.z);
x3.norm();
t4.mul(&x3);
x3.copy(&t1);
x3.add(&t2);
t4.sub(&x3);
t4.norm();
x3.copy(&self.x);
x3.add(&self.z);
x3.norm();
y3.add(&Q.z);
y3.norm();
x3.mul(&y3);
y3.copy(&t0);
y3.add(&t2);
y3.rsub(&x3);
y3.norm();
z3.copy(&t2);
if rom::CURVE_B_I == 0 {
z3.mul(&b);
} else {
z3.imul(rom::CURVE_B_I);
}
x3.copy(&y3);
x3.sub(&z3);
x3.norm();
z3.copy(&x3);
z3.add(&x3);
x3.add(&z3);
z3.copy(&t1);
z3.sub(&x3);
z3.norm();
x3.add(&t1);
x3.norm();
if rom::CURVE_B_I == 0 {
y3.mul(&b);
} else {
y3.imul(rom::CURVE_B_I);
}
t1.copy(&t2);
t1.add(&t2);
t2.add(&t1);
y3.sub(&t2);
y3.sub(&t0);
y3.norm();
t1.copy(&y3);
t1.add(&y3);
y3.add(&t1);
y3.norm();
t1.copy(&t0);
t1.add(&t0);
t0.add(&t1);
t0.sub(&t2);
t0.norm();
t1.copy(&t4);
t1.mul(&y3);
t2.copy(&t0);
t2.mul(&y3);
y3.copy(&x3);
y3.mul(&z3);
y3.add(&t2);
x3.mul(&t3);
x3.sub(&t1);
z3.mul(&t4);
t1.copy(&t3);
t1.mul(&t0);
z3.add(&t1);
self.x.copy(&x3);
self.x.norm();
self.y.copy(&y3);
self.y.norm();
self.z.copy(&z3);
self.z.norm();
}
}
if CURVETYPE == EDWARDS {
let bb = FP::new_big(&BIG::new_ints(&rom::CURVE_B));
let mut a = FP::new_copy(&self.z);
let mut b = FP::new();
let mut c = FP::new_copy(&self.x);
let mut d = FP::new_copy(&self.y);
let mut e = FP::new();
let mut f = FP::new();
let mut g = FP::new();
a.mul(&Q.z);
b.copy(&a);
b.sqr();
c.mul(&Q.x);
d.mul(&Q.y);
e.copy(&c);
e.mul(&d);
e.mul(&bb);
f.copy(&b);
f.sub(&e);
g.copy(&b);
g.add(&e);
if rom::CURVE_A == 1 {
e.copy(&d);
e.sub(&c);
}
c.add(&d);
b.copy(&self.x);
b.add(&self.y);
d.copy(&Q.x);
d.add(&Q.y);
b.norm();
d.norm();
b.mul(&d);
b.sub(&c);
b.norm();
f.norm();
b.mul(&f);
self.x.copy(&a);
self.x.mul(&b);
g.norm();
if rom::CURVE_A == 1 {
e.norm();
c.copy(&e);
c.mul(&g);
}
if rom::CURVE_A == -1 {
c.norm();
c.mul(&g);
}
self.y.copy(&a);
self.y.mul(&c);
self.z.copy(&f);
self.z.mul(&g);
}
return;
}
pub fn dadd(&mut self, Q: &ECP, W: &ECP) {
let mut a = FP::new_copy(&self.x);
let mut b = FP::new_copy(&self.x);
let mut c = FP::new_copy(&Q.x);
let mut d = FP::new_copy(&Q.x);
let mut da = FP::new();
let mut cb = FP::new();
a.add(&self.z);
b.sub(&self.z);
c.add(&Q.z);
d.sub(&Q.z);
a.norm();
d.norm();
da.copy(&d);
da.mul(&a);
c.norm();
b.norm();
cb.copy(&c);
cb.mul(&b);
a.copy(&da);
a.add(&cb);
a.norm();
a.sqr();
b.copy(&da);
b.sub(&cb);
b.norm();
b.sqr();
self.x.copy(&a);
self.z.copy(&W.x);
self.z.mul(&b);
}
pub fn sub(&mut self, Q: &ECP) {
let mut NQ = ECP::new();
NQ.copy(Q);
NQ.neg();
self.add(&NQ);
}
pub fn pinmul(&self, e: i32, bts: i32) -> ECP {
if CURVETYPE == MONTGOMERY {
return self.mul(&mut BIG::new_int(e as isize));
} else {
let mut P = ECP::new();
let mut R0 = ECP::new();
let mut R1 = ECP::new();
R1.copy(&self);
for i in (0..bts).rev() {
let b = ((e >> i) & 1) as isize;
P.copy(&R1);
P.add(&mut R0);
R0.cswap(&mut R1, b);
R1.copy(&P);
R0.dbl();
R0.cswap(&mut R1, b);
}
P.copy(&R0);
return P;
}
}
pub fn mul(&self, e: &BIG) -> ECP {
if e.iszilch() || self.is_infinity() {
return ECP::new();
}
let mut P = ECP::new();
if CURVETYPE == MONTGOMERY {
let mut D = ECP::new();
let mut R0 = ECP::new();
R0.copy(&self);
let mut R1 = ECP::new();
R1.copy(&self);
R1.dbl();
D.copy(&self);
let nb = e.nbits();
for i in (0..nb - 1).rev() {
let b = e.bit(i);
P.copy(&R1);
P.dadd(&mut R0, &D);
R0.cswap(&mut R1, b);
R1.copy(&P);
R0.dbl();
R0.cswap(&mut R1, b);
}
P.copy(&R0)
} else {
let mut mt = BIG::new();
let mut t = BIG::new();
let mut Q = ECP::new();
let mut C = ECP::new();
let mut W: [ECP; 8] = [
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
];
const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 3) / 4;
let mut w: [i8; CT] = [0; CT];
Q.copy(&self);
Q.dbl();
W[0].copy(&self);
for i in 1..8 {
C.copy(&W[i - 1]);
W[i].copy(&C);
W[i].add(&mut Q);
}
t.copy(&e);
let s = t.parity();
t.inc(1);
t.norm();
let ns = t.parity();
mt.copy(&t);
mt.inc(1);
mt.norm();
t.cmove(&mt, s);
Q.cmove(&self, ns);
C.copy(&Q);
let nb = 1 + (t.nbits() + 3) / 4;
for i in 0..nb {
w[i] = (t.lastbits(5) - 16) as i8;
t.dec(w[i] as isize);
t.norm();
t.fshr(4);
}
w[nb] = t.lastbits(5) as i8;
P.copy(&W[((w[nb] as usize) - 1) / 2]);
for i in (0..nb).rev() {
Q.selector(&W, w[i] as i32);
P.dbl();
P.dbl();
P.dbl();
P.dbl();
P.add(&mut Q);
}
P.sub(&mut C);
}
return P;
}
pub fn mul2(&self, e: &BIG, Q: &ECP, f: &BIG) -> ECP {
let mut te = BIG::new();
let mut tf = BIG::new();
let mut mt = BIG::new();
let mut S = ECP::new();
let mut T = ECP::new();
let mut C = ECP::new();
let mut W: [ECP; 8] = [
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
];
const CT: usize = 1 + (big::NLEN * (big::BASEBITS as usize) + 1) / 2;
let mut w: [i8; CT] = [0; CT];
te.copy(e);
tf.copy(f);
W[1].copy(&self);
W[1].sub(Q);
W[2].copy(&self);
W[2].add(Q);
S.copy(&Q);
S.dbl();
C.copy(&W[1]);
W[0].copy(&C);
W[0].sub(&mut S);
C.copy(&W[2]);
W[3].copy(&C);
W[3].add(&mut S);
T.copy(&self);
T.dbl();
C.copy(&W[1]);
W[5].copy(&C);
W[5].add(&mut T);
C.copy(&W[2]);
W[6].copy(&C);
W[6].add(&mut T);
C.copy(&W[5]);
W[4].copy(&C);
W[4].sub(&mut S);
C.copy(&W[6]);
W[7].copy(&C);
W[7].add(&mut S);
let mut s = te.parity();
te.inc(1);
te.norm();
let mut ns = te.parity();
mt.copy(&te);
mt.inc(1);
mt.norm();
te.cmove(&mt, s);
T.cmove(&self, ns);
C.copy(&T);
s = tf.parity();
tf.inc(1);
tf.norm();
ns = tf.parity();
mt.copy(&tf);
mt.inc(1);
mt.norm();
tf.cmove(&mt, s);
S.cmove(&Q, ns);
C.add(&mut S);
mt.copy(&te);
mt.add(&tf);
mt.norm();
let nb = 1 + (mt.nbits() + 1) / 2;
for i in 0..nb {
let a = te.lastbits(3) - 4;
te.dec(a);
te.norm();
te.fshr(2);
let b = tf.lastbits(3) - 4;
tf.dec(b);
tf.norm();
tf.fshr(2);
w[i] = (4 * a + b) as i8;
}
w[nb] = (4 * te.lastbits(3) + tf.lastbits(3)) as i8;
S.copy(&W[((w[nb] as usize) - 1) / 2]);
for i in (0..nb).rev() {
T.selector(&W, w[i] as i32);
S.dbl();
S.dbl();
S.add(&mut T);
}
S.sub(&mut C);
return S;
}
pub fn cfp(&mut self) {
let cf = rom::CURVE_COF_I;
if cf == 1 {
return;
}
if cf == 4 {
self.dbl();
self.dbl();
return;
}
if cf == 8 {
self.dbl();
self.dbl();
self.dbl();
return;
}
let c = BIG::new_ints(&rom::CURVE_COF);
let P = self.mul(&c);
self.copy(&P);
}
#[allow(non_snake_case)]
pub fn hap2point(h: &BIG) -> ECP {
let mut P: ECP;
let mut x =BIG::new_copy(&h);
loop {
if CURVETYPE != MONTGOMERY {
P = ECP::new_bigint(&x, 0);
} else {
P = ECP::new_big(&x);
}
x.inc(1);
x.norm();
if !P.is_infinity() {
break;
}
}
return P;
}
#[allow(non_snake_case)]
pub fn map2point(h: &FP) -> ECP {
let mut P = ECP::new();
if CURVETYPE == MONTGOMERY {
let mut X1=FP::new();
let mut X2=FP::new();
let mut t =FP::new_copy(h);
let one=FP::new_int(1);
let A=FP::new_int(rom::CURVE_A);
t.sqr();
if fp::PM1D2 == 2 {
t.dbl();
}
if fp::PM1D2 == 1 {
t.neg();
}
if fp::PM1D2 > 2 {
t.imul(fp::QNRI as isize);
}
t.add(&one);
t.norm();
t.inverse();
X1.copy(&t); X1.mul(&A);
X1.neg();
X2.copy(&X1);
X2.add(&A); X2.norm();
X2.neg();
let rhs=ECP::rhs(&X2);
X1.cmove(&X2,rhs.qr(None));
let a=X1.redc();
P.copy(&ECP::new_big(&a));
}
if CURVETYPE == EDWARDS {
let mut X1=FP::new();
let mut X2=FP::new();
let mut t=FP::new_copy(h);
let mut w1=FP::new();
let mut w2=FP::new();
let one=FP::new_int(1);
let mut B = FP::new_big(&BIG::new_ints(&rom::CURVE_B));
let mut A: FP;
let mut K=FP::new();
let sgn=t.sign();
let rfc: isize;
if fp::MODTYPE != fp::GENERALISED_MERSENNE {
A=FP::new_copy(&B);
if rom::CURVE_A==1 {
A.add(&one);
B.sub(&one);
} else {
A.sub(&one);
B.add(&one);
}
A.norm(); B.norm();
A.div2();
B.div2();
B.div2();
K.copy(&B);
K.neg();
K.inverse();
rfc=fp::RIADZ;
if rfc==1 {
A.mul(&K);
K=K.sqrt(None);
} else {
B.sqr();
}
} else {
rfc=1;
A=FP::new_int(156326);
}
t.sqr();
if fp::PM1D2 == 2 {
t.dbl();
}
if fp::PM1D2 == 1 {
t.neg();
}
if fp::PM1D2 > 2 {
t.imul(fp::QNRI as isize);
}
t.add(&one); t.norm();
t.inverse();
X1.copy(&t); X1.mul(&A);
X1.neg();
X2.copy(&X1);
X2.add(&A); X2.norm();
X2.neg();
X1.norm();
t.copy(&X1); t.sqr(); w1.copy(&t); w1.mul(&X1);
t.mul(&A); w1.add(&t);
if rfc==0 {
t.copy(&X1); t.mul(&B);
w1.add(&t);
} else {
w1.add(&X1);
}
w1.norm();
X2.norm();
t.copy(&X2); t.sqr(); w2.copy(&t); w2.mul(&X2);
t.mul(&A); w2.add(&t);
if rfc==0 {
t.copy(&X2); t.mul(&B);
w2.add(&t);
} else {
w2.add(&X2);
}
w2.norm();
let qres=w2.qr(None);
X1.cmove(&X2,qres);
w1.cmove(&w2,qres);
let mut Y=w1.sqrt(None);
if rfc==0 {
X1.mul(&K);
Y.mul(&K);
}
let ne=Y.sign()^sgn;
let mut NY=FP::new_copy(&Y); NY.neg(); NY.norm();
Y.cmove(&NY,ne);
if fp::MODTYPE == fp::GENERALISED_MERSENNE {
t.copy(&X1); t.sqr();
NY.copy(&t); NY.add(&one); NY.norm();
t.sub(&one); t.norm();
w1.copy(&t); w1.mul(&Y);
w1.dbl(); w1.dbl(); w1.norm();
t.sqr();
Y.sqr(); Y.dbl(); Y.dbl(); Y.norm();
w2.copy(&t); w2.add(&Y); w2.norm();
w2.inverse();
w1.mul(&w2);
w2.copy(&Y); w2.sub(&t); w2.norm();
w2.mul(&X1);
t.mul(&X1);
X1.copy(&w1);
Y.div2();
w1.copy(&Y); w1.mul(&NY);
w1.rsub(&t); w1.norm();
w1.inverse();
Y.copy(&w2); Y.mul(&w1);
} else {
w1.copy(&X1); w1.add(&one); w1.norm();
w2.copy(&X1); w2.sub(&one); w2.norm();
t.copy(&w1); t.mul(&Y);
t.inverse();
X1.mul(&w1);
X1.mul(&t);
if rfc==1 {
X1.mul(&K);
}
Y.mul(&w2);
Y.mul(&t);
}
let x=X1.redc();
let y=Y.redc();
P.copy(&ECP::new_bigs(&x,&y));
}
if CURVETYPE==WEIERSTRASS {
let mut X1=FP::new();
let mut X2=FP::new();
let mut X3=FP::new();
let one=FP::new_int(1);
let B = FP::new_big(&BIG::new_ints(&rom::CURVE_B));
let mut Y=FP::new();
let mut NY=FP::new();
let mut t=FP::new_copy(h);
let mut x=BIG::new_int(0);
let sgn=t.sign();
if rom::CURVE_A != 0
{
let mut A=FP::new_int(rom::CURVE_A);
t.sqr();
t.imul(fp::RIADZ);
let mut w=FP::new_copy(&t); w.add(&one); w.norm();
w.mul(&t);
A.mul(&w);
A.inverse();
w.add(&one); w.norm();
w.mul(&B);
w.neg(); w.norm();
X2.copy(&w); X2.mul(&A);
X3.copy(&t); X3.mul(&X2);
let mut rhs=ECP::rhs(&X3);
X2.cmove(&X3,rhs.qr(None));
rhs.copy(&ECP::rhs(&X2));
Y.copy(&rhs.sqrt(None));
x.copy(&X2.redc());
} else {
let Z=fp::RIADZ;
X1.copy(&FP::new_int(Z));
X3.copy(&X1);
let mut A=ECP::rhs(&X1);
t.sqr();
Y.copy(&A); Y.mul(&t);
t.copy(&one); t.add(&Y); t.norm();
Y.rsub(&one); Y.norm();
NY.copy(&t); NY.mul(&Y); NY.inverse();
A.neg(); A.norm();
let mut w=FP::new_copy(&A); w.imul(3); X2.copy(&w.sqrt(None)); w.copy(&X2);
w.imul(Z);
w.mul(&h); w.mul(&Y); w.mul(&NY);
X1.neg(); X1.norm(); X1.div2();
X2.copy(&X1);
X1.sub(&w); X1.norm();
X2.add(&w); X2.norm();
A.dbl(); A.dbl(); A.norm();
t.sqr(); t.mul(&NY); t.sqr();
A.mul(&t);
t.copy(&FP::new_int(Z*Z*3));
t.inverse();
A.mul(&t);
X3.add(&A); X3.norm();
let mut rhs=ECP::rhs(&X2);
X3.cmove(&X2,rhs.qr(None));
rhs.copy(&ECP::rhs(&X1));
X3.cmove(&X1,rhs.qr(None));
rhs.copy(&ECP::rhs(&X3));
Y.copy(&rhs.sqrt(None));
x.copy(&X3.redc());
}
let ne=Y.sign()^sgn;
NY.copy(&Y); NY.neg(); NY.norm();
Y.cmove(&NY,ne);
let y=Y.redc();
P.copy(&ECP::new_bigs(&x,&y));
}
return P;
}
#[allow(non_snake_case)]
pub fn mapit(h: &[u8]) -> ECP {
let q = BIG::new_ints(&rom::MODULUS);
let mut dx = DBIG::frombytes(h);
let mut x=dx.dmod(&q);
let mut P=ECP::hap2point(&mut x);
P.cfp();
return P;
}
pub fn generator() -> ECP {
let G: ECP;
let gx = BIG::new_ints(&rom::CURVE_GX);
if CURVETYPE != MONTGOMERY {
let gy = BIG::new_ints(&rom::CURVE_GY);
G = ECP::new_bigs(&gx, &gy);
} else {
G = ECP::new_big(&gx);
}
return G;
}
}