/
desede.go
171 lines (159 loc) · 4.81 KB
/
desede.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
package desede
import (
"crypto/cipher"
"crypto/des"
"errors"
"github.com/freewu/crypto-go/padding"
"strings"
)
type TripleDES struct {
Mode string // 加密模式 ECB / CBC / CFB / OFB / CTR default: ECB
Padding string // 填充模式 NoPadding / ZeroPadding / PKCS7 / PKCS5
}
// GetInstance 实例化一个 des 对象 如: GetInstance("ECB/PKCS7Padding")
func GetInstance(str string) *TripleDES {
if str != "" {
arr := strings.Split(str, "/")
// todo 需要验证处理
if len(arr) == 1 {
return &TripleDES{Mode: arr[0], Padding: "PKCS7Padding"}
}
return &TripleDES{Mode: arr[0], Padding: arr[1]}
}
return &TripleDES{Mode: "ECB", Padding: "PKCS7Padding"}
}
// 补码处理
func (d *TripleDES) padding(data []byte, blockSize int) ([]byte, error) {
switch d.Padding {
case "NoPadding":
return padding.NoPaddingPack(data, blockSize)
case "ZeroPadding":
return padding.ZeroPaddingPack(data, blockSize)
case "PKCS7Padding":
return padding.PKCS7PaddingPack(data, blockSize)
case "PKCS5Padding":
return padding.PKCS5PaddingPack(data, blockSize)
case "X923Padding":
return padding.X923PaddingPack(data, blockSize)
case "ISO78164Padding":
return padding.ISO78164PaddingPack(data, blockSize)
case "ISO10126Padding":
return padding.ISO10126PaddingPack(data, blockSize)
case "TBCPadding":
return padding.TBCPaddingPack(data, blockSize)
}
return nil, errors.New("no such padding algorithm")
}
// 去掉补码处理
func (d *TripleDES) unpadding(data []byte) ([]byte, error) {
switch d.Padding {
case "NoPadding":
return padding.NoPaddingUnPack(data), nil
case "ZeroPadding":
return padding.ZeroPaddingUnPack(data), nil
case "PKCS7Padding":
return padding.PKCS7PaddingUnPack(data), nil
case "PKCS5Padding":
return padding.PKCS5PaddingUnPack(data), nil
case "X923Padding":
return padding.X923PaddingUnPack(data), nil
case "ISO78164Padding":
return padding.ISO78164PaddingUnPack(data), nil
case "ISO10126Padding":
return padding.ISO10126PaddingUnPack(data), nil
case "TBCPadding":
return padding.TBCPaddingUnPack(data), nil
}
return nil, errors.New("no such unpadding algorithm")
}
// Encrypt 加密处理
func (d *TripleDES) Encrypt(data []byte, key []byte, iv []byte) ([]byte, error) {
// 将字节秘钥转换成block快
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
// 补码处理
data, err = d.padding(data, block.BlockSize())
if err != nil {
return nil, err
}
// 创建明文长度的字节数组
encrypted := make([]byte, len(data))
switch d.Mode {
case "CBC":
blockMode := cipher.NewCBCEncrypter(block, iv)
// 加密明文,加密后的数据放到数组中
blockMode.CryptBlocks(encrypted, data)
return encrypted, nil
case "ECB": // go 默认隐藏了 ECB模式, 因为go认为ECB不安全, 所以不建议使用,就隐藏了
bs := block.BlockSize()
dst := encrypted
for len(data) > 0 {
//对明文按照blocksize进行分块加密
//必要时可以使用go关键字进行并行加密
block.Encrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
return encrypted, nil
case "CFB":
blockMode := cipher.NewCFBEncrypter(block, iv)
// 加密明文,加密后的数据放到数组中
blockMode.XORKeyStream(encrypted, data)
return encrypted, nil
case "OFB":
blockMode := cipher.NewOFB(block, iv)
blockMode.XORKeyStream(encrypted, data)
return encrypted, nil
case "CTR":
blockMode := cipher.NewCTR(block, iv)
blockMode.XORKeyStream(encrypted, data)
return encrypted, nil
}
return nil, errors.New("no such mode")
}
// Decrypt 解密处理
func (d *TripleDES) Decrypt(data []byte, key []byte, iv []byte) ([]byte, error) {
// 将字节秘钥转换成block快
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
// 传入的解密数据不是满块
if len(data)%block.BlockSize() != 0 {
return nil, errors.New("crypto/cipher: input not full blocks")
}
// 创建明文长度的字节数组
decrypted := make([]byte, len(data))
switch d.Mode {
case "CBC":
blockMode := cipher.NewCBCDecrypter(block, iv)
// 加密明文,加密后的数据放到数组中
blockMode.CryptBlocks(decrypted, data)
return d.unpadding(decrypted)
case "ECB":
bs := block.BlockSize()
dst := decrypted
for len(data) > 0 {
block.Decrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
return d.unpadding(decrypted)
case "CFB":
blockMode := cipher.NewCFBDecrypter(block, iv)
// 加密明文,加密后的数据放到数组中
blockMode.XORKeyStream(decrypted, data)
return d.unpadding(decrypted)
case "OFB":
blockMode := cipher.NewOFB(block, iv)
blockMode.XORKeyStream(decrypted, data)
return d.unpadding(decrypted)
case "CTR":
blockMode := cipher.NewCTR(block, iv)
blockMode.XORKeyStream(decrypted, data)
return d.unpadding(decrypted)
}
return nil, errors.New("no such mode")
}