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