我无法成功验证来自Trello的webhook请求。这就是我所知道的。
Trello的webhook文档here声明:
每个webhook触发器都包含HTTP标头X-Trello-Webhook。标头是HMAC-SHA1哈希的base64摘要。散列内容是完整请求主体和callbackURL的串联,与webhook创建期间提供的内容完全相同。用于签署此文本的密钥是您的应用程序的秘密。
这是可以理解的。他们继续说
由于节点中加密实用程序的某些默认值,我们签名的有效负载被视为二进制字符串,而不是utf-8。例如,如果你使用en-dash字符(U + 2013或8211十进制),并在Node中创建一个二进制缓冲区,它将显示为[19]的缓冲区,这是8个最不重要的比特8211.这是在摘要中用于计算SHA-1的值。
这对我来说不太清楚。我的理解是有效载荷的每个字符(body + callbackURL)都被放入一个8位整数,忽略了溢出。 (因为8211 == 0b10000000010011,而0b00010011 == 19)这就是我认为我的问题所在。
我用来容纳Trello的节点有效负载问题的函数是:
func bitShift(s string) []byte {
var byteString []byte
// For each rune in the string
for _, c := range s {
// Create a byte slice
b := []byte(string(c))
// Take the sign off the least significant byte
tmp := b[len(b)-1] << 1
tmp = tmp >> 1
// Append it to the byte string
byteString = append(byteString, tmp)
}
return byteString
}
我也很可能在基本验证步骤中做错了。对我来说看起来没问题,虽然我对此有点新鲜。
// VerifyNotificationHeader ...
func VerifyNotificationHeader(signedHeader, trelloAPISecret string, requestURL *url.URL, body []byte) bool {
// Put callbackURL and body into byte slice
urlBytes := bitShift(requestURL.String())
bitBody := bitShift(string(body))
// Sign, hash, and encode the payload
secret := []byte(trelloAPISecret)
keyHMAC := hmac.New(sha1.New, secret)
keyHMAC.Write(append(bitBody, urlBytes...))
signedHMAC := keyHMAC.Sum(nil)
base64signedHMAC := base64.StdEncoding.EncodeToString(signedHMAC)
if comp := strings.EqualFold(base64signedHMAC, signedHeader); !comp {
return false
}
return true
}
如果您需要更多信息,请与我们联系。谢谢!
更新:这已解决,请查看答案。
答案 0 :(得分:2)
你为什么要扔掉MSB?您将每个rune
转换为byte
,这是无符号的(实际上是uint8
的别名),因此该位保存您正在丢失的信息。
您可以考虑使用这样的函数:
func ascii(s string) []byte {
var ret []byte
for _, r := range s {
ret = append(ret, byte(r))
}
return ret
}
由于rune
是int32
的别名,因此转化为byte
只会删除前24位,这就是您想要的。
(警告:这假设是小端的。)
答案 1 :(得分:1)
我的代码存在两个问题。主要问题是我对requestURL.String()
使用了callbackURL
。
在上面的comments http.Request.URL
:
对于大多数请求,Path和RawQuery以外的字段都将为空。
事实证明,requestURL.String()
仅提供[Path]
的{{1}}部分。正确的callbackURL是
[Scheme]://[Host][Path]
在this answer中指出了第二个问题,对于任何身体包含第8位字符的请求,验证将失败。