mirror of https://github.com/golang/go.git
[release-branch.go1.20] crypto/ecdh: explicitly reject mismatched curves in ECDH
Return an explicit error when PrivateKey.ECDH is called with a PublicKey
which uses a different Curve. Also document this requirement, even
though it is perhaps obvious.
Updates #58131.
Fixes #58498.
Change-Id: I739181a3f1283bed14fb5ee7eb78658b854d28d8
Reviewed-on: https://go-review.googlesource.com/c/go/+/464335
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Auto-Submit: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
(cherry picked from commit 67d8916d55)
Reviewed-on: https://go-review.googlesource.com/c/go/+/471602
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
0f4483cfdc
commit
aaace6dda7
|
|
@ -10,6 +10,7 @@ import (
|
|||
"crypto"
|
||||
"crypto/internal/boring"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
|
@ -109,7 +110,8 @@ type PrivateKey struct {
|
|||
publicKeyOnce sync.Once
|
||||
}
|
||||
|
||||
// ECDH performs a ECDH exchange and returns the shared secret.
|
||||
// ECDH performs a ECDH exchange and returns the shared secret. The PrivateKey
|
||||
// and PublicKey must use the same curve.
|
||||
//
|
||||
// For NIST curves, this performs ECDH as specified in SEC 1, Version 2.0,
|
||||
// Section 3.3.1, and returns the x-coordinate encoded according to SEC 1,
|
||||
|
|
@ -118,6 +120,9 @@ type PrivateKey struct {
|
|||
// For X25519, this performs ECDH as specified in RFC 7748, Section 6.1. If
|
||||
// the result is the all-zero value, ECDH returns an error.
|
||||
func (k *PrivateKey) ECDH(remote *PublicKey) ([]byte, error) {
|
||||
if k.curve != remote.curve {
|
||||
return nil, errors.New("crypto/ecdh: private key and public key curves do not match")
|
||||
}
|
||||
return k.curve.ecdh(k, remote)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -487,3 +487,39 @@ func TestLinker(t *testing.T) {
|
|||
t.Error("no P384 symbols found in program using ecdh.P384, test is broken")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMismatchedCurves(t *testing.T) {
|
||||
curves := []struct {
|
||||
name string
|
||||
curve ecdh.Curve
|
||||
}{
|
||||
{"P256", ecdh.P256()},
|
||||
{"P384", ecdh.P384()},
|
||||
{"P521", ecdh.P521()},
|
||||
{"X25519", ecdh.X25519()},
|
||||
}
|
||||
|
||||
for _, privCurve := range curves {
|
||||
priv, err := privCurve.curve.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate test key: %s", err)
|
||||
}
|
||||
|
||||
for _, pubCurve := range curves {
|
||||
if privCurve == pubCurve {
|
||||
continue
|
||||
}
|
||||
t.Run(fmt.Sprintf("%s/%s", privCurve.name, pubCurve.name), func(t *testing.T) {
|
||||
pub, err := pubCurve.curve.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate test key: %s", err)
|
||||
}
|
||||
expected := "crypto/ecdh: private key and public key curves do not match"
|
||||
_, err = priv.ECDH(pub.PublicKey())
|
||||
if err.Error() != expected {
|
||||
t.Fatalf("unexpected error: want %q, got %q", expected, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue