package ripemd160x_test import ( "bytes" "encoding/base64" "encoding/hex" "errors" "os" "path/filepath" "strings" "testing" "code.yun.ink/pkg/encryptx/ripemd160x" ) // 测试向量来源:RIPEMD-160 官方测试向量(Bosselaers/Preneel), // 与 golang.org/x/crypto/ripemd160 自带测试用例一致。 var vectors = []struct { name string input string want string }{ {"空串", "", "9c1185a5c5e9fc54612808977ee8f548b2258d31"}, {"a", "a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"}, {"abc", "abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"}, {"message digest", "message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"}, {"a-z", "abcdefghijklmnopqrstuvwxyz", "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"}, } type failingReader struct{} func (failingReader) Read([]byte) (int, error) { return 0, errors.New("模拟读取失败") } func TestConstants(t *testing.T) { if ripemd160x.Size != 20 { t.Fatalf("Size = %d, 期望 20", ripemd160x.Size) } if ripemd160x.BlockSize != 64 { t.Fatalf("BlockSize = %d, 期望 64", ripemd160x.BlockSize) } } func TestVectors(t *testing.T) { for _, v := range vectors { t.Run(v.name, func(t *testing.T) { data := []byte(v.input) sum := ripemd160x.Sum(data) if len(sum) != ripemd160x.Size { t.Fatalf("Sum 长度 = %d, 期望 %d", len(sum), ripemd160x.Size) } if got := hex.EncodeToString(sum); got != v.want { t.Errorf("Sum = %s, 期望 %s", got, v.want) } if got := ripemd160x.Hex(data); got != v.want { t.Errorf("Hex = %s, 期望 %s", got, v.want) } if want := base64.StdEncoding.EncodeToString(sum); ripemd160x.Base64(data) != want { t.Errorf("Base64 = %s, 期望 %s", ripemd160x.Base64(data), want) } h := ripemd160x.New() if _, err := h.Write(data); err != nil { t.Fatalf("Write 失败: %v", err) } if got := hex.EncodeToString(h.Sum(nil)); got != v.want { t.Errorf("New+Write = %s, 期望 %s", got, v.want) } }) } } func TestStreamingMatchesSum(t *testing.T) { data := []byte(strings.Repeat("encryptx-ripemd160-", 100)) h := ripemd160x.New() for i := 0; i < len(data); i += 19 { end := i + 19 if end > len(data) { end = len(data) } if _, err := h.Write(data[i:end]); err != nil { t.Fatalf("Write 失败: %v", err) } } if got, want := h.Sum(nil), ripemd160x.Sum(data); !bytes.Equal(got, want) { t.Errorf("分块写入 = %x, 期望 %x", got, want) } } func TestReaderConsistency(t *testing.T) { const s = "encryptx 一致性检查" sum, err := ripemd160x.SumReader(strings.NewReader(s)) if err != nil { t.Fatalf("SumReader 失败: %v", err) } if want := ripemd160x.Sum([]byte(s)); !bytes.Equal(sum, want) { t.Errorf("SumReader = %x, 期望 %x", sum, want) } hexStr, err := ripemd160x.HexReader(strings.NewReader(s)) if err != nil { t.Fatalf("HexReader 失败: %v", err) } if want := ripemd160x.Hex([]byte(s)); hexStr != want { t.Errorf("HexReader = %s, 期望 %s", hexStr, want) } } func TestReaderErrors(t *testing.T) { if _, err := ripemd160x.SumReader(nil); err == nil { t.Fatal("nil 读取器应返回 error") } if _, err := ripemd160x.HexReader(nil); err == nil { t.Fatal("nil 读取器应返回 error") } if _, err := ripemd160x.SumReader(failingReader{}); err == nil { t.Fatal("读取失败时应返回 error") } } func TestHexFile(t *testing.T) { dir := t.TempDir() content := []byte("文件内容 file content\n") path := filepath.Join(dir, "sample.bin") if err := os.WriteFile(path, content, 0o600); err != nil { t.Fatalf("写入测试文件失败: %v", err) } got, err := ripemd160x.HexFile(path) if err != nil { t.Fatalf("HexFile 失败: %v", err) } if want := ripemd160x.Hex(content); got != want { t.Errorf("HexFile = %s, 期望 %s", got, want) } } func TestHexFileErrors(t *testing.T) { if _, err := ripemd160x.HexFile(filepath.Join(t.TempDir(), "不存在.bin")); err == nil { t.Fatal("不存在的文件应返回 error") } if _, err := ripemd160x.HexFile(""); err == nil { t.Fatal("空路径应返回 error") } if _, err := ripemd160x.HexFile(t.TempDir()); err == nil { t.Fatal("目录路径应返回 error") } } func TestLargeInput(t *testing.T) { data := largeData(1 << 20) want := ripemd160x.Hex(data) if got := ripemd160x.Hex(data); got != want { t.Errorf("重复计算结果不一致: %s vs %s", got, want) } got, err := ripemd160x.HexReader(bytes.NewReader(data)) if err != nil { t.Fatalf("HexReader 失败: %v", err) } if got != want { t.Errorf("HexReader = %s, 期望 %s", got, want) } h := ripemd160x.New() if _, err := h.Write(data[:1<<19]); err != nil { t.Fatalf("Write 失败: %v", err) } if _, err := h.Write(data[1<<19:]); err != nil { t.Fatalf("Write 失败: %v", err) } if got := hex.EncodeToString(h.Sum(nil)); got != want { t.Errorf("1MiB 分块 = %s, 期望 %s", got, want) } } // largeData 生成确定性的 n 字节数据。 func largeData(n int) []byte { b := make([]byte, n) for i := range b { b[i] = byte(i*31 + i/7) } return b }