/
sign_func.go
69 lines (63 loc) · 1.63 KB
/
sign_func.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package apiclient
import (
"bytes"
"crypto/hmac"
"crypto/md5"
"encoding/hex"
"net/url"
"sort"
)
// MakeSign return the signature of url values signed by
// hmac/md5 with specified sign key.
func MakeSign(values url.Values, key string) []byte {
values.Del("api_sign")
qs := []byte(EncodeValues(values))
mac := hmac.New(md5.New, []byte(key))
mac.Write(qs)
return mac.Sum(nil)
}
// MakeSignString return the signature of url values as string
// signed by hmac/md5 with specified sign key.
func MakeSignString(values url.Values, key string) string {
t := MakeSign(values, key)
return hex.EncodeToString(t)
}
// CheckSign return true if specified sign is the signature
// of url values.
func CheckSign(values url.Values, key string, sign []byte) bool {
expected := MakeSignString(values, key)
return hmac.Equal([]byte(expected), []byte(sign))
}
// EncodeValues encodes the values into "URL encoded" form
// ("bar=baz&foo=quux") sorted by key and values.
// Changed from url.Values.Encode()
func EncodeValues(v url.Values) string {
if v == nil {
return ""
}
var buf bytes.Buffer
keys := make([]string, 0, len(v))
for k := range v {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
// we add this
// clone and sort
// vs:=v[k]
vs := make([]string, 0, len(v[k]))
for _, x := range v[k] {
vs = append(vs, x)
}
sort.Strings(vs)
prefix := url.QueryEscape(k) + "="
for _, v := range vs {
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(prefix)
buf.WriteString(url.QueryEscape(v))
}
}
return buf.String()
}