-
Notifications
You must be signed in to change notification settings - Fork 38
/
signature.go
175 lines (156 loc) · 4.22 KB
/
signature.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package auth
import (
"bytes"
"crypto/sha1"
"encoding/hex"
"reflect"
"sort"
"strconv"
)
type SignatureResult struct {
SortedKeys []string
WithoutPrivateKey string
Origin string
Hashed [20]byte
Sign string
}
func CalculateSignature(params map[string]interface{}, privateKey string) SignatureResult {
var r SignatureResult
r.SortedKeys = extractKeys(params)
var buf bytes.Buffer
for _, k := range r.SortedKeys {
buf.WriteString(k)
buf.WriteString(any2String(params[k]))
}
r.WithoutPrivateKey = buf.String()
buf.WriteString(privateKey)
r.Origin = buf.String()
r.Hashed = sha1.Sum([]byte(r.Origin))
r.Sign = hex.EncodeToString(r.Hashed[:])
return r
}
// extractKeys extract all Keys from map[string]interface{}
func extractKeys(m map[string]interface{}) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
// sign generate signature
func sign(params map[string]interface{}, privateKey string) string {
str := map2String(params) + privateKey
hashed := sha1.Sum([]byte(str))
return hex.EncodeToString(hashed[:])
}
// simple2String convert map type to string
func map2String(params map[string]interface{}) (str string) {
for _, k := range extractKeys(params) {
str += k + any2String(params[k])
}
return
}
// any2String convert any type to string
func any2String(v interface{}) string {
switch v := v.(type) {
case string, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64,
*string, *bool, *int, *int8, *int16, *int32, *int64, *uint, *uint8, *uint16, *uint32, *uint64, *float32, *float64:
return simple2String(v)
case []interface{}:
return slice2String(v)
case map[string]interface{}:
return map2String(v)
default:
return reflect2String(reflect.ValueOf(v))
}
}
// simple2String convert slice type to string
func slice2String(arr []interface{}) (str string) {
for _, v := range arr {
switch v := v.(type) {
case string, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64,
*string, *bool, *int, *int8, *int16, *int32, *int64, *uint, *uint8, *uint16, *uint32, *uint64, *float32, *float64:
str += simple2String(v)
case []interface{}:
str += slice2String(v)
case map[string]interface{}:
str += map2String(v)
default:
str += reflect2String(reflect.ValueOf(v))
}
}
return
}
// simple2String convert simple type to string
func simple2String(v interface{}) string {
switch v := v.(type) {
case string:
return v
case bool:
return strconv.FormatBool(v)
case int:
return strconv.FormatInt(int64(v), 10)
case int8:
return strconv.FormatInt(int64(v), 10)
case int16:
return strconv.FormatInt(int64(v), 10)
case int32:
return strconv.FormatInt(int64(v), 10)
case int64:
return strconv.FormatInt(v, 10)
case uint:
return strconv.FormatInt(int64(v), 10)
case uint8:
return strconv.FormatInt(int64(v), 10)
case uint16:
return strconv.FormatInt(int64(v), 10)
case uint32:
return strconv.FormatInt(int64(v), 10)
case uint64:
return strconv.FormatInt(int64(v), 10)
case float32:
return strconv.FormatFloat(float64(v), 'f', -1, 64)
case float64:
return strconv.FormatFloat(v, 'f', -1, 64)
case *string:
return *v
case *bool:
return strconv.FormatBool(*v)
case *int:
return strconv.FormatInt(int64(*v), 10)
case *int8:
return strconv.FormatInt(int64(*v), 10)
case *int16:
return strconv.FormatInt(int64(*v), 10)
case *int32:
return strconv.FormatInt(int64(*v), 10)
case *int64:
return strconv.FormatInt(*v, 10)
case *uint:
return strconv.FormatInt(int64(*v), 10)
case *uint8:
return strconv.FormatInt(int64(*v), 10)
case *uint16:
return strconv.FormatInt(int64(*v), 10)
case *uint32:
return strconv.FormatInt(int64(*v), 10)
case *uint64:
return strconv.FormatInt(int64(*v), 10)
case *float32:
return strconv.FormatFloat(float64(*v), 'f', -1, 64)
case *float64:
return strconv.FormatFloat(*v, 'f', -1, 64)
}
return ""
}
// reflect2String convert array and slice to string in reflect way
func reflect2String(rv reflect.Value) (str string) {
if rv.Kind() != reflect.Array && rv.Kind() != reflect.Slice {
return
}
for i := 0; i < rv.Len(); i++ {
str += any2String(rv.Index(i).Interface())
}
return
}