| /* |
| 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. |
| */ |
| |
| package XXX |
| |
| //import "fmt" |
| |
| //const WEIERSTRASS int = 0 |
| //const EDWARDS int = 1 |
| //const MONTGOMERY int = 2 |
| //const NOT int = 0 |
| //const BN int = 1 |
| //const BLS int = 2 |
| //const D_TYPE int = 0 |
| //const M_TYPE int = 1 |
| //const POSITIVEX int = 0 |
| //const NEGATIVEX int = 1 |
| |
| |
| //const CURVETYPE int = @CT@ |
| //const CURVE_PAIRING_TYPE int = @PF@ |
| //const SEXTIC_TWIST int = @ST@ |
| //const SIGN_OF_X int = @SX@ |
| |
| //const HASH_TYPE int = @HT@ |
| //const AESKEY int = @AK@ |
| |
| /* Elliptic Curve Point Structure */ |
| |
| type ECP struct { |
| x *FP |
| y *FP |
| z *FP |
| } |
| |
| /* Constructors */ |
| func NewECP() *ECP { |
| E := new(ECP) |
| E.x = NewFPint(0) |
| E.y = NewFPint(1) |
| if CURVETYPE == EDWARDS { |
| E.z = NewFPint(1) |
| } else { |
| E.z = NewFPint(0) |
| } |
| return E |
| } |
| |
| /* set (x,y) from two BIGs */ |
| func NewECPbigs(ix *BIG, iy *BIG) *ECP { |
| E := new(ECP) |
| E.x = NewFPbig(ix) |
| E.y = NewFPbig(iy) |
| E.z = NewFPint(1) |
| E.x.norm() |
| rhs := RHS(E.x) |
| |
| if CURVETYPE == MONTGOMERY { |
| if rhs.jacobi() != 1 { |
| E.inf() |
| } |
| } else { |
| y2 := NewFPcopy(E.y) |
| y2.sqr() |
| if !y2.Equals(rhs) { |
| E.inf() |
| } |
| } |
| return E |
| } |
| |
| /* set (x,y) from BIG and a bit */ |
| func NewECPbigint(ix *BIG, s int) *ECP { |
| E := new(ECP) |
| E.x = NewFPbig(ix) |
| E.y = NewFPint(0) |
| E.x.norm() |
| rhs := RHS(E.x) |
| E.z = NewFPint(1) |
| if rhs.jacobi() == 1 { |
| ny := rhs.sqrt() |
| if ny.redc().parity() != s { |
| ny.neg() |
| } |
| E.y.copy(ny) |
| } else { |
| E.inf() |
| } |
| return E |
| } |
| |
| /* set from x - calculate y from curve equation */ |
| func NewECPbig(ix *BIG) *ECP { |
| E := new(ECP) |
| E.x = NewFPbig(ix) |
| E.y = NewFPint(0) |
| E.x.norm() |
| rhs := RHS(E.x) |
| E.z = NewFPint(1) |
| if rhs.jacobi() == 1 { |
| if CURVETYPE != MONTGOMERY { |
| E.y.copy(rhs.sqrt()) |
| } |
| } else { |
| E.inf() |
| } |
| return E |
| } |
| |
| /* test for O point-at-infinity */ |
| func (E *ECP) Is_infinity() bool { |
| // if E.INF {return true} |
| E.x.reduce() |
| E.z.reduce() |
| if CURVETYPE == EDWARDS { |
| E.y.reduce() |
| return (E.x.iszilch() && E.y.Equals(E.z)) |
| } |
| if CURVETYPE == WEIERSTRASS { |
| E.y.reduce() |
| return (E.x.iszilch() && E.z.iszilch()) |
| } |
| if CURVETYPE == MONTGOMERY { |
| return E.z.iszilch() |
| } |
| return true |
| } |
| |
| /* Conditional swap of P and Q dependant on d */ |
| func (E *ECP) cswap(Q *ECP, d int) { |
| E.x.cswap(Q.x, d) |
| if CURVETYPE != MONTGOMERY { |
| E.y.cswap(Q.y, d) |
| } |
| E.z.cswap(Q.z, d) |
| } |
| |
| /* Conditional move of Q to P dependant on d */ |
| func (E *ECP) cmove(Q *ECP, d int) { |
| E.x.cmove(Q.x, d) |
| if CURVETYPE != MONTGOMERY { |
| E.y.cmove(Q.y, d) |
| } |
| E.z.cmove(Q.z, d) |
| } |
| |
| /* return 1 if b==c, no branching */ |
| func teq(b int32, c int32) int { |
| x := b ^ c |
| x -= 1 // if x=0, x now -1 |
| return int((x >> 31) & 1) |
| } |
| |
| /* this=P */ |
| func (E *ECP) Copy(P *ECP) { |
| E.x.copy(P.x) |
| if CURVETYPE != MONTGOMERY { |
| E.y.copy(P.y) |
| } |
| E.z.copy(P.z) |
| } |
| |
| /* this=-this */ |
| func (E *ECP) neg() { |
| if CURVETYPE == WEIERSTRASS { |
| E.y.neg() |
| E.y.norm() |
| } |
| if CURVETYPE == EDWARDS { |
| E.x.neg() |
| E.x.norm() |
| } |
| return |
| } |
| |
| /* Constant time select from pre-computed table */ |
| func (E *ECP) selector(W []*ECP, b int32) { |
| MP := NewECP() |
| m := b >> 31 |
| babs := (b ^ m) - m |
| |
| babs = (babs - 1) / 2 |
| |
| E.cmove(W[0], teq(babs, 0)) // conditional move |
| E.cmove(W[1], teq(babs, 1)) |
| E.cmove(W[2], teq(babs, 2)) |
| E.cmove(W[3], teq(babs, 3)) |
| E.cmove(W[4], teq(babs, 4)) |
| E.cmove(W[5], teq(babs, 5)) |
| E.cmove(W[6], teq(babs, 6)) |
| E.cmove(W[7], teq(babs, 7)) |
| |
| MP.Copy(E) |
| MP.neg() |
| E.cmove(MP, int(m&1)) |
| } |
| |
| /* set this=O */ |
| func (E *ECP) inf() { |
| E.x.zero() |
| if CURVETYPE != MONTGOMERY { |
| E.y.one() |
| } |
| if CURVETYPE != EDWARDS { |
| E.z.zero() |
| } else { |
| E.z.one() |
| } |
| } |
| |
| /* Test P == Q */ |
| func (E *ECP) Equals(Q *ECP) bool { |
| a := NewFPint(0) |
| b := NewFPint(0) |
| a.copy(E.x) |
| a.mul(Q.z) |
| a.reduce() |
| b.copy(Q.x) |
| b.mul(E.z) |
| b.reduce() |
| if !a.Equals(b) { |
| return false |
| } |
| if CURVETYPE != MONTGOMERY { |
| a.copy(E.y) |
| a.mul(Q.z) |
| a.reduce() |
| b.copy(Q.y) |
| b.mul(E.z) |
| b.reduce() |
| if !a.Equals(b) { |
| return false |
| } |
| } |
| |
| return true |
| } |
| |
| /* Calculate RHS of curve equation */ |
| func RHS(x *FP) *FP { |
| r := NewFPcopy(x) |
| r.sqr() |
| |
| if CURVETYPE == WEIERSTRASS { // x^3+Ax+B |
| b := NewFPbig(NewBIGints(CURVE_B)) |
| r.mul(x) |
| if CURVE_A == -3 { |
| cx := NewFPcopy(x) |
| cx.imul(3) |
| cx.neg() |
| cx.norm() |
| r.add(cx) |
| } |
| r.add(b) |
| } |
| if CURVETYPE == EDWARDS { // (Ax^2-1)/(Bx^2-1) |
| b := NewFPbig(NewBIGints(CURVE_B)) |
| |
| one := NewFPint(1) |
| b.mul(r) |
| b.sub(one) |
| b.norm() |
| if CURVE_A == -1 { |
| r.neg() |
| } |
| r.sub(one) |
| r.norm() |
| b.inverse() |
| r.mul(b) |
| } |
| if CURVETYPE == MONTGOMERY { // x^3+Ax^2+x |
| x3 := NewFPint(0) |
| x3.copy(r) |
| x3.mul(x) |
| r.imul(CURVE_A) |
| r.add(x3) |
| r.add(x) |
| } |
| r.reduce() |
| return r |
| } |
| |
| /* set to affine - from (x,y,z) to (x,y) */ |
| func (E *ECP) Affine() { |
| if E.Is_infinity() { |
| return |
| } |
| one := NewFPint(1) |
| if E.z.Equals(one) { |
| return |
| } |
| E.z.inverse() |
| E.x.mul(E.z) |
| E.x.reduce() |
| |
| if CURVETYPE != MONTGOMERY { |
| E.y.mul(E.z) |
| E.y.reduce() |
| } |
| E.z.copy(one) |
| } |
| |
| /* extract x as a BIG */ |
| func (E *ECP) GetX() *BIG { |
| W := NewECP() |
| W.Copy(E) |
| W.Affine() |
| return W.x.redc() |
| } |
| |
| /* extract y as a BIG */ |
| func (E *ECP) GetY() *BIG { |
| W := NewECP() |
| W.Copy(E) |
| W.Affine() |
| return W.y.redc() |
| } |
| |
| /* get sign of Y */ |
| func (E *ECP) GetS() int { |
| y := E.GetY() |
| return y.parity() |
| } |
| |
| /* extract x as an FP */ |
| func (E *ECP) getx() *FP { |
| return E.x |
| } |
| |
| /* extract y as an FP */ |
| func (E *ECP) gety() *FP { |
| return E.y |
| } |
| |
| /* extract z as an FP */ |
| func (E *ECP) getz() *FP { |
| return E.z |
| } |
| |
| /* convert to byte array */ |
| func (E *ECP) ToBytes(b []byte, compress bool) { |
| var t [int(MODBYTES)]byte |
| MB := int(MODBYTES) |
| W := NewECP() |
| W.Copy(E) |
| W.Affine() |
| W.x.redc().ToBytes(t[:]) |
| for i := 0; i < MB; i++ { |
| 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(t[:]) |
| for i := 0; i < MB; i++ { |
| b[i+MB+1] = t[i] |
| } |
| } |
| |
| /* convert from byte array to point */ |
| func ECP_fromBytes(b []byte) *ECP { |
| var t [int(MODBYTES)]byte |
| MB := int(MODBYTES) |
| p := NewBIGints(Modulus) |
| |
| for i := 0; i < MB; i++ { |
| t[i] = b[i+1] |
| } |
| px := FromBytes(t[:]) |
| if Comp(px, p) >= 0 { |
| return NewECP() |
| } |
| |
| if CURVETYPE == MONTGOMERY { |
| return NewECPbig(px) |
| } |
| |
| if b[0] == 0x04 { |
| for i := 0; i < MB; i++ { |
| t[i] = b[i+MB+1] |
| } |
| py := FromBytes(t[:]) |
| if Comp(py, p) >= 0 { |
| return NewECP() |
| } |
| return NewECPbigs(px, py) |
| } |
| |
| if b[0] == 0x02 || b[0] == 0x03 { |
| return NewECPbigint(px, int(b[0]&1)) |
| } |
| |
| return NewECP() |
| } |
| |
| /* convert to hex string */ |
| func (E *ECP) ToString() string { |
| W := NewECP() |
| W.Copy(E) |
| W.Affine() |
| if W.Is_infinity() { |
| return "infinity" |
| } |
| if CURVETYPE == MONTGOMERY { |
| return "(" + W.x.redc().ToString() + ")" |
| } else { |
| return "(" + W.x.redc().ToString() + "," + W.y.redc().ToString() + ")" |
| } |
| } |
| |
| /* this*=2 */ |
| func (E *ECP) dbl() { |
| |
| if CURVETYPE == WEIERSTRASS { |
| if CURVE_A == 0 { |
| t0 := NewFPcopy(E.y) |
| t0.sqr() |
| t1 := NewFPcopy(E.y) |
| t1.mul(E.z) |
| t2 := NewFPcopy(E.z) |
| t2.sqr() |
| |
| E.z.copy(t0) |
| E.z.add(t0) |
| E.z.norm() |
| E.z.add(E.z) |
| E.z.add(E.z) |
| E.z.norm() |
| t2.imul(3 * CURVE_B_I) |
| |
| x3 := NewFPcopy(t2) |
| x3.mul(E.z) |
| |
| y3 := NewFPcopy(t0) |
| y3.add(t2) |
| y3.norm() |
| E.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(E.x) |
| t1.mul(E.y) |
| E.x.copy(t0) |
| E.x.norm() |
| E.x.mul(t1) |
| E.x.add(E.x) |
| E.x.norm() |
| E.y.copy(y3) |
| E.y.norm() |
| } else { |
| t0 := NewFPcopy(E.x) |
| t1 := NewFPcopy(E.y) |
| t2 := NewFPcopy(E.z) |
| t3 := NewFPcopy(E.x) |
| z3 := NewFPcopy(E.z) |
| y3 := NewFPint(0) |
| x3 := NewFPint(0) |
| b := NewFPint(0) |
| |
| if CURVE_B_I == 0 { |
| b.copy(NewFPbig(NewBIGints(CURVE_B))) |
| } |
| |
| t0.sqr() //1 x^2 |
| t1.sqr() //2 y^2 |
| t2.sqr() //3 |
| |
| t3.mul(E.y) //4 |
| t3.add(t3) |
| t3.norm() //5 |
| z3.mul(E.x) //6 |
| z3.add(z3) |
| z3.norm() //7 |
| y3.copy(t2) |
| |
| if CURVE_B_I == 0 { |
| y3.mul(b) |
| } else { |
| y3.imul(CURVE_B_I) |
| } |
| |
| y3.sub(z3) //9 *** |
| x3.copy(y3) |
| x3.add(y3) |
| x3.norm() //10 |
| |
| y3.add(x3) //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) //16 |
| t2.add(t3) //17 |
| |
| if CURVE_B_I == 0 { |
| z3.mul(b) |
| } else { |
| z3.imul(CURVE_B_I) |
| } |
| |
| z3.sub(t2) //19 |
| z3.sub(t0) |
| z3.norm() //20 *** |
| t3.copy(z3) |
| t3.add(z3) //21 |
| |
| z3.add(t3) |
| z3.norm() //22 |
| t3.copy(t0) |
| t3.add(t0) //23 |
| t0.add(t3) //24 |
| t0.sub(t2) |
| t0.norm() //25 |
| |
| t0.mul(z3) //26 |
| y3.add(t0) //27 |
| t0.copy(E.y) |
| t0.mul(E.z) //28 |
| t0.add(t0) |
| t0.norm() //29 |
| z3.mul(t0) //30 |
| x3.sub(z3) //x3.norm();//31 |
| t0.add(t0) |
| t0.norm() //32 |
| t1.add(t1) |
| t1.norm() //33 |
| z3.copy(t0) |
| z3.mul(t1) //34 |
| |
| E.x.copy(x3) |
| E.x.norm() |
| E.y.copy(y3) |
| E.y.norm() |
| E.z.copy(z3) |
| E.z.norm() |
| } |
| } |
| |
| if CURVETYPE == EDWARDS { |
| C := NewFPcopy(E.x) |
| D := NewFPcopy(E.y) |
| H := NewFPcopy(E.z) |
| J := NewFPint(0) |
| |
| E.x.mul(E.y) |
| E.x.add(E.x) |
| E.x.norm() |
| C.sqr() |
| D.sqr() |
| if CURVE_A == -1 { |
| C.neg() |
| } |
| E.y.copy(C) |
| E.y.add(D) |
| E.y.norm() |
| |
| H.sqr() |
| H.add(H) |
| E.z.copy(E.y) |
| J.copy(E.y) |
| J.sub(H) |
| J.norm() |
| E.x.mul(J) |
| C.sub(D) |
| C.norm() |
| E.y.mul(C) |
| E.z.mul(J) |
| |
| } |
| if CURVETYPE == MONTGOMERY { |
| A := NewFPcopy(E.x) |
| B := NewFPcopy(E.x) |
| AA := NewFPint(0) |
| BB := NewFPint(0) |
| C := NewFPint(0) |
| |
| A.add(E.z) |
| A.norm() |
| AA.copy(A) |
| AA.sqr() |
| B.sub(E.z) |
| B.norm() |
| BB.copy(B) |
| BB.sqr() |
| C.copy(AA) |
| C.sub(BB) |
| C.norm() |
| |
| E.x.copy(AA) |
| E.x.mul(BB) |
| |
| A.copy(C) |
| A.imul((CURVE_A + 2) / 4) |
| |
| BB.add(A) |
| BB.norm() |
| E.z.copy(BB) |
| E.z.mul(C) |
| } |
| return |
| } |
| |
| /* this+=Q */ |
| func (E *ECP) Add(Q *ECP) { |
| |
| if CURVETYPE == WEIERSTRASS { |
| if CURVE_A == 0 { |
| b := 3 * CURVE_B_I |
| t0 := NewFPcopy(E.x) |
| t0.mul(Q.x) |
| t1 := NewFPcopy(E.y) |
| t1.mul(Q.y) |
| t2 := NewFPcopy(E.z) |
| t2.mul(Q.z) |
| t3 := NewFPcopy(E.x) |
| t3.add(E.y) |
| t3.norm() |
| t4 := NewFPcopy(Q.x) |
| t4.add(Q.y) |
| t4.norm() |
| t3.mul(t4) |
| t4.copy(t0) |
| t4.add(t1) |
| |
| t3.sub(t4) |
| t3.norm() |
| t4.copy(E.y) |
| t4.add(E.z) |
| t4.norm() |
| x3 := NewFPcopy(Q.y) |
| x3.add(Q.z) |
| x3.norm() |
| |
| t4.mul(x3) |
| x3.copy(t1) |
| x3.add(t2) |
| |
| t4.sub(x3) |
| t4.norm() |
| x3.copy(E.x) |
| x3.add(E.z) |
| x3.norm() |
| y3 := NewFPcopy(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) |
| |
| z3 := NewFPcopy(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) |
| |
| E.x.copy(x3) |
| E.x.norm() |
| E.y.copy(y3) |
| E.y.norm() |
| E.z.copy(z3) |
| E.z.norm() |
| } else { |
| |
| t0 := NewFPcopy(E.x) |
| t1 := NewFPcopy(E.y) |
| t2 := NewFPcopy(E.z) |
| t3 := NewFPcopy(E.x) |
| t4 := NewFPcopy(Q.x) |
| z3 := NewFPint(0) |
| y3 := NewFPcopy(Q.x) |
| x3 := NewFPcopy(Q.y) |
| b := NewFPint(0) |
| |
| if CURVE_B_I == 0 { |
| b.copy(NewFPbig(NewBIGints(CURVE_B))) |
| } |
| |
| t0.mul(Q.x) //1 |
| t1.mul(Q.y) //2 |
| t2.mul(Q.z) //3 |
| |
| t3.add(E.y) |
| t3.norm() //4 |
| t4.add(Q.y) |
| t4.norm() //5 |
| t3.mul(t4) //6 |
| t4.copy(t0) |
| t4.add(t1) //7 |
| t3.sub(t4) |
| t3.norm() //8 |
| t4.copy(E.y) |
| t4.add(E.z) |
| t4.norm() //9 |
| x3.add(Q.z) |
| x3.norm() //10 |
| t4.mul(x3) //11 |
| x3.copy(t1) |
| x3.add(t2) //12 |
| |
| t4.sub(x3) |
| t4.norm() //13 |
| x3.copy(E.x) |
| x3.add(E.z) |
| x3.norm() //14 |
| y3.add(Q.z) |
| y3.norm() //15 |
| |
| x3.mul(y3) //16 |
| y3.copy(t0) |
| y3.add(t2) //17 |
| |
| y3.rsub(x3) |
| y3.norm() //18 |
| z3.copy(t2) |
| |
| if CURVE_B_I == 0 { |
| z3.mul(b) |
| } else { |
| z3.imul(CURVE_B_I) |
| } |
| |
| x3.copy(y3) |
| x3.sub(z3) |
| x3.norm() //20 |
| z3.copy(x3) |
| z3.add(x3) //21 |
| |
| x3.add(z3) //22 |
| z3.copy(t1) |
| z3.sub(x3) |
| z3.norm() //23 |
| x3.add(t1) |
| x3.norm() //24 |
| |
| if CURVE_B_I == 0 { |
| y3.mul(b) |
| } else { |
| y3.imul(CURVE_B_I) |
| } |
| |
| t1.copy(t2) |
| t1.add(t2) //26 |
| t2.add(t1) //27 |
| |
| y3.sub(t2) //28 |
| |
| y3.sub(t0) |
| y3.norm() //29 |
| t1.copy(y3) |
| t1.add(y3) //30 |
| y3.add(t1) |
| y3.norm() //31 |
| |
| t1.copy(t0) |
| t1.add(t0) //32 |
| t0.add(t1) //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) //38 |
| x3.mul(t3) //39 |
| x3.sub(t1) //40 |
| z3.mul(t4) //41 |
| t1.copy(t3) |
| t1.mul(t0) //42 |
| z3.add(t1) |
| E.x.copy(x3) |
| E.x.norm() |
| E.y.copy(y3) |
| E.y.norm() |
| E.z.copy(z3) |
| E.z.norm() |
| |
| } |
| } |
| if CURVETYPE == EDWARDS { |
| b := NewFPbig(NewBIGints(CURVE_B)) |
| A := NewFPcopy(E.z) |
| B := NewFPint(0) |
| C := NewFPcopy(E.x) |
| D := NewFPcopy(E.y) |
| EE := NewFPint(0) |
| F := NewFPint(0) |
| G := NewFPint(0) |
| |
| A.mul(Q.z) |
| B.copy(A) |
| B.sqr() |
| C.mul(Q.x) |
| D.mul(Q.y) |
| |
| EE.copy(C) |
| EE.mul(D) |
| EE.mul(b) |
| F.copy(B) |
| F.sub(EE) |
| G.copy(B) |
| G.add(EE) |
| |
| if CURVE_A == 1 { |
| EE.copy(D) |
| EE.sub(C) |
| } |
| C.add(D) |
| |
| B.copy(E.x) |
| B.add(E.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) |
| E.x.copy(A) |
| E.x.mul(B) |
| G.norm() |
| if CURVE_A == 1 { |
| EE.norm() |
| C.copy(EE) |
| C.mul(G) |
| } |
| if CURVE_A == -1 { |
| C.norm() |
| C.mul(G) |
| } |
| E.y.copy(A) |
| E.y.mul(C) |
| E.z.copy(F) |
| E.z.mul(G) |
| } |
| return |
| } |
| |
| /* Differential Add for Montgomery curves. this+=Q where W is this-Q and is affine. */ |
| func (E *ECP) dadd(Q *ECP, W *ECP) { |
| A := NewFPcopy(E.x) |
| B := NewFPcopy(E.x) |
| C := NewFPcopy(Q.x) |
| D := NewFPcopy(Q.x) |
| DA := NewFPint(0) |
| CB := NewFPint(0) |
| |
| A.add(E.z) |
| B.sub(E.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() |
| |
| E.x.copy(A) |
| E.z.copy(W.x) |
| E.z.mul(B) |
| |
| } |
| |
| /* this-=Q */ |
| func (E *ECP) Sub(Q *ECP) { |
| NQ := NewECP() |
| NQ.Copy(Q) |
| NQ.neg() |
| E.Add(NQ) |
| } |
| |
| /* constant time multiply by small integer of length bts - use ladder */ |
| func (E *ECP) pinmul(e int32, bts int32) *ECP { |
| if CURVETYPE == MONTGOMERY { |
| return E.mul(NewBIGint(int(e))) |
| } else { |
| P := NewECP() |
| R0 := NewECP() |
| R1 := NewECP() |
| R1.Copy(E) |
| |
| for i := bts - 1; i >= 0; i-- { |
| b := int((e >> uint32(i)) & 1) |
| P.Copy(R1) |
| P.Add(R0) |
| R0.cswap(R1, b) |
| R1.Copy(P) |
| R0.dbl() |
| R0.cswap(R1, b) |
| } |
| P.Copy(R0) |
| P.Affine() |
| return P |
| } |
| } |
| |
| /* return e.this */ |
| |
| func (E *ECP) mul(e *BIG) *ECP { |
| if e.iszilch() || E.Is_infinity() { |
| return NewECP() |
| } |
| P := NewECP() |
| if CURVETYPE == MONTGOMERY { |
| /* use Ladder */ |
| D := NewECP() |
| R0 := NewECP() |
| R0.Copy(E) |
| R1 := NewECP() |
| R1.Copy(E) |
| R1.dbl() |
| D.Copy(E) |
| D.Affine() |
| nb := e.nbits() |
| for i := nb - 2; i >= 0; i-- { |
| b := int(e.bit(i)) |
| P.Copy(R1) |
| P.dadd(R0, D) |
| R0.cswap(R1, b) |
| R1.Copy(P) |
| R0.dbl() |
| R0.cswap(R1, b) |
| } |
| P.Copy(R0) |
| } else { |
| // fixed size windows |
| mt := NewBIG() |
| t := NewBIG() |
| Q := NewECP() |
| C := NewECP() |
| |
| var W []*ECP |
| var w [1 + (NLEN*int(BASEBITS)+3)/4]int8 |
| |
| Q.Copy(E) |
| Q.dbl() |
| |
| W = append(W, NewECP()) |
| W[0].Copy(E) |
| |
| for i := 1; i < 8; i++ { |
| W = append(W, NewECP()) |
| W[i].Copy(W[i-1]) |
| W[i].Add(Q) |
| } |
| |
| // make exponent odd - add 2P if even, P if odd |
| t.copy(e) |
| s := int(t.parity()) |
| t.inc(1) |
| t.norm() |
| ns := int(t.parity()) |
| mt.copy(t) |
| mt.inc(1) |
| mt.norm() |
| t.cmove(mt, s) |
| Q.cmove(E, ns) |
| C.Copy(Q) |
| |
| nb := 1 + (t.nbits()+3)/4 |
| |
| // convert exponent to signed 4-bit window |
| for i := 0; i < nb; i++ { |
| w[i] = int8(t.lastbits(5) - 16) |
| t.dec(int(w[i])) |
| t.norm() |
| t.fshr(4) |
| } |
| w[nb] = int8(t.lastbits(5)) |
| |
| P.Copy(W[(int(w[nb])-1)/2]) |
| for i := nb - 1; i >= 0; i-- { |
| Q.selector(W, int32(w[i])) |
| P.dbl() |
| P.dbl() |
| P.dbl() |
| P.dbl() |
| P.Add(Q) |
| } |
| P.Sub(C) /* apply correction */ |
| } |
| P.Affine() |
| return P |
| } |
| |
| /* Public version */ |
| func (E *ECP) Mul(e *BIG) *ECP { |
| return E.mul(e) |
| } |
| |
| /* Return e.this+f.Q */ |
| |
| func (E *ECP) Mul2(e *BIG, Q *ECP, f *BIG) *ECP { |
| te := NewBIG() |
| tf := NewBIG() |
| mt := NewBIG() |
| S := NewECP() |
| T := NewECP() |
| C := NewECP() |
| var W []*ECP |
| var w [1 + (NLEN*int(BASEBITS)+1)/2]int8 |
| |
| te.copy(e) |
| tf.copy(f) |
| |
| // precompute table |
| for i := 0; i < 8; i++ { |
| W = append(W, NewECP()) |
| } |
| W[1].Copy(E) |
| W[1].Sub(Q) |
| W[2].Copy(E) |
| W[2].Add(Q) |
| S.Copy(Q) |
| S.dbl() |
| W[0].Copy(W[1]) |
| W[0].Sub(S) |
| W[3].Copy(W[2]) |
| W[3].Add(S) |
| T.Copy(E) |
| T.dbl() |
| W[5].Copy(W[1]) |
| W[5].Add(T) |
| W[6].Copy(W[2]) |
| W[6].Add(T) |
| W[4].Copy(W[5]) |
| W[4].Sub(S) |
| W[7].Copy(W[6]) |
| W[7].Add(S) |
| |
| // if multiplier is odd, add 2, else add 1 to multiplier, and add 2P or P to correction |
| |
| s := int(te.parity()) |
| te.inc(1) |
| te.norm() |
| ns := int(te.parity()) |
| mt.copy(te) |
| mt.inc(1) |
| mt.norm() |
| te.cmove(mt, s) |
| T.cmove(E, ns) |
| C.Copy(T) |
| |
| s = int(tf.parity()) |
| tf.inc(1) |
| tf.norm() |
| ns = int(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() |
| nb := 1 + (mt.nbits()+1)/2 |
| |
| // convert exponent to signed 2-bit window |
| for i := 0; i < nb; i++ { |
| a := (te.lastbits(3) - 4) |
| te.dec(int(a)) |
| te.norm() |
| te.fshr(2) |
| b := (tf.lastbits(3) - 4) |
| tf.dec(int(b)) |
| tf.norm() |
| tf.fshr(2) |
| w[i] = int8(4*a + b) |
| } |
| w[nb] = int8(4*te.lastbits(3) + tf.lastbits(3)) |
| S.Copy(W[(w[nb]-1)/2]) |
| |
| for i := nb - 1; i >= 0; i-- { |
| T.selector(W, int32(w[i])) |
| S.dbl() |
| S.dbl() |
| S.Add(T) |
| } |
| S.Sub(C) /* apply correction */ |
| S.Affine() |
| return S |
| } |
| |
| func (E *ECP) cfp() { |
| cf := CURVE_Cof_I |
| if cf == 1 { |
| return |
| } |
| if cf == 4 { |
| E.dbl() |
| E.dbl() |
| return |
| } |
| if cf == 8 { |
| E.dbl() |
| E.dbl() |
| E.dbl() |
| return |
| } |
| c := NewBIGints(CURVE_Cof) |
| E.Copy(E.mul(c)) |
| } |
| |
| func ECP_mapit(h []byte) *ECP { |
| q := NewBIGints(Modulus) |
| x := FromBytes(h[:]) |
| x.Mod(q) |
| var P *ECP |
| |
| for true { |
| for true { |
| if CURVETYPE != MONTGOMERY { |
| P = NewECPbigint(x, 0) |
| } else { |
| P = NewECPbig(x) |
| } |
| x.inc(1) |
| x.norm() |
| if !P.Is_infinity() { |
| break |
| } |
| } |
| P.cfp() |
| if !P.Is_infinity() { |
| break |
| } |
| } |
| |
| return P |
| } |
| |
| func ECP_generator() *ECP { |
| var G *ECP |
| |
| gx := NewBIGints(CURVE_Gx) |
| if CURVETYPE != MONTGOMERY { |
| gy := NewBIGints(CURVE_Gy) |
| G = NewECPbigs(gx, gy) |
| } else { |
| G = NewECPbig(gx) |
| } |
| return G |
| } |