-
Notifications
You must be signed in to change notification settings - Fork 0
/
aes.go
190 lines (167 loc) · 4.5 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
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
// AES: Advanced Encrypt Standard
//
// Desc: base block, 128 bit per block.
//
// Three Factor:
// 1.secret size(bit): 128、192、256
// 2.padding: NoPadding:
// PKCS5Padding(default)
// PKCS7Padding
// ISO10126Padding
// 3.work mode:
// ECB(Electronic Codebook Book, default)
// CBC(Cipher Block Chaining)
// CTR(Counter)
// CFB(Cipher FeedBack)
// OFB(Output FeedBack)
package encrypt
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"errors"
)
type Mode uint8
const (
// block encrypt
CBC Mode = 1 + iota
ECB
CTR
// stream encrypt
CFB
OFB
)
var (
ErrWorkModeNotSupport = errors.New("work mode not support ")
)
type aseHelper struct {
mode Mode
}
func NewAES(mode Mode) *aseHelper {
return &aseHelper{
mode: mode,
}
}
// Encrypt
//
// @param []byte plaintext
// @param string secret
//
// @return []byte ciphertext, error err
func (a *aseHelper) Encrypt(plaintext []byte, secret string) (ciphertext []byte, err error) {
var block cipher.Block
if block, err = aes.NewCipher([]byte(secret)); err != nil {
return
}
switch a.mode {
case ECB:
blockSize := block.BlockSize()
plaintext = a.PKCS7Padding(plaintext, blockSize)
ciphertext = make([]byte, len(plaintext))
// block encrypt
for start, end := 0, blockSize; start < len(plaintext); start, end = start+blockSize, end+blockSize {
block.Encrypt(ciphertext[start:end], plaintext[start:end])
}
break
case CBC:
blockSize := block.BlockSize()
plaintext = a.PKCS7Padding(plaintext, blockSize)
ciphertext = make([]byte, len(plaintext))
iv := []byte(secret)[:blockSize]
encrypt := cipher.NewCBCEncrypter(block, iv)
encrypt.CryptBlocks(ciphertext, plaintext)
break
case CTR:
break
case CFB:
break
case OFB:
break
default:
err = ErrWorkModeNotSupport
break
}
return
}
// Decrypt
//
// @param []byte ciphertext
// @param string secret
//
// @return []byte plaintext, error err
func (a *aseHelper) Decrypt(ciphertext []byte, secret string) (plaintext []byte, err error) {
var block cipher.Block
if block, err = aes.NewCipher([]byte(secret)); err != nil {
return
}
switch a.mode {
case ECB:
blockSize := block.BlockSize()
plaintext = make([]byte, len(ciphertext))
for start, end := 0, blockSize; start < len(ciphertext); start, end = start+blockSize, end+blockSize {
block.Decrypt(plaintext[start:end], ciphertext[start:end])
}
plaintext = a.PKCS7UnPadding(plaintext)
break
case CBC:
blockSize := block.BlockSize()
plaintext = make([]byte, len(ciphertext))
vi := []byte(secret)[:blockSize]
encrypt := cipher.NewCBCDecrypter(block, vi)
encrypt.CryptBlocks(plaintext, ciphertext)
plaintext = a.PKCS7UnPadding(plaintext)
break
case CTR:
break
case CFB:
break
case OFB:
break
default:
err = ErrWorkModeNotSupport
break
}
return
}
// PKCS5Padding(是 PKCS7Padding 的子集,块大小固定为8字节)
// 原理:如果明文块少于 blockSize 个字节(按16字节分组即128bit,一般按秘钥字节数位分组步长),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。
// @param []byte ciphertext
// @param int blockSize
//
// @return []byte
func (a *aseHelper) PKCS5Padding(ciphertext []byte) []byte {
return a.PKCS7Padding(ciphertext, 8)
}
// PKCS5UnPadding
// @param []byte origData
//
// @return []byte
func (a *aseHelper) PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unPadding := int(origData[length-1])
return origData[:(length - unPadding)]
}
// PKCS7Padding
// 原理:如果明文块少于 blockSize 个字节(按16字节分组即128bit,一般按秘钥字节数位分组步长),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。
// @param []byte ciphertext
// @param int blockSize
//
// @return []byte
func (a *aseHelper) PKCS7Padding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(cipherText, padText...)
}
// PKCS7UnPadding
func (a *aseHelper) PKCS7UnPadding(data []byte) []byte {
length := len(data)
unPadding := int(data[length-1])
return data[:(length - unPadding)]
}
// ISO10126填充
// 原理:如果明文块少于 blockSize 个字节(按16字节分组即128bit,一般按秘钥字节数位分组步长),在明文块末尾补足相应数量的字节,最后一个字符值等于缺少的字符数,其他字符填充随机数。
func (a *aseHelper) ISO10126Padding() {
}
// ISO10126解填充
func (a *aseHelper) ISO10126UnPadding() {
}