1 package goldilocks
2
3 import (
4 "errors"
5 "fmt"
6
7 fp "github.com/cloudflare/circl/math/fp448"
8 )
9
10
11 type Point struct{ x, y, z, ta, tb fp.Elt }
12
13 func (P Point) String() string {
14 return fmt.Sprintf("x: %v\ny: %v\nz: %v\nta: %v\ntb: %v", P.x, P.y, P.z, P.ta, P.tb)
15 }
16
17
18 func FromAffine(x, y *fp.Elt) (*Point, error) {
19 P := &Point{
20 x: *x,
21 y: *y,
22 z: fp.One(),
23 ta: *x,
24 tb: *y,
25 }
26 if !(Curve{}).IsOnCurve(P) {
27 return P, errors.New("point not on curve")
28 }
29 return P, nil
30 }
31
32
33
34 func isLessThan(x, y []byte) bool {
35 i := len(x) - 1
36 for i > 0 && x[i] == y[i] {
37 i--
38 }
39 return x[i] < y[i]
40 }
41
42
43 func FromBytes(in []byte) (*Point, error) {
44 if len(in) < fp.Size+1 {
45 return nil, errors.New("wrong input length")
46 }
47 err := errors.New("invalid decoding")
48 P := &Point{}
49 signX := in[fp.Size] >> 7
50 copy(P.y[:], in[:fp.Size])
51 p := fp.P()
52 if !isLessThan(P.y[:], p[:]) {
53 return nil, err
54 }
55
56 u, v := &fp.Elt{}, &fp.Elt{}
57 one := fp.One()
58 fp.Sqr(u, &P.y)
59 fp.Mul(v, u, ¶mD)
60 fp.Sub(u, u, &one)
61 fp.Sub(v, v, &one)
62 isQR := fp.InvSqrt(&P.x, u, v)
63 if !isQR {
64 return nil, err
65 }
66 fp.Modp(&P.x)
67 if fp.IsZero(&P.x) && signX == 1 {
68 return nil, err
69 }
70 if signX != (P.x[0] & 1) {
71 fp.Neg(&P.x, &P.x)
72 }
73 P.ta = P.x
74 P.tb = P.y
75 P.z = fp.One()
76 return P, nil
77 }
78
79
80 func (P *Point) IsIdentity() bool {
81 return fp.IsZero(&P.x) && !fp.IsZero(&P.y) && !fp.IsZero(&P.z) && P.y == P.z
82 }
83
84
85 func (P *Point) IsEqual(Q *Point) bool {
86 l, r := &fp.Elt{}, &fp.Elt{}
87 fp.Mul(l, &P.x, &Q.z)
88 fp.Mul(r, &Q.x, &P.z)
89 fp.Sub(l, l, r)
90 b := fp.IsZero(l)
91 fp.Mul(l, &P.y, &Q.z)
92 fp.Mul(r, &Q.y, &P.z)
93 fp.Sub(l, l, r)
94 b = b && fp.IsZero(l)
95 fp.Mul(l, &P.ta, &P.tb)
96 fp.Mul(l, l, &Q.z)
97 fp.Mul(r, &Q.ta, &Q.tb)
98 fp.Mul(r, r, &P.z)
99 fp.Sub(l, l, r)
100 b = b && fp.IsZero(l)
101 return b
102 }
103
104
105 func (P *Point) Neg() { fp.Neg(&P.x, &P.x); fp.Neg(&P.ta, &P.ta) }
106
107
108 func (P *Point) ToAffine() (x, y fp.Elt) {
109 fp.Inv(&P.z, &P.z)
110 fp.Mul(&P.x, &P.x, &P.z)
111 fp.Mul(&P.y, &P.y, &P.z)
112 fp.Modp(&P.x)
113 fp.Modp(&P.y)
114 fp.SetOne(&P.z)
115 P.ta = P.x
116 P.tb = P.y
117 return P.x, P.y
118 }
119
120
121 func (P *Point) ToBytes(out []byte) error {
122 if len(out) < fp.Size+1 {
123 return errors.New("invalid decoding")
124 }
125 x, y := P.ToAffine()
126 out[fp.Size] = (x[0] & 1) << 7
127 return fp.ToBytes(out[:fp.Size], &y)
128 }
129
130
131 func (P *Point) MarshalBinary() (data []byte, err error) {
132 data = make([]byte, fp.Size+1)
133 err = P.ToBytes(data[:fp.Size+1])
134 return data, err
135 }
136
137
138 func (P *Point) UnmarshalBinary(data []byte) error { Q, err := FromBytes(data); *P = *Q; return err }
139
140
141 func (P *Point) Double() { P.Add(P) }
142
143
144 func (P *Point) Add(Q *Point) {
145
146
147
148 x1, y1, z1, ta1, tb1 := &P.x, &P.y, &P.z, &P.ta, &P.tb
149 x2, y2, z2, ta2, tb2 := &Q.x, &Q.y, &Q.z, &Q.ta, &Q.tb
150 x3, y3, z3, E, H := &P.x, &P.y, &P.z, &P.ta, &P.tb
151 A, B, C, D := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{}
152 t1, t2, F, G := C, D, &fp.Elt{}, &fp.Elt{}
153 fp.Mul(t1, ta1, tb1)
154 fp.Mul(t2, ta2, tb2)
155 fp.Mul(A, x1, x2)
156 fp.Mul(B, y1, y2)
157 fp.Mul(C, t1, t2)
158 fp.Mul(C, C, ¶mD)
159 fp.Mul(D, z1, z2)
160 fp.Add(F, x1, y1)
161 fp.Add(E, x2, y2)
162 fp.Mul(E, E, F)
163 fp.Sub(E, E, A)
164 fp.Sub(E, E, B)
165 fp.Sub(F, D, C)
166 fp.Add(G, D, C)
167 fp.Sub(H, B, A)
168 fp.Mul(z3, F, G)
169 fp.Mul(x3, E, F)
170 fp.Mul(y3, G, H)
171 }
172
View as plain text