/
xcrypto.go
296 lines (248 loc) · 8.11 KB
/
xcrypto.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
package xcrypto
import (
"bytes"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/base32"
"encoding/base64"
"encoding/hex"
"github.com/Aoi-hosizora/ahlib/xstring"
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/md4"
"golang.org/x/crypto/sha3"
"hash"
"hash/adler32"
"hash/crc32"
"hash/fnv"
)
// ====
// hash
// ====
// FNV32 uses fnv32 to hash string to uint32.
func FNV32(text string) uint32 {
algorithm := fnv.New32() // hash/fnv
return Uint32Hasher(algorithm, text)
}
// FNV32a uses fnv32a to hash string to uint32.
func FNV32a(text string) uint32 {
algorithm := fnv.New32a() // hash/fnv
return Uint32Hasher(algorithm, text)
}
// FNV64 uses fnv64 to hash string to uint64.
func FNV64(text string) uint64 {
algorithm := fnv.New64() // hash/fnv
return Uint64Hasher(algorithm, text)
}
// FNV64a uses fnv64a to hash string to uint64.
func FNV64a(text string) uint64 {
algorithm := fnv.New64a() // hash/fnv
return Uint64Hasher(algorithm, text)
}
// CRC32 uses crc32 to hash string to uint32.
func CRC32(text string) uint32 {
algorithm := crc32.NewIEEE() // hash/crc32
return Uint32Hasher(algorithm, text)
}
// ADLER32 uses adler32 to hash string to uint32.
func ADLER32(text string) uint32 {
algorithm := adler32.New() // hash/adler32
return Uint32Hasher(algorithm, text)
}
// Reference: https://crypto.stackexchange.com/questions/68307/what-is-the-difference-between-sha-3-and-sha-256
// MD4 uses md4 to hash string.
func MD4(text string) string {
algorithm := md4.New() // x/crypto/md4
return StringHasher(algorithm, text)
}
// MD5 uses md5 to hash string.
func MD5(text string) string {
algorithm := md5.New() // crypto/md5
return StringHasher(algorithm, text)
}
// SHA1 uses sha-1 to hash string.
func SHA1(text string) string {
algorithm := sha1.New() // crypto/sha1
return StringHasher(algorithm, text)
}
// SHA224 uses sha2-224 to hash string.
func SHA224(text string) string {
algorithm := sha256.New224() // crypto/sha256
return StringHasher(algorithm, text)
}
// SHA256 uses sha2-256 to hash string.
func SHA256(text string) string {
algorithm := sha256.New() // crypto/sha256
return StringHasher(algorithm, text)
}
// SHA384 uses sha2-384 to hash string.
func SHA384(text string) string {
algorithm := sha512.New384() // crypto/sha512
return StringHasher(algorithm, text)
}
// SHA512 uses sha2-512 to hash string.
func SHA512(text string) string {
algorithm := sha512.New() // crypto/sha512
return StringHasher(algorithm, text)
}
// SHA512_224 uses sha2-512/224 to hash string.
func SHA512_224(text string) string {
algorithm := sha512.New512_224() // crypto/sha512
return StringHasher(algorithm, text)
}
// SHA512_256 uses sha2-512/256 to hash string.
func SHA512_256(text string) string {
algorithm := sha512.New512_256() // crypto/sha512
return StringHasher(algorithm, text)
}
// SHA3_224 uses sha3-224 to hash string.
func SHA3_224(text string) string {
algorithm := sha3.New224() // x/crypto/sha3
return StringHasher(algorithm, text)
}
// SHA3_256 uses sha3-256 to hash string.
func SHA3_256(text string) string {
algorithm := sha3.New256() // x/crypto/sha3
return StringHasher(algorithm, text)
}
// SHA3_384 uses sha3-384 to hash string.
func SHA3_384(text string) string {
algorithm := sha3.New384() // x/crypto/sha3
return StringHasher(algorithm, text)
}
// SHA3_512 uses sha3-512 to hash string.
func SHA3_512(text string) string {
algorithm := sha3.New512() // x/crypto/sha3
return StringHasher(algorithm, text)
}
// Uint32Hasher uses hash.Hash32 to encode string to uint32.
func Uint32Hasher(algorithm hash.Hash32, text string) uint32 {
_, _ = algorithm.Write(xstring.FastStob(text))
return algorithm.Sum32()
}
// Uint64Hasher uses hash.Hash64 to encode string to uint64.
func Uint64Hasher(algorithm hash.Hash64, text string) uint64 {
_, _ = algorithm.Write(xstring.FastStob(text))
return algorithm.Sum64()
}
// StringHasher uses hash.Hash to encode string to string.
func StringHasher(algorithm hash.Hash, text string) string {
_, _ = algorithm.Write(xstring.FastStob(text))
return HexEncodeToString(algorithm.Sum(nil))
}
// ===============
// encode & decode
// ===============
// HexEncodeToBytes encodes bytes to hex bytes.
func HexEncodeToBytes(data []byte) []byte {
dst := make([]byte, hex.EncodedLen(len(data))) // encoding/hex
hex.Encode(dst, data)
return dst
}
// HexEncodeToString encodes bytes to hex string.
func HexEncodeToString(data []byte) string {
return xstring.FastBtos(HexEncodeToBytes(data))
}
// HexDecodeFromBytes decodes bytes from hex bytes.
func HexDecodeFromBytes(data []byte) ([]byte, error) {
buf := make([]byte, hex.DecodedLen(len(data))) // encoding/hex
n, err := hex.Decode(buf, data)
return buf[:n], err
}
// HexDecodeFromString decodes bytes from hex string.
func HexDecodeFromString(data string) ([]byte, error) {
return HexDecodeFromBytes(xstring.FastStob(data))
}
// Base32EncodeToBytes encodes bytes to base32 bytes.
func Base32EncodeToBytes(data []byte) []byte {
enc := base32.StdEncoding // encoding/base32
buf := make([]byte, enc.EncodedLen(len(data)))
enc.Encode(buf, data)
return buf
}
// Base32EncodeToString encodes bytes to base32 string.
func Base32EncodeToString(data []byte) string {
return xstring.FastBtos(Base32EncodeToBytes(data))
}
// Base32DecodeFromBytes decodes bytes from base32 bytes.
func Base32DecodeFromBytes(data []byte) ([]byte, error) {
enc := base32.StdEncoding // encoding/base32
buf := make([]byte, enc.DecodedLen(len(data)))
n, err := enc.Decode(buf, data)
return buf[:n], err
}
// Base32DecodeFromString decodes bytes from base32 string.
func Base32DecodeFromString(data string) ([]byte, error) {
return Base32DecodeFromBytes(xstring.FastStob(data))
}
// Base64EncodeToBytes encodes bytes to base64 bytes.
func Base64EncodeToBytes(data []byte) []byte {
enc := base64.StdEncoding // encoding/base64
buf := make([]byte, enc.EncodedLen(len(data)))
enc.Encode(buf, data)
return buf
}
// Base64EncodeToString encodes bytes to base64 string.
func Base64EncodeToString(data []byte) string {
return xstring.FastBtos(Base64EncodeToBytes(data))
}
// Base64DecodeFromBytes decodes bytes from base64 bytes.
func Base64DecodeFromBytes(data []byte) ([]byte, error) {
enc := base64.StdEncoding // encoding/base64
buf := make([]byte, enc.DecodedLen(len(data)))
n, err := enc.Decode(buf, data)
return buf[:n], err
}
// Base64DecodeFromString decodes bytes from base64 string.
func Base64DecodeFromString(data string) ([]byte, error) {
return Base64DecodeFromBytes(xstring.FastStob(data))
}
// ====
// pkcs
// ====
const (
panicBlockSize = "xcrypto: blockSize must larger then 0"
)
// PKCS5Padding uses PKCS#5 and PKCS#7 to pad data to block aligned bytes.
func PKCS5Padding(data []byte, blockSize int) []byte {
if blockSize <= 0 {
panic(panicBlockSize)
}
padLen := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padLen)}, padLen)
return append(data, padText...)
}
// PKCS5Padding uses PKCS#5 and PKCS#7 to trim data from block aligned bytes.
func PKCS5Trimming(data []byte) []byte {
length := len(data)
padLen := int(data[length-1])
return data[:length-padLen]
}
// ======
// bcrypt
// ======
const (
BcryptMinCost int = 4 // The bcrypt minimum allowable cost.
BcryptMaxCost int = 31 // The bcrypt maximum allowable cost.
BcryptDefaultCost int = 10 // The bcrypt default cost, and this will actually be set if a cost is below BcryptMinCost.
)
// BcryptEncrypt uses bcrypt to encrypt password using given cost.
func BcryptEncrypt(password []byte, cost int) ([]byte, error) {
return bcrypt.GenerateFromPassword(password, cost) // x/crypto/bcrypt
}
// BcryptEncryptWithDefaultCost uses bcrypt to encrypt password using BcryptDefaultCost.
func BcryptEncryptWithDefaultCost(password []byte) ([]byte, error) {
return BcryptEncrypt(password, BcryptDefaultCost)
}
// BcryptCompare compares hashed encrypted password and given password.
func BcryptCompare(password, encrypted []byte) (ok bool, err error) {
err = bcrypt.CompareHashAndPassword(encrypted, password) // x/crypto/bcrypt
if err != nil {
if err == bcrypt.ErrMismatchedHashAndPassword { // don't use errors.Is
return false, nil
}
return false, err
}
return true, nil
}