tokenFactory/relay/channel/task/tencentvod/sign.go

101 lines
3.1 KiB
Go

package tencentvod
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/service"
)
const vodService = "vod"
const vodAPIVersion = "2018-07-17"
func sha256hex(s string) string {
b := sha256.Sum256([]byte(s))
return hex.EncodeToString(b[:])
}
func hmacSha256(s, key string) []byte {
h := hmac.New(sha256.New, []byte(key))
_, _ = h.Write([]byte(s))
return h.Sum(nil)
}
func tc3Authorization(secretID, secretKey, host, action string, timestamp int64, payloadJSON []byte) string {
httpRequestMethod := "POST"
canonicalURI := "/"
canonicalQueryString := ""
actionLower := strings.ToLower(action)
canonicalHeaders := fmt.Sprintf("content-type:%s\nhost:%s\nx-tc-action:%s\n", "application/json", host, actionLower)
signedHeaders := "content-type;host;x-tc-action"
hashedRequestPayload := sha256hex(string(payloadJSON))
canonicalRequest := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s",
httpRequestMethod, canonicalURI, canonicalQueryString, canonicalHeaders, signedHeaders, hashedRequestPayload)
algorithm := "TC3-HMAC-SHA256"
requestTimestamp := strconv.FormatInt(timestamp, 10)
ts, _ := strconv.ParseInt(requestTimestamp, 10, 64)
t := time.Unix(ts, 0).UTC()
date := t.Format("2006-01-02")
credentialScope := fmt.Sprintf("%s/%s/tc3_request", date, vodService)
hashedCanonicalRequest := sha256hex(canonicalRequest)
string2sign := fmt.Sprintf("%s\n%s\n%s\n%s", algorithm, requestTimestamp, credentialScope, hashedCanonicalRequest)
secretDate := hmacSha256(date, "TC3"+secretKey)
secretService := hmacSha256(vodService, string(secretDate))
signingKey := hmacSha256("tc3_request", string(secretService))
signature := hex.EncodeToString(hmacSha256(string2sign, string(signingKey)))
return fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
algorithm, secretID, credentialScope, signedHeaders, signature)
}
func SignedPOSTJSON(proxy string, endpoint string, region string, cred Credentials, action string, payloadJSON []byte) (*http.Response, error) {
u, err := url.Parse(strings.TrimSpace(endpoint))
if err != nil || u.Host == "" {
return nil, fmt.Errorf("invalid endpoint URL")
}
if u.Scheme == "" {
u.Scheme = "https"
}
fullURL := u.Scheme + "://" + u.Host + "/"
host := u.Host
ts := common.GetTimestamp()
auth := tc3Authorization(cred.SecretID, cred.SecretKey, host, action, ts, payloadJSON)
req, err := http.NewRequest(http.MethodPost, fullURL, bytes.NewReader(payloadJSON))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", auth)
req.Header.Set("X-TC-Action", action)
req.Header.Set("X-TC-Version", vodAPIVersion)
req.Header.Set("X-TC-Timestamp", strconv.FormatInt(ts, 10))
if strings.TrimSpace(region) != "" {
req.Header.Set("X-TC-Region", strings.TrimSpace(region))
}
var client *http.Client
if strings.TrimSpace(proxy) != "" {
client, err = service.NewProxyHttpClient(strings.TrimSpace(proxy))
if err != nil {
return nil, err
}
} else {
client = service.GetHttpClient()
}
return client.Do(req)
}