-
Notifications
You must be signed in to change notification settings - Fork 146
/
Copy pathCOSEncryptionClient.java
288 lines (249 loc) · 11.7 KB
/
COSEncryptionClient.java
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/*
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
* According to cos feature, we modify some class,comment, field name, etc.
*/
package com.qcloud.cos;
import java.io.File;
import com.qcloud.cos.auth.COSCredentialsProvider;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.internal.COSDirect;
import com.qcloud.cos.internal.crypto.COSCryptoModule;
import com.qcloud.cos.internal.crypto.CryptoConfiguration;
import com.qcloud.cos.internal.crypto.CryptoModuleDispatcher;
import com.qcloud.cos.internal.crypto.EncryptionMaterialsProvider;
import com.qcloud.cos.internal.crypto.QCLOUDKMS;
import com.qcloud.cos.internal.crypto.TencentCloudKMSClient;
import com.qcloud.cos.model.AbortMultipartUploadRequest;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.COSObjectId;
import com.qcloud.cos.model.CompleteMultipartUploadRequest;
import com.qcloud.cos.model.CompleteMultipartUploadResult;
import com.qcloud.cos.model.CopyPartRequest;
import com.qcloud.cos.model.CopyPartResult;
import com.qcloud.cos.model.DeleteObjectRequest;
import com.qcloud.cos.model.EncryptedInitiateMultipartUploadRequest;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.InitiateMultipartUploadRequest;
import com.qcloud.cos.model.InitiateMultipartUploadResult;
import com.qcloud.cos.model.InstructionFileId;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutInstructionFileRequest;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.UploadPartRequest;
import com.qcloud.cos.model.UploadPartResult;
import com.tencentcloudapi.common.profile.ClientProfile;
public class COSEncryptionClient extends COSClient implements COSEncryption {
private final COSCryptoModule crypto;
/**
* True if the a default KMS client is constructed, which will be shut down when this instance
* of COS encryption client is shutdown. False otherwise, which means the users who provided the
* KMS client would be responsible to shut down the KMS client.
*/
private final boolean isKMSClientInternal;
private final QCLOUDKMS kms;
public COSEncryptionClient(COSCredentialsProvider credentialsProvider,
EncryptionMaterialsProvider kekMaterialsProvider, ClientConfig clientConfig,
CryptoConfiguration cryptoConfig) {
this(null, credentialsProvider, kekMaterialsProvider, clientConfig, cryptoConfig);
}
public COSEncryptionClient(COSCredentialsProvider credentialsProvider,
EncryptionMaterialsProvider kekMaterialsProvider, ClientConfig clientConfig,
CryptoConfiguration cryptoConfig,ClientProfile clientProfile) {
this(null, credentialsProvider, kekMaterialsProvider, clientConfig, cryptoConfig, clientProfile);
}
public COSEncryptionClient(QCLOUDKMS kms, COSCredentialsProvider credentialsProvider,
EncryptionMaterialsProvider kekMaterialsProvider, ClientConfig clientConfig,
CryptoConfiguration cryptoConfig) {
super(credentialsProvider.getCredentials(), clientConfig);
assertParameterNotNull(kekMaterialsProvider,
"EncryptionMaterialsProvider parameter must not be null.");
assertParameterNotNull(cryptoConfig, "CryptoConfiguration parameter must not be null.");
this.isKMSClientInternal = kms == null;
this.kms = isKMSClientInternal ?
newTencentCloudKMSClient(credentialsProvider, clientConfig, cryptoConfig) : kms;
this.crypto = new CryptoModuleDispatcher(this.kms, new COSDirectImpl(), credentialsProvider,
kekMaterialsProvider, cryptoConfig);
}
public COSEncryptionClient(QCLOUDKMS kms, COSCredentialsProvider credentialsProvider,
EncryptionMaterialsProvider kekMaterialsProvider, ClientConfig clientConfig,
CryptoConfiguration cryptoConfig, ClientProfile clientProfile) {
super(credentialsProvider.getCredentials(), clientConfig);
assertParameterNotNull(kekMaterialsProvider,
"EncryptionMaterialsProvider parameter must not be null.");
assertParameterNotNull(cryptoConfig, "CryptoConfiguration parameter must not be null.");
this.isKMSClientInternal = kms == null;
this.kms = isKMSClientInternal ?
newTencentCloudKMSClient(credentialsProvider, clientConfig, cryptoConfig, clientProfile) : kms;
this.crypto = new CryptoModuleDispatcher(this.kms, new COSDirectImpl(), credentialsProvider,
kekMaterialsProvider, cryptoConfig);
}
private TencentCloudKMSClient newTencentCloudKMSClient(
COSCredentialsProvider credentialsProvider,
ClientConfig clientConfig,
CryptoConfiguration cryptoConfig) {
String region = cryptoConfig.getKmsRegion();
if (region == null) {
region = clientConfig.getRegion().getRegionName();
}
final TencentCloudKMSClient kmsClient = new TencentCloudKMSClient(credentialsProvider, region);
return kmsClient;
}
private TencentCloudKMSClient newTencentCloudKMSClient(
COSCredentialsProvider credentialsProvider,
ClientConfig clientConfig,
CryptoConfiguration cryptoConfig,
ClientProfile clientProfile) {
String region = cryptoConfig.getKmsRegion();
if (region == null) {
region = clientConfig.getRegion().getRegionName();
}
final TencentCloudKMSClient kmsClient = new TencentCloudKMSClient(credentialsProvider, region, clientProfile);
return kmsClient;
}
private void assertParameterNotNull(Object parameterValue, String errorMessage) {
if (parameterValue == null)
throw new IllegalArgumentException(errorMessage);
}
@Override
public PutObjectResult putObject(PutObjectRequest req) {
return crypto.putObjectSecurely(req.clone());
}
@Override
public COSObject getObject(GetObjectRequest req) {
return crypto.getObjectSecurely(req);
}
@Override
public ObjectMetadata getObject(GetObjectRequest req, File dest) {
return crypto.getObjectSecurely(req, dest);
}
@Override
public void deleteObject(DeleteObjectRequest req) {
// Delete the object
super.deleteObject(req);
// If it exists, delete the instruction file.
InstructionFileId ifid =
new COSObjectId(req.getBucketName(), req.getKey()).instructionFileId();
DeleteObjectRequest instructionDeleteRequest = (DeleteObjectRequest) req.clone();
instructionDeleteRequest.withBucketName(ifid.getBucket()).withKey(ifid.getKey());
super.deleteObject(instructionDeleteRequest);
}
@Override
public CompleteMultipartUploadResult completeMultipartUpload(
CompleteMultipartUploadRequest req) {
return crypto.completeMultipartUploadSecurely(req);
}
@Override
public InitiateMultipartUploadResult initiateMultipartUpload(
InitiateMultipartUploadRequest req) {
boolean isCreateEncryptionMaterial = true;
if (req instanceof EncryptedInitiateMultipartUploadRequest) {
EncryptedInitiateMultipartUploadRequest cryptoReq =
(EncryptedInitiateMultipartUploadRequest) req;
isCreateEncryptionMaterial = cryptoReq.isCreateEncryptionMaterial();
}
return isCreateEncryptionMaterial ? crypto.initiateMultipartUploadSecurely(req)
: super.initiateMultipartUpload(req);
}
/**
* {@inheritDoc}
*
* <p>
* Because the encryption process requires context from block N-1 in order to encrypt block N,
* parts uploaded with the COSEncryptionClient (as opposed to the normal COSClient) must be
* uploaded serially, and in order. Otherwise, the previous encryption context isn't available
* to use when encrypting the current part.
*/
@Override
public UploadPartResult uploadPart(UploadPartRequest uploadPartRequest)
throws CosClientException, CosServiceException {
return crypto.uploadPartSecurely(uploadPartRequest);
}
@Override
public CopyPartResult copyPart(CopyPartRequest copyPartRequest) {
return crypto.copyPartSecurely(copyPartRequest);
}
@Override
public void abortMultipartUpload(AbortMultipartUploadRequest req) {
crypto.abortMultipartUploadSecurely(req);
}
/**
* Creates a new crypto instruction file by re-encrypting the CEK of an existing encrypted COS
* object with a new encryption material identifiable via a new set of material description.
* <p>
* User of this method is responsible for explicitly deleting/updating the instruction file so
* created should the corresponding COS object is deleted/created.
*
* @return the result of the put (instruction file) operation.
*/
public PutObjectResult putInstructionFile(PutInstructionFileRequest req) {
return crypto.putInstructionFileSecurely(req);
}
/**
* {@inheritDoc}
* <p>
* If the a default internal KMS client has been constructed, it will also be shut down by
* calling this method. Otherwise, users who provided the KMS client would be responsible to
* shut down the KMS client extrinsic to this method.
*/
@Override
public void shutdown() {
super.shutdown();
if (isKMSClientInternal)
kms.shutdown();
}
// /////////////////// Access to the methods in the super class //////////
/**
* An internal implementation used to provide limited but direct access to the underlying
* methods of COSClient without any encryption or decryption operations.
*/
public final class COSDirectImpl extends COSDirect {
@Override
public PutObjectResult putObject(PutObjectRequest req) {
return COSEncryptionClient.super.putObject(req);
}
@Override
public COSObject getObject(GetObjectRequest req) {
return COSEncryptionClient.super.getObject(req);
}
@Override
public ObjectMetadata getObject(GetObjectRequest req, File dest) {
return COSEncryptionClient.super.getObject(req, dest);
}
@Override
public CompleteMultipartUploadResult completeMultipartUpload(
CompleteMultipartUploadRequest req) {
return COSEncryptionClient.super.completeMultipartUpload(req);
}
@Override
public InitiateMultipartUploadResult initiateMultipartUpload(
InitiateMultipartUploadRequest req) {
return COSEncryptionClient.super.initiateMultipartUpload(req);
}
@Override
public UploadPartResult uploadPart(UploadPartRequest req)
throws CosClientException, CosServiceException {
return COSEncryptionClient.super.uploadPart(req);
}
@Override
public CopyPartResult copyPart(CopyPartRequest req) {
return COSEncryptionClient.super.copyPart(req);
}
@Override
public void abortMultipartUpload(AbortMultipartUploadRequest req) {
COSEncryptionClient.super.abortMultipartUpload(req);
}
}
}