refactor: 抽取symm通用加解密分发并统一hashx未知算法错误语义

This commit is contained in:
2026-03-18 14:32:55 +08:00
parent 4fa79744e8
commit 8d0f32015c
7 changed files with 341 additions and 564 deletions
+47 -64
View File
@@ -8,6 +8,7 @@ import (
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"hash"
"hash/crc32"
"io"
@@ -146,6 +147,27 @@ func Crc32AStr(data []byte) string {
return hex.EncodeToString(crc32aDigest(data))
}
func buildHasher(method string) (hash.Hash, hash.Hash32, error) {
switch method {
case "md5":
return md5.New(), nil, nil
case "sha1":
return sha1.New(), nil, nil
case "sha224":
return sha256.New224(), nil, nil
case "sha256":
return sha256.New(), nil, nil
case "sha384":
return sha512.New384(), nil, nil
case "sha512":
return sha512.New(), nil, nil
case "crc32":
return nil, crc32.NewIEEE(), nil
default:
return nil, nil, fmt.Errorf("%w: %s", ErrUnsupportedMethod, method)
}
}
func SumAll(data []byte, methods []string) (map[string][]byte, error) {
if len(methods) == 0 {
methods = []string{"sha512", "sha256", "sha384", "sha224", "sha1", "crc32", "md5"}
@@ -156,25 +178,15 @@ func SumAll(data []byte, methods []string) (map[string][]byte, error) {
var crc hash.Hash32
for _, method := range methods {
switch method {
case "md5":
hashers[method] = md5.New()
case "sha1":
hashers[method] = sha1.New()
case "sha224":
hashers[method] = sha256.New224()
case "sha256":
hashers[method] = sha256.New()
case "sha384":
hashers[method] = sha512.New384()
case "sha512":
hashers[method] = sha512.New()
case "crc32":
if crc == nil {
crc = crc32.NewIEEE()
}
default:
// Keep compatibility with previous behavior: unknown methods are ignored.
h, h32, err := buildHasher(method)
if err != nil {
return nil, err
}
if h != nil {
hashers[method] = h
}
if h32 != nil && crc == nil {
crc = h32
}
}
@@ -206,40 +218,22 @@ func FileSum(filePath, method string, progress func(float64)) (string, error) {
return "", err
}
h, h32, err := buildHasher(method)
if err != nil {
return "", err
}
var (
h hash.Hash
h32 hash.Hash32
is32 bool
total int64
size = stat.Size()
)
switch method {
case "sha512":
h = sha512.New()
case "sha384":
h = sha512.New384()
case "sha256":
h = sha256.New()
case "sha224":
h = sha256.New224()
case "sha1":
h = sha1.New()
case "md5":
h = md5.New()
case "crc32":
h32 = crc32.NewIEEE()
is32 = true
default:
return "", errors.New(ErrUnsupportedMethod.Error() + ": " + method)
}
buf := make([]byte, 1024*1024)
for {
n, readErr := fp.Read(buf)
if n > 0 {
total += int64(n)
if is32 {
if h32 != nil {
_, _ = h32.Write(buf[:n])
} else {
_, _ = h.Write(buf[:n])
@@ -254,7 +248,7 @@ func FileSum(filePath, method string, progress func(float64)) (string, error) {
}
}
if is32 {
if h32 != nil {
return hex.EncodeToString(h32.Sum(nil)), nil
}
return hex.EncodeToString(h.Sum(nil)), nil
@@ -279,25 +273,15 @@ func FileSumAll(filePath string, methods []string, progress func(float64)) (map[
hashers := make(map[string]hash.Hash, len(methods))
var crc hash.Hash32
for _, method := range methods {
switch method {
case "md5":
hashers[method] = md5.New()
case "sha1":
hashers[method] = sha1.New()
case "sha224":
hashers[method] = sha256.New224()
case "sha256":
hashers[method] = sha256.New()
case "sha384":
hashers[method] = sha512.New384()
case "sha512":
hashers[method] = sha512.New()
case "crc32":
if crc == nil {
crc = crc32.NewIEEE()
}
default:
// Keep compatibility with previous behavior: unknown methods are ignored.
h, h32, err := buildHasher(method)
if err != nil {
return nil, err
}
if h != nil {
hashers[method] = h
}
if h32 != nil && crc == nil {
crc = h32
}
}
@@ -335,7 +319,6 @@ func FileSumAll(filePath string, methods []string, progress func(float64)) (map[
}
return result, nil
}
func reportProgress(progress func(float64), current, total int64) {
if progress == nil {
return
+17 -14
View File
@@ -29,16 +29,10 @@ func TestSM3AndCRC32A(t *testing.T) {
}
}
func TestSumAllUnknownMethodIgnored(t *testing.T) {
res, err := SumAll([]byte("abc"), []string{"sha1", "unknown"})
if err != nil {
t.Fatalf("SumAll returned error: %v", err)
}
if _, ok := res["sha1"]; !ok {
t.Fatalf("expected sha1 in result")
}
if _, ok := res["unknown"]; ok {
t.Fatalf("unknown method should be ignored")
func TestSumAllUnsupportedMethod(t *testing.T) {
_, err := SumAll([]byte("abc"), []string{"sha1", "unknown"})
if err == nil {
t.Fatalf("expected unsupported method error")
}
}
@@ -63,7 +57,7 @@ func TestFileSumAndFileSumAll(t *testing.T) {
t.Fatalf("progress callback should be called")
}
all, err := FileSumAll(path, []string{"sha1", "crc32", "unknown"}, nil)
all, err := FileSumAll(path, []string{"sha1", "crc32"}, nil)
if err != nil {
t.Fatalf("FileSumAll failed: %v", err)
}
@@ -73,9 +67,6 @@ func TestFileSumAndFileSumAll(t *testing.T) {
if _, ok := all["crc32"]; !ok {
t.Fatalf("expected crc32 in FileSumAll")
}
if _, ok := all["unknown"]; ok {
t.Fatalf("unknown method should not appear")
}
}
func TestFileSumUnsupportedMethod(t *testing.T) {
@@ -88,6 +79,18 @@ func TestFileSumUnsupportedMethod(t *testing.T) {
t.Fatalf("expected unsupported method error")
}
}
func TestFileSumAllUnsupportedMethod(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "sum.txt")
if err := os.WriteFile(path, []byte("x"), 0o644); err != nil {
t.Fatalf("WriteFile failed: %v", err)
}
if _, err := FileSumAll(path, []string{"sha256", "not-support"}, nil); err == nil {
t.Fatalf("expected unsupported method error")
}
}
func TestPBKDF2SHA256Vector(t *testing.T) {
got, err := DerivePBKDF2SHA256Key("password", []byte("salt"), 1, 32)
if err != nil {