| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you 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. |
| */ |
| |
| use xxx::fp::FP; |
| use xxx::big::BIG; |
| use xxx::big; |
| use xxx::rom; |
| |
| pub struct ECP { |
| x:FP, |
| y:FP, |
| z:FP, |
| // inf: bool |
| } |
| |
| 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=@CT@; |
| pub const CURVE_PAIRING_TYPE:usize=@PF@; |
| pub const SEXTIC_TWIST:usize=@ST@; |
| pub const SIGN_OF_X:usize=@SX@; |
| |
| pub const HASH_TYPE:usize=@HT@; |
| pub const AESKEY:usize=@AK@; |
| |
| #[allow(non_snake_case)] |
| impl ECP { |
| |
| pub fn pnew() -> ECP { |
| ECP { |
| x: FP::new(), |
| y: FP::new_int(1), |
| z: FP::new(), |
| // inf: true |
| } |
| |
| } |
| |
| pub fn new() -> ECP { |
| let mut E=ECP::pnew(); |
| if CURVETYPE==EDWARDS { |
| E.z.one(); |
| } |
| return E; |
| } |
| |
| /* set (x,y) from two BIGs */ |
| 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.jacobi()==1 { |
| // E.inf=false; |
| } else {E.inf()} |
| } else { |
| let mut y2=FP::new_copy(&E.y); |
| y2.sqr(); |
| if y2.equals(&mut rhs) { |
| // E.inf=false |
| } else {E.inf()} |
| } |
| return E; |
| } |
| |
| /* set (x,y) from BIG and a bit */ |
| pub fn new_bigint(ix: &BIG,s: isize) -> ECP { |
| let mut E=ECP::new(); |
| E.x.bcopy(ix); |
| E.x.norm(); |
| E.z.one(); |
| |
| let mut rhs=ECP::rhs(&E.x); |
| |
| if rhs.jacobi()==1 { |
| let mut ny=rhs.sqrt(); |
| if ny.redc().parity()!=s {ny.neg()} |
| E.y.copy(&ny); |
| // E.inf=false; |
| } else {E.inf()} |
| return E; |
| } |
| |
| #[allow(non_snake_case)] |
| /* set from x - calculate y from curve equation */ |
| pub fn new_big(ix: &BIG) -> ECP { |
| let mut E=ECP::new(); |
| E.x.bcopy(ix); |
| E.x.norm(); |
| E.z.one(); |
| let mut rhs=ECP::rhs(&E.x); |
| if rhs.jacobi()==1 { |
| if CURVETYPE!=MONTGOMERY {E.y.copy(&rhs.sqrt())} |
| // E.inf=false; |
| } else {E.inf();} |
| return E; |
| } |
| |
| /* set this=O */ |
| pub fn inf(&mut self) { |
| // self.inf=true; |
| self.x.zero(); |
| if CURVETYPE!=MONTGOMERY { |
| self.y.one(); |
| } |
| if CURVETYPE!=EDWARDS { |
| self.z.zero(); |
| } else {self.z.one()} |
| } |
| |
| /* Calculate RHS of curve equation */ |
| fn rhs(x: &FP) -> FP { |
| //x.norm(); |
| let mut r=FP::new_copy(x); |
| r.sqr(); |
| |
| if CURVETYPE==WEIERSTRASS { // x^3+Ax+B |
| 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 { // (Ax^2-1)/(Bx^2-1) |
| 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 { // x^3+Ax^2+x |
| 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; |
| } |
| |
| /* test for O point-at-infinity */ |
| pub fn is_infinity(&self) -> bool { |
| // if self.inf {return true} |
| let xx=FP::new_copy(&self.x); |
| let zz=FP::new_copy(&self.z); |
| |
| if CURVETYPE==EDWARDS { |
| let yy=FP::new_copy(&self.y); |
| return xx.iszilch() && yy.equals(&zz); |
| } |
| if CURVETYPE==WEIERSTRASS { |
| return xx.iszilch() && zz.iszilch(); |
| } |
| if CURVETYPE==MONTGOMERY { |
| return zz.iszilch(); |
| } |
| return true; |
| } |
| |
| /* Conditional swap of P and Q dependant on d */ |
| 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); |
| /* |
| let mut bd=true; |
| if d==0 {bd=false} |
| bd=bd&&(self.inf!=Q.inf); |
| self.inf=bd!=self.inf; |
| Q.inf=bd!=Q.inf; */ |
| } |
| |
| /* Conditional move of Q to P dependant on 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); |
| /* |
| let mut bd=true; |
| if d==0 {bd=false} |
| self.inf=(self.inf!=((self.inf!=Q.inf)&&bd)); */ |
| } |
| |
| /* return 1 if b==c, no branching */ |
| fn teq(b: i32,c: i32) -> isize { |
| let mut x=b^c; |
| x-=1; // if x=0, x now -1 |
| return ((x>>31)&1) as isize; |
| } |
| |
| /* this=P */ |
| 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); |
| // self.inf=P.inf; |
| } |
| |
| /* this=-this */ |
| pub fn neg(&mut self) { |
| // if self.is_infinity() {return} |
| if CURVETYPE==WEIERSTRASS { |
| self.y.neg(); self.y.norm(); |
| } |
| if CURVETYPE==EDWARDS { |
| self.x.neg(); self.x.norm(); |
| } |
| return; |
| } |
| /* multiply x coordinate */ |
| pub fn mulx(&mut self,c: &mut FP) { |
| self.x.mul(c); |
| } |
| |
| /* Constant time select from pre-computed table */ |
| fn selector(&mut self, W: &[ECP],b: i32) { // unsure about &[& syntax. An array of pointers I hope.. |
| 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)); // conditional move |
| 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); |
| } |
| |
| /* Test P == Q */ |
| pub fn equals(&mut self,Q: &mut ECP) -> bool { |
| // if self.is_infinity() && Q.is_infinity() {return true} |
| // if self.is_infinity() || Q.is_infinity() {return false} |
| |
| 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; |
| } |
| |
| /* set to affine - from (x,y,z) to (x,y) */ |
| 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); |
| } |
| |
| /* extract x as a BIG */ |
| pub fn getx(&self) -> BIG { |
| let mut W=ECP::new(); W.copy(self); |
| W.affine(); |
| return W.x.redc(); |
| } |
| |
| /* extract y as a BIG */ |
| pub fn gety(&self) -> BIG { |
| let mut W=ECP::new(); W.copy(self); |
| W.affine(); |
| return W.y.redc(); |
| } |
| |
| /* get sign of Y */ |
| pub fn gets(&self) -> isize { |
| let y=self.gety(); |
| return y.parity(); |
| } |
| |
| /* extract x as an FP */ |
| pub fn getpx(&self) -> FP { |
| let w=FP::new_copy(&self.x); |
| return w; |
| } |
| /* extract y as an FP */ |
| pub fn getpy(&self) -> FP { |
| let w=FP::new_copy(&self.y); |
| return w; |
| } |
| |
| /* extract z as an FP */ |
| pub fn getpz(&self) -> FP { |
| let w=FP::new_copy(&self.z); |
| return w; |
| } |
| |
| /* convert to byte array */ |
| 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); |
| for i in 0..mb {b[i+1]=t[i]} |
| |
| if CURVETYPE==MONTGOMERY { |
| b[0]=0x06; |
| return; |
| } |
| |
| 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]} |
| } |
| |
| /* convert from byte array to point */ |
| 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); |
| |
| 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 CURVETYPE==MONTGOMERY { |
| return ECP::new_big(&px) |
| } |
| |
| 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() |
| } |
| |
| /* convert to hex string */ |
| pub fn tostring(&self) -> String { |
| let mut W=ECP::new(); W.copy(self); |
| if W.is_infinity() {return String::from("infinity")} |
| //self.affine(); |
| if CURVETYPE==MONTGOMERY { |
| return format!("({})",W.x.redc().tostring()); |
| } else {return format!("({},{})",W.x.redc().tostring(),W.y.redc().tostring())} ; |
| } |
| |
| /* this*=2 */ |
| pub fn dbl(&mut self) { |
| // if self.inf {return} |
| |
| 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(); //1 x^2 |
| t1.sqr(); //2 y^2 |
| t2.sqr(); //3 |
| |
| t3.mul(&self.y); //4 |
| t3.dbl(); t3.norm();//5 |
| z3.mul(&self.x); //6 |
| z3.dbl(); z3.norm();//7 |
| y3.copy(&t2); |
| |
| if rom::CURVE_B_I==0 { |
| y3.mul(&b); //8 |
| } else { |
| y3.imul(rom::CURVE_B_I); |
| } |
| |
| y3.sub(&z3); //y3.norm(); //9 *** |
| x3.copy(&y3); x3.add(&y3); x3.norm();//10 |
| |
| y3.add(&x3); //y3.norm();//11 |
| x3.copy(&t1); x3.sub(&y3); x3.norm();//12 |
| y3.add(&t1); y3.norm();//13 |
| y3.mul(&x3); //14 |
| x3.mul(&t3); //15 |
| t3.copy(&t2); t3.add(&t2); //t3.norm(); //16 |
| t2.add(&t3); //t2.norm(); //17 |
| |
| if rom::CURVE_B_I==0 { |
| z3.mul(&b); //18 |
| } else { |
| z3.imul(rom::CURVE_B_I); |
| } |
| |
| z3.sub(&t2); //z3.norm();//19 |
| z3.sub(&t0); z3.norm();//20 *** |
| t3.copy(&z3); t3.add(&z3); //t3.norm();//21 |
| |
| z3.add(&t3); z3.norm(); //22 |
| t3.copy(&t0); t3.add(&t0); //t3.norm(); //23 |
| t0.add(&t3); //t0.norm();//24 |
| t0.sub(&t2); t0.norm();//25 |
| |
| t0.mul(&z3);//26 |
| y3.add(&t0); //y3.norm();//27 |
| t0.copy(&self.y); t0.mul(&self.z);//28 |
| t0.dbl(); t0.norm(); //29 |
| z3.mul(&t0);//30 |
| x3.sub(&z3); //x3.norm();//31 |
| t0.dbl(); t0.norm();//32 |
| t1.dbl(); t1.norm();//33 |
| z3.copy(&t0); z3.mul(&t1);//34 |
| |
| 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); |
| |
| // self.x.norm(); |
| // self.y.norm(); |
| // self.z.norm(); |
| } |
| 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; |
| } |
| |
| /* self+=Q */ |
| pub fn add(&mut self,Q:&ECP) |
| { |
| /* if self.inf { |
| self.copy(&Q); |
| return; |
| } |
| if Q.inf {return} */ |
| |
| 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); //1 |
| t1.mul(&Q.y); //2 |
| t2.mul(&Q.z); //3 |
| |
| t3.add(&self.y); t3.norm(); //4 |
| t4.add(&Q.y); t4.norm();//5 |
| t3.mul(&t4);//6 |
| t4.copy(&t0); t4.add(&t1); //t4.norm(); //7 |
| t3.sub(&t4); t3.norm(); //8 |
| t4.copy(&self.y); t4.add(&self.z); t4.norm();//9 |
| x3.add(&Q.z); x3.norm();//10 |
| t4.mul(&x3); //11 |
| x3.copy(&t1); x3.add(&t2); //x3.norm();//12 |
| |
| t4.sub(&x3); t4.norm();//13 |
| x3.copy(&self.x); x3.add(&self.z); x3.norm(); //14 |
| y3.add(&Q.z); y3.norm();//15 |
| |
| x3.mul(&y3); //16 |
| y3.copy(&t0); y3.add(&t2); //y3.norm();//17 |
| |
| y3.rsub(&x3); y3.norm(); //18 |
| z3.copy(&t2); |
| |
| |
| if rom::CURVE_B_I==0 { |
| z3.mul(&b); //18 |
| } else { |
| z3.imul(rom::CURVE_B_I); |
| } |
| |
| x3.copy(&y3); x3.sub(&z3); x3.norm(); //20 |
| z3.copy(&x3); z3.add(&x3); //z3.norm(); //21 |
| |
| x3.add(&z3); //x3.norm(); //22 |
| z3.copy(&t1); z3.sub(&x3); z3.norm(); //23 |
| x3.add(&t1); x3.norm(); //24 |
| |
| if rom::CURVE_B_I==0 { |
| y3.mul(&b); //18 |
| } else { |
| y3.imul(rom::CURVE_B_I); |
| } |
| |
| t1.copy(&t2); t1.add(&t2); //t1.norm();//26 |
| t2.add(&t1); //t2.norm();//27 |
| |
| y3.sub(&t2); //y3.norm(); //28 |
| |
| y3.sub(&t0); y3.norm(); //29 |
| t1.copy(&y3); t1.add(&y3); //t1.norm();//30 |
| y3.add(&t1); y3.norm(); //31 |
| |
| t1.copy(&t0); t1.add(&t0); //t1.norm(); //32 |
| t0.add(&t1); //t0.norm();//33 |
| t0.sub(&t2); t0.norm();//34 |
| t1.copy(&t4); t1.mul(&y3);//35 |
| t2.copy(&t0); t2.mul(&y3);//36 |
| y3.copy(&x3); y3.mul(&z3);//37 |
| y3.add(&t2); //y3.norm();//38 |
| x3.mul(&t3);//39 |
| x3.sub(&t1);//40 |
| z3.mul(&t4);//41 |
| t1.copy(&t3); t1.mul(&t0);//42 |
| 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; |
| } |
| |
| /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ |
| 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); |
| } |
| |
| /* self-=Q */ |
| pub fn sub(&mut self,Q:&ECP) { |
| let mut NQ=ECP::new(); NQ.copy(Q); |
| NQ.neg(); |
| self.add(&NQ); |
| } |
| |
| /* constant time multiply by small integer of length bts - use ladder */ |
| 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); |
| P.affine(); |
| return P; |
| } |
| } |
| |
| /* return e.self */ |
| |
| pub fn mul(&self,e:&BIG) -> ECP { |
| if e.iszilch() || self.is_infinity() {return ECP::new()} |
| let mut P=ECP::new(); |
| if CURVETYPE==MONTGOMERY { |
| /* use Ladder */ |
| 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=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 { |
| // fixed size windows |
| 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]; |
| |
| // self.affine(); |
| |
| 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); |
| } |
| |
| // make exponent odd - add 2P if even, P if odd |
| 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; |
| |
| // convert exponent to signed 4-bit window |
| 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); /* apply correction */ |
| } |
| P.affine(); |
| return P; |
| } |
| |
| /* Return e.this+f.Q */ |
| |
| 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]; |
| |
| // self.affine(); |
| // Q.affine(); |
| |
| te.copy(e); |
| tf.copy(f); |
| |
| // precompute table |
| |
| 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); // copy to C is stupid Rust thing.. |
| 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); |
| |
| // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction |
| |
| 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; |
| |
| // convert exponent to signed 2-bit window |
| 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); /* apply correction */ |
| S.affine(); |
| return S; |
| } |
| |
| pub fn cfp(&mut self) { |
| let cf=rom::CURVE_COF_I; |
| if cf==1 {return} |
| if cf==4 { |
| self.dbl(); self.dbl(); |
| //self.affine(); |
| return; |
| } |
| if cf==8 { |
| self.dbl(); self.dbl(); self.dbl(); |
| //self.affine(); |
| return; |
| } |
| let c=BIG::new_ints(&rom::CURVE_COF); |
| let P=self.mul(&c); |
| self.copy(&P); |
| } |
| |
| |
| #[allow(non_snake_case)] |
| pub fn mapit(h: &[u8]) -> ECP { |
| let mut q=BIG::new_ints(&rom::MODULUS); |
| let mut x=BIG::frombytes(h); |
| x.rmod(&mut q); |
| let mut P:ECP; |
| |
| loop { |
| 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.cfp(); |
| if !P.is_infinity() {break} |
| } |
| |
| 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; |
| } |
| |
| } |
| /* |
| fn main() |
| { |
| let mut E=ECP::new(); |
| |
| let mut W:[&ECP;8]=[&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new(),&ECP::new()]; |
| |
| let mut gx=BIG::new_ints(&rom::CURVE_GX); |
| let mut gy=BIG::new(); |
| let mut P=ECP::new(); |
| |
| if CURVETYPE!=MONTGOMERY {gy.copy(&BIG::new_ints(&rom::CURVE_GY))} |
| let mut r=BIG::new_ints(&rom::CURVE_ORDER); |
| |
| //r.dec(7); |
| |
| println!("gx= {}",gx.tostring()); |
| |
| if CURVETYPE!=MONTGOMERY { |
| println!("gy= {}",gy.tostring()); |
| } |
| |
| if CURVETYPE!=MONTGOMERY { |
| P.copy(&ECP::new_bigs(&gx,&gy))} |
| else {P.copy(&ECP::new_big(&gx))} |
| |
| println!("P= {}",P.tostring()); |
| |
| let mut R=P.mul(&mut r); |
| //for i in 0..10000 (R=P.mul(r)); |
| |
| println!("R= {}",R.tostring()); |
| |
| } |
| */ |