Files
xk-hy-transit-go/internal/fileauth/upload.go
2026-06-04 08:15:50 +08:00

133 lines
4.1 KiB
Go
Raw 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 fileauth
import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
"time"
)
const algorithmJavaUpload = "fileauth-java-upload"
// MarshalPutPolicyUpload 生产 putPolicyscope=仅 bucket无 returnBody与 FileAuth.java HashMap 字段顺序一致)。
func MarshalPutPolicyUpload(bucket string, deadlineUnix int64) ([]byte, error) {
bucket = strings.TrimSpace(bucket)
if bucket == "" {
return nil, errors.New("empty bucket")
}
if deadlineUnix <= 0 {
return nil, errors.New("invalid deadline")
}
scopeJSON, err := json.Marshal(bucket)
if err != nil {
return nil, err
}
return []byte(`{"scope":` + string(scopeJSON) + `,"deadline":` + strconv.FormatInt(deadlineUnix, 10) + `}`), nil
}
// signPolicyJava 与 FileAuth.java sign(byte[]) 一致HMAC-SHA1(secret, policyJSON) → URL-safe Base64。
func signPolicyJava(secret string, policyJSON []byte) (string, error) {
mac := hmac.New(sha1.New, []byte(secret))
if _, err := mac.Write(policyJSON); err != nil {
return "", fmt.Errorf("hmac: %w", err)
}
return encodeURLSafe(mac.Sum(nil)), nil
}
// BuildUploadTokenFromPolicy 按 FileAuth.java createUploadToken 生成 token。
func BuildUploadTokenFromPolicy(accessKey, secret string, putPolicyJSON []byte, algorithm string) (UploadTokenParts, error) {
accessKey = strings.TrimSpace(accessKey)
secret = strings.TrimSpace(secret)
if accessKey == "" || secret == "" {
return UploadTokenParts{}, errors.New("empty key or secret")
}
if len(putPolicyJSON) == 0 {
return UploadTokenParts{}, errors.New("empty putPolicy")
}
if algorithm == "" {
algorithm = algorithmJavaUpload
}
policyJSON := string(putPolicyJSON)
sign, err := signPolicyJava(secret, putPolicyJSON)
if err != nil {
return UploadTokenParts{}, err
}
policyB64 := encodeURLSafe(putPolicyJSON)
token := accessKey + ":" + sign + ":" + policyB64
var policy struct {
Deadline int64 `json:"deadline"`
}
_ = json.Unmarshal(putPolicyJSON, &policy)
return UploadTokenParts{
AccessKey: accessKey,
PolicyJSON: policyJSON,
EncodedPutPolicy: policyB64,
SignInput: policyJSON,
EncodedSign: sign,
UploadToken: token,
DeadlineUnix: policy.Deadline,
Algorithm: algorithm,
}, nil
}
// BuildUploadTokenPartsForUpload 生产路径scope=仅 bucket。
func BuildUploadTokenPartsForUpload(accessKey, secret, bucket string, deadlineUnix int64) (UploadTokenParts, error) {
accessKey = strings.TrimSpace(accessKey)
secret = strings.TrimSpace(secret)
bucket = strings.TrimSpace(bucket)
if accessKey == "" || secret == "" {
return UploadTokenParts{}, errors.New("empty key or secret")
}
if bucket == "" {
return UploadTokenParts{}, errors.New("empty bucket")
}
if deadlineUnix <= 0 {
return UploadTokenParts{}, errors.New("invalid deadline")
}
jsonPolicy, err := MarshalPutPolicyUpload(bucket, deadlineUnix)
if err != nil {
return UploadTokenParts{}, err
}
parts, err := BuildUploadTokenFromPolicy(accessKey, secret, jsonPolicy, algorithmJavaUpload)
if err != nil {
return UploadTokenParts{}, err
}
now := time.Now().Unix()
expires := deadlineUnix - now
if expires < 0 {
expires = 0
}
parts.ExpiresSec = expires
return parts, nil
}
// BuildUploadTokenPartsAtFile filename 不参与 scopetoken policy scope=仅 bucket
func BuildUploadTokenPartsAtFile(accessKey, secret, bucket, filename string, deadlineUnix int64) (UploadTokenParts, error) {
_ = filename
return BuildUploadTokenPartsForUpload(accessKey, secret, bucket, deadlineUnix)
}
// CreateUploadTokenAtFile 生产上传凭证。
func CreateUploadTokenAtFile(accessKey, secret, bucket, filename string, deadlineUnix int64) (string, error) {
parts, err := BuildUploadTokenPartsAtFile(accessKey, secret, bucket, filename, deadlineUnix)
if err != nil {
return "", err
}
return parts.UploadToken, nil
}
// HMACSignHex 返回 HMAC-SHA1(policyJSON) 原始字节的十六进制(调试用)。
func HMACSignHex(secret, policyJSON string) string {
mac := hmac.New(sha1.New, []byte(secret))
_, _ = mac.Write([]byte(policyJSON))
return hex.EncodeToString(mac.Sum(nil))
}