103 lines
3.6 KiB
Go
103 lines
3.6 KiB
Go
// Package ripemd160x 提供 RIPEMD-160 摘要计算,以及十六进制/Base64 编码与流式、文件接口。
|
|||
|
|
//
|
||
|
|
// # 安全警告
|
||
|
|
//
|
||
|
|
// RIPEMD-160 的输出只有 160 位,且已不再被视为现代安全强度的哈希:
|
||
|
|
// 它仅用于兼容旧系统(典型场景是 Bitcoin 等加密货币的 P2PKH 地址,
|
||
|
|
// 即 RIPEMD160(SHA256(pubkey))),不可用于口令存储、口令派生或数字签名。
|
||
|
|
// 其上游实现 golang.org/x/crypto/ripemd160 已被官方标记为废弃(deprecated)。
|
||
|
|
// 新代码请使用 sha256x、sha512x、sha3x 或 blake2x。
|
||
|
|
package ripemd160x
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/base64"
|
||
|
|
"encoding/hex"
|
||
|
|
"fmt"
|
||
|
|
"hash"
|
||
|
|
"io"
|
||
|
|
"os"
|
||
|
|
|
||
|
|
//lint:ignore SA1019 RIPEMD-160 已被上游标记为废弃;本包保留它只为兼容既有系统(如比特币地址),包注释已明确警告其不可用于新设计。
|
||
|
|
"golang.org/x/crypto/ripemd160"
|
||
|
|
)
|
||
|
|
|
||
|
|
const (
|
||
|
|
// Size 是 RIPEMD-160 摘要的字节数(20)。
|
||
|
|
Size = ripemd160.Size
|
||
|
|
// BlockSize 是 RIPEMD-160 分组的字节数(64)。
|
||
|
|
BlockSize = ripemd160.BlockSize
|
||
|
|
)
|
||
|
|
|
||
|
|
// New 返回一个计算 RIPEMD-160 摘要的 hash.Hash,可反复 Write 以流式处理数据。
|
||
|
|
//
|
||
|
|
// 安全警告:RIPEMD-160 仅用于兼容旧系统(如 Bitcoin 地址),不可用于口令或签名。
|
||
|
|
func New() hash.Hash {
|
||
|
|
return ripemd160.New()
|
||
|
|
}
|
||
|
|
|
||
|
|
// Sum 返回 data 的 RIPEMD-160 摘要(Size 字节原始数据)。
|
||
|
|
//
|
||
|
|
// 安全警告:RIPEMD-160 仅用于兼容旧系统(如 Bitcoin 地址),不可用于口令或签名。
|
||
|
|
func Sum(data []byte) []byte {
|
||
|
|
h := ripemd160.New()
|
||
|
|
_, _ = h.Write(data)
|
||
|
|
return h.Sum(nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Hex 返回 data 的 RIPEMD-160 摘要的小写十六进制字符串。
|
||
|
|
//
|
||
|
|
// 安全警告:RIPEMD-160 仅用于兼容旧系统(如 Bitcoin 地址),不可用于口令或签名。
|
||
|
|
func Hex(data []byte) string {
|
||
|
|
return hex.EncodeToString(Sum(data))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Base64 返回 data 的 RIPEMD-160 摘要的标准 Base64 字符串。
|
||
|
|
//
|
||
|
|
// 安全警告:RIPEMD-160 仅用于兼容旧系统(如 Bitcoin 地址),不可用于口令或签名。
|
||
|
|
func Base64(data []byte) string {
|
||
|
|
return base64.StdEncoding.EncodeToString(Sum(data))
|
||
|
|
}
|
||
|
|
|
||
|
|
// SumReader 读取 r 中的全部数据并返回其 RIPEMD-160 摘要;读取失败时返回包装后的 error。
|
||
|
|
//
|
||
|
|
// 安全警告:RIPEMD-160 仅用于兼容旧系统(如 Bitcoin 地址),不可用于口令或签名。
|
||
|
|
func SumReader(r io.Reader) ([]byte, error) {
|
||
|
|
if r == nil {
|
||
|
|
return nil, fmt.Errorf("ripemd160x: 读取器为 nil")
|
||
|
|
}
|
||
|
|
h := ripemd160.New()
|
||
|
|
if _, err := io.Copy(h, r); err != nil {
|
||
|
|
return nil, fmt.Errorf("ripemd160x: 读取数据失败: %w", err)
|
||
|
|
}
|
||
|
|
return h.Sum(nil), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// HexReader 读取 r 中的全部数据并返回其 RIPEMD-160 摘要的小写十六进制字符串。
|
||
|
|
//
|
||
|
|
// 安全警告:RIPEMD-160 仅用于兼容旧系统(如 Bitcoin 地址),不可用于口令或签名。
|
||
|
|
func HexReader(r io.Reader) (string, error) {
|
||
|
|
sum, err := SumReader(r)
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
return hex.EncodeToString(sum), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// HexFile 计算 path 所指向文件的 RIPEMD-160 摘要并返回小写十六进制字符串;
|
||
|
|
// 文件不存在或读取失败时返回包装后的 error,不 panic。
|
||
|
|
//
|
||
|
|
// 安全警告:RIPEMD-160 仅用于兼容旧系统(如 Bitcoin 地址),不可用于口令或签名。
|
||
|
|
func HexFile(path string) (string, error) {
|
||
|
|
f, err := os.Open(path)
|
||
|
|
if err != nil {
|
||
|
|
return "", fmt.Errorf("ripemd160x: 打开文件 %q 失败: %w", path, err)
|
||
|
|
}
|
||
|
|
defer f.Close()
|
||
|
|
|
||
|
|
sum, err := SumReader(f)
|
||
|
|
if err != nil {
|
||
|
|
return "", fmt.Errorf("ripemd160x: 计算文件 %q 摘要失败: %w", path, err)
|
||
|
|
}
|
||
|
|
return hex.EncodeToString(sum), nil
|
||
|
|
}
|