use crate::c41417::big;
use crate::c41417::big::BIG;
use crate::c41417::dbig::DBIG;
use crate::c41417::fp::FP;
use crate::c41417::fp;
use crate::c41417::rom;
#[derive(Clone)]
pub struct ECP {
x: FP,
y: FP,
z: FP,
}
#[cfg(feature = "std")]
impl std::fmt::Debug for ECP {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "{}", self.tostring())
}
}
#[cfg(feature = "std")]
impl std::fmt::Display for ECP {
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "{}", self.tostring())
}
}
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 BLS12: usize = 2;
pub const BLS24: usize = 3;
pub const BLS48: usize = 4;
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=EDWARDS;
pub const CURVE_A:isize=1;
pub const CURVE_PAIRING_TYPE:usize=NOT;
pub const SEXTIC_TWIST:usize=NOT;
pub const SIGN_OF_X:usize=NOT;
pub const ATE_BITS:usize=NOT;
pub const G2_TABLE:usize=NOT;
pub const HTC_ISO:usize=0;
pub const HTC_ISO_G2:usize=0;
pub const ALLOW_ALT_COMPRESS:bool=false;
pub const HASH_TYPE:usize=64;
pub const AESKEY:usize=32;
#[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();
}
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 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(&rhs) {
E.inf();
}
}
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 rhs = ECP::rhs(&E.x);
if rhs.qr(Some(&mut hint)) == 1 {
let mut ny = rhs.sqrt(Some(&hint));
if ny.sign() != s {
ny.neg(); ny.norm()
}
E.y.copy(&ny);
} else {
E.inf()
}
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 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();
}
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 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 CURVE_A == -1 {
r.neg()
}
r.sub(&one);
r.norm();
b.inverse(None);
r.mul(&b);
}
if CURVETYPE == MONTGOMERY {
let mut x3 = FP::new();
x3.copy(&r);
x3.mul(x);
r.imul(CURVE_A);
r.add(&x3);
r.add(&x);
}
r.reduce();
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();
}
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; ((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();
}
}
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(&self, Q: &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(&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(&b) {
return false;
}
}
true
}
pub fn affine(&mut self) {
if self.is_infinity() {
return;
}
let one = FP::new_int(1);
if self.z.equals(&one) {
return;
}
self.z.inverse(None);
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();
W.x.redc()
}
pub fn gety(&self) -> BIG {
let mut W = ECP::new();
W.copy(self);
W.affine();
W.y.redc()
}
pub fn gets(&self) -> isize {
let mut W = ECP::new();
W.copy(self);
W.affine();
W.y.sign()
}
pub fn getpx(&self) -> FP {
FP::new_copy(&self.x)
}
pub fn getpy(&self) -> FP {
FP::new_copy(&self.y)
}
pub fn getpz(&self) -> FP {
FP::new_copy(&self.z)
}
pub fn tobytes(&self, b: &mut [u8], compress: bool) {
const MB:usize = big::MODBYTES as usize;
let mut t: [u8; MB] = [0; MB];
let mut alt=false;
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;
}
if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS {
alt=true;
}
if alt {
for i in 0..MB {
b[i]=t[i];
}
if compress {
b[0]|=0x80;
if W.y.islarger()==1 {
b[0]|=0x20;
}
} else {
W.y.redc().tobytes(&mut t);
for i in 0..MB {
b[i+MB]=t[i];
}
}
} else {
for i in 0..MB {
b[i + 1] = t[i];
}
if compress {
b[0] = 0x02;
if W.y.sign() == 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 {
const MB:usize = big::MODBYTES as usize;
let mut t: [u8; MB] = [0; MB];
let mut alt=false;
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);
}
if (fp::MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS {
alt=true;
}
if alt {
for i in 0..MB {
t[i]=b[i];
}
t[0]&=0x1f;
let px=BIG::frombytes(&t);
if (b[0]&0x80)==0 {
for i in 0 ..MB {
t[i]=b[i+MB];
}
let py=BIG::frombytes(&t);
return ECP::new_bigs(&px, &py);
} else {
let sgn=(b[0]&0x20)>>5;
let mut P=ECP::new_bigint(&px,0);
let cmp=P.y.islarger();
if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) {
P.neg();
}
return P;
}
} else {
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);
}
}
ECP::new()
}
#[cfg(feature = "std")]
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 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 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((CURVE_A + 2) / 4);
bb.add(&a);
bb.norm();
self.z.copy(&bb);
self.z.mul(&c);
}
}
pub fn add(&mut self, Q: &ECP) {
if CURVETYPE == WEIERSTRASS {
if 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 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 CURVE_A == 1 {
e.norm();
c.copy(&e);
c.mul(&g);
}
if CURVE_A == -1 {
c.norm();
c.mul(&g);
}
self.y.copy(&a);
self.y.mul(&c);
self.z.copy(&f);
self.z.mul(&g);
}
}
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 {
self.mul(&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(&R0);
R0.cswap(&mut R1, b);
R1.copy(&P);
R0.dbl();
R0.cswap(&mut R1, b);
}
P.copy(&R0);
P
}
}
pub fn mul(&self, e: &BIG) -> ECP {
return self.clmul(e,e);
}
pub fn clmul(&self, e: &BIG, maxe: &BIG) -> ECP {
if e.iszilch() || self.is_infinity() {
return ECP::new();
}
let mut P = ECP::new();
let mut cm = BIG::new_copy(e); cm.or(maxe);
let max=cm.nbits();
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); D.affine();
let nb = max;
for i in (0..nb - 1).rev() {
let b = e.bit(i);
P.copy(&R1);
P.dadd(&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(&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 + (max + 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.selector(&W, w[nb] as i32);
for i in (0..nb).rev() {
Q.selector(&W, w[i] as i32);
P.dbl();
P.dbl();
P.dbl();
P.dbl();
P.add(&Q);
}
P.sub(&C);
}
P
}
pub fn muln(n: usize, X: &[ECP], e: &[BIG]) -> ECP {
let mut B: [ECP; 16] = [
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
ECP::new(),
];
let mut mt = BIG::new();
let mut t = BIG::new();
let mut P = ECP::new();
let mut S = ECP::new();
let mut R = ECP::new();
mt.copy(&e[0]); mt.norm();
for i in 1..n { t.copy(&e[i]); t.norm();
let k=BIG::comp(&t,&mt);
mt.cmove(&t,(k+1)/2);
}
let nb=(mt.nbits()+3)/4;
for i in (0..nb).rev() { for j in 0..16 {
B[j].inf();
}
for j in 0..n {
mt.copy(&e[j]); mt.norm();
mt.shr((i*4) as usize);
let k=mt.lastbits(4) as usize;
B[k].add(&X[j]);
}
R.inf(); S.inf();
for j in (1..16).rev() {
R.add(&B[j]);
S.add(&R);
}
for _ in 0..4 {
P.dbl();
}
P.add(&S);
}
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(&S); C.copy(&W[2]);
W[3].copy(&C);
W[3].add(&S);
T.copy(&self);
T.dbl();
C.copy(&W[1]);
W[5].copy(&C);
W[5].add(&T);
C.copy(&W[2]);
W[6].copy(&C);
W[6].add(&T);
C.copy(&W[5]);
W[4].copy(&C);
W[4].sub(&S);
C.copy(&W[6]);
W[7].copy(&C);
W[7].add(&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(&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.selector(&W, w[nb] as i32);
for i in (0..nb).rev() {
T.selector(&W, w[i] as i32);
S.dbl();
S.dbl();
S.add(&T);
}
S.sub(&C);
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;
}
}
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 mut w =FP::new();
let one=FP::new_int(1);
let A=FP::new_int(CURVE_A);
let mut N =FP::new();
let mut D =FP::new();
let mut hint =FP::new();
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.norm();
D.copy(&t); D.add(&one); D.norm();
X1.copy(&A);
X1.neg(); X1.norm(); X2.copy(&X1);
X2.mul(&t);
w.copy(&X1); w.sqr(); N.copy(&w); N.mul(&X1);
w.mul(&A); w.mul(&D); N.add(&w);
t.copy(&D); t.sqr();
t.mul(&X1);
N.add(&t); N.norm();
t.copy(&N); t.mul(&D); let qres=t.qr(Some(&mut hint)); w.copy(&t); w.inverse(Some(&hint));
D.copy(&w); D.mul(&N); X1.mul(&D); X2.mul(&D); X1.cmove(&X2,1-qres);
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 w=FP::new();
let one=FP::new_int(1);
let mut A=FP::new();
let mut w1=FP::new();
let mut w2=FP::new();
let mut B = FP::new_big(&BIG::new_ints(&rom::CURVE_B));
let mut Y=FP::new();
let mut K=FP::new();
let mut D=FP::new();
let mut hint=FP::new();
let rfc: isize;
if fp::MODTYPE != fp::GENERALISED_MERSENNE {
A.copy(&B);
if 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.norm();
K.invsqrt(&mut w2,&mut w1); K.copy(&w2);
rfc=fp::RIADZ;
if rfc==1 {
A.mul(&K);
K.mul(&w1);
} else {
B.sqr();
}
} else {
rfc=1;
A.copy(&FP::new_int(156326));
}
t.sqr(); let mut qnr=0;
if fp::PM1D2 == 2 {
t.dbl();
qnr=2;
}
if fp::PM1D2 == 1 {
t.neg();
qnr = -1;
}
if fp::PM1D2 > 2 {
t.imul(fp::QNRI as isize); qnr=fp::QNRI as isize;
}
t.norm();
D.copy(&t); D.add(&one); D.norm(); X1.copy(&A);
X1.neg(); X1.norm(); X2.copy(&X1); X2.mul(&t);
w.copy(&X1); w.sqr(); w1.copy(&w); w1.mul(&X1);
w.mul(&A); w.mul(&D); w1.add(&w);
w2.copy(&D); w2.sqr();
if rfc==0 {
w.copy(&X1); w.mul(&B);
w2.mul(&w);
w1.add(&w2); } else {
w2.mul(&X1);
w1.add(&w2); }
w1.norm();
B.copy(&w1); B.mul(&D); let qres=B.qr(Some(&mut hint)); w.copy(&B); w.inverse(Some(&hint));
D.copy(&w); D.mul(&w1); X1.mul(&D); X2.mul(&D); D.sqr();
w1.copy(&B); w1.imul(qnr);
w.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC)));
w.mul(&hint);
w2.copy(&D); w2.mul(&h);
X1.cmove(&X2,1-qres);
B.cmove(&w1,1-qres);
hint.cmove(&w,1-qres);
D.cmove(&w2,1-qres);
Y.copy(&B.sqrt(Some(&hint)));
Y.mul(&D);
w.copy(&Y); w.neg(); w.norm();
Y.cmove(&w,qres^Y.sign());
if rfc==0 {
X1.mul(&K);
Y.mul(&K);
}
if fp::MODTYPE == fp::GENERALISED_MERSENNE {
t.copy(&X1); t.sqr();
w.copy(&t); w.add(&one); w.norm();
t.sub(&one); t.norm();
w1.copy(&t); w1.mul(&Y);
w1.dbl(); X2.copy(&w1); X2.add(&w1); X2.norm();
t.sqr();
Y.sqr(); Y.dbl(); Y.dbl(); Y.norm();
B.copy(&t); B.add(&Y); B.norm();
w2.copy(&Y); w2.sub(&t); w2.norm();
w2.mul(&X1);
t.mul(&X1);
Y.div2();
w1.copy(&Y); w1.mul(&w);
w1.rsub(&t); w1.norm();
t.copy(&X2); t.mul(&w1); P.x.copy(&t);
t.copy(&w2); t.mul(&B);
P.y.copy(&t);
t.copy(&w1); t.mul(&B);
P.z.copy(&t);
return P;
} else {
w1.copy(&X1); w1.add(&one); w1.norm(); w2.copy(&X1); w2.sub(&one); w2.norm(); t.copy(&w1); t.mul(&Y);
X1.mul(&w1);
if rfc==1 {
X1.mul(&K);
}
Y.mul(&w2); P.x.copy(&X1);
P.y.copy(&Y);
P.z.copy(&t);
return P
}
}
if CURVETYPE==WEIERSTRASS {
let mut A=FP::new();
let mut B=FP::new();
let mut X1=FP::new();
let mut X2=FP::new();
let mut X3=FP::new();
let one=FP::new_int(1);
let mut Y=FP::new();
let mut D=FP::new();
let mut t=FP::new_copy(h);
let mut w=FP::new();
let mut D2=FP::new();
let mut hint=FP::new();
let mut GX1=FP::new();
let sgn=t.sign();
if CURVE_A != 0 || HTC_ISO != 0
{ if HTC_ISO != 0 {
} else {
A.copy(&FP::new_int(CURVE_A));
B.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_B)));
}
t.sqr();
t.imul(fp::RIADZ); w.copy(&t); w.add(&one); w.norm();
w.mul(&t); D.copy(&A);
D.mul(&w);
w.add(&one); w.norm();
w.mul(&B);
w.neg(); w.norm();
X2.copy(&w);
X3.copy(&t); X3.mul(&X2);
GX1.copy(&X2); GX1.sqr(); D2.copy(&D);
D2.sqr(); w.copy(&A); w.mul(&D2); GX1.add(&w); GX1.norm(); GX1.mul(&X2); D2.mul(&D); w.copy(&B); w.mul(&D2); GX1.add(&w); GX1.norm();
w.copy(&GX1); w.mul(&D);
let qr=w.qr(Some(&mut hint));
D.copy(&w); D.inverse(Some(&hint));
D.mul(&GX1);
X2.mul(&D);
X3.mul(&D);
t.mul(h);
D2.copy(&D); D2.sqr();
D.copy(&D2); D.mul(&t);
t.copy(&w); t.imul(fp::RIADZ);
X1.copy(&FP::new_big(&BIG::new_ints(&rom::CURVE_HTPC)));
X1.mul(&hint);
X2.cmove(&X3,1-qr);
D2.cmove(&D,1-qr);
w.cmove(&t,1-qr);
hint.cmove(&X1,1-qr);
Y.copy(&w.sqrt(Some(&hint)));
Y.mul(&D2);
let ne=Y.sign()^sgn;
w.copy(&Y); w.neg(); w.norm();
Y.cmove(&w,ne);
if HTC_ISO != 0 {
} else {
let x=X2.redc();
let y=Y.redc();
P.copy(&ECP::new_bigs(&x,&y));
return P;
}
} else {
}
}
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 x=dx.dmod(&q);
let mut P=ECP::hap2point(&x);
P.cfp();
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);
}
G
}
}