Files
go-trustlog/api/model/hash.go
ryan d313449c5c refactor: 重构trustlog-sdk目录结构到trustlog/go-trustlog
- 将所有trustlog-sdk文件移动到trustlog/go-trustlog/目录
- 更新README中所有import路径从trustlog-sdk改为go-trustlog
- 更新cookiecutter配置文件中的项目名称
- 更新根目录.lefthook.yml以引用新位置的配置
- 添加go.sum文件到版本控制
- 删除过时的示例文件

这次重构与trustlog-server保持一致的目录结构,
为未来支持多语言SDK(Python、Java等)预留空间。
2025-12-22 13:37:57 +08:00

268 lines
6.5 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 model
import (
"context"
"crypto/md5"
"crypto/sha1"
stdsha256 "crypto/sha256"
stdsha512 "crypto/sha512"
"encoding/hex"
"hash"
"io"
"os"
"strings"
"sync"
miniosha256 "github.com/minio/sha256-simd"
"github.com/zeebo/blake3"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/md4" //nolint:staticcheck // 保留弱加密算法以支持遗留系统兼容性
"golang.org/x/crypto/ripemd160" //nolint:staticcheck // 保留弱加密算法以支持遗留系统兼容性
"golang.org/x/crypto/sha3"
)
// HashType 定义支持的哈希算法类型.
type HashType string
const (
MD5 HashType = "md5"
SHA1 HashType = "sha1"
SHA224 HashType = "sha224"
SHA256 HashType = "sha256"
SHA384 HashType = "sha384"
SHA512 HashType = "sha512"
Sha512224 HashType = "sha512_224"
Sha512256 HashType = "sha512_256"
Sha256Simd HashType = "sha256-simd"
BLAKE3 HashType = "blake3"
BLAKE2B HashType = "blake2b"
BLAKE2S HashType = "blake2s"
MD4 HashType = "md4"
RIPEMD160 HashType = "ripemd160"
Sha3224 HashType = "sha3-224"
Sha3256 HashType = "sha3-256"
Sha3384 HashType = "sha3-384"
Sha3512 HashType = "sha3-512"
)
// 使用 map 来存储支持的算法,提高查找效率.
//
//nolint:gochecknoglobals // 全局缓存用于算法查找和实例复用.
var (
supportedAlgorithms []string
supportedAlgorithmsMap map[string]bool
supportedAlgorithmsOnce sync.Once
// 享元模式:存储已创建的 HashTool 实例.
toolPool = make(map[HashType]*HashTool)
poolMutex sync.RWMutex
)
// HashTool 哈希工具类.
type HashTool struct {
hashType HashType
}
// GetHashTool 获取指定类型的 HashTool.
func GetHashTool(hashType HashType) *HashTool {
poolMutex.RLock()
if tool, exists := toolPool[hashType]; exists {
poolMutex.RUnlock()
return tool
}
poolMutex.RUnlock()
poolMutex.Lock()
defer poolMutex.Unlock()
if tool, exists := toolPool[hashType]; exists {
return tool
}
tool := &HashTool{hashType: hashType}
toolPool[hashType] = tool
return tool
}
// NewHashTool 创建新的哈希工具实例.
func NewHashTool(hashType HashType) *HashTool {
return &HashTool{hashType: hashType}
}
// getHasher 根据哈希类型获取对应的哈希器.
func (h *HashTool) getHasher() hash.Hash {
switch h.hashType {
case MD5:
return md5.New()
case SHA1:
return sha1.New()
case SHA224:
return stdsha256.New224()
case SHA256:
return stdsha256.New()
case SHA384:
return stdsha512.New384()
case SHA512:
return stdsha512.New()
case Sha512224:
return stdsha512.New512_224()
case Sha512256:
return stdsha512.New512_256()
// 第三方算法
case Sha256Simd:
return miniosha256.New()
case BLAKE3:
return blake3.New()
case BLAKE2B:
hasher, _ := blake2b.New512(nil)
return hasher
case BLAKE2S:
hasher, _ := blake2s.New256(nil)
return hasher
case MD4:
return md4.New()
case RIPEMD160:
return ripemd160.New()
case Sha3224:
return sha3.New224()
case Sha3256:
return sha3.New256()
case Sha3384:
return sha3.New384()
case Sha3512:
return sha3.New512()
default:
return stdsha256.New() // 默认使用 SHA256
}
}
// hashData 通用的哈希计算函数.
func (h *HashTool) hashData(processFunc func(hasher hash.Hash) error) (string, error) {
hasher := h.getHasher()
if err := processFunc(hasher); err != nil {
return "", err
}
return hex.EncodeToString(hasher.Sum(nil)), nil
}
// HashString 对字符串进行哈希计算.
func (h *HashTool) HashString(data string) (string, error) {
return h.hashData(func(hasher hash.Hash) error {
_, err := hasher.Write([]byte(data))
return err
})
}
// HashBytes 对字节数组进行哈希计算.
func (h *HashTool) HashBytes(data []byte) (string, error) {
return h.hashData(func(hasher hash.Hash) error {
_, err := hasher.Write(data)
return err
})
}
// HashBytesRaw 对字节数组进行哈希计算返回原始字节数组非hex字符串.
func (h *HashTool) HashBytesRaw(data []byte) ([]byte, error) {
hasher := h.getHasher()
if _, err := hasher.Write(data); err != nil {
return nil, err
}
return hasher.Sum(nil), nil
}
// HashFile 对文件进行哈希计算.
func (h *HashTool) HashFile(_ context.Context, filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
defer file.Close()
return h.hashData(func(hasher hash.Hash) error {
_, copyErr := io.Copy(hasher, file)
return copyErr
})
}
// HashStream 对流数据进行哈希计算.
func (h *HashTool) HashStream(reader io.Reader) (string, error) {
return h.hashData(func(hasher hash.Hash) error {
_, err := io.Copy(hasher, reader)
return err
})
}
// initSupportedAlgorithms 初始化支持的算法数据.
func initSupportedAlgorithms() {
algorithms := []HashType{
MD5, SHA1, SHA224, SHA256, SHA384, SHA512,
Sha512224, Sha512256, Sha256Simd, BLAKE3,
BLAKE2B, BLAKE2S, MD4, RIPEMD160,
Sha3224, Sha3256, Sha3384, Sha3512,
}
supportedAlgorithms = make([]string, len(algorithms))
supportedAlgorithmsMap = make(map[string]bool, len(algorithms))
for i, alg := range algorithms {
algStr := string(alg)
supportedAlgorithms[i] = algStr
supportedAlgorithmsMap[strings.ToLower(algStr)] = true
}
}
// GetSupportedAlgorithms 获取支持的哈希算法列表.
func GetSupportedAlgorithms() []string {
supportedAlgorithmsOnce.Do(initSupportedAlgorithms)
return supportedAlgorithms
}
// IsAlgorithmSupported 检查算法是否支持 - 使用 map 提高性能.
func IsAlgorithmSupported(algorithm string) bool {
supportedAlgorithmsOnce.Do(initSupportedAlgorithms)
return supportedAlgorithmsMap[strings.ToLower(algorithm)]
}
// CompareHash 比较哈希值.
func (h *HashTool) CompareHash(data, expectedHash string) (bool, error) {
actualHash, err := h.HashString(data)
if err != nil {
return false, err
}
return strings.EqualFold(actualHash, expectedHash), nil
}
// CompareFileHash 比较文件哈希值.
func (h *HashTool) CompareFileHash(ctx context.Context, filePath, expectedHash string) (bool, error) {
actualHash, err := h.HashFile(ctx, filePath)
if err != nil {
return false, err
}
return strings.EqualFold(actualHash, expectedHash), nil
}
// GetHashType 获取当前工具使用的哈希类型.
func (h *HashTool) GetHashType() HashType {
return h.hashType
}
type HashData interface {
Key() string
Hash() string
Type() HashType
}
type Hashable interface {
DoHash(ctx context.Context) (HashData, error)
}
type HashList []HashData
func (h HashList) GetHashType() HashType {
return h[0].Type()
}