#Go Signature Generator
#sg.go
package ssofy
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/url"
"sort"
"strings"
)
type Signature struct {
Hash string `json:"hash"`
Salt string `json:"salt"`
}
func GenerateSignature(urlStr string, params interface{}, secret string, salt string) (Signature, error) {
u, err := url.Parse(urlStr)
if err != nil {
return Signature{}, err
}
path := u.Path
toSign := path + getValues(params, "") + salt
hash, err := generateHMAC(toSign, []byte(secret))
if err != nil {
return Signature{}, err
}
return Signature{
Hash: hash,
Salt: salt,
}, nil
}
func generateHMAC(message string, key []byte) (string, error) {
h := hmac.New(sha256.New, key)
_, err := h.Write([]byte(message))
if err != nil {
return "", err
}
hash := hex.EncodeToString(h.Sum(nil))
return hash, nil
}
func getValues(obj interface{}, prefix string) string {
var values []string
if m, ok := obj.(map[string]interface{}); ok {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
values = append(values, getValues(m[k], k))
}
} else if s, ok := obj.([]interface{}); ok {
for i, v := range s {
values = append(values, getValues(v, fmt.Sprintf("%s[%d]", prefix, i)))
}
} else if b, ok := obj.(bool); ok {
if b {
values = append(values, "1")
} else {
values = append(values, "0")
}
} else if obj == nil {
values = append(values, "")
} else {
values = append(values, fmt.Sprintf("%v", obj))
}
return strings.Join(values, "")
}