Skip to content

Commit

Permalink
Use ecdsa.{SignASN1,VerifyASN1} in `subtle.{ECDSASigner,ECDSAVerifi…
Browse files Browse the repository at this point in the history
…er}`

This avoids using the legacy `ecdsa.Sign` [1] for DER encoded signatures -- this is still used for the IEEE_P1363 encoding, and `ecdsa.Verify` [2]. The `crypto/ecdsa` package is moving away from using `math/big` [3].

[1] https://github.com/golang/go/blob/fe7d97d0322c283462b38c0f53bc340b642fe1cb/src/crypto/ecdsa/ecdsa_legacy.go#L59
[2] https://github.com/golang/go/blob/fe7d97d0322c283462b38c0f53bc340b642fe1cb/src/crypto/ecdsa/ecdsa_legacy.go#L135
[3] golang/go@08f2091

PiperOrigin-RevId: 698354627
Change-Id: I3b83575d614a65127f480a41cf90d76288444f4c
  • Loading branch information
morambro authored and copybara-github committed Nov 20, 2024
1 parent 8401621 commit 9a4e757
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 19 deletions.
30 changes: 20 additions & 10 deletions signature/subtle/ecdsa_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,25 @@ func (e *ECDSASigner) Sign(data []byte) ([]byte, error) {
if err != nil {
return nil, err
}
r, s, err := ecdsa.Sign(rand.Reader, e.privateKey, hashed)
if err != nil {
return nil, fmt.Errorf("ecdsa_signer: signing failed: %s", err)
}
// format the signature
sig := NewECDSASignature(r, s)
ret, err := sig.EncodeECDSASignature(e.encoding, e.privateKey.PublicKey.Curve.Params().Name)
if err != nil {
return nil, fmt.Errorf("ecdsa_signer: signing failed: %s", err)
var signatureBytes []byte
switch e.encoding {
case "IEEE_P1363":
r, s, err := ecdsa.Sign(rand.Reader, e.privateKey, hashed)
if err != nil {
return nil, err
}
sig := NewECDSASignature(r, s)
signatureBytes, err = sig.EncodeECDSASignature(e.encoding, e.privateKey.PublicKey.Curve.Params().Name)
if err != nil {
return nil, fmt.Errorf("ecdsa_signer: signing failed: %s", err)
}
case "DER":
signatureBytes, err = ecdsa.SignASN1(rand.Reader, e.privateKey, hashed)
if err != nil {
return nil, fmt.Errorf("ecdsa_signer: signing failed: %s", err)
}
default:
return nil, fmt.Errorf("ecdsa_signer: unsupported encoding: %s", e.encoding)
}
return ret, nil
return signatureBytes, nil
}
28 changes: 19 additions & 9 deletions signature/subtle/ecdsa_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ import (
"hash"
"math/big"

internalecdsa "github.com/tink-crypto/tink-go/v2/internal/signature/ecdsa"
"github.com/tink-crypto/tink-go/v2/subtle"
)

var errInvalidECDSASignature = errors.New("ecdsa_verifier: invalid signature")

// ECDSAVerifier is an implementation of Verifier for ECDSA.
// At the moment, the implementation only accepts signatures with strict DER encoding.
type ECDSAVerifier struct {
Expand Down Expand Up @@ -67,17 +66,28 @@ func NewECDSAVerifierFromPublicKey(hashAlg string, encoding string, publicKey *e
// Verify verifies whether the given signature is valid for the given data.
// It returns an error if the signature is not valid; nil otherwise.
func (e *ECDSAVerifier) Verify(signatureBytes, data []byte) error {
signature, err := DecodeECDSASignature(signatureBytes, e.encoding)
if err != nil {
return fmt.Errorf("ecdsa_verifier: %s", err)
}
hashed, err := subtle.ComputeHash(e.hashFunc, data)
if err != nil {
return err
}
valid := ecdsa.Verify(e.publicKey, hashed, signature.R, signature.S)
if !valid {
return errInvalidECDSASignature
var asn1Signature []byte
switch e.encoding {
case "DER":
asn1Signature = signatureBytes
case "IEEE_P1363":
decodedSig, err := internalecdsa.IEEEP1363Decode(signatureBytes)
if err != nil {
return err
}
asn1Signature, err = internalecdsa.ASN1Encode(decodedSig)
if err != nil {
return err
}
default:
return fmt.Errorf("ecdsa: unsupported encoding: %s", e.encoding)
}
if ok := ecdsa.VerifyASN1(e.publicKey, hashed, asn1Signature); !ok {
return fmt.Errorf("ecdsa_verifier: invalid signature")
}
return nil
}

0 comments on commit 9a4e757

Please sign in to comment.