Files
MAcode/tcs-iptv/internal/hash/sdk.go
T
selfrelease a329d4906b init: AIGC-Hub/AVCC 方案文档 + TCS-IPTV 内容可信锁定系统 MVP
- 方案文档: AVCC 体系建设、IPTV TCS 需求(0-req)/PRD(1-prd)/任务(2-task)/二三四期任务
- tcs-iptv: Go 后端(哈希SDK/MA码生成/可信数据空间mock/业务编排/HTTP API+HMAC鉴权)
- web-console: React+AntD 监管大屏(角色工作台/全流程演示/监管片库)
- 一剧一码+集级哈希, 集级下架/恢复, 全栈测试通过
2026-06-14 16:50:31 +08:00

79 lines
2.1 KiB
Go

package hash
import (
"fmt"
"os"
)
// HashPackage 是哈希值包,对应需求1-AC5。
// 仅包含哈希与元数据,绝不包含原始内容(需求20-AC2)。
type HashPackage struct {
FileSHA256 string `json:"file_sha256"`
MerkleRoot string `json:"merkle_root"`
SegmentHashes []string `json:"segment_hashes"`
PerceptualHash string `json:"perceptual_hash,omitempty"`
FileSize int64 `json:"file_size"`
SegmentSize int `json:"segment_size"`
}
// Options 控制哈希计算行为。
type Options struct {
SegmentSize int // 分段大小;<=0 用默认
PerceptualHash string // 上层已抽帧并算好的感知哈希(可选)
}
// ComputeFile 对母版文件计算完整哈希值包(文件哈希 + 分段 Merkle)。
// 感知哈希需上层先抽帧,再通过 opts.PerceptualHash 传入或单独调用 AHash/DHash。
func ComputeFile(path string, opts Options) (*HashPackage, error) {
info, err := os.Stat(path)
if err != nil {
return nil, fmt.Errorf("hash: stat file: %w", err)
}
if info.IsDir() {
return nil, fmt.Errorf("hash: path is a directory: %s", path)
}
if info.Size() == 0 {
return nil, ErrEmptyInput
}
segSize := opts.SegmentSize
if segSize <= 0 {
segSize = DefaultSegmentSize
}
fileHash, err := FileSHA256(path)
if err != nil {
return nil, fmt.Errorf("hash: file sha256: %w", err)
}
segments, err := SegmentHashes(path, segSize)
if err != nil {
return nil, fmt.Errorf("hash: segment hashes: %w", err)
}
tree := BuildMerkleTree(segments)
return &HashPackage{
FileSHA256: fileHash,
MerkleRoot: tree.Root(),
SegmentHashes: segments,
PerceptualHash: opts.PerceptualHash,
FileSize: info.Size(),
SegmentSize: segSize,
}, nil
}
// Validate 校验哈希值包的完整性(需求2-AC5:缺文件哈希/Merkle根则非法)。
func (p *HashPackage) Validate() error {
if p == nil {
return fmt.Errorf("hash: nil package")
}
if p.FileSHA256 == "" {
return fmt.Errorf("hash: missing file_sha256")
}
if p.MerkleRoot == "" {
return fmt.Errorf("hash: missing merkle_root")
}
return nil
}