Move signature validation for websub to own file
This commit is contained in:
parent
2d39edac8e
commit
dc557efde9
|
@ -2,15 +2,14 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"p83.nl/go/ekster/pkg/websub"
|
||||
)
|
||||
|
||||
type incomingHandler struct {
|
||||
|
@ -85,8 +84,9 @@ func (h *incomingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
// match signature
|
||||
sig := r.Header.Get("X-Hub-Signature")
|
||||
if sig != "" {
|
||||
if err := isHubSignatureValid(sig, feedContent, secret); err != nil {
|
||||
http.Error(w, fmt.Sprintf("Error in signature: %s", err), 400)
|
||||
if err := websub.ValidateHubSignature(sig, feedContent, []byte(secret)); err != nil {
|
||||
log.Printf("could not validate signature: %+v", err)
|
||||
http.Error(w, fmt.Sprintf("could not validate signature: %s", err), 400)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -94,32 +94,9 @@ func (h *incomingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
ct := r.Header.Get("Content-Type")
|
||||
err = h.Backend.UpdateFeed(feed, ct, bytes.NewBuffer(feedContent))
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Unknown format of body: %s (%s)", ct, err), 400)
|
||||
http.Error(w, fmt.Sprintf("could not update feed: %s (%s)", ct, err), 400)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func isHubSignatureValid(sig string, feedContent []byte, secret string) error {
|
||||
parts := strings.Split(sig, "=")
|
||||
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("signature format is not like sha1=signature")
|
||||
}
|
||||
|
||||
if parts[0] != "sha1" {
|
||||
return fmt.Errorf("signature format is not like sha1=signature")
|
||||
}
|
||||
|
||||
// verification
|
||||
mac := hmac.New(sha1.New, []byte(secret))
|
||||
mac.Write(feedContent)
|
||||
signature := mac.Sum(nil)
|
||||
|
||||
if fmt.Sprintf("%x", signature) != parts[1] {
|
||||
return fmt.Errorf("signature does not match feed %s %s", signature, parts[1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
41
pkg/websub/signature.go
Normal file
41
pkg/websub/signature.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package websub
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ValidateHubSignature validate a sha1 signature that could be send with the
|
||||
// hub as an extra header
|
||||
func ValidateHubSignature(sig string, feedContent, secret []byte) error {
|
||||
parts := strings.Split(sig, "=")
|
||||
|
||||
if len(parts) != 2 {
|
||||
return errors.New("signature format is not like sha1=signature")
|
||||
}
|
||||
|
||||
if parts[0] != "sha1" {
|
||||
return errors.New("signature format is not like sha1=signature")
|
||||
}
|
||||
|
||||
// verification
|
||||
mac := hmac.New(sha1.New, secret)
|
||||
mac.Write(feedContent)
|
||||
signature := mac.Sum(nil)
|
||||
|
||||
signature2, err := hex.DecodeString(parts[1])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not decode signature")
|
||||
}
|
||||
|
||||
if !hmac.Equal(signature, signature2) {
|
||||
return fmt.Errorf("signature does not match feed %s %s", signature, parts[1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
22
pkg/websub/signature_test.go
Normal file
22
pkg/websub/signature_test.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package websub
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidateHubSignature(t *testing.T) {
|
||||
secret := []byte("this is a test secret")
|
||||
feedContent := []byte("hello world")
|
||||
|
||||
mac := hmac.New(sha1.New, secret)
|
||||
mac.Write(feedContent)
|
||||
signature := mac.Sum(nil)
|
||||
|
||||
err := ValidateHubSignature(fmt.Sprintf("sha1=%x", signature), feedContent, secret)
|
||||
assert.NoError(t, err, "error should be nil")
|
||||
}
|
Loading…
Reference in New Issue
Block a user