-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
hash.go
131 lines (110 loc) · 2.85 KB
/
hash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package utils
import (
"bytes"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"hash"
"io"
"os"
"github.com/Laisky/errors/v2"
"github.com/cespare/xxhash"
"github.com/Laisky/go-utils/v4/log"
)
// HashSHA128String calculate string's hash by sha256
//
// Deprecated: use Hash instead
func HashSHA128String(val string) string {
b := sha1.Sum([]byte(val))
return hex.EncodeToString(b[:])
}
// HashSHA256String calculate string's hash by sha256
//
// Deprecated: use Hash instead
func HashSHA256String(val string) string {
b := sha256.Sum256([]byte(val))
return hex.EncodeToString(b[:])
}
// HashXxhashString calculate string's hash by sha256
//
// Deprecated: use Hash instead
func HashXxhashString(val string) string {
b := xxhash.New().Sum([]byte(val))
return hex.EncodeToString(b)
}
// HashTypeInterface hashs
type HashTypeInterface interface {
String() string
Hasher() (hash.Hash, error)
}
// HashType hashs
type HashType string
// String name of hash
func (h HashType) String() string {
return string(h)
}
// Hasher new hasher by hash type
func (h HashType) Hasher() (hash.Hash, error) {
switch h {
case HashTypeMD5:
log.Shared.Warn("md5 is not safe or fast, use sha256 instead")
return md5.New(), nil
case HashTypeSha1:
return sha1.New(), nil
case HashTypeSha256:
return sha256.New(), nil
case HashTypeSha512:
return sha512.New(), nil
case HashTypeXxhash:
return xxhash.New(), nil
}
return nil, errors.Errorf("unknon hasher %q", h.String())
}
const (
// HashTypeMD5 MD5
HashTypeMD5 HashType = "md5"
// HashTypeSha1 Sha1
HashTypeSha1 HashType = "sha1"
// HashTypeSha256 Sha256
HashTypeSha256 HashType = "sha256"
// HashTypeSha512 Sha512
HashTypeSha512 HashType = "sha512"
// HashTypeXxhash Xxhash
HashTypeXxhash HashType = "xxhash"
)
// Hash generate signature by hash
func Hash(hashType HashTypeInterface, content io.Reader) (signature []byte, err error) {
hasher, err := hashType.Hasher()
if err != nil {
return nil, errors.Wrap(err, "get hasher")
}
if _, err = io.Copy(hasher, content); err != nil {
return nil, errors.Wrap(err, "read from content")
}
return hasher.Sum(nil), nil
}
// FileHash generate file signature by hash
func FileHash(hashType HashTypeInterface, filepath string) (signature []byte, err error) {
fp, err := os.Open(filepath)
if err != nil {
return nil, errors.Wrap(err, "open file")
}
defer LogErr(fp.Close, log.Shared)
return Hash(hashType, fp)
}
// HashVerify verify by hash
func HashVerify(hashType HashTypeInterface, content io.Reader, signature []byte) (err error) {
hasher, err := hashType.Hasher()
if err != nil {
return errors.Wrap(err, "get hasher")
}
if _, err = io.Copy(hasher, content); err != nil {
return errors.Wrap(err, "read from content")
}
if !bytes.Equal(hasher.Sum(nil), signature) {
return errors.Errorf("signature not match")
}
return nil
}