636 lines
17 KiB
Go
636 lines
17 KiB
Go
// This file is auto-generated, don't edit it. Thanks.
|
|
/**
|
|
* This is for OpenApi Util
|
|
*/
|
|
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto"
|
|
"crypto/hmac"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha1"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"encoding/pem"
|
|
"errors"
|
|
"fmt"
|
|
"hash"
|
|
"io"
|
|
"net/http"
|
|
"net/textproto"
|
|
"net/url"
|
|
"reflect"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
util "github.com/alibabacloud-go/tea-utils/service"
|
|
"github.com/alibabacloud-go/tea/tea"
|
|
"github.com/tjfoc/gmsm/sm3"
|
|
)
|
|
|
|
const (
|
|
PEM_BEGIN = "-----BEGIN RSA PRIVATE KEY-----\n"
|
|
PEM_END = "\n-----END RSA PRIVATE KEY-----"
|
|
)
|
|
|
|
type Sorter struct {
|
|
Keys []string
|
|
Vals []string
|
|
}
|
|
|
|
func newSorter(m map[string]string) *Sorter {
|
|
hs := &Sorter{
|
|
Keys: make([]string, 0, len(m)),
|
|
Vals: make([]string, 0, len(m)),
|
|
}
|
|
|
|
for k, v := range m {
|
|
hs.Keys = append(hs.Keys, k)
|
|
hs.Vals = append(hs.Vals, v)
|
|
}
|
|
return hs
|
|
}
|
|
|
|
// Sort is an additional function for function SignHeader.
|
|
func (hs *Sorter) Sort() {
|
|
sort.Sort(hs)
|
|
}
|
|
|
|
// Len is an additional function for function SignHeader.
|
|
func (hs *Sorter) Len() int {
|
|
return len(hs.Vals)
|
|
}
|
|
|
|
// Less is an additional function for function SignHeader.
|
|
func (hs *Sorter) Less(i, j int) bool {
|
|
return bytes.Compare([]byte(hs.Keys[i]), []byte(hs.Keys[j])) < 0
|
|
}
|
|
|
|
// Swap is an additional function for function SignHeader.
|
|
func (hs *Sorter) Swap(i, j int) {
|
|
hs.Vals[i], hs.Vals[j] = hs.Vals[j], hs.Vals[i]
|
|
hs.Keys[i], hs.Keys[j] = hs.Keys[j], hs.Keys[i]
|
|
}
|
|
|
|
/**
|
|
* Convert all params of body other than type of readable into content
|
|
* @param body source Model
|
|
* @param content target Model
|
|
* @return void
|
|
*/
|
|
func Convert(body interface{}, content interface{}) {
|
|
res := make(map[string]interface{})
|
|
val := reflect.ValueOf(body).Elem()
|
|
dataType := val.Type()
|
|
for i := 0; i < dataType.NumField(); i++ {
|
|
field := dataType.Field(i)
|
|
name, _ := field.Tag.Lookup("json")
|
|
name = strings.Split(name, ",omitempty")[0]
|
|
_, ok := val.Field(i).Interface().(io.Reader)
|
|
if !ok {
|
|
res[name] = val.Field(i).Interface()
|
|
}
|
|
}
|
|
byt, _ := json.Marshal(res)
|
|
json.Unmarshal(byt, content)
|
|
}
|
|
|
|
/**
|
|
* Get the string to be signed according to request
|
|
* @param request which contains signed messages
|
|
* @return the signed string
|
|
*/
|
|
func GetStringToSign(request *tea.Request) (_result *string) {
|
|
return tea.String(getStringToSign(request))
|
|
}
|
|
|
|
func getStringToSign(request *tea.Request) string {
|
|
resource := tea.StringValue(request.Pathname)
|
|
queryParams := request.Query
|
|
// sort QueryParams by key
|
|
var queryKeys []string
|
|
for key := range queryParams {
|
|
queryKeys = append(queryKeys, key)
|
|
}
|
|
sort.Strings(queryKeys)
|
|
tmp := ""
|
|
for i := 0; i < len(queryKeys); i++ {
|
|
queryKey := queryKeys[i]
|
|
v := tea.StringValue(queryParams[queryKey])
|
|
if v != "" {
|
|
tmp = tmp + "&" + queryKey + "=" + v
|
|
} else {
|
|
tmp = tmp + "&" + queryKey
|
|
}
|
|
}
|
|
if tmp != "" {
|
|
tmp = strings.TrimLeft(tmp, "&")
|
|
resource = resource + "?" + tmp
|
|
}
|
|
return getSignedStr(request, resource)
|
|
}
|
|
|
|
func getSignedStr(req *tea.Request, canonicalizedResource string) string {
|
|
temp := make(map[string]string)
|
|
|
|
for k, v := range req.Headers {
|
|
if strings.HasPrefix(strings.ToLower(k), "x-acs-") {
|
|
temp[strings.ToLower(k)] = tea.StringValue(v)
|
|
}
|
|
}
|
|
hs := newSorter(temp)
|
|
|
|
// Sort the temp by the ascending order
|
|
hs.Sort()
|
|
|
|
// Get the canonicalizedOSSHeaders
|
|
canonicalizedOSSHeaders := ""
|
|
for i := range hs.Keys {
|
|
canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n"
|
|
}
|
|
|
|
// Give other parameters values
|
|
// when sign URL, date is expires
|
|
date := tea.StringValue(req.Headers["date"])
|
|
accept := tea.StringValue(req.Headers["accept"])
|
|
contentType := tea.StringValue(req.Headers["content-type"])
|
|
contentMd5 := tea.StringValue(req.Headers["content-md5"])
|
|
|
|
signStr := tea.StringValue(req.Method) + "\n" + accept + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource
|
|
return signStr
|
|
}
|
|
|
|
/**
|
|
* Get signature according to stringToSign, secret
|
|
* @param stringToSign the signed string
|
|
* @param secret accesskey secret
|
|
* @return the signature
|
|
*/
|
|
func GetROASignature(stringToSign *string, secret *string) (_result *string) {
|
|
h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(tea.StringValue(secret)))
|
|
io.WriteString(h, tea.StringValue(stringToSign))
|
|
signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
|
|
return tea.String(signedStr)
|
|
}
|
|
|
|
func GetEndpoint(endpoint *string, server *bool, endpointType *string) *string {
|
|
if tea.StringValue(endpointType) == "internal" {
|
|
strs := strings.Split(tea.StringValue(endpoint), ".")
|
|
strs[0] += "-internal"
|
|
endpoint = tea.String(strings.Join(strs, "."))
|
|
}
|
|
if tea.BoolValue(server) && tea.StringValue(endpointType) == "accelerate" {
|
|
return tea.String("oss-accelerate.aliyuncs.com")
|
|
}
|
|
|
|
return endpoint
|
|
}
|
|
|
|
func HexEncode(raw []byte) *string {
|
|
return tea.String(hex.EncodeToString(raw))
|
|
}
|
|
|
|
func Hash(raw []byte, signatureAlgorithm *string) []byte {
|
|
signType := tea.StringValue(signatureAlgorithm)
|
|
if signType == "ACS3-HMAC-SHA256" || signType == "ACS3-RSA-SHA256" {
|
|
h := sha256.New()
|
|
h.Write(raw)
|
|
return h.Sum(nil)
|
|
} else if signType == "ACS3-HMAC-SM3" {
|
|
h := sm3.New()
|
|
h.Write(raw)
|
|
return h.Sum(nil)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetEncodePath(path *string) *string {
|
|
uri := tea.StringValue(path)
|
|
strs := strings.Split(uri, "/")
|
|
for i, v := range strs {
|
|
strs[i] = url.QueryEscape(v)
|
|
}
|
|
uri = strings.Join(strs, "/")
|
|
uri = strings.Replace(uri, "+", "%20", -1)
|
|
uri = strings.Replace(uri, "*", "%2A", -1)
|
|
uri = strings.Replace(uri, "%7E", "~", -1)
|
|
return tea.String(uri)
|
|
}
|
|
|
|
func GetEncodeParam(param *string) *string {
|
|
uri := tea.StringValue(param)
|
|
uri = url.QueryEscape(uri)
|
|
uri = strings.Replace(uri, "+", "%20", -1)
|
|
uri = strings.Replace(uri, "*", "%2A", -1)
|
|
uri = strings.Replace(uri, "%7E", "~", -1)
|
|
return tea.String(uri)
|
|
}
|
|
|
|
func GetAuthorization(request *tea.Request, signatureAlgorithm, payload, acesskey, secret *string) *string {
|
|
canonicalURI := tea.StringValue(request.Pathname)
|
|
if canonicalURI == "" {
|
|
canonicalURI = "/"
|
|
}
|
|
|
|
canonicalURI = strings.Replace(canonicalURI, "+", "%20", -1)
|
|
canonicalURI = strings.Replace(canonicalURI, "*", "%2A", -1)
|
|
canonicalURI = strings.Replace(canonicalURI, "%7E", "~", -1)
|
|
|
|
method := tea.StringValue(request.Method)
|
|
canonicalQueryString := getCanonicalQueryString(request.Query)
|
|
canonicalheaders, signedHeaders := getCanonicalHeaders(request.Headers)
|
|
|
|
canonicalRequest := method + "\n" + canonicalURI + "\n" + canonicalQueryString + "\n" + canonicalheaders + "\n" +
|
|
strings.Join(signedHeaders, ";") + "\n" + tea.StringValue(payload)
|
|
signType := tea.StringValue(signatureAlgorithm)
|
|
StringToSign := signType + "\n" + tea.StringValue(HexEncode(Hash([]byte(canonicalRequest), signatureAlgorithm)))
|
|
signature := tea.StringValue(HexEncode(SignatureMethod(tea.StringValue(secret), StringToSign, signType)))
|
|
auth := signType + " Credential=" + tea.StringValue(acesskey) + ",SignedHeaders=" +
|
|
strings.Join(signedHeaders, ";") + ",Signature=" + signature
|
|
return tea.String(auth)
|
|
}
|
|
|
|
func SignatureMethod(secret, source, signatureAlgorithm string) []byte {
|
|
if signatureAlgorithm == "ACS3-HMAC-SHA256" {
|
|
h := hmac.New(sha256.New, []byte(secret))
|
|
h.Write([]byte(source))
|
|
return h.Sum(nil)
|
|
} else if signatureAlgorithm == "ACS3-HMAC-SM3" {
|
|
h := hmac.New(sm3.New, []byte(secret))
|
|
h.Write([]byte(source))
|
|
return h.Sum(nil)
|
|
} else if signatureAlgorithm == "ACS3-RSA-SHA256" {
|
|
return rsaSign(source, secret)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func rsaSign(content, secret string) []byte {
|
|
h := crypto.SHA256.New()
|
|
h.Write([]byte(content))
|
|
hashed := h.Sum(nil)
|
|
priv, err := parsePrivateKey(secret)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
sign, err := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, hashed)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return sign
|
|
}
|
|
|
|
func parsePrivateKey(privateKey string) (*rsa.PrivateKey, error) {
|
|
privateKey = formatPrivateKey(privateKey)
|
|
block, _ := pem.Decode([]byte(privateKey))
|
|
if block == nil {
|
|
return nil, errors.New("PrivateKey is invalid")
|
|
}
|
|
priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
switch priKey.(type) {
|
|
case *rsa.PrivateKey:
|
|
return priKey.(*rsa.PrivateKey), nil
|
|
default:
|
|
return nil, nil
|
|
}
|
|
}
|
|
|
|
func formatPrivateKey(privateKey string) string {
|
|
if !strings.HasPrefix(privateKey, PEM_BEGIN) {
|
|
privateKey = PEM_BEGIN + privateKey
|
|
}
|
|
|
|
if !strings.HasSuffix(privateKey, PEM_END) {
|
|
privateKey += PEM_END
|
|
}
|
|
return privateKey
|
|
}
|
|
|
|
func getCanonicalHeaders(headers map[string]*string) (string, []string) {
|
|
tmp := make(map[string]string)
|
|
tmpHeader := http.Header{}
|
|
for k, v := range headers {
|
|
if strings.HasPrefix(strings.ToLower(k), "x-acs-") || strings.ToLower(k) == "host" ||
|
|
strings.ToLower(k) == "content-type" {
|
|
tmp[strings.ToLower(k)] = strings.TrimSpace(tea.StringValue(v))
|
|
tmpHeader.Add(strings.ToLower(k), strings.TrimSpace(tea.StringValue(v)))
|
|
}
|
|
}
|
|
hs := newSorter(tmp)
|
|
|
|
// Sort the temp by the ascending order
|
|
hs.Sort()
|
|
canonicalheaders := ""
|
|
for _, key := range hs.Keys {
|
|
vals := tmpHeader[textproto.CanonicalMIMEHeaderKey(key)]
|
|
sort.Strings(vals)
|
|
canonicalheaders += key + ":" + strings.Join(vals, ",") + "\n"
|
|
}
|
|
|
|
return canonicalheaders, hs.Keys
|
|
}
|
|
|
|
func getCanonicalQueryString(query map[string]*string) string {
|
|
canonicalQueryString := ""
|
|
if tea.BoolValue(util.IsUnset(query)) {
|
|
return canonicalQueryString
|
|
}
|
|
tmp := make(map[string]string)
|
|
for k, v := range query {
|
|
tmp[k] = tea.StringValue(v)
|
|
}
|
|
|
|
hs := newSorter(tmp)
|
|
|
|
// Sort the temp by the ascending order
|
|
hs.Sort()
|
|
for i := range hs.Keys {
|
|
if hs.Vals[i] != "" {
|
|
canonicalQueryString += "&" + hs.Keys[i] + "=" + url.QueryEscape(hs.Vals[i])
|
|
} else {
|
|
canonicalQueryString += "&" + hs.Keys[i] + "="
|
|
}
|
|
}
|
|
canonicalQueryString = strings.Replace(canonicalQueryString, "+", "%20", -1)
|
|
canonicalQueryString = strings.Replace(canonicalQueryString, "*", "%2A", -1)
|
|
canonicalQueryString = strings.Replace(canonicalQueryString, "%7E", "~", -1)
|
|
|
|
if canonicalQueryString != "" {
|
|
canonicalQueryString = strings.TrimLeft(canonicalQueryString, "&")
|
|
}
|
|
return canonicalQueryString
|
|
}
|
|
|
|
/**
|
|
* Parse filter into a form string
|
|
* @param filter object
|
|
* @return the string
|
|
*/
|
|
func ToForm(filter map[string]interface{}) (_result *string) {
|
|
tmp := make(map[string]interface{})
|
|
byt, _ := json.Marshal(filter)
|
|
d := json.NewDecoder(bytes.NewReader(byt))
|
|
d.UseNumber()
|
|
_ = d.Decode(&tmp)
|
|
|
|
result := make(map[string]*string)
|
|
for key, value := range tmp {
|
|
filterValue := reflect.ValueOf(value)
|
|
flatRepeatedList(filterValue, result, key)
|
|
}
|
|
|
|
m := util.AnyifyMapValue(result)
|
|
return util.ToFormString(m)
|
|
}
|
|
|
|
func flatRepeatedList(dataValue reflect.Value, result map[string]*string, prefix string) {
|
|
if !dataValue.IsValid() {
|
|
return
|
|
}
|
|
|
|
dataType := dataValue.Type()
|
|
if dataType.Kind().String() == "slice" {
|
|
handleRepeatedParams(dataValue, result, prefix)
|
|
} else if dataType.Kind().String() == "map" {
|
|
handleMap(dataValue, result, prefix)
|
|
} else {
|
|
result[prefix] = tea.String(fmt.Sprintf("%v", dataValue.Interface()))
|
|
}
|
|
}
|
|
|
|
func handleRepeatedParams(repeatedFieldValue reflect.Value, result map[string]*string, prefix string) {
|
|
if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
|
|
for m := 0; m < repeatedFieldValue.Len(); m++ {
|
|
elementValue := repeatedFieldValue.Index(m)
|
|
key := prefix + "." + strconv.Itoa(m+1)
|
|
fieldValue := reflect.ValueOf(elementValue.Interface())
|
|
if fieldValue.Kind().String() == "map" {
|
|
handleMap(fieldValue, result, key)
|
|
} else {
|
|
result[key] = tea.String(fmt.Sprintf("%v", fieldValue.Interface()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func handleMap(valueField reflect.Value, result map[string]*string, prefix string) {
|
|
if valueField.IsValid() && valueField.String() != "" {
|
|
valueFieldType := valueField.Type()
|
|
if valueFieldType.Kind().String() == "map" {
|
|
var byt []byte
|
|
byt, _ = json.Marshal(valueField.Interface())
|
|
cache := make(map[string]interface{})
|
|
d := json.NewDecoder(bytes.NewReader(byt))
|
|
d.UseNumber()
|
|
_ = d.Decode(&cache)
|
|
for key, value := range cache {
|
|
pre := ""
|
|
if prefix != "" {
|
|
pre = prefix + "." + key
|
|
} else {
|
|
pre = key
|
|
}
|
|
fieldValue := reflect.ValueOf(value)
|
|
flatRepeatedList(fieldValue, result, pre)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get timestamp
|
|
* @return the timestamp string
|
|
*/
|
|
func GetTimestamp() (_result *string) {
|
|
gmt := time.FixedZone("GMT", 0)
|
|
return tea.String(time.Now().In(gmt).Format("2006-01-02T15:04:05Z"))
|
|
}
|
|
|
|
/**
|
|
* Parse filter into a object which's type is map[string]string
|
|
* @param filter query param
|
|
* @return the object
|
|
*/
|
|
func Query(filter interface{}) (_result map[string]*string) {
|
|
tmp := make(map[string]interface{})
|
|
byt, _ := json.Marshal(filter)
|
|
d := json.NewDecoder(bytes.NewReader(byt))
|
|
d.UseNumber()
|
|
_ = d.Decode(&tmp)
|
|
|
|
result := make(map[string]*string)
|
|
for key, value := range tmp {
|
|
filterValue := reflect.ValueOf(value)
|
|
flatRepeatedList(filterValue, result, key)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Get signature according to signedParams, method and secret
|
|
* @param signedParams params which need to be signed
|
|
* @param method http method e.g. GET
|
|
* @param secret AccessKeySecret
|
|
* @return the signature
|
|
*/
|
|
func GetRPCSignature(signedParams map[string]*string, method *string, secret *string) (_result *string) {
|
|
stringToSign := buildRpcStringToSign(signedParams, tea.StringValue(method))
|
|
signature := sign(stringToSign, tea.StringValue(secret), "&")
|
|
return tea.String(signature)
|
|
}
|
|
|
|
/**
|
|
* Parse array into a string with specified style
|
|
* @param array the array
|
|
* @param prefix the prefix string
|
|
* @style specified style e.g. repeatList
|
|
* @return the string
|
|
*/
|
|
func ArrayToStringWithSpecifiedStyle(array interface{}, prefix *string, style *string) (_result *string) {
|
|
if tea.BoolValue(util.IsUnset(array)) {
|
|
return tea.String("")
|
|
}
|
|
|
|
sty := tea.StringValue(style)
|
|
if sty == "repeatList" {
|
|
tmp := map[string]interface{}{
|
|
tea.StringValue(prefix): array,
|
|
}
|
|
return flatRepeatList(tmp)
|
|
} else if sty == "simple" || sty == "spaceDelimited" || sty == "pipeDelimited" {
|
|
return flatArray(array, sty)
|
|
} else if sty == "json" {
|
|
return util.ToJSONString(array)
|
|
}
|
|
return tea.String("")
|
|
}
|
|
|
|
func ParseToMap(in interface{}) map[string]interface{} {
|
|
if tea.BoolValue(util.IsUnset(in)) {
|
|
return nil
|
|
}
|
|
|
|
tmp := make(map[string]interface{})
|
|
byt, _ := json.Marshal(in)
|
|
d := json.NewDecoder(bytes.NewReader(byt))
|
|
d.UseNumber()
|
|
err := d.Decode(&tmp)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return tmp
|
|
}
|
|
|
|
func flatRepeatList(filter map[string]interface{}) (_result *string) {
|
|
tmp := make(map[string]interface{})
|
|
byt, _ := json.Marshal(filter)
|
|
d := json.NewDecoder(bytes.NewReader(byt))
|
|
d.UseNumber()
|
|
_ = d.Decode(&tmp)
|
|
|
|
result := make(map[string]*string)
|
|
for key, value := range tmp {
|
|
filterValue := reflect.ValueOf(value)
|
|
flatRepeatedList(filterValue, result, key)
|
|
}
|
|
|
|
res := make(map[string]string)
|
|
for k, v := range result {
|
|
res[k] = tea.StringValue(v)
|
|
}
|
|
hs := newSorter(res)
|
|
|
|
hs.Sort()
|
|
|
|
// Get the canonicalizedOSSHeaders
|
|
t := ""
|
|
for i := range hs.Keys {
|
|
if i == len(hs.Keys)-1 {
|
|
t += hs.Keys[i] + "=" + hs.Vals[i]
|
|
} else {
|
|
t += hs.Keys[i] + "=" + hs.Vals[i] + "&&"
|
|
}
|
|
}
|
|
return tea.String(t)
|
|
}
|
|
|
|
func flatArray(array interface{}, sty string) *string {
|
|
t := reflect.ValueOf(array)
|
|
strs := make([]string, 0)
|
|
for i := 0; i < t.Len(); i++ {
|
|
tmp := t.Index(i)
|
|
if tmp.Kind() == reflect.Ptr || tmp.Kind() == reflect.Interface {
|
|
tmp = tmp.Elem()
|
|
}
|
|
|
|
if tmp.Kind() == reflect.Ptr {
|
|
tmp = tmp.Elem()
|
|
}
|
|
if tmp.Kind() == reflect.String {
|
|
strs = append(strs, tmp.String())
|
|
} else {
|
|
inter := tmp.Interface()
|
|
byt, _ := json.Marshal(inter)
|
|
strs = append(strs, string(byt))
|
|
}
|
|
}
|
|
str := ""
|
|
if sty == "simple" {
|
|
str = strings.Join(strs, ",")
|
|
} else if sty == "spaceDelimited" {
|
|
str = strings.Join(strs, " ")
|
|
} else if sty == "pipeDelimited" {
|
|
str = strings.Join(strs, "|")
|
|
}
|
|
return tea.String(str)
|
|
}
|
|
|
|
func buildRpcStringToSign(signedParam map[string]*string, method string) (stringToSign string) {
|
|
signParams := make(map[string]string)
|
|
for key, value := range signedParam {
|
|
signParams[key] = tea.StringValue(value)
|
|
}
|
|
|
|
stringToSign = getUrlFormedMap(signParams)
|
|
stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
|
|
stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
|
|
stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
|
|
stringToSign = url.QueryEscape(stringToSign)
|
|
stringToSign = method + "&%2F&" + stringToSign
|
|
return
|
|
}
|
|
|
|
func getUrlFormedMap(source map[string]string) (urlEncoded string) {
|
|
urlEncoder := url.Values{}
|
|
for key, value := range source {
|
|
urlEncoder.Add(key, value)
|
|
}
|
|
urlEncoded = urlEncoder.Encode()
|
|
return
|
|
}
|
|
|
|
func sign(stringToSign, accessKeySecret, secretSuffix string) string {
|
|
secret := accessKeySecret + secretSuffix
|
|
signedBytes := shaHmac1(stringToSign, secret)
|
|
signedString := base64.StdEncoding.EncodeToString(signedBytes)
|
|
return signedString
|
|
}
|
|
|
|
func shaHmac1(source, secret string) []byte {
|
|
key := []byte(secret)
|
|
hmac := hmac.New(sha1.New, key)
|
|
hmac.Write([]byte(source))
|
|
return hmac.Sum(nil)
|
|
}
|