this repo has no description
1package knotserver
2
3import (
4 "crypto/hmac"
5 "crypto/sha256"
6 "encoding/hex"
7 "log"
8 "net/http"
9 "time"
10)
11
12func (h *Handle) VerifySignature(next http.Handler) http.Handler {
13 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
14 signature := r.Header.Get("X-Signature")
15 log.Println(signature)
16 if signature == "" || !h.verifyHMAC(signature, r) {
17 writeError(w, "signature verification failed", http.StatusForbidden)
18 return
19 }
20 next.ServeHTTP(w, r)
21 })
22}
23
24func (h *Handle) verifyHMAC(signature string, r *http.Request) bool {
25 secret := h.c.Server.Secret
26 timestamp := r.Header.Get("X-Timestamp")
27 if timestamp == "" {
28 return false
29 }
30
31 // Verify that the timestamp is not older than a minute
32 reqTime, err := time.Parse(time.RFC3339, timestamp)
33 if err != nil {
34 return false
35 }
36 if time.Since(reqTime) > time.Minute {
37 return false
38 }
39
40 message := r.Method + r.URL.Path + timestamp
41
42 mac := hmac.New(sha256.New, []byte(secret))
43 mac.Write([]byte(message))
44 expectedMAC := mac.Sum(nil)
45
46 signatureBytes, err := hex.DecodeString(signature)
47 if err != nil {
48 return false
49 }
50
51 return hmac.Equal(signatureBytes, expectedMAC)
52}