-
Notifications
You must be signed in to change notification settings - Fork 479
/
Copy pathaes.go
142 lines (114 loc) · 3.14 KB
/
aes.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
package utils
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"errors"
"golang.org/x/crypto/pbkdf2"
"hash"
)
const (
Pkcs5SaltLength = 8
Pkcs5DefaultIter = 2048
EvpMaxIvLength = 16
Pkcs5DefaultMagic = "Salted__"
)
var (
ErrKeyLength = errors.New("the key length is illegal")
)
func AesEncryptWithSalt(plaintext, key []byte, iterCount int, magic string, h func() hash.Hash) (dst []byte, err error) {
if iterCount <= 0 {
iterCount = Pkcs5DefaultIter
}
if h == nil {
h = md5.New
}
salt := make([]byte, Pkcs5SaltLength)
_, err = rand.Read(salt)
var sKey = pbkdf2.Key(key, salt, iterCount, len(key), h)
var sIV = pbkdf2.Key(sKey, salt, iterCount, EvpMaxIvLength, h)
dst, err = AesCbcDecrypt(plaintext, sKey, sIV)
dst = append(salt, dst...)
dst = append([]byte(magic), dst...)
return dst, err
}
func AesDecryptWithSalt(cipherText, key []byte, iterCount int, magic string, h func() hash.Hash) (dst []byte, err error) {
if iterCount <= 0 {
iterCount = Pkcs5DefaultIter
}
if h == nil {
h = md5.New
}
salt := cipherText[len(magic) : len(magic)+Pkcs5SaltLength]
sKey := pbkdf2.Key(key, salt, iterCount, len(key), h)
sIV := pbkdf2.Key(sKey, salt, iterCount, EvpMaxIvLength, h)
dst, err = AesCbcDecrypt(cipherText[len(magic)+Pkcs5SaltLength:], sKey, sIV)
return dst, err
}
// CBC模式
func AesCbcEncrypt(plaintext, key, iv []byte) ([]byte, error) {
if len(key) != 16 && len(key) != 24 && len(key) != 32 {
return nil, ErrKeyLength
}
var block, err = aes.NewCipher(key)
if err != nil {
return nil, err
}
var blockSize = block.BlockSize()
iv = iv[:blockSize]
var src = PKCS7Padding(plaintext, blockSize)
var dst = make([]byte, len(src))
var mode = cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(dst, src)
return dst, nil
}
func AesCbcDecrypt(cipherText, key, iv []byte) ([]byte, error) {
var block, err = aes.NewCipher(key)
if err != nil {
return nil, err
}
var blockSize = block.BlockSize()
iv = iv[:blockSize]
var dst = make([]byte, len(cipherText))
var mode = cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(dst, cipherText)
dst = PKCS7UnPadding(dst)
return dst, nil
}
// CFB模式
func AesCfbEncrypt(plaintext, key, iv []byte) ([]byte, error) {
var block, err = aes.NewCipher(key)
if err != nil {
return nil, err
}
var blockSize = block.BlockSize()
iv = iv[:blockSize]
var dst = make([]byte, len(plaintext))
var mode = cipher.NewCFBEncrypter(block, iv)
mode.XORKeyStream(dst, plaintext)
return dst, nil
}
func AesCfbDecrypt(cipherText, key, iv []byte) ([]byte, error) {
var block, err = aes.NewCipher(key)
if err != nil {
return nil, err
}
var blockSize = block.BlockSize()
iv = iv[:blockSize]
var dst = make([]byte, len(cipherText))
var mode = cipher.NewCFBDecrypter(block, iv)
mode.XORKeyStream(dst, cipherText)
return dst, nil
}
func PKCS7Padding(text []byte, blockSize int) []byte {
var diff = blockSize - len(text)%blockSize
var paddingText = bytes.Repeat([]byte{byte(diff)}, diff)
return append(text, paddingText...)
}
func PKCS7UnPadding(text []byte) []byte {
var length = len(text)
var unPadding = int(text[length-1])
return text[:(length - unPadding)]
}