diff --git a/ecdsa_test.go b/ecdsa_test.go index 1cb2c12..e549c02 100644 --- a/ecdsa_test.go +++ b/ecdsa_test.go @@ -172,18 +172,6 @@ func generateTestECDSAKey(t *testing.T) *ecdsa.PrivateKey { return key } -func Test_customCurveKeySigner(t *testing.T) { - // https://github.com/veraison/go-cose/issues/59 - pCustom := *elliptic.P256().Params() - pCustom.Name = "P-custom" - pCustom.BitSize /= 2 - key, err := ecdsa.GenerateKey(&pCustom, rand.Reader) - if err != nil { - t.Fatalf("ecdsa.GenerateKey() error = %v", err) - } - testSignVerify(t, AlgorithmES256, key, false) -} - func Test_ecdsaKeySigner(t *testing.T) { key := generateTestECDSAKey(t) testSignVerify(t, AlgorithmES256, key, false) diff --git a/go.mod b/go.mod index 7e60365..fad879c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/veraison/go-cose -go 1.18 +go 1.21 require github.com/fxamacker/cbor/v2 v2.5.0 diff --git a/key.go b/key.go index 71ad331..53b1242 100644 --- a/key.go +++ b/key.go @@ -2,9 +2,11 @@ package cose import ( "crypto" + "crypto/ecdh" "crypto/ecdsa" "crypto/ed25519" "crypto/elliptic" + "crypto/x509" "errors" "fmt" "math/big" @@ -703,8 +705,29 @@ func (k *Key) PrivateKey() (crypto.PrivateKey, error) { switch alg { case AlgorithmES256, AlgorithmES384, AlgorithmES512: - var curve elliptic.Curve + _, x, y, d := k.EC2() + if len(x) == 0 || len(y) == 0 { + var curve ecdh.Curve + switch alg { + case AlgorithmES256: + curve = ecdh.P256() + case AlgorithmES384: + curve = ecdh.P384() + case AlgorithmES512: + curve = ecdh.P521() + } + key, err := curve.NewPrivateKey(d) + if err != nil { + return nil, err + } + encodedKey, err := x509.MarshalPKCS8PrivateKey(key) + if err != nil { + return nil, err + } + return x509.ParsePKCS8PrivateKey(encodedKey) + } + var curve elliptic.Curve switch alg { case AlgorithmES256: curve = elliptic.P256() @@ -714,14 +737,8 @@ func (k *Key) PrivateKey() (crypto.PrivateKey, error) { curve = elliptic.P521() } - _, x, y, d := k.EC2() - var bx, by *big.Int - if len(x) == 0 || len(y) == 0 { - bx, by = curve.ScalarBaseMult(d) - } else { - bx = new(big.Int).SetBytes(x) - by = new(big.Int).SetBytes(y) - } + bx := new(big.Int).SetBytes(x) + by := new(big.Int).SetBytes(y) bd := new(big.Int).SetBytes(d) return &ecdsa.PrivateKey{ diff --git a/verifier.go b/verifier.go index 69e576f..09957ad 100644 --- a/verifier.go +++ b/verifier.go @@ -36,6 +36,8 @@ type DigestVerifier interface { // NewVerifier returns a verifier with a given public key. // Only golang built-in crypto public keys of type `*rsa.PublicKey`, // `*ecdsa.PublicKey`, and `ed25519.PublicKey` are accepted. +// When `*ecdsa.PublicKey` is specified, its curve must be supported by +// crypto/ecdh. // // The returned signer for rsa and ecdsa keys also implements `cose.DigestSigner`. func NewVerifier(alg Algorithm, key crypto.PublicKey) (Verifier, error) { @@ -60,8 +62,11 @@ func NewVerifier(alg Algorithm, key crypto.PublicKey) (Verifier, error) { if !ok { return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) } - if !vk.Curve.IsOnCurve(vk.X, vk.Y) { - return nil, errors.New("public key point is not on curve") + if _, err := vk.ECDH(); err != nil { + if err.Error() == "ecdsa: invalid public key" { + return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) + } + return nil, fmt.Errorf("%v: %w: %v", alg, ErrInvalidPubKey, err) } return &ecdsaVerifier{ alg: alg, diff --git a/verifier_test.go b/verifier_test.go index 5295133..82d84ca 100644 --- a/verifier_test.go +++ b/verifier_test.go @@ -48,6 +48,13 @@ func TestNewVerifier(t *testing.T) { // craft an EC public key with the x-coord not on curve ecdsaKeyPointNotOnCurve := generateBogusECKey() + // craft an EC public key with a curve not supported by crypto/ecdh + ecdsaKeyUnsupportedCurve := &ecdsa.PublicKey{ + Curve: ecdsaKey.Curve.Params(), + X: ecdsaKey.X, + Y: ecdsaKey.Y, + } + // run tests tests := []struct { name string @@ -125,7 +132,13 @@ func TestNewVerifier(t *testing.T) { name: "bogus ecdsa public key (point not on curve)", alg: AlgorithmES256, key: ecdsaKeyPointNotOnCurve, - wantErr: "public key point is not on curve", + wantErr: "ES256: invalid public key", + }, + { + name: "ecdsa public key with unsupported curve", + alg: AlgorithmES256, + key: ecdsaKeyUnsupportedCurve, + wantErr: "ES256: invalid public key: ecdsa: unsupported curve by crypto/ecdh", }, } for _, tt := range tests {