Skip to content

Commit 13dfdf9

Browse files
liyanzhang505huiguangjun
authored andcommitted
add client-side encryption.
1 parent c564383 commit 13dfdf9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+6875
-23
lines changed

pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@
5959
<artifactId>aliyun-java-sdk-ecs</artifactId>
6060
<version>4.2.0</version>
6161
</dependency>
62+
<dependency>
63+
<groupId>com.aliyun</groupId>
64+
<artifactId>aliyun-java-sdk-kms</artifactId>
65+
<version>2.7.0</version>
66+
</dependency>
67+
<dependency>
68+
<groupId>org.bouncycastle</groupId>
69+
<artifactId>bcprov-jdk15on</artifactId>
70+
<version>1.62</version>
71+
</dependency>
6272
<dependency>
6373
<groupId>junit</groupId>
6474
<artifactId>junit</artifactId>

src/main/java/com/aliyun/oss/ClientErrorCode.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,9 @@ public interface ClientErrorCode {
5656
* The input stream is not repeatable for reading.
5757
*/
5858
static final String NONREPEATABLE_REQUEST = "NonRepeatableRequest";
59-
59+
60+
/**
61+
* Thread interrupted while reading the input stream.
62+
*/
63+
static final String INPUTSTREAM_READING_ABORTED = "InputStreamReadingAborted";
6064
}

src/main/java/com/aliyun/oss/OSSClient.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,26 @@ public class OSSClient implements OSS {
7878
private OSSDownloadOperation downloadOperation;
7979
private LiveChannelOperation liveChannelOperation;
8080

81+
/**Gets the inner multipartOperation, used for subclass to do implement opreation.*/
82+
public OSSMultipartOperation getMultipartOperation() {
83+
return multipartOperation;
84+
}
85+
86+
/**Gets the inner objectOperation, used for subclass to do implement opreation.*/
87+
public OSSObjectOperation getObjectOperation() {
88+
return objectOperation;
89+
}
90+
91+
/**Sets the inner downloadOperation.*/
92+
public void setDownloadOperation(OSSDownloadOperation downloadOperation) {
93+
this.downloadOperation = downloadOperation;
94+
}
95+
96+
/**Sets the inner uploadOperation.*/
97+
public void setUploadOperation(OSSUploadOperation uploadOperation) {
98+
this.uploadOperation = uploadOperation;
99+
}
100+
81101
/**
82102
* Uses the default OSS Endpoint(http://oss-cn-hangzhou.aliyuncs.com) and
83103
* Access Id/Access Key to create a new {@link OSSClient} instance.
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package com.aliyun.oss;
21+
22+
import java.io.File;
23+
import java.io.InputStream;
24+
import java.net.URL;
25+
import java.util.Map;
26+
import com.aliyun.oss.common.auth.CredentialsProvider;
27+
import com.aliyun.oss.crypto.*;
28+
import com.aliyun.oss.internal.OSSDownloadOperationEncrypted;
29+
import com.aliyun.oss.internal.OSSUploadOperationEncrypted;
30+
import com.aliyun.oss.model.*;
31+
import static com.aliyun.oss.crypto.CryptoModuleBase.hasEncryptionInfo;
32+
33+
/**
34+
* OSSEncryptionClient is used to do client-side encryption.
35+
*/
36+
public class OSSEncryptionClient extends OSSClient {
37+
public static final String USER_AGENT_SUFFIX = "/OSSEncryptionClient";
38+
private final EncryptionMaterials encryptionMaterials;
39+
private final CryptoConfiguration cryptoConfig;
40+
private final OSSDirect ossDirect = new OSSDirectImpl();
41+
42+
public OSSEncryptionClient(String endpoint, CredentialsProvider credsProvider, ClientConfiguration clientConfig,
43+
EncryptionMaterials encryptionMaterials, CryptoConfiguration cryptoConfig) {
44+
super(endpoint, credsProvider, clientConfig);
45+
assertParameterNotNull(credsProvider, "CredentialsProvider");
46+
assertParameterNotNull(encryptionMaterials, "EncryptionMaterials");
47+
if(encryptionMaterials instanceof KmsEncryptionMaterials) {
48+
((KmsEncryptionMaterials)encryptionMaterials).setKmsCredentialsProvider(credsProvider);
49+
}
50+
this.cryptoConfig = cryptoConfig == null ? CryptoConfiguration.DEFAULT : cryptoConfig;
51+
this.encryptionMaterials = encryptionMaterials;
52+
}
53+
54+
@Override
55+
public PutObjectResult putObject(PutObjectRequest req) throws OSSException, ClientException {
56+
CryptoModule crypto = new CryptoModuleDispatcher(ossDirect, encryptionMaterials, cryptoConfig);
57+
return crypto.putObjectSecurely(req);
58+
}
59+
60+
@Override
61+
public OSSObject getObject(GetObjectRequest req) throws OSSException, ClientException {
62+
if(req.isUseUrlSignature()) {
63+
throw new ClientException("Encryption client error, get object with url opreation is disabled in encryption client." +
64+
"Please use normal oss client method {@OSSClient#getObject(GetObjectRequest req)}.");
65+
}
66+
CryptoModule crypto = new CryptoModuleDispatcher(ossDirect, encryptionMaterials, cryptoConfig);
67+
return crypto.getObjectSecurely(req);
68+
}
69+
70+
@Override
71+
public ObjectMetadata getObject(GetObjectRequest req, File file) throws OSSException, ClientException {
72+
CryptoModule crypto = new CryptoModuleDispatcher(ossDirect, encryptionMaterials, cryptoConfig);
73+
return crypto.getObjectSecurely(req, file);
74+
}
75+
76+
@Override
77+
public UploadFileResult uploadFile(UploadFileRequest uploadFileRequest) throws Throwable {
78+
OSSUploadOperationEncrypted ossUploadOperationEncrypted = new OSSUploadOperationEncrypted(this, encryptionMaterials);
79+
this.setUploadOperation(ossUploadOperationEncrypted);
80+
return super.uploadFile(uploadFileRequest);
81+
}
82+
83+
@Override
84+
public DownloadFileResult downloadFile(DownloadFileRequest downloadFileRequest) throws Throwable {
85+
GenericRequest genericRequest = new GenericRequest(downloadFileRequest.getBucketName(), downloadFileRequest.getKey());
86+
String versionId = downloadFileRequest.getVersionId();
87+
if (versionId != null) {
88+
genericRequest.setVersionId(versionId);
89+
}
90+
Payer payer = downloadFileRequest.getRequestPayer();
91+
if (payer != null) {
92+
genericRequest.setRequestPayer(payer);
93+
}
94+
ObjectMetadata objectMetadata = getObjectMetadata(genericRequest);
95+
96+
long objectSize = objectMetadata.getContentLength();
97+
if (objectSize <= downloadFileRequest.getPartSize()) {
98+
GetObjectRequest getObjectRequest = convertToGetObjectRequest(downloadFileRequest);
99+
objectMetadata = this.getObject(getObjectRequest, new File(downloadFileRequest.getDownloadFile()));
100+
DownloadFileResult downloadFileResult = new DownloadFileResult();
101+
downloadFileResult.setObjectMetadata(objectMetadata);
102+
return downloadFileResult;
103+
} else {
104+
if (!hasEncryptionInfo(objectMetadata)) {
105+
return super.downloadFile(downloadFileRequest);
106+
} else {
107+
long partSize = downloadFileRequest.getPartSize();
108+
if (0 != (partSize % CryptoScheme.BLOCK_SIZE) || partSize <= 0) {
109+
throw new IllegalArgumentException("download file part size is not 16 bytes alignment.");
110+
}
111+
OSSDownloadOperationEncrypted ossDownloadOperationEncrypted = new OSSDownloadOperationEncrypted(this);
112+
this.setDownloadOperation(ossDownloadOperationEncrypted);
113+
return super.downloadFile(downloadFileRequest);
114+
}
115+
}
116+
}
117+
118+
private static GetObjectRequest convertToGetObjectRequest(DownloadFileRequest downloadFileRequest) {
119+
GetObjectRequest getObjectRequest = new GetObjectRequest(downloadFileRequest.getBucketName(),
120+
downloadFileRequest.getKey());
121+
getObjectRequest.setMatchingETagConstraints(downloadFileRequest.getMatchingETagConstraints());
122+
getObjectRequest.setNonmatchingETagConstraints(downloadFileRequest.getNonmatchingETagConstraints());
123+
getObjectRequest.setModifiedSinceConstraint(downloadFileRequest.getModifiedSinceConstraint());
124+
getObjectRequest.setUnmodifiedSinceConstraint(downloadFileRequest.getUnmodifiedSinceConstraint());
125+
getObjectRequest.setResponseHeaders(downloadFileRequest.getResponseHeaders());
126+
127+
long[] range = downloadFileRequest.getRange();
128+
if (range != null) {
129+
getObjectRequest.setRange(range[0], range[1]);
130+
}
131+
132+
String versionId = downloadFileRequest.getVersionId();
133+
if (versionId != null) {
134+
getObjectRequest.setVersionId(versionId);
135+
}
136+
137+
Payer payer = downloadFileRequest.getRequestPayer();
138+
if (payer != null) {
139+
getObjectRequest.setRequestPayer(payer);
140+
}
141+
142+
int limit = downloadFileRequest.getTrafficLimit();
143+
if (limit > 0) {
144+
getObjectRequest.setTrafficLimit(limit);
145+
}
146+
147+
return getObjectRequest;
148+
}
149+
150+
public InitiateMultipartUploadResult initiateMultipartUpload(InitiateMultipartUploadRequest request,
151+
MultipartUploadCryptoContext context)
152+
throws OSSException, ClientException {
153+
CryptoModule crypto = new CryptoModuleDispatcher(ossDirect, encryptionMaterials, cryptoConfig);
154+
return crypto.initiateMultipartUploadSecurely(request, context);
155+
}
156+
157+
public UploadPartResult uploadPart(UploadPartRequest request, MultipartUploadCryptoContext context) {
158+
CryptoModule crypto = new CryptoModuleDispatcher(ossDirect, encryptionMaterials, cryptoConfig);
159+
return crypto.uploadPartSecurely(request, context);
160+
}
161+
162+
public CompleteMultipartUploadResult completeMultipartUpload(CompleteMultipartUploadRequest request,
163+
MultipartUploadCryptoContext context)
164+
throws OSSException, ClientException {
165+
return super.completeMultipartUpload(request);
166+
}
167+
168+
169+
///////////////////////////////////////////////////////////////////////////////////////////////
170+
////////////////////////////////// Disabled api in encryption client///////////////////////////
171+
/**
172+
* Note: This method is disabled in encryption client.
173+
*
174+
* @deprecated please use encryption client method
175+
* {@link OSSEncryptionClient#initiateMultipartUpload(InitiateMultipartUploadRequest request, MultipartUploadCryptoContext context)}.
176+
*/
177+
@Override
178+
@Deprecated
179+
public InitiateMultipartUploadResult initiateMultipartUpload(InitiateMultipartUploadRequest request) throws ClientException {
180+
throw new ClientException("Encryption client error, you should provide a multipart upload context to the encryption client. " +
181+
"Please use encryption client method {@link OSSEncryptionClient#initiateMultipartUpload(InitiateMultipartUploadRequest request, " +
182+
"MultipartUploadCryptoContext context)}.");
183+
}
184+
185+
/**
186+
* Note: This method is disabled in encryption client.
187+
*
188+
* @deprecated please use encryption client method
189+
* {@link OSSEncryptionClient#uploadPart(UploadPartRequest request, MultipartUploadCryptoContext context)}.
190+
*/
191+
@Override
192+
@Deprecated
193+
public UploadPartResult uploadPart(UploadPartRequest request) throws ClientException {
194+
throw new ClientException("Encryption client error, you should provide a multipart upload context to the encryption client. " +
195+
"Please use encryption client method {@link OSSEncryptionClient#uploadPart(UploadPartRequest request, MultipartUploadCryptoContext context)}.");
196+
}
197+
198+
/**
199+
* Note: This method is disabled in encryption client.
200+
*
201+
* @deprecated please use normal oss client method
202+
* {@link OSSClient#appendObject(AppendObjectRequest appendObjectRequest)}.
203+
*/
204+
@Override
205+
@Deprecated
206+
public AppendObjectResult appendObject(AppendObjectRequest appendObjectRequest) throws ClientException {
207+
throw new ClientException("Encryption client error, this method is disabled in encryption client." +
208+
"Please use normal oss client method {@link OSSClient#appendObject(AppendObjectRequest appendObjectRequest)} method");
209+
}
210+
211+
/**
212+
* Note: This method is disabled in encryption client.
213+
*
214+
* @deprecated please use normal oss client method
215+
* {@link OSSClient#uploadPartCopy(UploadPartCopyRequest request)}.
216+
*/
217+
@Override
218+
@Deprecated
219+
public UploadPartCopyResult uploadPartCopy(UploadPartCopyRequest request) throws ClientException {
220+
throw new ClientException("Encryption client error, this method is disabled in encryption client." +
221+
"Please use normal oss client method {@link OSSClient#uploadPartCopy(UploadPartCopyRequest request)}");
222+
}
223+
224+
/**
225+
* Note: This method is disabled in encryption client.
226+
*
227+
* @deprecated please use normal oss client method
228+
* {@link OSSClient}#putObject(URL signedUrl, InputStream requestContent, long contentLength,
229+
* Map<String, String> requestHeaders, boolean useChunkEncoding).
230+
*/
231+
@Override
232+
@Deprecated
233+
public PutObjectResult putObject(URL signedUrl, InputStream requestContent, long contentLength,
234+
Map<String, String> requestHeaders, boolean useChunkEncoding) throws ClientException {
235+
throw new ClientException("Encryption client error, this method is disabled in encryption client." +
236+
"Please use normal oss client method {@link OSSClient#putObject(URL signedUrl, InputStream requestContent, "
237+
+ "long contentLength, Map<String, String> requestHeaders, boolean useChunkEncoding)");
238+
}
239+
240+
241+
private final class OSSDirectImpl implements OSSDirect {
242+
@Override
243+
public ClientConfiguration getInnerClientConfiguration() {
244+
return OSSEncryptionClient.this.getClientConfiguration();
245+
}
246+
247+
@Override
248+
public PutObjectResult putObject(PutObjectRequest putObjectRequest) {
249+
return OSSEncryptionClient.super.putObject(putObjectRequest);
250+
}
251+
252+
@Override
253+
public OSSObject getObject(GetObjectRequest getObjectRequest) {
254+
return OSSEncryptionClient.super.getObject(getObjectRequest);
255+
}
256+
257+
@Override
258+
public void abortMultipartUpload(AbortMultipartUploadRequest request) {
259+
OSSEncryptionClient.super.abortMultipartUpload(request);
260+
}
261+
262+
@Override
263+
public CompleteMultipartUploadResult completeMultipartUpload(CompleteMultipartUploadRequest request) {
264+
return OSSEncryptionClient.super.completeMultipartUpload(request);
265+
}
266+
267+
@Override
268+
public InitiateMultipartUploadResult initiateMultipartUpload(InitiateMultipartUploadRequest request) {
269+
return OSSEncryptionClient.super.initiateMultipartUpload(request);
270+
}
271+
272+
@Override
273+
public UploadPartResult uploadPart(UploadPartRequest request) {
274+
return OSSEncryptionClient.super.uploadPart(request);
275+
}
276+
}
277+
278+
private void assertParameterNotNull(Object parameterValue,
279+
String errorMessage) {
280+
if (parameterValue == null)
281+
throw new IllegalArgumentException(errorMessage);
282+
}
283+
}

0 commit comments

Comments
 (0)