-
Notifications
You must be signed in to change notification settings - Fork 0
/
aes.go
143 lines (130 loc) · 4.24 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
package habits
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/hex"
"io"
)
// AesCBCStrEncrypt key长度必须为16, 24或者32, 返回hex.EncodeToString 后的字符串
// 这边IV直接就使用 key
func AesCBCStrEncrypt(key, origin string) (string, error) {
// 转成字节数组
originByte := Str2SliceByte(origin)
keyByte := Str2SliceByte(key)
// 分组秘钥
// NewCipher该函数限制了输入k的长度必须为16, 24或者32
block, err := aes.NewCipher(keyByte)
if err != nil {
return "", NewHabitError("key 不可用, 必须为16, 24, 32长度的字符!")
}
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 补全码
pk := pkcs7Padding(originByte, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, keyByte[:blockSize])
// 创建数组
out := make([]byte, len(pk))
// 加密
blockMode.CryptBlocks(out, pk)
return hex.EncodeToString(out), nil
}
// key长度必须为16, 24或者32, 参数origin 为hex.EncodeToString 后的字符串
// 这边IV直接就使用 key
func AesCBCStrDecrypt(key, origin string) (string, error) {
// 转成字节数组
originByte, err := hex.DecodeString(origin)
if err != nil {
return "", NewHabitError("密文错误, 无法解密!")
}
keyByte := Str2SliceByte(key)
// 分组秘钥
block, _ := aes.NewCipher(keyByte)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 加密模式
blockMode := cipher.NewCBCDecrypter(block, keyByte[:blockSize])
// 创建数组
out := make([]byte, len(originByte))
// 解密
blockMode.CryptBlocks(out, originByte)
//去除加密是补全的字节, 加密是把补全的位数存入了加密字符串字节切片的最后几位
// 去补全码
out, err = pkcs7UnPadding(out)
return string(out), err
}
// ########### AES CRT
// key长度必须为16, 24或者32
func AesCRTCrypt(key, origin string) (string, error) {
// 转成字节数组
plainText := Str2SliceByte(origin)
keyByte := Str2SliceByte(key)
//1. 创建cipher.Block接口
block, err := aes.NewCipher(keyByte)
if err != nil {
return "", err
}
//2. 创建分组模式,在crypto/cipher包中
iv := bytes.Repeat(Str2SliceByte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
//3. 加密
dst := make([]byte, len(plainText))
stream.XORKeyStream(dst, plainText)
return string(dst), nil
}
// ########### AES OFB
// key长度必须为16, 24或者32
func AesOFBStrEncrypt(key, origin string) (string, error) {
// 转成字节数组
originByte := Str2SliceByte(origin)
keyByte := Str2SliceByte(key)
originByte = pkcs7Padding(originByte, aes.BlockSize)
block, _ := aes.NewCipher(keyByte)
out := make([]byte, aes.BlockSize+len(originByte))
iv := out[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(out[aes.BlockSize:], originByte)
return string(out), nil
}
// key长度必须为16, 24或者32
func AesOFBStrDecrypt(key, origin string) (string, error) {
originByte := Str2SliceByte(origin)
keyByte := Str2SliceByte(key)
block, _ := aes.NewCipher(keyByte)
iv := originByte[:aes.BlockSize]
originByte = originByte[aes.BlockSize:]
if len(originByte)%aes.BlockSize != 0 {
return "", HabitError{Msg: "解密失败: data is not a multiple of the block size"}
}
out := make([]byte, len(originByte))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(out, originByte)
out, err := pkcs7UnPadding(out)
return string(out), err
}
// 补码
// AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
// 补全blockSize的倍数个数, 即len(pk)%blockSize=0
func pkcs7Padding(ciphertext []byte, blocksize int) []byte {
padding := blocksize - len(ciphertext)%blocksize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// 去码
func pkcs7UnPadding(origin []byte) ([]byte, error) {
length := len(origin)
if length < 1 {
return Str2SliceByte(""), HabitError{Msg: "解密失败!"}
}
unpadding := int(origin[length-1])
//这边取最后一位就一定是加密时补全的位数
if length < unpadding {
return Str2SliceByte(""), HabitError{Msg: "解密失败!"}
}
return origin[:(length - unpadding)], nil
}