github.com/creativeprojects/go-selfupdate@v1.2.0/update/verifier.go (about)

     1  package update
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/ecdsa"
     6  	"crypto/rsa"
     7  	"encoding/asn1"
     8  	"errors"
     9  	"math/big"
    10  )
    11  
    12  // Verifier defines an interface for verifying an update's signature with a public key.
    13  type Verifier interface {
    14  	VerifySignature(checksum, signature []byte, h crypto.Hash, publicKey crypto.PublicKey) error
    15  }
    16  
    17  type verifyFn func([]byte, []byte, crypto.Hash, crypto.PublicKey) error
    18  
    19  func (fn verifyFn) VerifySignature(checksum []byte, signature []byte, hash crypto.Hash, publicKey crypto.PublicKey) error {
    20  	return fn(checksum, signature, hash, publicKey)
    21  }
    22  
    23  // NewRSAVerifier returns a Verifier that uses the RSA algorithm to verify updates.
    24  func NewRSAVerifier() Verifier {
    25  	return verifyFn(func(checksum, signature []byte, hash crypto.Hash, publicKey crypto.PublicKey) error {
    26  		key, ok := publicKey.(*rsa.PublicKey)
    27  		if !ok {
    28  			return errors.New("not a valid RSA public key")
    29  		}
    30  		return rsa.VerifyPKCS1v15(key, hash, checksum, signature)
    31  	})
    32  }
    33  
    34  type rsDER struct {
    35  	R *big.Int
    36  	S *big.Int
    37  }
    38  
    39  // NewECDSAVerifier returns a Verifier that uses the ECDSA algorithm to verify updates.
    40  func NewECDSAVerifier() Verifier {
    41  	return verifyFn(func(checksum, signature []byte, hash crypto.Hash, publicKey crypto.PublicKey) error {
    42  		key, ok := publicKey.(*ecdsa.PublicKey)
    43  		if !ok {
    44  			return errors.New("not a valid ECDSA public key")
    45  		}
    46  		var rs rsDER
    47  		if _, err := asn1.Unmarshal(signature, &rs); err != nil {
    48  			return err
    49  		}
    50  		if !ecdsa.Verify(key, checksum, rs.R, rs.S) {
    51  			return errors.New("failed to verify ECDSA signature")
    52  		}
    53  		return nil
    54  	})
    55  }