github.phpd.cn/thought-machine/please@v12.2.0+incompatible/src/update/verify.go (about) 1 // +build !bootstrap 2 3 package update 4 5 import ( 6 "bytes" 7 "io" 8 "io/ioutil" 9 10 "golang.org/x/crypto/openpgp" 11 ) 12 13 // identity is the signing identity of this key. 14 const identity = "Please Releases <releases@please.build>" 15 16 // verifySignature verifies an OpenPGP detached signature of a file. 17 // It returns true if the signature is correct according to our key. 18 func verifySignature(signed, signature io.Reader) bool { 19 entities, err := openpgp.ReadArmoredKeyRing(bytes.NewReader(MustAsset("pubkey.gpg.asc"))) 20 if err != nil { 21 log.Fatalf("%s", err) // Shouldn't happen 22 } 23 signer, err := openpgp.CheckArmoredDetachedSignature(entities, signed, signature) 24 if err != nil { 25 log.Error("Bad signature: %s", err) 26 return false 27 } 28 log.Notice("Good signature from %s", signer.Identities[identity].UserId.Email) 29 return true 30 } 31 32 // verifyDownload fetches a detached signature for a download and verifies it's OK. 33 // It returns a reader to the verified content. 34 func verifyDownload(signed io.Reader, url string) io.Reader { 35 signature := mustDownload(url+".asc", false) 36 defer signature.Close() 37 return mustVerifySignature(signed, signature) 38 } 39 40 // mustVerifySignature verifies an OpenPGP detached signature of a file. 41 // It panics if the signature is not correct. 42 // On success it returns an equivalent reader to the original. 43 func mustVerifySignature(signed, signature io.Reader) io.Reader { 44 // We need to be able to reuse the body again afterwards so we have to 45 // download the original into a buffer. 46 b, err := ioutil.ReadAll(signed) 47 if err != nil { 48 panic(err) 49 } 50 log.Notice("Verifying signature of downloaded tarball...") 51 if !verifySignature(bytes.NewReader(b), signature) { 52 panic("Invalid signature on downloaded file, possible tampering; will not continue.") 53 } 54 return bytes.NewReader(b) 55 }