Skip to content

Commit 796b37e

Browse files
committed
Updates internal packages of Ed448.
1 parent f5957e7 commit 796b37e

File tree

3 files changed

+74
-73
lines changed

3 files changed

+74
-73
lines changed

sign/ed448/ed448.go

+26-12
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ import (
3333
"io"
3434
"strconv"
3535

36-
"github.com/cloudflare/circl/ecc/goldilocks"
3736
sha3 "github.com/cloudflare/circl/internal/shake"
37+
"github.com/cloudflare/circl/sign/ed448/internal/goldilocks"
3838
)
3939

4040
const (
@@ -189,7 +189,12 @@ func newKeyFromSeed(privateKey, seed []byte) {
189189
deriveSecretScalar(s, h[:paramB])
190190

191191
copy(privateKey[:SeedSize], seed)
192-
_ = goldilocks.Curve{}.ScalarBaseMult(s).ToBytes(privateKey[SeedSize:])
192+
var P goldilocks.Point
193+
P.ScalarBaseMult(s)
194+
err := P.Encode(&pair.public)
195+
if err != nil {
196+
panic(err)
197+
}
193198
}
194199

195200
func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) {
@@ -231,10 +236,11 @@ func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash
231236
// 3. Compute the point [r]B.
232237
r := &goldilocks.Scalar{}
233238
r.FromBytes(rPM[:])
234-
R := (&[paramB]byte{})[:]
235-
if err := (goldilocks.Curve{}.ScalarBaseMult(r).ToBytes(R)); err != nil {
236-
panic(err)
237-
}
239+
var R goldilocks.Point
240+
var encR [goldilocks.EncodingSize]byte
241+
R.ScalarBaseMult(r)
242+
err := R.Encode(&encR)
243+
238244
// 4. Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114)
239245
var hRAM [hashSize]byte
240246
H.Reset()
@@ -254,7 +260,7 @@ func sign(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash
254260
S.Add(S, r)
255261

256262
// 6. The signature is the concatenation of R and S.
257-
copy(signature[:paramB], R[:])
263+
copy(signature[:paramB], encR[:])
258264
copy(signature[paramB:], S[:])
259265
}
260266

@@ -287,7 +293,10 @@ func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool
287293
return false
288294
}
289295

290-
P, err := goldilocks.FromBytes(public)
296+
var encPublic [goldilocks.EncodingSize]byte
297+
copy(encPublic[:], public)
298+
P := &goldilocks.Point{}
299+
err := P.Decode(&encPublic)
291300
if err != nil {
292301
return false
293302
}
@@ -320,10 +329,15 @@ func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool
320329
S := &goldilocks.Scalar{}
321330
S.FromBytes(signature[paramB:])
322331

323-
encR := (&[paramB]byte{})[:]
324332
P.Neg()
325-
_ = goldilocks.Curve{}.CombinedMult(S, k, P).ToBytes(encR)
326-
return bytes.Equal(R, encR)
333+
var Q goldilocks.Point
334+
Q.CombinedMult(S, k, P)
335+
var encR [goldilocks.EncodingSize]byte
336+
err = Q.Encode(&encR)
337+
if err != nil {
338+
return false
339+
}
340+
return bytes.Equal(R, encR[:])
327341
}
328342

329343
// VerifyAny returns true if the signature is valid. Failure cases are invalid
@@ -378,7 +392,7 @@ func deriveSecretScalar(s *goldilocks.Scalar, h []byte) {
378392

379393
// isLessThanOrder returns true if 0 <= x < order and if the last byte of x is zero.
380394
func isLessThanOrder(x []byte) bool {
381-
order := goldilocks.Curve{}.Order()
395+
order := goldilocks.Order()
382396
i := len(order) - 1
383397
for i > 0 && x[i] == order[i] {
384398
i--

sign/ed448/internal/goldilocks/goldilocks.go

+45-58
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
// Package goldilocks provides goldilocks curve operations required by Ed448.
1+
// Package goldilocks provides arithmetic operations on the Goldilocks curve.
22
//
33
// Goldilocks Curve
44
//
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
76
// Goldilocks: ax^2+y^2 = 1 + dx^2y^2, where a=1 and d=-39081.
87
// This curve was proposed by Hamburg (1) and is also known as edwards448
98
// after RFC-7748 (2).
@@ -36,8 +35,6 @@ const EncodingSize = fp.Size + 1
3635
// ErrInvalidDecoding alerts of an error during decoding a point.
3736
var ErrInvalidDecoding = errors.New("invalid decoding")
3837

39-
func (P *Point) Neg() { fp.Neg(&P.X, &P.X); fp.Neg(&P.Ta, &P.Ta) }
40-
4138
// Decode if succeeds constructs a point by decoding the first
4239
// EncodingSize bytes of data.
4340
func (P *Point) Decode(data *[EncodingSize]byte) error {
@@ -66,12 +63,10 @@ func (P *Point) Decode(data *[EncodingSize]byte) error {
6663
fp.Cmov(&P.Ta, x, b)
6764
fp.Cmov(&P.Tb, y, b)
6865
fp.Cmov(&P.Z, &one, b)
69-
70-
var err error
7166
if !isValid {
72-
err = ErrInvalidDecoding
67+
return ErrInvalidDecoding
7368
}
74-
return err
69+
return nil
7570
}
7671

7772
// Encode sets data with the unique encoding of the point P.
@@ -83,65 +78,60 @@ func (P *Point) Encode(data *[EncodingSize]byte) error {
8378
fp.Modp(x)
8479
fp.Modp(y)
8580
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)
8882
}
8983

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) {
9587
k4 := &Scalar{}
9688
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)
10092
}
10193

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) {
10498
m4, n4 := &Scalar{}, &Scalar{}
10599
divBy4(m4, m)
106100
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)
112105
}
113106

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) }
134117

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) {
137123
Px, Py, Pz := &P.X, &P.Y, &P.Z
138124
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+
}
145135
fp.Sqr(e, e) // (x+y)^2
146136
fp.Sub(e, e, a) // (x+y)^2-A
147137
fp.Sub(e, e, b) // E = (x+y)^2-A-B
@@ -153,9 +143,6 @@ func push(Q *Point, P *ted448.Point) {
153143
fp.Mul(&Q.Y, g, h) // Y = G * H, // T = E * H
154144
}
155145

156-
// divBy4 calculates z = x/4 mod order.
157-
func divBy4(z, x *Scalar) { z.Mul(x, &invFour) }
158-
159146
// isLessThan returns true if 0 <= x < y, and assumes that slices are of the
160147
// same length and are interpreted in little-endian order.
161148
func isLessThan(x, y []byte) bool {
@@ -177,7 +164,7 @@ var (
177164
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
178165
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
179166
}
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.
181168
paramD = fp.Elt{
182169
0x56, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
183170
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

sign/ed448/internal/goldilocks/goldilocks_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ func TestScalarMult(t *testing.T) {
4747
for i := 0; i < testTimes; i++ {
4848
_, _ = rand.Read(k[:])
4949

50-
ScalarBaseMult(&P, k)
51-
CombinedMult(&Q, k, zero, &I) // k*G + 0*I
50+
P.ScalarBaseMult(k)
51+
Q.CombinedMult(k, zero, &I) // k*G + 0*I
5252
err0 := P.Encode(&got)
5353
err1 := Q.Encode(&want)
5454
if err0 != nil || err1 != nil || got != want {
@@ -108,7 +108,7 @@ func BenchmarkEncoding(b *testing.B) {
108108
var k Scalar
109109
_, _ = rand.Read(k[:])
110110
var P Point
111-
ScalarBaseMult(&P, &k)
111+
P.ScalarBaseMult(&k)
112112
b.Run("Marshal", func(b *testing.B) {
113113
for i := 0; i < b.N; i++ {
114114
_ = P.Encode(&data)

0 commit comments

Comments
 (0)