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() }