mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-10 18:25:17 +00:00
1851 lines
29 KiB
Go
1851 lines
29 KiB
Go
/*
|
|
* Copyright (c) 2012-2020 MIRACL UK Ltd.
|
|
*
|
|
* This file is part of MIRACL Core
|
|
* (see https://github.com/miracl/core).
|
|
*
|
|
* Licensed 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 bls48581
|
|
|
|
//import "fmt"
|
|
/* Elliptic Curve Point Structure */
|
|
|
|
type ECP struct {
|
|
x *FP
|
|
y *FP
|
|
z *FP
|
|
}
|
|
|
|
/* Constructors */
|
|
func NewECP() *ECP {
|
|
E := new(ECP)
|
|
E.x = NewFP()
|
|
E.y = NewFPint(1)
|
|
if CURVETYPE == EDWARDS {
|
|
E.z = NewFPint(1)
|
|
} else {
|
|
E.z = NewFP()
|
|
}
|
|
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.qr(nil) != 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 = NewFP()
|
|
E.x.norm()
|
|
rhs := RHS(E.x)
|
|
E.z = NewFPint(1)
|
|
hint := NewFP()
|
|
if rhs.qr(hint) == 1 {
|
|
ny := rhs.sqrt(hint)
|
|
if ny.sign() != s {
|
|
ny.neg()
|
|
ny.norm()
|
|
}
|
|
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 = NewFP()
|
|
E.x.norm()
|
|
rhs := RHS(E.x)
|
|
E.z = NewFPint(1)
|
|
hint := NewFP()
|
|
if rhs.qr(hint) == 1 {
|
|
if CURVETYPE != MONTGOMERY {
|
|
E.y.copy(rhs.sqrt(hint))
|
|
}
|
|
} else {
|
|
E.inf()
|
|
}
|
|
return E
|
|
}
|
|
|
|
/* test for O point-at-infinity */
|
|
func (E *ECP) Is_infinity() bool {
|
|
// if E.INF {return true}
|
|
|
|
if CURVETYPE == EDWARDS {
|
|
return (E.x.iszilch() && E.y.Equals(E.z))
|
|
}
|
|
if CURVETYPE == WEIERSTRASS {
|
|
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 := NewFP()
|
|
b := NewFP()
|
|
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(nil)
|
|
r.mul(b)
|
|
}
|
|
if CURVETYPE == MONTGOMERY { // x^3+Ax^2+x
|
|
x3 := NewFP()
|
|
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(nil)
|
|
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 {
|
|
W := NewECP()
|
|
W.Copy(E)
|
|
W.Affine()
|
|
return W.y.sign()
|
|
}
|
|
|
|
/* 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)
|
|
alt := false
|
|
W := NewECP()
|
|
W.Copy(E)
|
|
W.Affine()
|
|
W.x.redc().ToBytes(t[:])
|
|
|
|
if CURVETYPE == MONTGOMERY {
|
|
for i := 0; i < MB; i++ {
|
|
b[i] = t[i]
|
|
}
|
|
//b[0] = 0x06
|
|
return
|
|
}
|
|
|
|
if (MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS {
|
|
alt = true
|
|
}
|
|
|
|
if alt {
|
|
for i := 0; i < MB; i++ {
|
|
b[i] = t[i]
|
|
}
|
|
if compress {
|
|
b[0] |= 0x80
|
|
if W.y.islarger() == 1 {
|
|
b[0] |= 0x20
|
|
}
|
|
} else {
|
|
W.y.redc().ToBytes(t[:])
|
|
for i := 0; i < MB; i++ {
|
|
b[i+MB] = t[i]
|
|
}
|
|
}
|
|
} else {
|
|
for i := 0; i < MB; i++ {
|
|
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(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)
|
|
alt := false
|
|
|
|
if CURVETYPE == MONTGOMERY {
|
|
for i := 0; i < MB; i++ {
|
|
t[i] = b[i]
|
|
}
|
|
px := FromBytes(t[:])
|
|
if Comp(px, p) >= 0 {
|
|
return NewECP()
|
|
}
|
|
return NewECPbig(px)
|
|
}
|
|
|
|
if (MODBITS-1)%8 <= 4 && ALLOW_ALT_COMPRESS {
|
|
alt = true
|
|
}
|
|
|
|
if alt {
|
|
for i := 0; i < MB; i++ {
|
|
t[i] = b[i]
|
|
}
|
|
t[0] &= 0x1f
|
|
px := FromBytes(t[:])
|
|
if (b[0] & 0x80) == 0 {
|
|
for i := 0; i < MB; i++ {
|
|
t[i] = b[i+MB]
|
|
}
|
|
py := FromBytes(t[:])
|
|
return NewECPbigs(px, py)
|
|
} else {
|
|
sgn := (b[0] & 0x20) >> 5
|
|
P := NewECPbigint(px, 0)
|
|
cmp := P.y.islarger()
|
|
if (sgn == 1 && cmp != 1) || (sgn == 0 && cmp == 1) {
|
|
P.Neg()
|
|
}
|
|
return P
|
|
}
|
|
} else {
|
|
for i := 0; i < MB; i++ {
|
|
t[i] = b[i+1]
|
|
}
|
|
px := FromBytes(t[:])
|
|
if Comp(px, p) >= 0 {
|
|
return NewECP()
|
|
}
|
|
|
|
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 := NewFP()
|
|
x3 := NewFP()
|
|
b := NewFP()
|
|
|
|
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 := NewFP()
|
|
|
|
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 := NewFP()
|
|
BB := NewFP()
|
|
C := NewFP()
|
|
|
|
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 := NewFP()
|
|
y3 := NewFPcopy(Q.x)
|
|
x3 := NewFPcopy(Q.y)
|
|
b := NewFP()
|
|
|
|
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 := NewFP()
|
|
C := NewFPcopy(E.x)
|
|
D := NewFPcopy(E.y)
|
|
EE := NewFP()
|
|
F := NewFP()
|
|
G := NewFP()
|
|
|
|
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 := NewFP()
|
|
CB := NewFP()
|
|
|
|
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)
|
|
return P
|
|
}
|
|
}
|
|
|
|
// Point multiplication, multiplies a point P by a scalar e
|
|
// This code has no inherent awareness of the order of the curve, or the order of the point.
|
|
// The order of the curve will be h.r, where h is a cofactor, and r is a large prime
|
|
// Typically P will be of order r (but not always), and typically e will be less than r (but not always)
|
|
// A problem can arise if a secret e is a few bits less than r, as the leading zeros in e will leak via a timing attack
|
|
// The secret e may however be greater than r (see RFC7748 which combines elimination of a small cofactor h with the point multiplication, using an e>r)
|
|
// Our solution is to use as a multiplier an e, whose length in bits is that of the logical OR of e and r, hence allowing e>r while forcing inclusion of leading zeros if e<r.
|
|
// The point multiplication methods used will process leading zeros correctly.
|
|
|
|
// So this function leaks information about the length of e...
|
|
func (E *ECP) mul(e *BIG) *ECP {
|
|
return E.clmul(e, e)
|
|
}
|
|
|
|
// .. but this one does not (typically set maxe=r)
|
|
// Set P=e*P
|
|
/* return e.this */
|
|
func (E *ECP) clmul(e *BIG, maxe *BIG) *ECP {
|
|
if e.iszilch() || E.Is_infinity() {
|
|
return NewECP()
|
|
}
|
|
P := NewECP()
|
|
cm := NewBIGcopy(e)
|
|
cm.or(maxe)
|
|
max := cm.nbits()
|
|
|
|
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 := max
|
|
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 + (max+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])
|
|
P.selector(W, int32(w[nb]))
|
|
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 */
|
|
}
|
|
return P
|
|
}
|
|
|
|
/* Public version */
|
|
func (E *ECP) Mul(e *BIG) *ECP {
|
|
return E.mul(e)
|
|
}
|
|
|
|
// Generic multi-multiplication, fixed 4-bit window, P=Sigma e_i*X_i
|
|
func ECP_muln(n int, X []*ECP, e []*BIG) *ECP {
|
|
P := NewECP()
|
|
R := NewECP()
|
|
S := NewECP()
|
|
var B []*ECP
|
|
t := NewBIG()
|
|
for i := 0; i < 16; i++ {
|
|
B = append(B, NewECP())
|
|
}
|
|
mt := NewBIGcopy(e[0])
|
|
mt.norm()
|
|
for i := 1; i < n; i++ { // find biggest
|
|
t.copy(e[i])
|
|
t.norm()
|
|
k := Comp(t, mt)
|
|
mt.cmove(t, (k+1)/2)
|
|
}
|
|
nb := (mt.nbits() + 3) / 4
|
|
for i := nb - 1; i >= 0; i-- {
|
|
for j := 0; j < 16; j++ {
|
|
B[j].inf()
|
|
}
|
|
for j := 0; j < n; j++ {
|
|
mt.copy(e[j])
|
|
mt.norm()
|
|
mt.shr(uint(i * 4))
|
|
k := mt.lastbits(4)
|
|
B[k].Add(X[j])
|
|
}
|
|
R.inf()
|
|
S.inf()
|
|
for j := 15; j >= 1; j-- {
|
|
R.Add(B[j])
|
|
S.Add(R)
|
|
}
|
|
for j := 0; j < 4; j++ {
|
|
P.dbl()
|
|
}
|
|
P.Add(S)
|
|
}
|
|
return P
|
|
}
|
|
|
|
/* 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])
|
|
S.selector(W, int32(w[nb]))
|
|
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 */
|
|
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))
|
|
}
|
|
|
|
/* Hunt and Peck a BIG to a curve point */
|
|
func ECP_hap2point(h *BIG) *ECP {
|
|
var P *ECP
|
|
x := NewBIGcopy(h)
|
|
|
|
for true {
|
|
if CURVETYPE != MONTGOMERY {
|
|
P = NewECPbigint(x, 0)
|
|
} else {
|
|
P = NewECPbig(x)
|
|
}
|
|
x.inc(1)
|
|
x.norm()
|
|
if !P.Is_infinity() {
|
|
break
|
|
}
|
|
}
|
|
return P
|
|
}
|
|
|
|
/* Constant time Map to Point */
|
|
func ECP_map2point(h *FP) *ECP {
|
|
P := NewECP()
|
|
|
|
if CURVETYPE == MONTGOMERY {
|
|
// Elligator 2
|
|
X1 := NewFP()
|
|
X2 := NewFP()
|
|
w := NewFP()
|
|
one := NewFPint(1)
|
|
A := NewFPint(CURVE_A)
|
|
t := NewFPcopy(h)
|
|
N := NewFP()
|
|
D := NewFP()
|
|
hint := NewFP()
|
|
|
|
t.sqr()
|
|
|
|
if PM1D2 == 2 {
|
|
t.add(t)
|
|
}
|
|
if PM1D2 == 1 {
|
|
t.neg()
|
|
}
|
|
if PM1D2 > 2 {
|
|
t.imul(QNRI)
|
|
}
|
|
|
|
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)
|
|
qres := t.qr(hint)
|
|
w.copy(t)
|
|
w.inverse(hint)
|
|
D.copy(w)
|
|
D.mul(N)
|
|
X1.mul(D)
|
|
X2.mul(D)
|
|
X1.cmove(X2, 1-qres)
|
|
|
|
a := X1.redc()
|
|
P.Copy(NewECPbig(a))
|
|
}
|
|
if CURVETYPE == EDWARDS {
|
|
// Elligator 2 - map to Montgomery, place point, map back
|
|
X1 := NewFP()
|
|
X2 := NewFP()
|
|
t := NewFPcopy(h)
|
|
w := NewFP()
|
|
one := NewFPint(1)
|
|
A := NewFP()
|
|
w1 := NewFP()
|
|
w2 := NewFP()
|
|
B := NewFPbig(NewBIGints(CURVE_B))
|
|
Y := NewFP()
|
|
K := NewFP()
|
|
D := NewFP()
|
|
hint := NewFP()
|
|
//Y3:=NewFP()
|
|
rfc := 0
|
|
|
|
if MODTYPE != 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.inverse(nil)
|
|
K.invsqrt(K, w1)
|
|
|
|
rfc = RIADZ
|
|
if rfc == 1 { // RFC7748
|
|
A.mul(K)
|
|
K.mul(w1)
|
|
//K=K.sqrt(nil)
|
|
} else {
|
|
B.sqr()
|
|
}
|
|
} else {
|
|
rfc = 1
|
|
A.copy(NewFPint(156326))
|
|
}
|
|
|
|
t.sqr()
|
|
qnr := 0
|
|
if PM1D2 == 2 {
|
|
t.add(t)
|
|
qnr = 2
|
|
}
|
|
if PM1D2 == 1 {
|
|
t.neg()
|
|
qnr = -1
|
|
}
|
|
if PM1D2 > 2 {
|
|
t.imul(QNRI)
|
|
qnr = QNRI
|
|
}
|
|
t.norm()
|
|
|
|
D.copy(t)
|
|
D.add(one)
|
|
D.norm()
|
|
X1.copy(A)
|
|
X1.neg()
|
|
X1.norm()
|
|
X2.copy(X1)
|
|
X2.mul(t)
|
|
|
|
// Figure out RHS of Montgomery curve in rational form gx1/d^3
|
|
|
|
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)
|
|
qres := B.qr(hint)
|
|
w.copy(B)
|
|
w.inverse(hint)
|
|
D.copy(w)
|
|
D.mul(w1)
|
|
X1.mul(D)
|
|
X2.mul(D)
|
|
D.sqr()
|
|
|
|
w1.copy(B)
|
|
w1.imul(qnr)
|
|
w.copy(NewFPbig(NewBIGints(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(hint))
|
|
Y.mul(D)
|
|
|
|
/*
|
|
Y.copy(B.sqrt(hint))
|
|
Y.mul(D)
|
|
|
|
B.imul(qnr)
|
|
w.copy(NewFPbig(NewBIGints(CURVE_HTPC)))
|
|
hint.mul(w)
|
|
|
|
Y3.copy(B.sqrt(hint))
|
|
D.mul(h)
|
|
Y3.mul(D)
|
|
|
|
X1.cmove(X2,1-qres)
|
|
Y.cmove(Y3,1-qres)
|
|
*/
|
|
w.copy(Y)
|
|
w.neg()
|
|
w.norm()
|
|
Y.cmove(w, qres^Y.sign())
|
|
|
|
if rfc == 0 {
|
|
X1.mul(K)
|
|
Y.mul(K)
|
|
}
|
|
|
|
if MODTYPE == 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.add(w1)
|
|
X2.copy(w1)
|
|
X2.add(w1)
|
|
X2.norm()
|
|
t.sqr()
|
|
Y.sqr()
|
|
Y.add(Y)
|
|
Y.add(Y)
|
|
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 {
|
|
// swu method
|
|
A := NewFP()
|
|
B := NewFP()
|
|
X1 := NewFP()
|
|
X2 := NewFP()
|
|
X3 := NewFP()
|
|
one := NewFPint(1)
|
|
Y := NewFP()
|
|
D := NewFP()
|
|
t := NewFPcopy(h)
|
|
w := NewFP()
|
|
D2 := NewFP()
|
|
hint := NewFP()
|
|
GX1 := NewFP()
|
|
//Y3:=NewFP()
|
|
sgn := t.sign()
|
|
|
|
if CURVE_A != 0 || HTC_ISO != 0 {
|
|
if HTC_ISO != 0 {
|
|
/* CAHCZS
|
|
A.copy(NewFPbig(NewBIGints(CURVE_Ad)))
|
|
B.copy(NewFPbig(NewBIGints(CURVE_Bd)))
|
|
CAHCZF */
|
|
} else {
|
|
A.copy(NewFPint(CURVE_A))
|
|
B.copy(NewFPbig(NewBIGints(CURVE_B)))
|
|
}
|
|
// SSWU method
|
|
t.sqr()
|
|
t.imul(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)
|
|
|
|
// x^3+Ad^2x+Bd^3
|
|
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)
|
|
qr := w.qr(hint)
|
|
D.copy(w)
|
|
D.inverse(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(RIADZ)
|
|
X1.copy(NewFPbig(NewBIGints(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(hint))
|
|
Y.mul(D2)
|
|
/*
|
|
Y.copy(w.sqrt(hint))
|
|
Y.mul(D2)
|
|
|
|
D2.mul(t)
|
|
w.imul(RIADZ)
|
|
|
|
X1.copy(NewFPbig(NewBIGints(CURVE_HTPC)))
|
|
hint.mul(X1)
|
|
|
|
Y3.copy(w.sqrt(hint))
|
|
Y3.mul(D2)
|
|
|
|
X2.cmove(X3,1-qr)
|
|
Y.cmove(Y3,1-qr)
|
|
*/
|
|
ne := Y.sign() ^ sgn
|
|
w.copy(Y)
|
|
w.neg()
|
|
w.norm()
|
|
Y.cmove(w, ne)
|
|
|
|
if HTC_ISO != 0 {
|
|
/* CAHCZS
|
|
k:=0
|
|
isox:=HTC_ISO
|
|
isoy:=3*(isox-1)/2
|
|
|
|
//xnum
|
|
xnum:=NewFPbig(NewBIGints(PC[k])); k+=1
|
|
for i:=0;i<isox;i++ {
|
|
xnum.mul(X2)
|
|
w.copy(NewFPbig(NewBIGints(PC[k]))); k+=1
|
|
xnum.add(w); xnum.norm()
|
|
}
|
|
//xden
|
|
xden:=NewFPcopy(X2)
|
|
w.copy(NewFPbig(NewBIGints(PC[k]))); k+=1
|
|
xden.add(w);xden.norm();
|
|
for i:=0;i<isox-2;i++ {
|
|
xden.mul(X2)
|
|
w.copy(NewFPbig(NewBIGints(PC[k]))); k+=1
|
|
xden.add(w); xden.norm()
|
|
}
|
|
//ynum
|
|
ynum:=NewFPbig(NewBIGints(PC[k])); k+=1
|
|
for i:=0;i<isoy;i++ {
|
|
ynum.mul(X2)
|
|
w.copy(NewFPbig(NewBIGints(PC[k]))); k+=1
|
|
ynum.add(w); ynum.norm()
|
|
}
|
|
yden:=NewFPcopy(X2)
|
|
w.copy(NewFPbig(NewBIGints(PC[k]))); k+=1
|
|
yden.add(w);yden.norm();
|
|
for i:=0;i<isoy-1;i++ {
|
|
yden.mul(X2)
|
|
w.copy(NewFPbig(NewBIGints(PC[k]))); k+=1
|
|
yden.add(w); yden.norm()
|
|
}
|
|
ynum.mul(Y)
|
|
w.copy(xnum); w.mul(yden)
|
|
P.x.copy(w)
|
|
w.copy(ynum); w.mul(xden)
|
|
P.y.copy(w)
|
|
w.copy(xden); w.mul(yden)
|
|
P.z.copy(w)
|
|
return P
|
|
CAHCZF */
|
|
} else {
|
|
x := X2.redc()
|
|
y := Y.redc()
|
|
P.Copy(NewECPbigs(x, y))
|
|
return P
|
|
}
|
|
} else {
|
|
// Shallue and van de Woestijne
|
|
// SQRTm3 not available, so preprocess this out
|
|
/* */
|
|
Z := RIADZ
|
|
X1.copy(NewFPint(Z))
|
|
X3.copy(X1)
|
|
A.copy(RHS(X1))
|
|
B.copy(NewFPbig(NewBIGints(SQRTm3)))
|
|
B.imul(Z)
|
|
|
|
t.sqr()
|
|
Y.copy(A)
|
|
Y.mul(t)
|
|
t.copy(one)
|
|
t.add(Y)
|
|
t.norm()
|
|
Y.rsub(one)
|
|
Y.norm()
|
|
D.copy(t)
|
|
D.mul(Y)
|
|
D.mul(B)
|
|
|
|
w.copy(A)
|
|
FP_tpo(D, w)
|
|
|
|
w.mul(B)
|
|
if w.sign() == 1 {
|
|
w.neg()
|
|
w.norm()
|
|
}
|
|
|
|
w.mul(B)
|
|
w.mul(h)
|
|
w.mul(Y)
|
|
w.mul(D)
|
|
|
|
X1.neg()
|
|
X1.norm()
|
|
X1.div2()
|
|
X2.copy(X1)
|
|
X1.sub(w)
|
|
X1.norm()
|
|
X2.add(w)
|
|
X2.norm()
|
|
A.add(A)
|
|
A.add(A)
|
|
A.norm()
|
|
t.sqr()
|
|
t.mul(D)
|
|
t.sqr()
|
|
A.mul(t)
|
|
X3.add(A)
|
|
X3.norm()
|
|
|
|
rhs := RHS(X2)
|
|
X3.cmove(X2, rhs.qr(nil))
|
|
rhs.copy(RHS(X1))
|
|
X3.cmove(X1, rhs.qr(nil))
|
|
rhs.copy(RHS(X3))
|
|
Y.copy(rhs.sqrt(nil))
|
|
|
|
ne := Y.sign() ^ sgn
|
|
w.copy(Y)
|
|
w.neg()
|
|
w.norm()
|
|
Y.cmove(w, ne)
|
|
|
|
x := X3.redc()
|
|
y := Y.redc()
|
|
P.Copy(NewECPbigs(x, y))
|
|
return P
|
|
/* */
|
|
}
|
|
}
|
|
return P
|
|
}
|
|
|
|
func ECP_mapit(h []byte) *ECP {
|
|
q := NewBIGints(Modulus)
|
|
dx := DBIG_fromBytes(h[:])
|
|
x := dx.Mod(q)
|
|
|
|
P := ECP_hap2point(x)
|
|
P.Cfp()
|
|
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
|
|
}
|