2026-09-30 15:49:12 +08:00
|
|
|
// Package sha256x 提供 SHA-224 与 SHA-256 摘要计算,以及十六进制/Base64 编码与流式、文件接口。
|
|
|
|
|
//
|
|
|
|
|
// 命名约定:带位数后缀的函数(Sum224、Hex224、New224 等)明确指定算法变体;
|
|
|
|
|
// 不带后缀的 Sum、Hex、Base64、New、SumReader、HexReader、HexFile 等价于 256 位变体,
|
|
|
|
|
// 因为 SHA-256 是本包最常用的变体。
|
2023-12-27 19:00:14 +08:00
|
|
|
package sha256x
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/sha256"
|
2026-09-30 15:49:12 +08:00
|
|
|
"encoding/base64"
|
2023-12-27 19:00:14 +08:00
|
|
|
"encoding/hex"
|
2026-09-30 15:49:12 +08:00
|
|
|
"fmt"
|
|
|
|
|
"hash"
|
|
|
|
|
"io"
|
|
|
|
|
"os"
|
2023-12-27 19:00:14 +08:00
|
|
|
)
|
|
|
|
|
|
2026-09-30 15:49:12 +08:00
|
|
|
const (
|
|
|
|
|
// Size224 是 SHA-224 摘要的字节数(28)。
|
|
|
|
|
Size224 = sha256.Size224
|
|
|
|
|
// Size256 是 SHA-256 摘要的字节数(32)。
|
|
|
|
|
Size256 = sha256.Size
|
|
|
|
|
// BlockSize 是 SHA-224/SHA-256 分组的字节数(64)。
|
|
|
|
|
BlockSize = sha256.BlockSize
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// New224 返回一个计算 SHA-224 摘要的 hash.Hash。
|
|
|
|
|
func New224() hash.Hash {
|
|
|
|
|
return sha256.New224()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New256 返回一个计算 SHA-256 摘要的 hash.Hash。
|
|
|
|
|
func New256() hash.Hash {
|
|
|
|
|
return sha256.New()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New 等价于 New256。
|
|
|
|
|
func New() hash.Hash {
|
|
|
|
|
return New256()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sum224 返回 data 的 SHA-224 摘要(Size224 字节原始数据)。
|
|
|
|
|
func Sum224(data []byte) []byte {
|
|
|
|
|
return sum(sha256.New224(), data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sum256 返回 data 的 SHA-256 摘要(Size256 字节原始数据)。
|
|
|
|
|
func Sum256(data []byte) []byte {
|
|
|
|
|
return sum(sha256.New(), data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sum 等价于 Sum256。
|
|
|
|
|
func Sum(data []byte) []byte {
|
|
|
|
|
return Sum256(data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hex224 返回 data 的 SHA-224 摘要的小写十六进制字符串。
|
|
|
|
|
func Hex224(data []byte) string {
|
|
|
|
|
return hex.EncodeToString(Sum224(data))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hex256 返回 data 的 SHA-256 摘要的小写十六进制字符串。
|
|
|
|
|
func Hex256(data []byte) string {
|
|
|
|
|
return hex.EncodeToString(Sum256(data))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Hex 等价于 Hex256。
|
|
|
|
|
func Hex(data []byte) string {
|
|
|
|
|
return Hex256(data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Base64Sum224 返回 data 的 SHA-224 摘要的标准 Base64 字符串。
|
|
|
|
|
func Base64Sum224(data []byte) string {
|
|
|
|
|
return base64.StdEncoding.EncodeToString(Sum224(data))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Base64Sum256 返回 data 的 SHA-256 摘要的标准 Base64 字符串。
|
|
|
|
|
func Base64Sum256(data []byte) string {
|
|
|
|
|
return base64.StdEncoding.EncodeToString(Sum256(data))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Base64 等价于 Base64Sum256。
|
|
|
|
|
func Base64(data []byte) string {
|
|
|
|
|
return Base64Sum256(data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SumReader 读取 r 中的全部数据并返回其 SHA-256 摘要;读取失败时返回包装后的 error。
|
|
|
|
|
func SumReader(r io.Reader) ([]byte, error) {
|
|
|
|
|
return sumReader(sha256.New(), r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// HexReader 读取 r 中的全部数据并返回其 SHA-256 摘要的小写十六进制字符串。
|
|
|
|
|
func HexReader(r io.Reader) (string, error) {
|
|
|
|
|
sum, err := SumReader(r)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return hex.EncodeToString(sum), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// HexFile 计算 path 所指向文件的 SHA-256 摘要并返回小写十六进制字符串;
|
|
|
|
|
// 文件不存在或读取失败时返回包装后的 error,不 panic。
|
|
|
|
|
func HexFile(path string) (string, error) {
|
|
|
|
|
return hexFile(path, sha256.New)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sum 把 data 一次性写入 h 并取出摘要。
|
|
|
|
|
func sum(h hash.Hash, data []byte) []byte {
|
|
|
|
|
_, _ = h.Write(data)
|
|
|
|
|
return h.Sum(nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sumReader 把 r 的全部内容写入 h 并取出摘要。
|
|
|
|
|
func sumReader(h hash.Hash, r io.Reader) ([]byte, error) {
|
|
|
|
|
if r == nil {
|
|
|
|
|
return nil, fmt.Errorf("sha256x: 读取器为 nil")
|
|
|
|
|
}
|
|
|
|
|
if _, err := io.Copy(h, r); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("sha256x: 读取数据失败: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return h.Sum(nil), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// hexFile 计算文件的小写十六进制摘要,newHash 提供具体算法实例。
|
|
|
|
|
func hexFile(path string, newHash func() hash.Hash) (string, error) {
|
|
|
|
|
f, err := os.Open(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", fmt.Errorf("sha256x: 打开文件 %q 失败: %w", path, err)
|
|
|
|
|
}
|
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
|
|
sum, err := sumReader(newHash(), f)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", fmt.Errorf("sha256x: 计算文件 %q 摘要失败: %w", path, err)
|
|
|
|
|
}
|
|
|
|
|
return hex.EncodeToString(sum), nil
|
2023-12-27 19:00:14 +08:00
|
|
|
}
|