Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Security 验证Trello Webhook签名_Security_Go_Hmac_Trello_Hmacsha1 - Fatal编程技术网

Security 验证Trello Webhook签名

Security 验证Trello Webhook签名,security,go,hmac,trello,hmacsha1,Security,Go,Hmac,Trello,Hmacsha1,我无法成功验证来自Trello的webhook请求。这是我所知道的 Trello的webhook文档说明: 每个webhook触发器都包含HTTP头X-Trello-webhook。标头是HMAC-SHA1哈希的base64摘要。哈希内容是完整请求正文和回调URL的连接,与webhook创建期间提供的内容完全相同。用于签署此文本的密钥是应用程序的机密 这是可以理解的。他们接着说 由于节点中加密实用程序的某些默认值,我们签名的有效负载被视为二进制字符串,而不是utf-8。例如,如果使用en-das

我无法成功验证来自Trello的webhook请求。这是我所知道的

Trello的webhook文档说明:

每个webhook触发器都包含HTTP头X-Trello-webhook。标头是HMAC-SHA1哈希的base64摘要。哈希内容是完整请求正文和回调URL的连接,与webhook创建期间提供的内容完全相同。用于签署此文本的密钥是应用程序的机密

这是可以理解的。他们接着说

由于节点中加密实用程序的某些默认值,我们签名的有效负载被视为二进制字符串,而不是utf-8。例如,如果使用en-dash字符(十进制的U+2013或8211),并在节点中从中创建一个二进制缓冲区,它将显示为[19]的缓冲区,这是8211的8个最低有效位。这是在摘要中用于计算SHA-1的值

我对此不太清楚。我的理解是,有效负载的每个字符(body+callbackURL)都被放入一个8位整数中,溢出被忽略。(因为8211==0B10000000011,而0B00011==19)这就是我的问题所在

我用于解决Trello节点有效负载问题的功能是:

func位移位(s字符串)[]字节{
var byteString[]字节
//对于字符串中的每个符文
对于u,c:=范围s{
//创建一个字节片
b:=[]字节(字符串(c))
//将符号从最低有效字节上去掉
tmp:=b[len(b)-1]>1
//将其附加到字节字符串
byteString=append(byteString,tmp)
}
通过测试环返回
}
我也很可能在基本验证步骤中出错。这对我来说没什么问题,尽管我对这有点陌生

//VerifyNotificationHeader。。。
func VerifyNotificationHeader(signedHeader,trelloAPISecret字符串,requestURL*url.url,正文[]字节)bool{
//将回调URL和正文放入字节片
urlBytes:=位移位(requestURL.String())
位体:=位移位(字符串(体))
//对有效负载进行签名、哈希和编码
机密:=[]字节(trelloAPISecret)
keyHMAC:=hmac.New(sha1.New,secret)
Write(追加(位体、urlBytes…)
signedHMAC:=keyHMAC.Sum(零)
base64signedHMAC:=base64.StdEncoding.EncodeToString(signedHMAC)
如果comp:=strings.EqualFold(base64signedHMAC,signedHeader);!comp{
返回错误
}
返回真值
}
如果你需要更多的信息,请告诉我。谢谢大家!


更新:问题解决了,请查看答案。

为什么要扔掉MSB?您正在将每个
符文
转换为
字节
,它是无符号的(实际上是
uint8
的别名),因此该位保存您丢失的信息

<>你可以考虑使用这样的函数来代替:

由于
rune
int32
的别名,因此对
字节的转换只会删除前24位,这正是您想要的


(注意:这假设没有结尾。)

我的代码有两个问题。主要问题是我对
callbackURL
使用了
requestURL.String()

在上面的
http.Request.URL
中:

对于大多数请求,Path和RawQuery以外的字段将为空

事实证明,
requestURL.String()
只给出了
[Scheme]://[Host][Path]
[Path]
部分。正确的回调URL是

callbackURL := "https://" + request.Host + request.URL.String()

第二个问题在中指出,如果请求的正文包含具有字符的第8位,则验证将失败

您是否有我们可以匹配的示例请求和签名?感谢您的关注!如果我无法在接下来的一两天内完成这项工作,我将添加测试这些功能所需的所有信息。目前,我不愿意创建一个新的Trello帐户,只是为了在这里分享这个秘密。我试图做类似的事情,但却出现了溢出错误,这就是为什么
bitShift
就是这样。这更干净!谢谢但我认为它们有相同的输出,对吗?在一个短划线上,是的,因为第7位(零索引)是零,但不适用于任何设置了该位的东西
bitShift
抛出该位,但
ascii
保留该位。例如,
bitShift(0b10001110)
产生
0b0001110
,其中
ascii(0b10001110)
只返回未更改的字节:
0b10001110
。我也很确定
bitShift
给出63而不是255的原因是直接从
rune
转换到
字符串,但我不确定。好吧,我不知道。你说得对。我一直在看字符串,因为我被从其他尝试中得到的错误弄糊涂了。我把这个放进去@doykle:注意,只有在保证数据中没有任何非utf8字节的情况下,这才可以。当go将字符串转换为符文时,任何无效的utf8都将转换为unicode替换字符0xfffd。我不知道在这种情况下节点库的行为会是什么。
callbackURL := "https://" + request.Host + request.URL.String()