Documentation ¶
Overview ¶
Package hmacval provides a type to verify HMAC signatures generated by Internet providers. It tries to provide a generic type that allow to verify as much providers as possible, without exposing specific functions fo each one nor exposing high level functionalities which are easy to perfom with the Golan package library
Example (Pusher) ¶
secret := "7ad3773142a6692b25b8" // We create a Val configured to check HMAC digests as Twilio generates val := hmacval.NewVal(sha256.New, nil, nil, nil, "", "") // We create an request to simulate how Pusher sends a WebHook request, err := http.NewRequest("POST", "https://mycompany.com/myapp", bytes.NewBuffer([]byte(`{"time_ms":1327078148132,"events":[{"name":"event_name","some":"data"}]}`))) request.Header.Set("X-Pusher-Signature", "26537b0c36841dc4e940291893424d4fba6af2a7510701f113e720df5d4f2577") if err != nil { log.Fatalf("Error creating request: %s", err) } // We can think the the following lines would be in one (or more) of our http.Handler digest, err := hex.DecodeString(request.Header.Get("X-Pusher-Signature")) if err != nil { log.Fatalf("Error decoding provided HMAC value: %s", err) } body, err := ioutil.ReadAll(request.Body) if err != nil { log.Fatalf("Error reading all the content in Request's body: %s", err) } defer closeBody(request) isValid := val(secret, string(body), nil, digest) fmt.Println(isValid)
Output: true
Example (Shopify) ¶
secret := "hush" // We create a Val configured to check HMAC digests as Shopify generates val := hmacval.NewVal( sha256.New, []string{"signature", "hmac"}, []string{"&", "%26", "%", "%25", "=", "%3D"}, []string{"&", "%26", "%", "%25"}, "=", "&") // We create an request to simulate how Shopify would send requests to our application proxy request, err := http.NewRequest("GET", "http://yourdomain.com?shop=some-shop.myshopify.com×tamp=1337178173&signature=6e39a2ea9e497af6cb806720da1f1bf3&hmac=c2812f39f84c32c2edaded339a1388abc9829babf351b684ab797f04cd94d4c7", nil) if err != nil { log.Fatalf("Error creating request: %s", err) } // We can think the the following lines would be in one (or more) of our http.Handler pq, err := url.ParseQuery(request.URL.RawQuery) if err != nil { log.Fatalf("Error parsing URL query: %s", err) } payload := make(map[string]string, len(pq)) for n, v := range pq { // Shopify doesn't define how to join queyr parameters which are present more than once // so we assume that we can just join them payload[n] = strings.Join(v, "") } digest, err := hex.DecodeString(payload["hmac"]) if err != nil { log.Fatalf("Error decoding provided HMAC value: %s", err) } isValid := val(secret, "", payload, digest) fmt.Println(isValid)
Output: true
Example (Twilio) ¶
secret := "12345" // We create a Val configured to check HMAC digests as Twilio generates val := hmacval.NewVal(sha1.New, nil, nil, nil, "", "") // We create an request to simulate how Twilio would send requests to us body := []byte(`{"Digits":"1234","To":"+18005551212","From":"+14158675309","Caller":"+14158675309","CallSid":"CA1234567890ABCDE"}`) request, err := http.NewRequest("POST", "https://mycompany.com/myapp.php?foo=1&bar=2", bytes.NewBuffer(body)) request.Header.Set("X-Twilio-Signature", "RSOYDt4T1cUTdK1PDd93/VVr8B8=") if err != nil { log.Fatalf("Error creating request: %s", err) } // We can think the the following lines would be in one (or more) of our http.Handler digest, err := base64.StdEncoding.DecodeString(request.Header.Get("X-Twilio-Signature")) if err != nil { log.Fatalf("Error decoding provided HMAC value: %s", err) } payload := make(map[string]string) jd := json.NewDecoder(request.Body) defer closeBody(request) if err := jd.Decode(&payload); err != nil { log.Fatalf("Error decoding JSON: %s", err) } isValid := val(secret, request.URL.String(), payload, digest) fmt.Println(isValid)
Output: true
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrSigKeyNotFound = errors.New("Signature key not found in payload")
ErrSigKeyNotFound is returned when payload doesn't contain a specified key with its own signature as a value
Functions ¶
This section is empty.
Types ¶
type Val ¶
Val is a function which compares the HMAC digest of the concatenation of the prefix (raw string which is taken without any transformation) and payload, using the provided secret with provided digest. It returns true if they match, otherwise false
func NewVal ¶
func NewVal(h func() hash.Hash, keysToExclude []string, keyRepls []string, valueRepls []string, keyValueLink string, pairsLink string) Val
NewVal creates a Val type value which will use the specified Hash algorithm, exclude the specified keys, make the specified replacements in keys & values, join the each key and value pair and all the pairs with the specified links. Replacements are expressed as pairs (odd slice positions are the strings value to be replaced by the following element in the slice)