jytest/signer/signer.go

110 lines
2.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package signer
import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"log"
"net/url"
"sort"
"strings"
"time"
)
// Config 签名配置
type Config struct {
AccessKey string
SecretKey string
Host string // https://jimeng.jianying.com
}
// Request 签名请求信息
type Request struct {
Method string // 恒为 POST
Path string // 如 /agent_openapi/v1/video/submit
Query url.Values // 通常为空
Body []byte // JSON 序列化后的请求体
ContentType string // 恒为 application/json
}
// Headers 生成鉴权相关请求头
func (c *Config) Headers(req *Request) (map[string]string, error) {
timestamp := fmt.Sprintf("%d", time.Now().Unix())
nonce, err := randomNonce()
if err != nil {
return nil, err
}
bodySHA := sha256Hex(req.Body)
canonicalQuery := canonicalQueryString(req.Query)
contentType := req.ContentType
if contentType == "" {
contentType = "application/json"
}
stringToSign := strings.Join([]string{
req.Method, req.Path, canonicalQuery, contentType,
bodySHA, timestamp, nonce, c.AccessKey,
}, "\n")
signature := hmacSHA256Base64URL(c.SecretKey, stringToSign)
// 调试日志:打印签名详情,便于排查 10006 错误
log.Printf("[SIGN] Path=%s BodyLen=%d BodySHA256=%s", req.Path, len(req.Body), bodySHA)
log.Printf("[SIGN] StringToSign=\n%s", stringToSign)
log.Printf("[SIGN] Signature=%s", signature)
return map[string]string{
"X-Agent-Access-Key": c.AccessKey,
"X-Agent-Timestamp": timestamp,
"X-Agent-Nonce": nonce,
"X-Agent-Body-SHA256": bodySHA,
"X-Agent-Signature-Method": "HMAC-SHA256",
"X-Agent-Version": "v1",
"X-Agent-Signature": signature,
}, nil
}
func randomNonce() (string, error) {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return "", err
}
return hex.EncodeToString(b), nil
}
func sha256Hex(data []byte) string {
sum := sha256.Sum256(data)
return hex.EncodeToString(sum[:]) // 小写
}
// query 按参数名 ASCII 升序,key/value 各自 RFC3986 编码后 & 连接
func canonicalQueryString(v url.Values) string {
if len(v) == 0 {
return ""
}
keys := make([]string, 0, len(v))
for k := range v {
keys = append(keys, k)
}
sort.Strings(keys)
var parts []string
for _, k := range keys {
for _, val := range v[k] {
parts = append(parts, escape(k)+"="+escape(val))
}
}
return strings.Join(parts, "&")
}
// RFC3986:空格 -> %20,~ 不编码
func escape(s string) string { return url.QueryEscape(s) }
func hmacSHA256Base64URL(key, data string) string {
mac := hmac.New(sha256.New, []byte(key))
mac.Write([]byte(data))
return base64.RawURLEncoding.EncodeToString(mac.Sum(nil)) // Raw 即无 padding
}