github.com/himawarisunflower/go-update@v0.0.0-20210917073417-3bee296db6a2/verifier.go (about)

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