-
Notifications
You must be signed in to change notification settings - Fork 25
/
cipher_cbc.go
134 lines (104 loc) · 3.04 KB
/
cipher_cbc.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
package pbes2
import (
"io"
"errors"
"crypto/cipher"
"encoding/asn1"
)
// cbc 模式加密参数
type cbcParams []byte
// cbc 模式加密
type CipherCBC struct {
cipherFunc func(key []byte) (cipher.Block, error)
keySize int
blockSize int
identifier asn1.ObjectIdentifier
hasKeyLength bool
needBmpPass bool
}
// 值大小
func (this CipherCBC) KeySize() int {
return this.keySize
}
// oid
func (this CipherCBC) OID() asn1.ObjectIdentifier {
return this.identifier
}
// 是否有 KeyLength
func (this CipherCBC) HasKeyLength() bool {
return this.hasKeyLength
}
// 密码是否需要 Bmp 处理
func (this CipherCBC) NeedBmpPassword() bool {
return this.needBmpPass
}
// 加密
func (this CipherCBC) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, []byte, error) {
block, err := this.cipherFunc(key)
if err != nil {
return nil, nil, errors.New("pkcs/cipher: failed to create cipher: " + err.Error())
}
// 随机生成 iv
iv := make(cbcParams, this.blockSize)
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, nil, errors.New("pkcs/cipher: failed to generate IV: " + err.Error())
}
// 加密数据补码
plaintext = pkcs7Padding(plaintext, this.blockSize)
// 需要保存的加密数据
encrypted := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted, plaintext)
// 编码 iv
paramBytes, err := asn1.Marshal(iv)
if err != nil {
return nil, nil, err
}
return encrypted, paramBytes, nil
}
// 解密
func (this CipherCBC) Decrypt(key, params, ciphertext []byte) ([]byte, error) {
// 解析出 iv
var iv cbcParams
if _, err := asn1.Unmarshal(params, &iv); err != nil {
return nil, errors.New("pkcs/cipher: invalid iv parameters")
}
block, err := this.cipherFunc(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(ciphertext)%blockSize != 0 {
return nil, errors.New("pkcs/cipher: encrypted PEM data is not a multiple of the block size")
}
if len(iv) != blockSize {
return nil, errors.New("pkcs/cipher: incorrect IV size")
}
plaintext := make([]byte, len(ciphertext))
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(plaintext, ciphertext)
// 判断数据是否为填充数据
dlen := len(plaintext)
if dlen == 0 || dlen%blockSize != 0 {
return nil, errors.New("pkcs/cipher: invalid padding")
}
// 解析加密数据
pt, err := pkcs7UnPadding(plaintext)
if err != nil {
return plaintext, nil
}
return pt, nil
}
// 设置 keySize
func (this CipherCBC) WithKeySize(keySize int) CipherCBC {
this.keySize = keySize
return this
}
func (this CipherCBC) WithHasKeyLength(hasKeyLength bool) CipherCBC {
this.hasKeyLength = hasKeyLength
return this
}
func (this CipherCBC) WithNeedBmpPassword(needBmpPass bool) CipherCBC {
this.needBmpPass = needBmpPass
return this
}