素材库认证与签名
Bearer API Key 与火山 ARK HMAC-SHA256 签名规则
素材库 Action API 支持 Bearer API Key 和 AK/SK HMAC-SHA256。两种方式任选其一,不要在同一个请求中混用。火山兼容视频生成任务接口使用 Authorization: Bearer,不使用素材 Action 的 AK/SK 签名。
认证方式一 : Bearer API Key
兼容网关可使用 Bearer API Key:
Authorization: Bearer sk-your-api-key
Content-Type: application/jsonAPI Key 所属用户必须启用并拥有素材访问权限。Token 过期、停用或 IP 白名单不匹配时,请求会被拒绝。
认证方式二 :AK/SK HMAC-SHA256
火山 SDK 和界云素材 SDK 使用 Access Key 与 Secret Key 签名。固定参数如下:
| 参数 | 值 |
|---|---|
| Region | cn-beijing |
| Service | ark |
| Algorithm | HMAC-SHA256 |
| Version | 2024-01-01 |
必需请求头:
Content-Type: application/json
Host: jieyun.cc
X-Date: 20260721T040000Z
X-Content-Sha256: <lowercase sha256 hex of request body>
Authorization: HMAC-SHA256 Credential=<AK>/<date>/cn-beijing/ark/request, SignedHeaders=content-type;host;x-content-sha256;x-date, Signature=<hex>Host 必须与实际 Endpoint 一致,当前使用 jieyun.cc。
签名步骤
- 对原始 JSON 请求体计算 SHA-256,将小写十六进制结果写入
X-Content-Sha256。 - 构造 Canonical Request:HTTP 方法、Canonical URI、Canonical Query String、Canonical Headers、Signed Headers 和请求体哈希。
- 使用
HMAC-SHA256、X-Date、凭证范围和 Canonical Request 哈希构造 String to Sign。 - 按日期、区域、服务名和
request的顺序派生签名密钥,再计算最终 Signature。
请求时间与服务端时间偏差不能超过 5 分钟。不支持 X-Security-Token 临时安全凭证。
Go 签名示例
下面的示例仅使用 Go 标准库,请通过环境变量传入 AK/SK。请求体必须先序列化为字节,再使用同一组字节计算哈希并发送;计算签名后不要重新格式化或修改 JSON。
package main
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"sort"
"strings"
"time"
)
const (
region = "cn-beijing"
service = "ark"
action = "CreateAssetGroup"
version = "2024-01-01"
)
func sha256Hex(value []byte) string {
sum := sha256.Sum256(value)
return hex.EncodeToString(sum[:])
}
func hmacSHA256(key []byte, value string) []byte {
mac := hmac.New(sha256.New, key)
mac.Write([]byte(value))
return mac.Sum(nil)
}
func encode(value string) string {
return strings.ReplaceAll(url.QueryEscape(value), "+", "%20")
}
func main() {
accessKey := os.Getenv("ARK_ACCESS_KEY")
secretKey := os.Getenv("ARK_SECRET_KEY")
if accessKey == "" || secretKey == "" {
panic("请设置 ARK_ACCESS_KEY 和 ARK_SECRET_KEY")
}
// 先确认请求体。后续计算哈希和发送请求必须复用 body。
body, err := json.Marshal(struct {
Name string `json:"Name"`
Description string `json:"Description"`
GroupType string `json:"GroupType"`
ProjectName string `json:"ProjectName"`
}{
Name: "产品素材",
Description: "产品图片和视频素材",
GroupType: "AIGC",
ProjectName: "default",
})
if err != nil {
panic(err)
}
endpoint, err := url.Parse("https://jieyun.cc/")
if err != nil {
panic(err)
}
query := map[string]string{
"Action": action,
"Version": version,
}
keys := make([]string, 0, len(query))
for key := range query {
keys = append(keys, key)
}
sort.Strings(keys)
parts := make([]string, 0, len(keys))
for _, key := range keys {
parts = append(parts, encode(key)+"="+encode(query[key]))
}
canonicalQuery := strings.Join(parts, "&")
endpoint.RawQuery = canonicalQuery
xDate := time.Now().UTC().Format("20060102T150405Z")
shortDate := xDate[:8]
payloadHash := sha256Hex(body)
signedHeaders := "content-type;host;x-content-sha256;x-date"
canonicalHeaders := strings.Join([]string{
"content-type:application/json",
"host:" + endpoint.Host,
"x-content-sha256:" + payloadHash,
"x-date:" + xDate,
"",
}, "\n")
canonicalRequest := strings.Join([]string{
"POST",
endpoint.EscapedPath(),
canonicalQuery,
canonicalHeaders,
signedHeaders,
payloadHash,
}, "\n")
credentialScope := fmt.Sprintf(
"%s/%s/%s/request",
shortDate,
region,
service,
)
stringToSign := strings.Join([]string{
"HMAC-SHA256",
xDate,
credentialScope,
sha256Hex([]byte(canonicalRequest)),
}, "\n")
dateKey := hmacSHA256([]byte(secretKey), shortDate)
regionKey := hmacSHA256(dateKey, region)
serviceKey := hmacSHA256(regionKey, service)
signingKey := hmacSHA256(serviceKey, "request")
signature := hex.EncodeToString(hmacSHA256(signingKey, stringToSign))
authorization := fmt.Sprintf(
"HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s",
accessKey,
credentialScope,
signedHeaders,
signature,
)
request, err := http.NewRequest(
http.MethodPost,
endpoint.String(),
bytes.NewReader(body),
)
if err != nil {
panic(err)
}
request.Header.Set("Authorization", authorization)
request.Header.Set("Content-Type", "application/json")
request.Header.Set("X-Date", xDate)
request.Header.Set("X-Content-Sha256", payloadHash)
response, err := http.DefaultClient.Do(request)
if err != nil {
panic(err)
}
defer response.Body.Close()
responseBody, err := io.ReadAll(response.Body)
if err != nil {
panic(err)
}
fmt.Printf("%s\n%s\n", response.Status, responseBody)
}运行示例:
ARK_ACCESS_KEY="ak-your-access-key" \
ARK_SECRET_KEY="your-secret-key" \
go run main.goSDK 配置
完整的 SDK 配置与调用示例请参阅素材库 API 概览。
config := volcengine.NewConfig().
WithCredentials(credentials.NewStaticCredentials(accessKey, secretKey, "")).
WithRegion("cn-beijing").
WithEndpoint("jieyun.cc")
client := ark.New(session.Must(session.NewSession(config)))SDK 会自动添加 Action、Version、请求体哈希和签名请求头。Endpoint 使用 jieyun.cc。