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 }