Skip to content

Commit 3f5fee2

Browse files
committed
fix: updated based on review
- added support for sha512 - added notes to docs
1 parent c6e809a commit 3f5fee2

File tree

2 files changed

+52
-41
lines changed

2 files changed

+52
-41
lines changed

docs/Hook-Rules.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ For the regex syntax, check out <http://golang.org/pkg/regexp/syntax/>
186186
}
187187
```
188188

189+
Note that if multiple signatures were passed via a comma separated string, each
190+
will be tried unless a match is found. For example:
191+
192+
```
193+
X-Hub-Signature: sha1=the-first-signature,sha1=the-second-signature
194+
```
195+
189196
### 4. Match payload-hash-sha256
190197
```json
191198
{
@@ -202,6 +209,13 @@ For the regex syntax, check out <http://golang.org/pkg/regexp/syntax/>
202209
}
203210
```
204211

212+
Note that if multiple signatures were passed via a comma separated string, each
213+
will be tried unless a match is found. For example:
214+
215+
```
216+
X-Hub-Signature: sha256=the-first-signature,sha256=the-second-signature
217+
```
218+
205219
### 5. Match payload-hash-sha512
206220
```json
207221
{
@@ -218,6 +232,13 @@ For the regex syntax, check out <http://golang.org/pkg/regexp/syntax/>
218232
}
219233
```
220234

235+
Note that if multiple signatures were passed via a comma separated string, each
236+
will be tried unless a match is found. For example:
237+
238+
```
239+
X-Hub-Signature: sha512=the-first-signature,sha512=the-second-signature
240+
```
241+
221242
### 6. Match Whitelisted IP range
222243

223244
The IP can be IPv4- or IPv6-formatted, using [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_blocks). To match a single IP address only, use `/32`.

hook/hook.go

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"encoding/json"
1313
"errors"
1414
"fmt"
15+
"hash"
1516
"io/ioutil"
1617
"log"
1718
"math"
@@ -113,33 +114,30 @@ func ExtractCommaSeparatedValues(source, prefix string) []string {
113114
return values
114115
}
115116

116-
func ExtractSignatures(signature, prefix string) []string {
117+
// ExtractSignatures will extract all the signatures from the source.
118+
func ExtractSignatures(source, prefix string) []string {
117119
// If there are multiple possible matches, let the comma seperated extractor
118120
// do it's work.
119-
if strings.Contains(signature, ",") {
120-
return ExtractCommaSeparatedValues(signature, prefix)
121+
if strings.Contains(source, ",") {
122+
return ExtractCommaSeparatedValues(source, prefix)
121123
}
122124

123125
// There were no commas, so just trim the prefix (if it even exists) and
124126
// pass it back.
125127
return []string{
126-
strings.TrimPrefix(signature, prefix),
128+
strings.TrimPrefix(source, prefix),
127129
}
128130
}
129131

130-
// CheckPayloadSignature calculates and verifies SHA1 signature of the given payload
131-
func CheckPayloadSignature(payload []byte, secret string, signature string) (string, error) {
132-
if secret == "" {
133-
return "", errors.New("signature validation secret can not be empty")
134-
}
135-
136-
signatures := ExtractSignatures(signature, "sha1=")
137-
138-
mac := hmac.New(sha1.New, []byte(secret))
132+
// ValidateMAC will verify that the expected mac for the given hash will match
133+
// the one provided.
134+
func ValidateMAC(payload []byte, mac hash.Hash, signatures []string) (string, error) {
135+
// Write the payload to the provided hash.
139136
_, err := mac.Write(payload)
140137
if err != nil {
141138
return "", err
142139
}
140+
143141
expectedMAC := hex.EncodeToString(mac.Sum(nil))
144142

145143
for _, signature := range signatures {
@@ -153,25 +151,30 @@ func CheckPayloadSignature(payload []byte, secret string, signature string) (str
153151
}
154152
}
155153

154+
// CheckPayloadSignature calculates and verifies SHA1 signature of the given payload
155+
func CheckPayloadSignature(payload []byte, secret string, signature string) (string, error) {
156+
if secret == "" {
157+
return "", errors.New("signature validation secret can not be empty")
158+
}
159+
160+
// Extract the signatures.
161+
signatures := ExtractSignatures(signature, "sha1=")
162+
163+
// Validate the MAC.
164+
return ValidateMAC(payload, hmac.New(sha1.New, []byte(secret)), signatures)
165+
}
166+
156167
// CheckPayloadSignature256 calculates and verifies SHA256 signature of the given payload
157168
func CheckPayloadSignature256(payload []byte, secret string, signature string) (string, error) {
158169
if secret == "" {
159170
return "", errors.New("signature validation secret can not be empty")
160171
}
161172

173+
// Extract the signatures.
162174
signatures := ExtractSignatures(signature, "sha256=")
163175

164-
mac := hmac.New(sha256.New, []byte(secret))
165-
_, err := mac.Write(payload)
166-
if err != nil {
167-
return "", err
168-
}
169-
expectedMAC := hex.EncodeToString(mac.Sum(nil))
170-
171-
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
172-
return expectedMAC, &SignatureError{signature}
173-
}
174-
return expectedMAC, err
176+
// Validate the MAC.
177+
return ValidateMAC(payload, hmac.New(sha256.New, []byte(secret)), signatures)
175178
}
176179

177180
// CheckPayloadSignature512 calculates and verifies SHA512 signature of the given payload
@@ -180,24 +183,11 @@ func CheckPayloadSignature512(payload []byte, secret string, signature string) (
180183
return "", errors.New("signature validation secret can not be empty")
181184
}
182185

183-
signature = strings.TrimPrefix(signature, "sha512=")
184-
185-
mac := hmac.New(sha512.New, []byte(secret))
186-
_, err := mac.Write(payload)
187-
if err != nil {
188-
return "", err
189-
}
190-
expectedMAC := hex.EncodeToString(mac.Sum(nil))
191-
192-
for _, signature := range signatures {
193-
if hmac.Equal([]byte(signature), []byte(expectedMAC)) {
194-
return expectedMAC, err
195-
}
196-
}
186+
// Extract the signatures.
187+
signatures := ExtractSignatures(signature, "sha512=")
197188

198-
return expectedMAC, &SignatureError{
199-
Signatures: signatures,
200-
}
189+
// Validate the MAC.
190+
return ValidateMAC(payload, hmac.New(sha512.New, []byte(secret)), signatures)
201191
}
202192

203193
func CheckScalrSignature(headers map[string]interface{}, body []byte, signingKey string, checkDate bool) (bool, error) {

0 commit comments

Comments
 (0)