1
- // Package goldilocks provides goldilocks curve operations required by Ed448 .
1
+ // Package goldilocks provides arithmetic operations on the Goldilocks curve .
2
2
//
3
3
// Goldilocks Curve
4
4
//
5
- // The goldilocks curve is defined over GF(2^448-2^224-1) by the twisted Edwards
6
- // curve
5
+ // The goldilocks curve is defined over GF(2^448-2^224-1) as
7
6
// Goldilocks: ax^2+y^2 = 1 + dx^2y^2, where a=1 and d=-39081.
8
7
// This curve was proposed by Hamburg (1) and is also known as edwards448
9
8
// after RFC-7748 (2).
@@ -36,8 +35,6 @@ const EncodingSize = fp.Size + 1
36
35
// ErrInvalidDecoding alerts of an error during decoding a point.
37
36
var ErrInvalidDecoding = errors .New ("invalid decoding" )
38
37
39
- func (P * Point ) Neg () { fp .Neg (& P .X , & P .X ); fp .Neg (& P .Ta , & P .Ta ) }
40
-
41
38
// Decode if succeeds constructs a point by decoding the first
42
39
// EncodingSize bytes of data.
43
40
func (P * Point ) Decode (data * [EncodingSize ]byte ) error {
@@ -66,12 +63,10 @@ func (P *Point) Decode(data *[EncodingSize]byte) error {
66
63
fp .Cmov (& P .Ta , x , b )
67
64
fp .Cmov (& P .Tb , y , b )
68
65
fp .Cmov (& P .Z , & one , b )
69
-
70
- var err error
71
66
if ! isValid {
72
- err = ErrInvalidDecoding
67
+ return ErrInvalidDecoding
73
68
}
74
- return err
69
+ return nil
75
70
}
76
71
77
72
// Encode sets data with the unique encoding of the point P.
@@ -83,65 +78,60 @@ func (P *Point) Encode(data *[EncodingSize]byte) error {
83
78
fp .Modp (x )
84
79
fp .Modp (y )
85
80
data [EncodingSize - 1 ] = (x [0 ] & 1 ) << 7
86
- err := fp .ToBytes (data [:fp .Size ], y )
87
- return err
81
+ return fp .ToBytes (data [:fp .Size ], y )
88
82
}
89
83
90
- // Order returns the number of points in the prime subgroup.
91
- func Order () Scalar { return ted448 .Order () }
92
-
93
- // ScalarBaseMult calculates Q = kG, where G is the generator of the Goldilocks curve. This function runs in constant time.
94
- func ScalarBaseMult (Q * Point , k * Scalar ) {
84
+ // ScalarBaseMult calculates P = kG, where G is the generator of the Goldilocks
85
+ // curve. This function runs in constant time.
86
+ func (P * Point ) ScalarBaseMult (k * Scalar ) {
95
87
k4 := & Scalar {}
96
88
divBy4 (k4 , k )
97
- R := & ted448.Point {}
98
- ted448 .ScalarBaseMult (R , k4 )
99
- push (Q , R )
89
+ var Q ted448.Point
90
+ ted448 .ScalarBaseMult (& Q , k4 )
91
+ push (P , & Q )
100
92
}
101
93
102
- // CombinedMult calculates Q = mG+nP, where G is the generator of the Goldilocks curve. This function does NOT run in constant time.
103
- func CombinedMult (Q * Point , m , n * Scalar , P * Point ) {
94
+ // CombinedMult calculates P = mG+nQ, where G is the generator of the Goldilocks
95
+ // curve. This function does NOT run in constant time as is only used for
96
+ // signature verification.
97
+ func (P * Point ) CombinedMult (m , n * Scalar , Q * Point ) {
104
98
m4 , n4 := & Scalar {}, & Scalar {}
105
99
divBy4 (m4 , m )
106
100
divBy4 (n4 , n )
107
- phiP := & ted448.Point {}
108
- R := & ted448.Point {}
109
- pull (phiP , P )
110
- ted448 .CombinedMult (R , m4 , n4 , phiP )
111
- push (Q , R )
101
+ var R , phiQ ted448.Point
102
+ pull (& phiQ , Q )
103
+ ted448 .CombinedMult (& R , m4 , n4 , & phiQ )
104
+ push (P , & R )
112
105
}
113
106
114
- // pull sends a point on the Goldilocks curve to a point on the twist curve.
115
- func pull (Q * ted448.Point , P * Point ) {
116
- Px , Py , Pz := & P .X , & P .Y , & P .Z
117
- a , b , c , d , e , f , g , h := & Q .X , & Q .Y , & Q .Z , & fp.Elt {}, & Q .Ta , & Q .X , & Q .Y , & Q .Tb
118
- fp .Add (e , Px , Py ) // x+y
119
- fp .Sqr (a , Px ) // A = x^2
120
- fp .Sqr (b , Py ) // B = y^2
121
- fp .Sqr (c , Pz ) // z^2
122
- fp .Add (c , c , c ) // C = 2*z^2
123
- * d = * a // D = A
124
- fp .Sqr (e , e ) // (x+y)^2
125
- fp .Sub (e , e , a ) // (x+y)^2-A
126
- fp .Sub (e , e , b ) // E = (x+y)^2-A-B
127
- fp .Add (h , b , d ) // H = B+D
128
- fp .Sub (g , b , d ) // G = B-D
129
- fp .Sub (f , c , h ) // F = C-H
130
- fp .Mul (& Q .Z , f , g ) // Z = F * G
131
- fp .Mul (& Q .X , e , f ) // X = E * F
132
- fp .Mul (& Q .Y , g , h ) // Y = G * H, // T = E * H
133
- }
107
+ func (P * Point ) Neg () { fp .Neg (& P .X , & P .X ); fp .Neg (& P .Ta , & P .Ta ) }
108
+
109
+ // Order returns a scalar with the order of the group.
110
+ func Order () Scalar { return ted448 .Order () }
111
+
112
+ // divBy4 calculates z = x/4 mod order.
113
+ func divBy4 (z , x * Scalar ) { z .Mul (x , & invFour ) }
114
+
115
+ // pull calculates Q = Iso4(P), where P is a Goldilocks point and Q is a ted448 point.
116
+ func pull (Q * ted448.Point , P * Point ) { isogeny4 (Q , (* ted448 .Point )(P ), true ) }
134
117
135
- // push sends a point on the twist curve to a point on the Goldilocks curve.
136
- func push (Q * Point , P * ted448.Point ) {
118
+ // push calculates Q = Iso4^-1(P), where P is a ted448 point and Q is a Goldilocks point.
119
+ func push (Q * Point , P * ted448.Point ) { isogeny4 ((* ted448 .Point )(Q ), P , false ) }
120
+
121
+ // isogeny4 is a birational map between ted448 and Goldilocks curves.
122
+ func isogeny4 (Q , P * ted448.Point , isPull bool ) {
137
123
Px , Py , Pz := & P .X , & P .Y , & P .Z
138
124
a , b , c , d , e , f , g , h := & Q .X , & Q .Y , & Q .Z , & fp.Elt {}, & Q .Ta , & Q .X , & Q .Y , & Q .Tb
139
- fp .Add (e , Px , Py ) // x+y
140
- fp .Sqr (a , Px ) // A = x^2
141
- fp .Sqr (b , Py ) // B = y^2
142
- fp .Sqr (c , Pz ) // z^2
143
- fp .Add (c , c , c ) // C = 2*z^2
144
- fp .Neg (d , a ) // D = -A
125
+ fp .Add (e , Px , Py ) // x+y
126
+ fp .Sqr (a , Px ) // A = x^2
127
+ fp .Sqr (b , Py ) // B = y^2
128
+ fp .Sqr (c , Pz ) // z^2
129
+ fp .Add (c , c , c ) // C = 2*z^2
130
+ if isPull {
131
+ * d = * a // D = A
132
+ } else {
133
+ fp .Neg (d , a ) // D = -A
134
+ }
145
135
fp .Sqr (e , e ) // (x+y)^2
146
136
fp .Sub (e , e , a ) // (x+y)^2-A
147
137
fp .Sub (e , e , b ) // E = (x+y)^2-A-B
@@ -153,9 +143,6 @@ func push(Q *Point, P *ted448.Point) {
153
143
fp .Mul (& Q .Y , g , h ) // Y = G * H, // T = E * H
154
144
}
155
145
156
- // divBy4 calculates z = x/4 mod order.
157
- func divBy4 (z , x * Scalar ) { z .Mul (x , & invFour ) }
158
-
159
146
// isLessThan returns true if 0 <= x < y, and assumes that slices are of the
160
147
// same length and are interpreted in little-endian order.
161
148
func isLessThan (x , y []byte ) bool {
@@ -177,7 +164,7 @@ var (
177
164
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
178
165
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0x0f ,
179
166
}
180
- // paramD is -39081 in Fp. This is the D parameter of the goldilocks curve.
167
+ // paramD is the D parameter of the Goldilocks curve, D=-39081 in Fp .
181
168
paramD = fp.Elt {
182
169
0x56 , 0x67 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
183
170
0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
0 commit comments