前言:

自己没事查询资料弄了个Go加密解密的文件,方便在日常中直接调用

写这个是为了方便开新项目懒得去找现成的代码,直接复制过去做仓库文件
具体怎么用我也写了调用例子,即使不懂加密规则至少会用嘛~
至于具体的加密规则,建议网上(B站)搜搜《电子科技大学密码学》比较基础详细

文件

包含 :

  • AES-CBC
  • Base64/58
  • 哈希
  • DES/3DES
  • RSA
  • 数字签名
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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
package public

import (
"bytes"
"crypto"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"golang.org/x/crypto/md4"
"math/big"
"os"
)

// ----------------------- AES-CBC -----------------------

func CBCEncrypt(text []byte, key []byte, iv []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println(err)
}
padText := PKCS7Padding(text, block.BlockSize()) // 填充
blockMode := cipher.NewCBCEncrypter(block, iv)
result := make([]byte, len(padText)) // 加密
blockMode.CryptBlocks(result, padText)
return result
}

func CBCDecrypt(encrypt []byte, key []byte, iv []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println(err)
}
blockMode := cipher.NewCBCDecrypter(block, iv)
result := make([]byte, len(encrypt))
blockMode.CryptBlocks(result, encrypt)
// 去除填充
result = UnPKCS7Padding(result)
return result
}

// PKCS7Padding 计算待填充的长度
func PKCS7Padding(text []byte, blockSize int) []byte {
padding := blockSize - len(text)%blockSize
var paddingText []byte
if padding == 0 {
paddingText = bytes.Repeat([]byte{byte(blockSize)}, blockSize) // 已对齐,填充一整块数据,每个数据为 blockSize
} else {
paddingText = bytes.Repeat([]byte{byte(padding)}, padding) // 未对齐 填充 padding 个数据,每个数据为 padding
}
return append(text, paddingText...)
}

// UnPKCS7Padding 取出填充的数据 以此来获得填充数据长度
func UnPKCS7Padding(text []byte) []byte {
unPadding := int(text[len(text)-1])
return text[:(len(text) - unPadding)]
}

// ----------------------- BASE64 -----------------------

func Base64Encoding(input []byte) string {
return base64.StdEncoding.EncodeToString(input)
}

func Base64Decoding(encodeString string) string {
decodeBytes, err := base64.StdEncoding.DecodeString(encodeString)
if err != nil {
return ""
}
return string(decodeBytes)
}

func Base64UrlEncoding(input []byte) string {
return base64.URLEncoding.EncodeToString(input)
}

func Base64UrlDecoding(encodeUrl string) string {
uDec, err := base64.URLEncoding.DecodeString(encodeUrl)
if err != nil {
return ""
}
return string(uDec)
}

// ----------------------- BASE58 -----------------------

var b58 = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")

// Base58Encoding base58编码
func Base58Encoding(src string) string {
srcByte := []byte(src)
// todo 转成十进制
i := big.NewInt(0).SetBytes(srcByte)
// todo 循环取余
var modSlice []byte
for i.Cmp(big.NewInt(0)) > 0 {
mod := big.NewInt(0)
i58 := big.NewInt(58)
i.DivMod(i, i58, mod) // 取余
modSlice = append(modSlice, b58[mod.Int64()]) // 将余数添加到数组中
}
// todo 把0使用字节'1'代替
for _, s := range srcByte {
if s != 0 {
break
}
modSlice = append(modSlice, byte('1'))
}

// todo 反转byte数组
retModSlice := ReverseByteArr(modSlice)
return string(retModSlice)
}

// Base58Decoding base58解码
func Base58Decoding(src string) string {
// 转成byte数组
srcByte := []byte(src)
// 这里得到的是十进制
ret := big.NewInt(0)
for _, b := range srcByte {
i := bytes.IndexByte(b58, b)
ret.Mul(ret, big.NewInt(58)) // 乘回去
ret.Add(ret, big.NewInt(int64(i))) // 相加
}

return string(ret.Bytes())

}

// ReverseByteArr byte数组进行反转方式2
func ReverseByteArr(b []byte) []byte {
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
b[i], b[j] = b[j], b[i]

}
return b
}

// ----------------------- 哈希算法 -----------------------

// HashMD4Encoding MD4哈希加密
func HashMD4Encoding(src string) string {
srcByte := []byte(src)
md4New := md4.New()
md4Bytes := md4New.Sum(srcByte)
return hex.EncodeToString(md4Bytes)
}

// HashMD5Encoding MD5哈希加密
func HashMD5Encoding(src string) string {
srcByte := []byte(src)
md5New := md5.New()
md5Bytes := md5New.Sum(srcByte)
return hex.EncodeToString(md5Bytes)
}

// HashSHA256Encoding SHA256哈希加密
func HashSHA256Encoding(src string) string {
sha256Bytes := sha256.Sum256([]byte(src))
return hex.EncodeToString(sha256Bytes[:])
}

// ----------------------- DES -----------------------

// DesEncoding 加密
func DesEncoding(src string, desKey []byte) (string, error) {
// todo desKey只支持8字节的长度
srcByte := []byte(src)
block, err := des.NewCipher(desKey)
if err != nil {
return src, err
}
// todo 密码填充
newSrcByte := PadPwd(srcByte, block.BlockSize())
dst := make([]byte, len(newSrcByte))
block.Encrypt(dst, newSrcByte)
// todo base64编码
pwd := base64.StdEncoding.EncodeToString(dst)
return pwd, nil
}

// DesDecoding 解密
func DesDecoding(pwd string, desKey []byte) (string, error) {
pwdByte, err := base64.StdEncoding.DecodeString(pwd)
if err != nil {
return pwd, err
}
block, errBlock := des.NewCipher(desKey)
if errBlock != nil {
return pwd, errBlock
}
dst := make([]byte, len(pwdByte))
block.Decrypt(dst, pwdByte)
dst, _ = UnPadPwd(dst)
return string(dst), nil
}

// PadPwd 填充密码长度
func PadPwd(srcByte []byte, blockSize int) []byte {
padNum := blockSize - len(srcByte)%blockSize
ret := bytes.Repeat([]byte{byte(padNum)}, padNum)
srcByte = append(srcByte, ret...)
return srcByte
}

// UnPadPwd 去掉填充的部分
func UnPadPwd(dst []byte) ([]byte, error) {
if len(dst) <= 0 {
return dst, errors.New("长度有误")
}
unPadNum := int(dst[len(dst)-1])
return dst[:(len(dst) - unPadNum)], nil
}

// ----------------------- 3DES-CBC -----------------------

// TDesEncoding 3des加密
func TDesEncoding(src string, desKey []byte) (string, error) {
// todo key 24位数
srcByte := []byte(src)
block, err := des.NewTripleDESCipher(desKey) // 和des的区别
if err != nil {
return src, err
}
// todo 密码填充
newSrcByte := PadPwd(srcByte, block.BlockSize())
dst := make([]byte, len(newSrcByte))
block.Encrypt(dst, newSrcByte)
// todo base64编码
pwd := base64.StdEncoding.EncodeToString(dst)
return pwd, nil
}

// TDesDecoding 3des解密
func TDesDecoding(pwd string, desKey []byte) (string, error) {
pwdByte, err := base64.StdEncoding.DecodeString(pwd)
if err != nil {
return pwd, err
}
block, errBlock := des.NewTripleDESCipher(desKey) // 和des的区别
if errBlock != nil {
return pwd, errBlock
}
dst := make([]byte, len(pwdByte))
block.Decrypt(dst, pwdByte)
dst, _ = UnPadPwd(dst)
return string(dst), nil
}

// ----------------------- RSA -----------------------

// SaveRsaKey 生成Rsa公钥私钥并保存
func SaveRsaKey(bits int) error {
// todo 处理钥匙
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
fmt.Println(err)
return err
}
publicKey := privateKey.PublicKey
x509Private := x509.MarshalPKCS1PrivateKey(privateKey) // 使用x509标准对私钥进行编码,AsN.1编码字符串
x509Public := x509.MarshalPKCS1PublicKey(&publicKey) // 使用x509标准对公钥进行编码,AsN.1编码字符串
blockPrivate := pem.Block{Type: "private key", Bytes: x509Private} // 对私钥封装block 结构数据
blockPublic := pem.Block{Type: "public key", Bytes: x509Public} // 对公钥封装block 结构数据

// todo 创建存放私钥的文件
privateFile, errPri := os.Create("privateKey.pem")
if errPri != nil {
return errPri
}
defer privateFile.Close()
pem.Encode(privateFile, &blockPrivate)
// todo 创建存放公钥的文件
publicFile, errPub := os.Create("publicKey.pem")
if errPub != nil {
return errPub
}
defer publicFile.Close()
pem.Encode(publicFile, &blockPublic)
return nil
}

// RsaEncoding 加密
func RsaEncoding(src, filePath string) ([]byte, error) {
srcByte := []byte(src)
// todo 打开文件
file, err := os.Open(filePath)
if err != nil {
return srcByte, err
}
// todo 获取文件信息
fileInfo, errInfo := file.Stat()
if errInfo != nil {
return srcByte, errInfo
}
// todo 读取文件内容
keyBytes := make([]byte, fileInfo.Size())
file.Read(keyBytes) // 读取内容到容器里面
block, _ := pem.Decode(keyBytes) // pem解码
publicKey, errPb := x509.ParsePKCS1PublicKey(block.Bytes) // x509解码
if errPb != nil {
return srcByte, errPb
}
// todo 使用公钥对明文进行加密
retByte, errRet := rsa.EncryptPKCS1v15(rand.Reader, publicKey, srcByte)
if errRet != nil {
return srcByte, errRet
}
return retByte, nil
}

// RsaDecoding 解密
func RsaDecoding(srcByte []byte, filePath string) ([]byte, error) {
// todo 打开文件
file, err := os.Open(filePath)
if err != nil {
return srcByte, err
}
// todo 获取文件信息
fileInfo, errInfo := file.Stat()
if errInfo != nil {
return srcByte, errInfo
}
// todo 读取文件内容
keyBytes := make([]byte, fileInfo.Size())
// 读取内容到容器里面
file.Read(keyBytes)
block, _ := pem.Decode(keyBytes) // pem解码
privateKey, errPb := x509.ParsePKCS1PrivateKey(block.Bytes) // x509解码
if errPb != nil {
return srcByte, errPb
}
// todo 进行解密
retByte, errRet := rsa.DecryptPKCS1v15(rand.Reader, privateKey, srcByte)
if errRet != nil {
return srcByte, errRet
}
return retByte, nil
}

// ----------------------- 数字签名 -----------------------

func GetPrivateKey(filePath string) (*rsa.PrivateKey, error) {
// todo 打开文件
file, err := os.Open(filePath)
if err != nil {
return &rsa.PrivateKey{}, err
}
// todo 获取文件信息
fileInfo, errInfo := file.Stat()
if errInfo != nil {
return &rsa.PrivateKey{}, errInfo
}
// todo 读取文件内容
keyBytes := make([]byte, fileInfo.Size())
file.Read(keyBytes) // 读取内容到容器里面
block, _ := pem.Decode(keyBytes) // pem解码
PrivateKey, errPb := x509.ParsePKCS1PrivateKey(block.Bytes) // x509解码
if errPb != nil {
return &rsa.PrivateKey{}, errPb
}
return PrivateKey, nil
}

func GetPublicKey(filePath string) (*rsa.PublicKey, error) {
// todo 打开文件
file, err := os.Open(filePath)
if err != nil {
return &rsa.PublicKey{}, err
}
// todo 获取文件信息
fileInfo, errInfo := file.Stat()
if errInfo != nil {
return &rsa.PublicKey{}, errInfo
}
// todo 读取文件内容
keyBytes := make([]byte, fileInfo.Size())
file.Read(keyBytes) // 读取内容到容器里面
block, _ := pem.Decode(keyBytes) // pem解码
publicKey, errPb := x509.ParsePKCS1PublicKey(block.Bytes) // x509解码
if errPb != nil {
return &rsa.PublicKey{}, errPb
}
return publicKey, nil
}

// RsaSign 数字签名
func RsaSign(filePath string, src string) ([]byte, error) {
// todo 获取私钥
private, err := GetPrivateKey(filePath)
if err != nil {
return []byte{}, err
}
// todo 签名
shaNew := sha256.New()
srcByte := []byte(src)
shaNew.Write(srcByte)
shaByte := shaNew.Sum(nil)
v15, err := rsa.SignPKCS1v15(rand.Reader, private, crypto.SHA256, shaByte)
if err != nil {
return []byte{}, err
}
return v15, nil
}

// RsaVerify 验证签名
func RsaVerify(sign []byte, src string, filePath string) (bool, error) {
// todo 拿到公钥
public, err := GetPublicKey(filePath)
if err != nil {
return false, err
}
// todo 验证签名
shaNew := sha256.New()
srcByte := []byte(src)
shaNew.Write(srcByte)
shaByte := shaNew.Sum(nil)
err = rsa.VerifyPKCS1v15(public, crypto.SHA256, shaByte, sign)
if err != nil {
return false, err
}
return true, nil
}

代码实现

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
package main

import (
"GoBackEnd/public"
"fmt"
"log"
)

func main() {
// AES-CBC
iv := []byte{0x19, 0x34, 0x57, 0x72, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x64, 0x14, 0x78, 0x90, 0xAC, 0xAE, 0x45}
key := []byte("1111111111111111")
AesCbc := public.CBCEncrypt([]byte("hello"), key, iv)
fmt.Println(AesCbc)
content := public.CBCDecrypt(AesCbc, key, iv)
fmt.Println(string(content))
// BASE64
encode := public.Base64Encoding([]byte("Hello"))
fmt.Println(encode)
decode := public.Base64Decoding(encode)
fmt.Println(decode)
// BASE58
encode = public.Base58Encoding("Hello")
fmt.Println(encode)
decode = public.Base58Decoding(encode)
fmt.Println(decode)
// 哈希算法
md4 := public.HashMD4Encoding("hello")
fmt.Println(md4)
md5 := public.HashMD5Encoding("hello")
fmt.Println(md5)
sha := public.HashSHA256Encoding("hello")
fmt.Println(sha)
// DES
encode, _ = public.DesEncoding("hello", []byte("11111111")) // 8位数
fmt.Println("Des:", encode)
decode, _ = public.DesDecoding(encode, []byte("11111111"))
fmt.Println("Des:", decode)
encode, _ = public.TDesEncoding("hello", []byte("111111111111111111111111")) // 24位数
fmt.Println(encode)
decode, _ = public.TDesDecoding(encode, []byte("111111111111111111111111"))
fmt.Println(decode)
// RSA
err := public.SaveRsaKey(2048)
if err != nil {
log.Println(err)
}
encoding, _ := public.RsaEncoding("hello", "publicKey.pem")
log.Println(public.Base64Encoding(encoding))
decoding, _ := public.RsaDecoding(encoding, "privateKey.pem")
log.Println(string(decoding))
// 数字签名
encoding, _ = public.RsaSign("privateKey.pem", "hello")
log.Println(encoding)
isTrue, _ := public.RsaVerify(encoding, "hello", "publicKey.pem")
log.Println(isTrue)
}