xref: /aosp_15_r20/external/tink/go/signature/subtle/ecdsa_verifier.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2020 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package subtle
18
19import (
20	"crypto/ecdsa"
21	"errors"
22	"fmt"
23	"hash"
24	"math/big"
25
26	"github.com/google/tink/go/subtle"
27)
28
29var errInvalidECDSASignature = errors.New("ecdsa_verifier: invalid signature")
30
31// ECDSAVerifier is an implementation of Verifier for ECDSA.
32// At the moment, the implementation only accepts signatures with strict DER encoding.
33type ECDSAVerifier struct {
34	publicKey *ecdsa.PublicKey
35	hashFunc  func() hash.Hash
36	encoding  string
37}
38
39// NewECDSAVerifier creates a new instance of ECDSAVerifier.
40func NewECDSAVerifier(hashAlg string, curve string, encoding string, x []byte, y []byte) (*ECDSAVerifier, error) {
41	publicKey := &ecdsa.PublicKey{
42		Curve: subtle.GetCurve(curve),
43		X:     new(big.Int).SetBytes(x),
44		Y:     new(big.Int).SetBytes(y),
45	}
46	return NewECDSAVerifierFromPublicKey(hashAlg, encoding, publicKey)
47}
48
49// NewECDSAVerifierFromPublicKey creates a new instance of ECDSAVerifier.
50func NewECDSAVerifierFromPublicKey(hashAlg string, encoding string, publicKey *ecdsa.PublicKey) (*ECDSAVerifier, error) {
51	if publicKey.Curve == nil {
52		return nil, errors.New("ecdsa_verifier: invalid curve")
53	}
54	if !publicKey.Curve.IsOnCurve(publicKey.X, publicKey.Y) {
55		return nil, fmt.Errorf("ecdsa_verifier: invalid public key")
56	}
57	curve := subtle.ConvertCurveName(publicKey.Curve.Params().Name)
58	if err := ValidateECDSAParams(hashAlg, curve, encoding); err != nil {
59		return nil, fmt.Errorf("ecdsa_verifier: %s", err)
60	}
61	hashFunc := subtle.GetHashFunc(hashAlg)
62	return &ECDSAVerifier{
63		publicKey: publicKey,
64		hashFunc:  hashFunc,
65		encoding:  encoding,
66	}, nil
67}
68
69// Verify verifies whether the given signature is valid for the given data.
70// It returns an error if the signature is not valid; nil otherwise.
71func (e *ECDSAVerifier) Verify(signatureBytes, data []byte) error {
72	signature, err := DecodeECDSASignature(signatureBytes, e.encoding)
73	if err != nil {
74		return fmt.Errorf("ecdsa_verifier: %s", err)
75	}
76	hashed, err := subtle.ComputeHash(e.hashFunc, data)
77	if err != nil {
78		return err
79	}
80	valid := ecdsa.Verify(e.publicKey, hashed, signature.R, signature.S)
81	if !valid {
82		return errInvalidECDSASignature
83	}
84	return nil
85}
86