forked from aliyun/aliyun-oss-go-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
aes_ctr_cipher.go
153 lines (125 loc) · 3.83 KB
/
aes_ctr_cipher.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
package osscrypto
import (
"io"
)
const (
aesKeySize = 32
ivSize = 16
)
// aesCtrCipherBuilder for building ContentCipher
type aesCtrCipherBuilder struct {
MasterCipher MasterCipher
}
// aesCtrCipher will use aes ctr algorithm
type aesCtrCipher struct {
CipherData CipherData
Cipher Cipher
}
// CreateAesCtrCipher creates ContentCipherBuilder
func CreateAesCtrCipher(cipher MasterCipher) ContentCipherBuilder {
return aesCtrCipherBuilder{MasterCipher: cipher}
}
// createCipherData create CipherData for encrypt object data
func (builder aesCtrCipherBuilder) createCipherData() (CipherData, error) {
var cd CipherData
var err error
err = cd.RandomKeyIv(aesKeySize, ivSize)
if err != nil {
return cd, err
}
cd.WrapAlgorithm = builder.MasterCipher.GetWrapAlgorithm()
cd.CEKAlgorithm = AesCtrAlgorithm
cd.MatDesc = builder.MasterCipher.GetMatDesc()
// EncryptedKey
cd.EncryptedKey, err = builder.MasterCipher.Encrypt(cd.Key)
if err != nil {
return cd, err
}
// EncryptedIV
cd.EncryptedIV, err = builder.MasterCipher.Encrypt(cd.IV)
if err != nil {
return cd, err
}
return cd, nil
}
// contentCipherCD is used to create ContentCipher with CipherData
func (builder aesCtrCipherBuilder) contentCipherCD(cd CipherData) (ContentCipher, error) {
cipher, err := newAesCtr(cd)
if err != nil {
return nil, err
}
return &aesCtrCipher{
CipherData: cd,
Cipher: cipher,
}, nil
}
// ContentCipher is used to create ContentCipher interface
func (builder aesCtrCipherBuilder) ContentCipher() (ContentCipher, error) {
cd, err := builder.createCipherData()
if err != nil {
return nil, err
}
return builder.contentCipherCD(cd)
}
// ContentCipherEnv is used to create a decrption ContentCipher from Envelope
func (builder aesCtrCipherBuilder) ContentCipherEnv(envelope Envelope) (ContentCipher, error) {
var cd CipherData
cd.EncryptedKey = make([]byte, len(envelope.CipherKey))
copy(cd.EncryptedKey, []byte(envelope.CipherKey))
plainKey, err := builder.MasterCipher.Decrypt([]byte(envelope.CipherKey))
if err != nil {
return nil, err
}
cd.Key = make([]byte, len(plainKey))
copy(cd.Key, plainKey)
cd.EncryptedIV = make([]byte, len(envelope.IV))
copy(cd.EncryptedIV, []byte(envelope.IV))
plainIV, err := builder.MasterCipher.Decrypt([]byte(envelope.IV))
if err != nil {
return nil, err
}
cd.IV = make([]byte, len(plainIV))
copy(cd.IV, plainIV)
cd.MatDesc = envelope.MatDesc
cd.WrapAlgorithm = envelope.WrapAlg
cd.CEKAlgorithm = envelope.CEKAlg
return builder.contentCipherCD(cd)
}
// GetMatDesc is used to get MasterCipher's MatDesc
func (builder aesCtrCipherBuilder) GetMatDesc() string {
return builder.MasterCipher.GetMatDesc()
}
// EncryptContents will generate a random key and iv and encrypt the data using ctr
func (cc *aesCtrCipher) EncryptContent(src io.Reader) (io.ReadCloser, error) {
reader := cc.Cipher.Encrypt(src)
return &CryptoEncrypter{Body: src, Encrypter: reader}, nil
}
// DecryptContent is used to decrypt object using ctr
func (cc *aesCtrCipher) DecryptContent(src io.Reader) (io.ReadCloser, error) {
reader := cc.Cipher.Decrypt(src)
return &CryptoDecrypter{Body: src, Decrypter: reader}, nil
}
// GetCipherData is used to get cipher data information
func (cc *aesCtrCipher) GetCipherData() *CipherData {
return &(cc.CipherData)
}
// GetCipherData returns cipher data
func (cc *aesCtrCipher) GetEncryptedLen(plainTextLen int64) int64 {
// AES CTR encryption mode does not change content length
return plainTextLen
}
// GetAlignLen is used to get align length
func (cc *aesCtrCipher) GetAlignLen() int {
return len(cc.CipherData.IV)
}
// Clone is used to create a new aesCtrCipher from itself
func (cc *aesCtrCipher) Clone(cd CipherData) (ContentCipher, error) {
cipher, err := newAesCtr(cd)
if err != nil {
return nil, err
}
return &aesCtrCipher{
CipherData: cd,
Cipher: cipher,
}, nil
}