Reputation: 4088
I'm making a little API using Go. I would like to be able to handle Github webhooks with secret token. I set up the secret on my webhook Github which is "azerty".
Now I try to verify that the incoming webhook has the correct secret token. I've read Github documentation which say the algorithm use HMAC with SHA1. But I can't verify the secret from the incoming Github webhook ...
func IsValidSignature(r *http.Request, key string) bool {
// KEY => azerty
gotHash := strings.SplitN(r.Header.Get("X-Hub-Signature"), "=", 2)
if gotHash[0] != "sha1" {
return false
}
defer r.Body.Close()
b, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("Cannot read the request body: %s\n", err)
return false
}
hash := hmac.New(sha1.New, []byte(key))
if _, err := hash.Write(b); err != nil {
log.Printf("Cannot compute the HMAC for request: %s\n", err)
return false
}
expectedHash := hex.EncodeToString(hash.Sum(nil))
log.Println("EXPECTED HASH:", expectedHash)
log.Println("GOT HASH:", gotHash[1])
return gotHash[1] == expectedHash
}
EXPECTED HASH: 10972179a3b0efc337f79ec41847062bc598bb04
GOT HASH: 36de72e0d386e36e2c7b034c85cd3b3889594992
To test, I copy the payload of the Github webhook in Postman with the right headers. I don't know why I get two different hash ... I've checked my key is non-empty with the correct value and my body is non-empty too.
Do I miss something?
Upvotes: 0
Views: 546
Reputation: 1074
I copy the payload of the Github webhook in Postman with the right header.
I've checked my key is non-empty with the correct value and my body is non-empty too.
The crypto is correct, except few minor issues. Obviously your body does not match the same body you have got from Github. Could be formatting, trailing newlines, etc. It must exactly byte-to-byte match the original body.
If this code works with Github and does not work with copy in Postman just replace X-Hub-Signature
in your fixture with that "wrong" hash.
Some extras:
hmac.Equal
for secure comparisonhash.Write
never returns errorsUpvotes: 3