Skip to content

Commit 320e4ad

Browse files
committed
crypto/elliptic: document and test that IsOnCurve(∞) == false
This also implies it can't be passed to Marshal. Fixes #37294 Change-Id: I1e6b6abd87ff31f323486958d5cb34a5c8f76b5f Reviewed-on: https://go-review.googlesource.com/c/go/+/239562 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Katie Hockman <katie@golang.org>
1 parent 9f33108 commit 320e4ad

File tree

2 files changed

+56
-30
lines changed

2 files changed

+56
-30
lines changed

src/crypto/elliptic/elliptic.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import (
2020
)
2121

2222
// A Curve represents a short-form Weierstrass curve with a=-3.
23-
// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
23+
//
24+
// Note that the point at infinity (0, 0) is not considered on the curve, and
25+
// although it can be returned by Add, Double, ScalarMult, or ScalarBaseMult, it
26+
// can't be marshaled or unmarshaled, and IsOnCurve will return false for it.
2427
type Curve interface {
2528
// Params returns the parameters for the curve.
2629
Params() *CurveParams
@@ -307,7 +310,8 @@ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err e
307310
return
308311
}
309312

310-
// Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62.
313+
// Marshal converts a point on the curve into the uncompressed form specified in
314+
// section 4.3.6 of ANSI X9.62.
311315
func Marshal(curve Curve, x, y *big.Int) []byte {
312316
byteLen := (curve.Params().BitSize + 7) / 8
313317

@@ -320,7 +324,8 @@ func Marshal(curve Curve, x, y *big.Int) []byte {
320324
return ret
321325
}
322326

323-
// MarshalCompressed converts a point into the compressed form specified in section 4.3.6 of ANSI X9.62.
327+
// MarshalCompressed converts a point on the curve into the compressed form
328+
// specified in section 4.3.6 of ANSI X9.62.
324329
func MarshalCompressed(curve Curve, x, y *big.Int) []byte {
325330
byteLen := (curve.Params().BitSize + 7) / 8
326331
compressed := make([]byte, 1+byteLen)

src/crypto/elliptic/elliptic_test.go

+48-27
Original file line numberDiff line numberDiff line change
@@ -418,41 +418,62 @@ func TestP256Mult(t *testing.T) {
418418
}
419419
}
420420

421-
func TestInfinity(t *testing.T) {
422-
tests := []struct {
423-
name string
424-
curve Curve
425-
}{
426-
{"p224", P224()},
427-
{"p256", P256()},
421+
func testInfinity(t *testing.T, curve Curve) {
422+
_, x, y, _ := GenerateKey(curve, rand.Reader)
423+
x, y = curve.ScalarMult(x, y, curve.Params().N.Bytes())
424+
if x.Sign() != 0 || y.Sign() != 0 {
425+
t.Errorf("x^q != ∞")
428426
}
429427

430-
for _, test := range tests {
431-
curve := test.curve
432-
x, y := curve.ScalarBaseMult(nil)
433-
if x.Sign() != 0 || y.Sign() != 0 {
434-
t.Errorf("%s: x^0 != ∞", test.name)
435-
}
428+
x, y = curve.ScalarBaseMult([]byte{0})
429+
if x.Sign() != 0 || y.Sign() != 0 {
430+
t.Errorf("b^0 != ∞")
436431
x.SetInt64(0)
437432
y.SetInt64(0)
433+
}
438434

439-
x2, y2 := curve.Double(x, y)
440-
if x2.Sign() != 0 || y2.Sign() != 0 {
441-
t.Errorf("%s: 2∞ != ∞", test.name)
442-
}
435+
x2, y2 := curve.Double(x, y)
436+
if x2.Sign() != 0 || y2.Sign() != 0 {
437+
t.Errorf("2∞ != ∞")
438+
}
443439

444-
baseX := curve.Params().Gx
445-
baseY := curve.Params().Gy
440+
baseX := curve.Params().Gx
441+
baseY := curve.Params().Gy
446442

447-
x3, y3 := curve.Add(baseX, baseY, x, y)
448-
if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
449-
t.Errorf("%s: x+∞ != x", test.name)
450-
}
443+
x3, y3 := curve.Add(baseX, baseY, x, y)
444+
if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
445+
t.Errorf("x+∞ != x")
446+
}
451447

452-
x4, y4 := curve.Add(x, y, baseX, baseY)
453-
if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
454-
t.Errorf("%s: ∞+x != x", test.name)
455-
}
448+
x4, y4 := curve.Add(x, y, baseX, baseY)
449+
if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
450+
t.Errorf("∞+x != x")
451+
}
452+
453+
if curve.IsOnCurve(x, y) {
454+
t.Errorf("IsOnCurve(∞) == true")
455+
}
456+
}
457+
458+
func TestInfinity(t *testing.T) {
459+
tests := []struct {
460+
name string
461+
curve Curve
462+
}{
463+
{"P-224", P224()},
464+
{"P-256", P256()},
465+
{"P-256/Generic", P256().Params()},
466+
{"P-384", P384()},
467+
{"P-521", P521()},
468+
}
469+
if testing.Short() {
470+
tests = tests[:1]
471+
}
472+
for _, test := range tests {
473+
curve := test.curve
474+
t.Run(test.name, func(t *testing.T) {
475+
testInfinity(t, curve)
476+
})
456477
}
457478
}
458479

0 commit comments

Comments
 (0)