Golang – Dropbox Webhook 签名验证 HMAC

huangapple go评论68阅读模式
英文:

Golang - Dropbox webhook signature validation hmac

问题

我正在编写一个需要使用Dropbox的Webhooks的程序。我没有找到任何现成的Go实现,所以我决定自己写一个。不幸的是,它似乎不起作用。

我认为问题可能出在hmac上,因为我很可能做错了什么,但我就是无法确定问题出在哪里。有什么想法吗?

以下是我的代码:

package dboxwebhook

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"errors"
	"io"
	"io/ioutil"
	"log"
)

type Signature struct {
	AppSecret []byte
	Signature []byte
}

func (w *Signature) Check(reqBody io.ReadCloser) error {

	if bytes.Compare(w.Signature, nil) == 0 {
		return errors.New("DropBox signature doesnt exist")
	}

	// building HMAC key (https://golang.org/pkg/crypto/hmac/)
	mac := hmac.New(sha256.New, w.AppSecret)
	requestBody, err := ioutil.ReadAll(reqBody)
	if err != nil {
		return err
	}

	mac.Write(requestBody)
	expectedMac := mac.Sum(nil)

	log.Println(w.AppSecret)
	log.Println(expectedMac)
	log.Println(w.Signature)

	// compare if it corresponds with the signature sent by DropBox
	comparison := hmac.Equal(w.Signature, expectedMac)

	if !comparison {
		return errors.New("Signature Check unsuccessful")
	}

	return nil
}

要测试这个代码,我唯一知道的方法是使用Dropbox的这个Python脚本

英文:

I am writing a program that needs to use Dropbox's webhooks. I haven't been able to find any Go implementation already in place, so I've decided to write mine. Unfortunately, it doesn't seem to work.

I think the issue here is with hmac, as I am most probably doing something wrong, but I just can't seem to understand where exactly the issue here. Any idea?

The following is what I have:

package dboxwebhook

import (
    "bytes"
    "crypto/hmac"
    "crypto/sha256"
    "errors"
    "io"
    "io/ioutil"
	"log"
)

type Signature struct {
    AppSecret []byte
    Signature []byte
}

func (w *Signature) Check(reqBody io.ReadCloser) error {

    if bytes.Compare(w.Signature, nil) == 0 {
	    return errors.New("DropBox signature doesnt exist")
    }

    // building HMAC key (https://golang.org/pkg/crypto/hmac/)
    mac := hmac.New(sha256.New, w.AppSecret)
    requestBody, err := ioutil.ReadAll(reqBody)
    if err != nil {
    	return err
    }

    mac.Write(requestBody)
    expectedMac := mac.Sum(nil)

    log.Println(w.AppSecret)
    log.Println(expectedMac)
    log.Println(w.Signature)

    // compare if it corresponds with the signature sent by DropBox
    comparison := hmac.Equal(w.Signature, expectedMac)

    if !comparison {
    	return errors.New("Signature Check unsuccessful")
    }

    return nil

}

To test this, the only way I know is to use this Python script from Dropbox.

答案1

得分: 5

Dropbox签名以字符串形式发送,位于HTTP头X-Dropbox-Signature中。

为了将其与hmac.Equal一起使用,您需要首先使用encoding/hex包将十六进制字符串表示解码为字节切片。

import "encoding/hex"

[...]
hexSignature, err := hex.DecodeString(w.Signature)
[...]

然后,您可以在比较中使用十六进制字节。

[...]
// compare if it corresponds with the signature sent by DropBox
comparison := hmac.Equal(hexSignature, expectedMac)
[...]
英文:

The Dropbox signature is sent as string in the HTTP header X-Dropbox-Signature.

So as to use it with hmac.Equal, you need to decode the hex string representation to a slice of byte first using package encoding/hex.

    import "encoding/hex"

    [...]
    hexSignature, err := hex.DecodeString(w.Signature)
    [...]

Then you can use the hex bytes in the comparison

    [...]
    // compare if it corresponds with the signature sent by DropBox
    comparison := hmac.Equal(hexSignature, expectedMac)
    [...]

huangapple
  • 本文由 发表于 2015年7月18日 23:52:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/31492897.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定