From 29cebf455c791966817c5c91871a37e5c4719aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Wed, 12 Jul 2023 14:59:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(hash):=E5=A2=9E=E5=8A=A0=E7=B3=BB=E5=88=97?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=92=8C=E7=AE=97=E6=B3=95=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++--- go.mod | 2 + go.sum | 4 ++ hash/crc16/crc16.go | 66 +++++++++++++++++++++++++++++ hash/crc32/crc32.go | 61 +++++++++++++++++++++++++++ hash/crc64/crc64.go | 59 ++++++++++++++++++++++++++ hash/crc8/crc8.go | 73 ++++++++++++++++++++++++++++++++ hash/md5/md5.go | 45 ++++++++++++++++++++ hash/sha1/sha1.go | 45 ++++++++++++++++++++ hash/sha256/sha256.go | 81 +++++++++++++++++++++++++++++++++++ hash/sha512/sha512.go | 98 +++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 543 insertions(+), 5 deletions(-) create mode 100644 hash/crc16/crc16.go create mode 100644 hash/crc32/crc32.go create mode 100644 hash/crc64/crc64.go create mode 100644 hash/crc8/crc8.go create mode 100644 hash/md5/md5.go create mode 100644 hash/sha1/sha1.go create mode 100644 hash/sha256/sha256.go create mode 100644 hash/sha512/sha512.go diff --git a/README.md b/README.md index 485da96..94c883d 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,15 @@ Golang 中可以使用的常用辅助功能工具箱。主要配备以下功能 - [ ] 2048 位长 - [ ] KeyPair 生成器 - [ ] RSA 签名算法 -- 散列算法。 - - [ ] Sha512 散列算法 - - [ ] Sha256 散列算法 - - [ ] Sha1 散列算法 - - [ ] MD5 散列算法 +- 散列及校验和算法。 + - [x] Sha512 散列算法 + - [x] Sha256 散列算法 + - [x] Sha1 散列算法 + - [x] MD5 散列算法 + - [x] CRC8 校验和算法 + - [x] CRC16 校验和算法 + - [x] CRC32 校验和算法 + - [x] CRC64 校验和算法 - [ ] 图像感知散列算法 - 唯一序列号生成器 - [ ] 冰雹 ID 生成器(短主机精简日期版雪花 ID) diff --git a/go.mod b/go.mod index df1815a..728de1b 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.20 require go.uber.org/zap v1.24.0 require ( + github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6 + github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index 3cb5c63..e9fc0b0 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6 h1:IIVxLyDUYErC950b8kecjoqDet8P5S4lcVRUOM6rdkU= +github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6/go.mod h1:JslaLRrzGsOKJgFEPBP65Whn+rdwDQSk0I0MCRFe2Zw= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f h1:1R9KdKjCNSd7F8iGTxIpoID9prlYH8nuNYKt0XvweHA= +github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f/go.mod h1:vQhwQ4meQEDfahT5kd61wLAF5AAeh5ZPLVI4JJ/tYo8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= diff --git a/hash/crc16/crc16.go b/hash/crc16/crc16.go new file mode 100644 index 0000000..b2bbe32 --- /dev/null +++ b/hash/crc16/crc16.go @@ -0,0 +1,66 @@ +// 提供CRC16校验和计算功能。 +package crc16 + +import ( + "encoding/hex" + "io" + "os" + + "github.com/howeyc/crc16" +) + +// 根据给定的校验表类型生成对应的校验器 +func hasherSelect(table string) crc16.Hash16 { + switch table { + case "CCITT": + return crc16.NewCCITT() + case "CCITT-FALSE": + return crc16.New(crc16.MakeTable(crc16.CCITTFalse)) + case "SCSI": + return crc16.NewSCSI() + case "IBM": + return crc16.NewIBM() + case "MBUS": + return crc16.New(crc16.MakeTable(crc16.MBUS)) + default: + return crc16.NewIBM() + } +} + +// 计算给定字节数组的CRC16校验和,返回字节数组 +func CRC16(data []byte, table ...string) []byte { + crcTable := append(table, "IBM") + hasher := hasherSelect(crcTable[0]) + hasher.Write(data) + return hasher.Sum(nil) +} + +// 计算给定字节数组的CRC16校验和,返回十六进制字符串 +func CRC16Hex(data []byte, table ...string) string { + return hex.EncodeToString(CRC16(data, table...)) +} + +// 计算指定文件的CRC16校验和,返回字节数组 +func SumFile(file string, table ...string) ([]byte, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + + crcTable := append(table, "IBM") + hasher := hasherSelect(crcTable[0]) + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// 计算指定文件的CRC16校验和,返回十六进制字符串 +func SumFileHex(file string, table ...string) (string, error) { + hash, err := SumFile(file, table...) + if err != nil { + return "", err + } + return hex.EncodeToString(hash), nil +} diff --git a/hash/crc32/crc32.go b/hash/crc32/crc32.go new file mode 100644 index 0000000..fc405de --- /dev/null +++ b/hash/crc32/crc32.go @@ -0,0 +1,61 @@ +// 提供CRC32校验和计算功能 +package crc32 + +import ( + "encoding/hex" + "hash/crc32" + "io" + "os" +) + +// 选择一个CRC32校验表 +func tableSelect(table string) *crc32.Table { + switch table { + case "IEEE": + return crc32.IEEETable + case "Castagnoli": + return crc32.MakeTable(crc32.Castagnoli) + case "Koopman": + return crc32.MakeTable(crc32.Koopman) + default: + return crc32.IEEETable + } +} + +// 计算给定字节数组的CRC32校验和,返回字节数组 +func CRC32(data []byte, table ...string) []byte { + crcTable := append(table, "IEEE") + hasher := crc32.New(tableSelect(crcTable[0])) + hasher.Write(data) + return hasher.Sum(nil) +} + +// 计算给定字节数组的CRC32校验和,返回十六进制字符串 +func CRC32Hex(data []byte, table ...string) string { + return hex.EncodeToString(CRC32(data, table...)) +} + +// 计算指定文件的CRC32校验和,返回字节数组 +func SumFile(file string, table ...string) ([]byte, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + + crcTable := append(table, "IEEE") + hasher := crc32.New(tableSelect(crcTable[0])) + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// 计算指定文件的CRC32校验和,返回十六进制字符串 +func SumFileHex(file string, table ...string) (string, error) { + hash, err := SumFile(file, table...) + if err != nil { + return "", err + } + return hex.EncodeToString(hash), nil +} diff --git a/hash/crc64/crc64.go b/hash/crc64/crc64.go new file mode 100644 index 0000000..19a9f7e --- /dev/null +++ b/hash/crc64/crc64.go @@ -0,0 +1,59 @@ +// 提供CRC64校验和计算功能。 +package crc64 + +import ( + "encoding/hex" + "hash/crc64" + "io" + "os" +) + +// 选择一个CRC64校验表。 +func tableSelect(table string) *crc64.Table { + switch table { + case "ECMA": + return crc64.MakeTable(crc64.ECMA) + case "ISO": + return crc64.MakeTable(crc64.ISO) + default: + return crc64.MakeTable(crc64.ISO) + } +} + +// 计算给定字节数组的CRC64校验和,返回字节数组。 +func CRC64(data []byte, table ...string) []byte { + crcTable := append(table, "ISO") + hasher := crc64.New(tableSelect(crcTable[0])) + hasher.Write(data) + return hasher.Sum(nil) +} + +// 计算给定字节数组的CRC64校验和,返回十六进制字符串。 +func CRC64Hex(data []byte, table ...string) string { + return hex.EncodeToString(CRC64(data, table...)) +} + +// 计算一个指定文件的CRC64校验和,返回字节数组。 +func SumFile(file string, table ...string) ([]byte, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + + crcTable := append(table, "ISO") + hasher := crc64.New(tableSelect(crcTable[0])) + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// 计算一个指定文件的CRC64校验和,返回十六进制字符串。 +func SumFileHex(file string, table ...string) (string, error) { + hash, err := SumFile(file, table...) + if err != nil { + return "", err + } + return hex.EncodeToString(hash), nil +} diff --git a/hash/crc8/crc8.go b/hash/crc8/crc8.go new file mode 100644 index 0000000..57b46ab --- /dev/null +++ b/hash/crc8/crc8.go @@ -0,0 +1,73 @@ +// 提供CRC8校验和计算功能。 +package crc8 + +import ( + "encoding/hex" + "os" + + "github.com/sigurn/crc8" +) + +// 根据提供的校验表名称生成对应的校验表 +func hasherSelect(table string) *crc8.Table { + switch table { + case "CRC8": + return crc8.MakeTable(crc8.CRC8) + case "CDMA2000": + return crc8.MakeTable(crc8.CRC8_CDMA2000) + case "DARC": + return crc8.MakeTable(crc8.CRC8_DARC) + case "DVB-S2": + return crc8.MakeTable(crc8.CRC8_DVB_S2) + case "EBU": + return crc8.MakeTable(crc8.CRC8_EBU) + case "I-CODE": + return crc8.MakeTable(crc8.CRC8_I_CODE) + case "ITU": + return crc8.MakeTable(crc8.CRC8_ITU) + case "MAXIM": + return crc8.MakeTable(crc8.CRC8_MAXIM) + case "ROHC": + return crc8.MakeTable(crc8.CRC8_ROHC) + case "WCDMA": + return crc8.MakeTable(crc8.CRC8_WCDMA) + default: + return crc8.MakeTable(crc8.CRC8) + } +} + +// 计算给定字节数组的CRC8校验和,返回字节数组 +func CRC8(data []byte, table ...string) []byte { + crcTable := append(table, "CRC8") + return []byte{crc8.Checksum(data, hasherSelect(crcTable[0]))} +} + +// 计算给定字节数组的CRC8校验和,返回十六进制字符串 +func CRC8Hex(data []byte, table ...string) string { + return hex.EncodeToString(CRC8(data, table...)) +} + +// 计算指定文件的CRC8校验和,返回字节数组 +func SumFile(file string, table ...string) ([]byte, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + + crcTable := append(table, "CRC8") + var buf = make([]byte, 0) + if _, err := f.Read(buf); err != nil { + return nil, err + } + return []byte{crc8.Checksum(buf, hasherSelect(crcTable[0]))}, nil +} + +// 计算指定文件的CRC8校验和,返回十六进制字符串 +func SumFileHex(file string, table ...string) (string, error) { + crc, err := SumFile(file, table...) + if err != nil { + return "", err + } + return hex.EncodeToString(crc), nil +} diff --git a/hash/md5/md5.go b/hash/md5/md5.go new file mode 100644 index 0000000..3e39a70 --- /dev/null +++ b/hash/md5/md5.go @@ -0,0 +1,45 @@ +// 提供MD5散列算法的函数。 +package md5 + +import ( + "crypto/md5" + "encoding/hex" + "io" + "os" +) + +// 计算给定字节数组的MD5校验和,返回字节数组。 +func MD5(data []byte) []byte { + hasher := md5.New() + hasher.Write(data) + return hasher.Sum(nil) +} + +// 计算给定字节数组的MD5校验和,返回十六进制字符串。 +func MD5Hex(data []byte) string { + return hex.EncodeToString(MD5(data)) +} + +// 计算一个指定文件的MD5校验和,返回字节数组。 +func SumFile(file string) ([]byte, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + + hasher := md5.New() + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// 计算一个指定文件的MD5校验和,返回十六进制字符串。 +func SumFileHex(file string) (string, error) { + hash, err := SumFile(file) + if err != nil { + return "", err + } + return hex.EncodeToString(hash), nil +} diff --git a/hash/sha1/sha1.go b/hash/sha1/sha1.go new file mode 100644 index 0000000..88ae85e --- /dev/null +++ b/hash/sha1/sha1.go @@ -0,0 +1,45 @@ +// 提供Sha1系列散列算法函数和校验和函数 +package sha1 + +import ( + "crypto/sha1" + "encoding/hex" + "io" + "os" +) + +// 计算给定字节数组的Sha1校验和,返回字节数组 +func Sha1(data []byte) []byte { + hasher := sha1.New() + hasher.Write(data) + return hasher.Sum(nil) +} + +// 计算给定字节数组的Sha1校验和,返回十六进制字符串 +func Sha1Hex(data []byte) string { + return hex.EncodeToString(Sha1(data)) +} + +// 计算一个指定文件的Sha1校验和,返回字节数组 +func SumFile(file string) ([]byte, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + + hasher := sha1.New() + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// 计算一个指定文件的Sha1校验和,返回十六进制字符串 +func SumFileHex(file string) (string, error) { + hash, err := SumFile(file) + if err != nil { + return "", err + } + return hex.EncodeToString(hash), nil +} diff --git a/hash/sha256/sha256.go b/hash/sha256/sha256.go new file mode 100644 index 0000000..7ca96a1 --- /dev/null +++ b/hash/sha256/sha256.go @@ -0,0 +1,81 @@ +// 提供Sha256系列散列算法函数和校验和函数。 +package sha256 + +import ( + "crypto/sha256" + "encoding/hex" + "hash" + "io" + "os" +) + +// 根据给定的位数返回一个散列算法的Hash实例。 +func hasherSelect(bitSize int) hash.Hash { + switch bitSize { + case 224: + return sha256.New224() + default: + return sha256.New() + } +} + +// 计算给定字节数组的Sha256校验和,返回字节数组。 +func Sha256(data []byte) []byte { + hasher := hasherSelect(256) + hasher.Write(data) + return hasher.Sum(nil) +} + +// 计算给定字节数组的Sha256/224校验和,返回字节数组。 +func Sha256_224(data []byte) []byte { + hasher := hasherSelect(224) + hasher.Write(data) + return hasher.Sum(nil) +} + +// 计算给定字节数组的Sha256校验和,返回十六进制字符串。 +func Sha256Hex(data []byte) string { + return hex.EncodeToString(Sha256(data)) +} + +// 计算给定字节数组的Sha256/224校验和,返回十六进制字符串。 +func Sha256_224Hex(data []byte) string { + return hex.EncodeToString(Sha256_224(data)) +} + +// 根据给定位数计算一个字节数组的Sha256校验和,返回字节数组。 +func Sum256(data []byte, bitSize ...int) []byte { + length := append(bitSize, 256) + hasher := hasherSelect(length[0]) + hasher.Write(data) + return hasher.Sum(nil) +} + +// 根据给定位数计算一个字节数组的Sha256校验和,返回十六进制字符串。 +func Sum256Hex(data []byte, bitSize ...int) string { + return hex.EncodeToString(Sum256(data, bitSize...)) +} + +// 根据给定位数计算一个文件的Sha256校验和,返回字节数组。 +func SumFile256(file string, bitSize ...int) ([]byte, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + + hasher := hasherSelect(bitSize[0]) + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// 根据给定位数计算一个文件的Sha256校验和,返回十六进制字符串。 +func SumFile256Hex(file string, bitSize ...int) (string, error) { + hash, err := SumFile256(file, bitSize...) + if err != nil { + return "", err + } + return hex.EncodeToString(hash), nil +} diff --git a/hash/sha512/sha512.go b/hash/sha512/sha512.go new file mode 100644 index 0000000..0fe7395 --- /dev/null +++ b/hash/sha512/sha512.go @@ -0,0 +1,98 @@ +// 提供Sha512系列散列算法函数和校验和函数。 +package sha512 + +import ( + "crypto/sha512" + "encoding/hex" + "hash" + "io" + "os" +) + +// 根据给定的位数返回一个散列算法的Hash实例。 +func hasherSelect(bitSize int) hash.Hash { + switch bitSize { + case 224: + return sha512.New512_224() + case 256: + return sha512.New512_256() + case 384: + return sha512.New384() + default: + return sha512.New() + } +} + +// 计算给定字节数组的Sha512校验和,返回字节数组。 +func Sha512(data []byte) []byte { + hash := hasherSelect(512) + hash.Write(data) + return hash.Sum(nil) +} + +// 计算给定字节数组的Sha512/384校验和,返回字节数组。 +func Sha512_384(data []byte) []byte { + hash := hasherSelect(384) + hash.Write(data) + return hash.Sum(nil) +} + +// 计算给定字节数组的Sha512/256校验和,返回字节数组。 +func Sha512_256(data []byte) []byte { + hash := hasherSelect(256) + hash.Write(data) + return hash.Sum(nil) +} + +// 计算给定字节数组的Sha512校验和,返回十六进制字符串。 +func Sha512Hex(data []byte) string { + return hex.EncodeToString(Sha512(data)) +} + +// 计算给定字节数组的Sha512/384校验和,返回十六进制字符串。 +func Sha512_384Hex(data []byte) string { + return hex.EncodeToString(Sha512_384(data)) +} + +// 计算给定字节数组的Sha512/256校验和,返回十六进制字符串。 +func Sha512_256Hex(data []byte) string { + return hex.EncodeToString(Sha512_256(data)) +} + +// 根据给定位数计算指定字节数组的校验和,返回字节数组。 +func Sum512(data []byte, bitSize ...int) []byte { + length := append(bitSize, 512) + var hasher = hasherSelect(length[0]) + hasher.Write(data) + return hasher.Sum(nil) +} + +// 根据给定位数计算指定字节数组的校验和,返回十六进制字符串。 +func Sum512Hex(data []byte, bitSize ...int) string { + return hex.EncodeToString(Sum512(data, bitSize...)) +} + +// 根据给定位数计算指定文件的校验和,返回字节数组。 +func SumFile512(path string, bitSize ...int) ([]byte, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + length := append(bitSize, 512) + var hasher = hasherSelect(length[0]) + if _, err := io.Copy(hasher, f); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +// 根据给定位数计算指定文件的校验和,返回十六进制字符串。 +func SumFile512Hex(path string, bitSize ...int) (string, error) { + data, err := SumFile512(path, bitSize...) + if err != nil { + return "", err + } + return hex.EncodeToString(data), nil +}