diff --git a/algorithm.go b/algorithm.go index 2d15d22..7a955af 100644 --- a/algorithm.go +++ b/algorithm.go @@ -24,16 +24,40 @@ const ( // ECDSA w/ SHA-256 by RFC 8152. // Requires an available crypto.SHA256. + // + // Note: use [AlgorithmESP256] only if you are certain that the recipient + // supports it. For maximum interoperability and backward compatibility, + // [AlgorithmES256] should remain the default choice. AlgorithmES256 Algorithm = -7 + // ECDSA using P-256 curve and SHA-256 by RFC 9864. + // Requires an available crypto.SHA256. + AlgorithmESP256 Algorithm = -9 + // ECDSA w/ SHA-384 by RFC 8152. // Requires an available crypto.SHA384. + // + // Note: use [AlgorithmESP384] only if you are certain that the recipient + // supports it. For maximum interoperability and backward compatibility, + // [AlgorithmES384] should remain the default choice. AlgorithmES384 Algorithm = -35 + // ECDSA using P-384 curve and SHA-384 by RFC 9864. + // Requires an available crypto.SHA384. + AlgorithmESP384 Algorithm = -51 + // ECDSA w/ SHA-512 by RFC 8152. // Requires an available crypto.SHA512. + // + // Note: use [AlgorithmESP512] only if you are certain that the recipient + // supports it. For maximum interoperability and backward compatibility, + // [AlgorithmES512] should remain the default choice. AlgorithmES512 Algorithm = -36 + // ECDSA using P-521 curve and SHA-512 by RFC 9864. + // Requires an available crypto.SHA512. + AlgorithmESP512 Algorithm = -52 + // PureEdDSA by RFC 8152. // // Deprecated: use [AlgorithmEdDSA] instead, which has @@ -41,7 +65,15 @@ const ( AlgorithmEd25519 Algorithm = -8 // PureEdDSA by RFC 8152. + // + // Note: use [AlgorithmEd25519EdDSA] only if you are certain that the recipient + // supports it. For maximum interoperability and backward compatibility, + // AlgorithmEdDSA should remain the default choice. AlgorithmEdDSA Algorithm = -8 + + // EdDSA restricted to the Ed25519 curve, as defined in RFC 9864. + // This algorithm is newer and may not be supported by all COSE libraries. + AlgorithmEd25519EdDSA Algorithm = -19 ) // Signature algorithms known, but not supported by this library. @@ -104,14 +136,24 @@ func (a Algorithm) String() string { return "RS512" case AlgorithmES256: return "ES256" + case AlgorithmESP256: + return "ESP256" case AlgorithmES384: return "ES384" + case AlgorithmESP384: + return "ESP384" case AlgorithmES512: return "ES512" + case AlgorithmESP512: + return "ESP512" case AlgorithmEdDSA: // As stated in RFC 8152 section 8.2, only the pure EdDSA version is // used for COSE. return "EdDSA" + case AlgorithmEd25519EdDSA: + // As stated in RFC 8152 section 8.2, only the pure EdDSA version is + // used for COSE. + return "Ed25519" case AlgorithmReserved: return "Reserved" case AlgorithmSHA256: @@ -129,11 +171,11 @@ func (a Algorithm) String() string { // library. func (a Algorithm) hashFunc() crypto.Hash { switch a { - case AlgorithmPS256, AlgorithmES256, AlgorithmSHA256: + case AlgorithmPS256, AlgorithmES256, AlgorithmESP256, AlgorithmSHA256: return crypto.SHA256 - case AlgorithmPS384, AlgorithmES384, AlgorithmSHA384: + case AlgorithmPS384, AlgorithmES384, AlgorithmESP384, AlgorithmSHA384: return crypto.SHA384 - case AlgorithmPS512, AlgorithmES512, AlgorithmSHA512: + case AlgorithmPS512, AlgorithmES512, AlgorithmESP512, AlgorithmSHA512: return crypto.SHA512 default: return 0 diff --git a/ecdsa_test.go b/ecdsa_test.go index e549c02..3578f3c 100644 --- a/ecdsa_test.go +++ b/ecdsa_test.go @@ -175,6 +175,7 @@ func generateTestECDSAKey(t *testing.T) *ecdsa.PrivateKey { func Test_ecdsaKeySigner(t *testing.T) { key := generateTestECDSAKey(t) testSignVerify(t, AlgorithmES256, key, false) + testSignVerify(t, AlgorithmESP256, key, false) } func Test_ecdsaCryptoSigner(t *testing.T) { @@ -184,6 +185,7 @@ func Test_ecdsaCryptoSigner(t *testing.T) { Signer: generateTestECDSAKey(t), } testSignVerify(t, AlgorithmES256, wrappedKey, true) + testSignVerify(t, AlgorithmESP256, wrappedKey, true) } func testSignVerify(t *testing.T, alg Algorithm, key crypto.Signer, isCryptoSigner bool) { @@ -256,6 +258,7 @@ func Test_ecdsaBadCryptoSigner_SignFailure(t *testing.T) { err: errors.New("sign failure"), } testSignFailure(t, AlgorithmES256, badSigner) + testSignFailure(t, AlgorithmESP256, badSigner) } func Test_ecdsaBadCryptoSigner_BadSignature(t *testing.T) { @@ -267,6 +270,7 @@ func Test_ecdsaBadCryptoSigner_BadSignature(t *testing.T) { signature: nil, } testSignFailure(t, AlgorithmES256, badSigner) + testSignFailure(t, AlgorithmESP256, badSigner) // malformed signature: bad r sig, err := asn1.Marshal(struct { @@ -283,6 +287,7 @@ func Test_ecdsaBadCryptoSigner_BadSignature(t *testing.T) { signature: sig, } testSignFailure(t, AlgorithmES256, badSigner) + testSignFailure(t, AlgorithmESP256, badSigner) // malformed signature: bad s sig, err = asn1.Marshal(struct { @@ -299,6 +304,7 @@ func Test_ecdsaBadCryptoSigner_BadSignature(t *testing.T) { signature: sig, } testSignFailure(t, AlgorithmES256, badSigner) + testSignFailure(t, AlgorithmESP256, badSigner) } func Test_ecdsaKeySigner_SignHashFailure(t *testing.T) { @@ -332,69 +338,99 @@ func testSignFailure(t *testing.T, alg Algorithm, key crypto.Signer) { } func Test_ecdsaVerifier_Verify_Success(t *testing.T) { - // generate key - alg := AlgorithmES256 - key := generateTestECDSAKey(t) + tests := []struct { + name string + alg Algorithm + }{ + {"ES256", AlgorithmES256}, + {"ESP256", AlgorithmESP256}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // generate key + key := generateTestECDSAKey(t) - // generate a valid signature - content, sig := signTestData(t, alg, key) + // generate a valid signature + content, sig := signTestData(t, tt.alg, key) - // set up verifier - verifier, err := NewVerifier(alg, key.Public()) - if err != nil { - t.Fatalf("NewVerifier() error = %v", err) - } - if _, ok := verifier.(*ecdsaVerifier); !ok { - t.Fatalf("NewVerifier() type = %v, want *ecdsaVerifier", reflect.TypeOf(verifier)) - } - if got := verifier.Algorithm(); got != alg { - t.Fatalf("Algorithm() = %v, want %v", got, alg) - } + // set up verifier + verifier, err := NewVerifier(tt.alg, key.Public()) + if err != nil { + t.Fatalf("NewVerifier() error = %v", err) + } + if _, ok := verifier.(*ecdsaVerifier); !ok { + t.Fatalf("NewVerifier() type = %v, want *ecdsaVerifier", reflect.TypeOf(verifier)) + } + if got := verifier.Algorithm(); got != tt.alg { + t.Fatalf("Algorithm() = %v, want %v", got, tt.alg) + } - // verify round trip - if err := verifier.Verify(content, sig); err != nil { - t.Fatalf("ecdsaVerifier.Verify() error = %v", err) + // verify round trip + if err := verifier.Verify(content, sig); err != nil { + t.Fatalf("ecdsaVerifier.Verify() error = %v", err) + } + }) } } func Test_ecdsaVerifier_Verify_AlgorithmMismatch(t *testing.T) { - // generate key - alg := AlgorithmES256 - key := generateTestECDSAKey(t) + tests := []struct { + name string + alg Algorithm + }{ + {"ES256", AlgorithmES256}, + {"ESP256", AlgorithmESP256}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // generate key + key := generateTestECDSAKey(t) - // generate a valid signature - content, sig := signTestData(t, alg, key) + // generate a valid signature + content, sig := signTestData(t, tt.alg, key) - // set up verifier with a different algorithm - verifier := &ecdsaVerifier{ - alg: AlgorithmES512, - key: &key.PublicKey, - } + // set up verifier with a different algorithm + verifier := &ecdsaVerifier{ + alg: AlgorithmES512, + key: &key.PublicKey, + } - // verification should fail on algorithm mismatch - if err := verifier.Verify(content, sig); err != ErrVerification { - t.Fatalf("ecdsaVerifier.Verify() error = %v, wantErr %v", err, ErrVerification) + // verification should fail on algorithm mismatch + if err := verifier.Verify(content, sig); err != ErrVerification { + t.Fatalf("ecdsaVerifier.Verify() error = %v, wantErr %v", err, ErrVerification) + } + }) } } func Test_ecdsaVerifier_Verify_KeyMismatch(t *testing.T) { - // generate key - alg := AlgorithmES256 - key := generateTestECDSAKey(t) + tests := []struct { + name string + alg Algorithm + }{ + {"ES256", AlgorithmES256}, + {"ESP256", AlgorithmESP256}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // generate key + key := generateTestECDSAKey(t) - // generate a valid signature - content, sig := signTestData(t, alg, key) + // generate a valid signature + content, sig := signTestData(t, tt.alg, key) - // set up verifier with a different key / new key - key = generateTestECDSAKey(t) - verifier := &ecdsaVerifier{ - alg: alg, - key: &key.PublicKey, - } + // set up verifier with a different key / new key + key = generateTestECDSAKey(t) + verifier := &ecdsaVerifier{ + alg: tt.alg, + key: &key.PublicKey, + } - // verification should fail on key mismatch - if err := verifier.Verify(content, sig); err != ErrVerification { - t.Fatalf("ecdsaVerifier.Verify() error = %v, wantErr %v", err, ErrVerification) + // verification should fail on key mismatch + if err := verifier.Verify(content, sig); err != ErrVerification { + t.Fatalf("ecdsaVerifier.Verify() error = %v, wantErr %v", err, ErrVerification) + } + }) } } diff --git a/ed25519.go b/ed25519.go index 813d32a..31eb3cf 100644 --- a/ed25519.go +++ b/ed25519.go @@ -8,12 +8,13 @@ import ( // ed25519Signer is a Pure EdDSA based signer with a generic crypto.Signer. type ed25519Signer struct { + alg Algorithm key crypto.Signer } // Algorithm returns the signing algorithm associated with the private key. func (es *ed25519Signer) Algorithm() Algorithm { - return AlgorithmEdDSA + return es.alg } // Sign signs message content with the private key, possibly using entropy from @@ -29,12 +30,13 @@ func (es *ed25519Signer) Sign(rand io.Reader, content []byte) ([]byte, error) { // ed25519Verifier is a Pure EdDSA based verifier with golang built-in keys. type ed25519Verifier struct { + alg Algorithm key ed25519.PublicKey } // Algorithm returns the signing algorithm associated with the public key. func (ev *ed25519Verifier) Algorithm() Algorithm { - return AlgorithmEdDSA + return ev.alg } // Verify verifies message content with the public key, returning nil for diff --git a/ed25519_test.go b/ed25519_test.go index 4ecddaf..34d8f86 100644 --- a/ed25519_test.go +++ b/ed25519_test.go @@ -16,91 +16,121 @@ func generateTestEd25519Key(t *testing.T) (ed25519.PublicKey, ed25519.PrivateKey } func Test_ed25519Signer(t *testing.T) { - // generate key - alg := AlgorithmEdDSA - _, key := generateTestEd25519Key(t) - - // set up signer - signer, err := NewSigner(alg, key) - if err != nil { - t.Fatalf("NewSigner() error = %v", err) - } - if _, ok := signer.(*ed25519Signer); !ok { - t.Fatalf("NewSigner() type = %v, want *ed25519Signer", reflect.TypeOf(signer)) - } - if got := signer.Algorithm(); got != alg { - t.Fatalf("Algorithm() = %v, want %v", got, alg) + tests := []struct { + name string + alg Algorithm + }{ + {"EdDSA", AlgorithmEdDSA}, + {"Ed25519EdDSA", AlgorithmEd25519EdDSA}, } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // generate key + _, key := generateTestEd25519Key(t) - // sign / verify round trip - // see also conformance_test.go for strict tests. - content := []byte("hello world") - sig, err := signer.Sign(rand.Reader, content) - if err != nil { - t.Fatalf("Sign() error = %v", err) - } + // set up signer + signer, err := NewSigner(tt.alg, key) + if err != nil { + t.Fatalf("NewSigner() error = %v", err) + } + if _, ok := signer.(*ed25519Signer); !ok { + t.Fatalf("NewSigner() type = %v, want *ed25519Signer", reflect.TypeOf(signer)) + } + if got := signer.Algorithm(); got != tt.alg { + t.Fatalf("Algorithm() = %v, want %v", got, tt.alg) + } - verifier, err := NewVerifier(alg, key.Public()) - if err != nil { - t.Fatalf("NewVerifier() error = %v", err) - } - if err := verifier.Verify(content, sig); err != nil { - t.Fatalf("Verifier.Verify() error = %v", err) - } + // sign / verify round trip + // see also conformance_test.go for strict tests. + content := []byte("hello world") + sig, err := signer.Sign(rand.Reader, content) + if err != nil { + t.Fatalf("Sign() error = %v", err) + } - _, ok := signer.(DigestSigner) - if ok { - t.Fatalf("signer shouldn't be a DigestSigner") - } - _, ok = verifier.(DigestVerifier) - if ok { - t.Fatalf("verifier shouldn't be a DigestVerifier") + verifier, err := NewVerifier(tt.alg, key.Public()) + if err != nil { + t.Fatalf("NewVerifier() error = %v", err) + } + if err := verifier.Verify(content, sig); err != nil { + t.Fatalf("Verifier.Verify() error = %v", err) + } + + _, ok := signer.(DigestSigner) + if ok { + t.Fatalf("signer shouldn't be a DigestSigner") + } + _, ok = verifier.(DigestVerifier) + if ok { + t.Fatalf("verifier shouldn't be a DigestVerifier") + } + }) } } func Test_ed25519Verifier_Verify_Success(t *testing.T) { - // generate key - alg := AlgorithmEdDSA - _, key := generateTestEd25519Key(t) + tests := []struct { + name string + alg Algorithm + }{ + {"EdDSA", AlgorithmEdDSA}, + {"Ed25519EdDSA", AlgorithmEd25519EdDSA}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // generate key + _, key := generateTestEd25519Key(t) - // generate a valid signature - content, sig := signTestData(t, alg, key) + // generate a valid signature + content, sig := signTestData(t, tt.alg, key) - // set up verifier - verifier, err := NewVerifier(alg, key.Public()) - if err != nil { - t.Fatalf("NewVerifier() error = %v", err) - } - if _, ok := verifier.(*ed25519Verifier); !ok { - t.Fatalf("NewVerifier() type = %v, want *ed25519Verifier", reflect.TypeOf(verifier)) - } - if got := verifier.Algorithm(); got != alg { - t.Fatalf("Algorithm() = %v, want %v", got, alg) - } + // set up verifier + verifier, err := NewVerifier(tt.alg, key.Public()) + if err != nil { + t.Fatalf("NewVerifier() error = %v", err) + } + if _, ok := verifier.(*ed25519Verifier); !ok { + t.Fatalf("NewVerifier() type = %v, want *ed25519Verifier", reflect.TypeOf(verifier)) + } + if got := verifier.Algorithm(); got != tt.alg { + t.Fatalf("Algorithm() = %v, want %v", got, tt.alg) + } - // verify round trip - if err := verifier.Verify(content, sig); err != nil { - t.Fatalf("ed25519Verifier.Verify() error = %v", err) + // verify round trip + if err := verifier.Verify(content, sig); err != nil { + t.Fatalf("ed25519Verifier.Verify() error = %v", err) + } + }) } } func Test_ed25519Verifier_Verify_KeyMismatch(t *testing.T) { - // generate key - alg := AlgorithmEdDSA - _, key := generateTestEd25519Key(t) + tests := []struct { + name string + alg Algorithm + }{ + {"EdDSA", AlgorithmEdDSA}, + {"Ed25519EdDSA", AlgorithmEd25519EdDSA}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // generate key + _, key := generateTestEd25519Key(t) - // generate a valid signature - content, sig := signTestData(t, alg, key) + // generate a valid signature + content, sig := signTestData(t, tt.alg, key) - // set up verifier with a different key / new key - vk, _ := generateTestEd25519Key(t) - verifier := &ed25519Verifier{ - key: vk, - } + // set up verifier with a different key / new key + vk, _ := generateTestEd25519Key(t) + verifier := &ed25519Verifier{ + key: vk, + } - // verification should fail on key mismatch - if err := verifier.Verify(content, sig); err != ErrVerification { - t.Fatalf("ed25519Verifier.Verify() error = %v, wantErr %v", err, ErrVerification) + // verification should fail on key mismatch + if err := verifier.Verify(content, sig); err != ErrVerification { + t.Fatalf("ed25519Verifier.Verify() error = %v, wantErr %v", err, ErrVerification) + } + }) } } diff --git a/key.go b/key.go index b657bff..12d3493 100644 --- a/key.go +++ b/key.go @@ -10,6 +10,7 @@ import ( "math/big" "reflect" "strconv" + "strings" ) const ( @@ -319,11 +320,11 @@ func NewKeyEC2(alg Algorithm, x, y, d []byte) (*Key, error) { var curve Curve switch alg { - case AlgorithmES256: + case AlgorithmES256, AlgorithmESP256: curve = CurveP256 - case AlgorithmES384: + case AlgorithmES384, AlgorithmESP384: curve = CurveP384 - case AlgorithmES512: + case AlgorithmES512, AlgorithmESP512: curve = CurveP521 default: return nil, fmt.Errorf("unsupported algorithm %q", alg) @@ -501,16 +502,20 @@ func (k Key) validate(op KeyOp) error { // If Algorithm is set, it must match the specified key parameters. if k.Algorithm != AlgorithmReserved { - expectedAlg, err := k.deriveAlgorithm() + candidateAlgs, err := k.deriveAlgorithms() if err != nil { return err } - if k.Algorithm != expectedAlg { + if !containsAlg(candidateAlgs, k.Algorithm) { + strs := make([]string, len(candidateAlgs)) + for i, a := range candidateAlgs { + strs[i] = a.String() + } return fmt.Errorf( - "found algorithm %q (expected %q)", + "found algorithm %q (expected one of {%q})", k.Algorithm.String(), - expectedAlg.String(), + strings.Join(strs, ","), ) } } @@ -518,6 +523,15 @@ func (k Key) validate(op KeyOp) error { return nil } +func containsAlg(algs []Algorithm, target Algorithm) bool { + for _, a := range algs { + if a == target { + return true + } + } + return false +} + func (k Key) canOp(op KeyOp) bool { if k.Ops == nil { return true @@ -658,21 +672,21 @@ func (k *Key) PublicKey() (crypto.PublicKey, error) { if err := k.validate(KeyOpVerify); err != nil { return nil, err } - alg, err := k.deriveAlgorithm() + algs, err := k.deriveAlgorithms() if err != nil { return nil, err } - switch alg { - case AlgorithmES256, AlgorithmES384, AlgorithmES512: + switch algs[0] { + case AlgorithmES256, AlgorithmES384, AlgorithmES512, AlgorithmESP256, AlgorithmESP384, AlgorithmESP512: var curve elliptic.Curve - switch alg { - case AlgorithmES256: + switch algs[0] { + case AlgorithmES256, AlgorithmESP256: curve = elliptic.P256() - case AlgorithmES384: + case AlgorithmES384, AlgorithmESP384: curve = elliptic.P384() - case AlgorithmES512: + case AlgorithmES512, AlgorithmESP512: curve = elliptic.P521() } @@ -683,7 +697,7 @@ func (k *Key) PublicKey() (crypto.PublicKey, error) { pub.Y.SetBytes(y) return pub, nil - case AlgorithmEdDSA: + case AlgorithmEdDSA, AlgorithmEd25519EdDSA: _, x, _ := k.OKP() return ed25519.PublicKey(x), nil default: @@ -697,25 +711,25 @@ func (k *Key) PrivateKey() (crypto.PrivateKey, error) { if err := k.validate(KeyOpSign); err != nil { return nil, err } - alg, err := k.deriveAlgorithm() + algs, err := k.deriveAlgorithms() if err != nil { return nil, err } - switch alg { - case AlgorithmES256, AlgorithmES384, AlgorithmES512: + switch algs[0] { + case AlgorithmES256, AlgorithmES384, AlgorithmES512, AlgorithmESP256, AlgorithmESP384, AlgorithmESP512: _, x, y, d := k.EC2() if len(x) == 0 || len(y) == 0 { return nil, fmt.Errorf("%w: compressed point not supported", ErrInvalidPrivKey) } var curve elliptic.Curve - switch alg { - case AlgorithmES256: + switch algs[0] { + case AlgorithmES256, AlgorithmESP256: curve = elliptic.P256() - case AlgorithmES384: + case AlgorithmES384, AlgorithmESP384: curve = elliptic.P384() - case AlgorithmES512: + case AlgorithmES512, AlgorithmESP512: curve = elliptic.P521() } @@ -727,7 +741,7 @@ func (k *Key) PrivateKey() (crypto.PrivateKey, error) { PublicKey: ecdsa.PublicKey{Curve: curve, X: bx, Y: by}, D: bd, }, nil - case AlgorithmEdDSA: + case AlgorithmEdDSA, AlgorithmEd25519EdDSA: _, x, d := k.OKP() if len(x) == 0 { return ed25519.NewKeyFromSeed(d), nil @@ -752,8 +766,8 @@ func (k *Key) AlgorithmOrDefault() (Algorithm, error) { if k.Algorithm != AlgorithmReserved { return k.Algorithm, nil } - - return k.deriveAlgorithm() + algs, err := k.deriveAlgorithms() + return algs[0], err } // Signer returns a Signer created using Key. @@ -797,37 +811,48 @@ func (k *Key) Verifier() (Verifier, error) { return NewVerifier(alg, pub) } -// deriveAlgorithm derives the intended algorithm for the key from its curve. -// The derivation is based on the recommendation in RFC 8152 that SHA-256 is -// only used with P-256, etc. For other combinations, the Algorithm in the Key -// must be explicitly set,so that this derivation is not used. -func (k *Key) deriveAlgorithm() (Algorithm, error) { +// deriveAlgorithms returns the set of algorithms implied by the Key. +// The returned slice always contains at least one Algorithm, and the first +// element represents the default algorithm for the given Key. +// +// For example, {Kty: EC2, Crv: P-256} derives {AlgorithmES256, AlgorithmESP256}. +// +// When called from validate(), the returned slice is treated as the set of +// candidate Algorithms. In most other contexts, only the first element is used +// as the default Algorithm. +// +// The derivation is based on the recommendation in RFC 8152 and RFC 9864 that +// SHA-256 is only used with P-256, etc. +// +// For other combinations, the Algorithm in the Key +// must be explicitly set, so that this derivation is not used. +func (k *Key) deriveAlgorithms() ([]Algorithm, error) { switch k.Type { case KeyTypeEC2: crv, _, _, _ := k.EC2() switch crv { case CurveP256: - return AlgorithmES256, nil + return []Algorithm{AlgorithmES256, AlgorithmESP256}, nil case CurveP384: - return AlgorithmES384, nil + return []Algorithm{AlgorithmES384, AlgorithmESP384}, nil case CurveP521: - return AlgorithmES512, nil + return []Algorithm{AlgorithmES512, AlgorithmESP512}, nil default: - return AlgorithmReserved, fmt.Errorf( + return []Algorithm{AlgorithmReserved}, fmt.Errorf( "unsupported curve %q for key type EC2", crv.String()) } case KeyTypeOKP: crv, _, _ := k.OKP() switch crv { case CurveEd25519: - return AlgorithmEdDSA, nil + return []Algorithm{AlgorithmEdDSA, AlgorithmEd25519EdDSA}, nil default: - return AlgorithmReserved, fmt.Errorf( + return []Algorithm{AlgorithmReserved}, fmt.Errorf( "unsupported curve %q for key type OKP", crv.String()) } default: // Symmetric algorithms are not supported in the current implementation. - return AlgorithmReserved, fmt.Errorf("unexpected key type %q", k.Type.String()) + return []Algorithm{AlgorithmReserved}, fmt.Errorf("unexpected key type %q", k.Type.String()) } } diff --git a/key_test.go b/key_test.go index 309cedc..753421c 100644 --- a/key_test.go +++ b/key_test.go @@ -422,7 +422,7 @@ func TestKey_UnmarshalCBOR(t *testing.T) { 0x28, 0x14, 0x87, 0xef, 0x4a, 0xe6, 0x7b, 0x46, }, want: nil, - wantErr: `found algorithm "ES256" (expected "EdDSA")`, + wantErr: `found algorithm "ES256" (expected one of {"EdDSA,Ed25519"})`, }, { name: "custom key", data: []byte{ @@ -937,6 +937,45 @@ func TestNewNewKeyEC2(t *testing.T) { }, }, wantErr: "", + }, { + name: "valid ESP256", args: args{AlgorithmESP256, ec256x, ec256y, ec256d}, + want: &Key{ + Type: KeyTypeEC2, + Algorithm: AlgorithmESP256, + Params: map[any]any{ + KeyLabelEC2Curve: CurveP256, + KeyLabelEC2X: ec256x, + KeyLabelEC2Y: ec256y, + KeyLabelEC2D: ec256d, + }, + }, + wantErr: "", + }, { + name: "valid ESP384", args: args{AlgorithmESP384, ec384x, ec384y, ec384d}, + want: &Key{ + Type: KeyTypeEC2, + Algorithm: AlgorithmESP384, + Params: map[any]any{ + KeyLabelEC2Curve: CurveP384, + KeyLabelEC2X: ec384x, + KeyLabelEC2Y: ec384y, + KeyLabelEC2D: ec384d, + }, + }, + wantErr: "", + }, { + name: "valid ESP521", args: args{AlgorithmESP512, ec521x, ec521y, ec521d}, + want: &Key{ + Type: KeyTypeEC2, + Algorithm: AlgorithmESP512, + Params: map[any]any{ + KeyLabelEC2Curve: CurveP521, + KeyLabelEC2X: ec521x, + KeyLabelEC2Y: ec521y, + KeyLabelEC2D: ec521d, + }, + }, + wantErr: "", }, { name: "invalid alg", args: args{Algorithm(-100), ec256x, ec256y, ec256d}, want: nil, diff --git a/signer.go b/signer.go index 28629e0..b130324 100644 --- a/signer.go +++ b/signer.go @@ -69,7 +69,7 @@ func NewSigner(alg Algorithm, key crypto.Signer) (Signer, error) { alg: alg, key: key, }, nil - case AlgorithmES256, AlgorithmES384, AlgorithmES512: + case AlgorithmES256, AlgorithmES384, AlgorithmES512, AlgorithmESP256, AlgorithmESP384, AlgorithmESP512: vk, ok := key.Public().(*ecdsa.PublicKey) if !ok { return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) @@ -85,11 +85,12 @@ func NewSigner(alg Algorithm, key crypto.Signer) (Signer, error) { key: vk, signer: key, }, nil - case AlgorithmEdDSA: + case AlgorithmEdDSA, AlgorithmEd25519EdDSA: if _, ok := key.Public().(ed25519.PublicKey); !ok { return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) } return &ed25519Signer{ + alg: alg, key: key, }, nil case AlgorithmReserved: diff --git a/signer_test.go b/signer_test.go index eb04f8a..032eb9a 100644 --- a/signer_test.go +++ b/signer_test.go @@ -80,6 +80,7 @@ func TestNewSigner(t *testing.T) { alg: AlgorithmEdDSA, key: ed25519Key, want: &ed25519Signer{ + alg: AlgorithmEdDSA, key: ed25519Key, }, }, diff --git a/verifier.go b/verifier.go index 992c38d..1c99845 100644 --- a/verifier.go +++ b/verifier.go @@ -60,7 +60,7 @@ func NewVerifier(alg Algorithm, key crypto.PublicKey) (Verifier, error) { alg: alg, key: vk, }, nil - case AlgorithmES256, AlgorithmES384, AlgorithmES512: + case AlgorithmES256, AlgorithmES384, AlgorithmES512, AlgorithmESP256, AlgorithmESP384, AlgorithmESP512: vk, ok := key.(*ecdsa.PublicKey) if !ok { return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) @@ -75,12 +75,13 @@ func NewVerifier(alg Algorithm, key crypto.PublicKey) (Verifier, error) { alg: alg, key: vk, }, nil - case AlgorithmEdDSA: + case AlgorithmEdDSA, AlgorithmEd25519EdDSA: vk, ok := key.(ed25519.PublicKey) if !ok { return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) } return &ed25519Verifier{ + alg: alg, key: vk, }, nil case AlgorithmReserved: diff --git a/verifier_test.go b/verifier_test.go index 82d84ca..91ade17 100644 --- a/verifier_test.go +++ b/verifier_test.go @@ -83,6 +83,7 @@ func TestNewVerifier(t *testing.T) { alg: AlgorithmEdDSA, key: ed25519Key, want: &ed25519Verifier{ + alg: AlgorithmEdDSA, key: ed25519Key, }, },