diff --git a/src/main/java/com/aliyun/oss/common/parser/RequestMarshallers.java b/src/main/java/com/aliyun/oss/common/parser/RequestMarshallers.java
index 4957d002..060e60a8 100644
--- a/src/main/java/com/aliyun/oss/common/parser/RequestMarshallers.java
+++ b/src/main/java/com/aliyun/oss/common/parser/RequestMarshallers.java
@@ -937,6 +937,9 @@ public byte[] marshall(SetBucketEncryptionRequest setBucketEncryptionRequest) {
} else {
xmlBody.append("");
}
+ if (sseByDefault.getKMSDataEncryption() != null) {
+ xmlBody.append("" + sseByDefault.getKMSDataEncryption() + "");
+ }
xmlBody.append("");
xmlBody.append("");
diff --git a/src/main/java/com/aliyun/oss/internal/OSSHeaders.java b/src/main/java/com/aliyun/oss/internal/OSSHeaders.java
index 0fe17e58..013e4128 100644
--- a/src/main/java/com/aliyun/oss/internal/OSSHeaders.java
+++ b/src/main/java/com/aliyun/oss/internal/OSSHeaders.java
@@ -32,6 +32,7 @@ public interface OSSHeaders extends HttpHeaders {
static final String OSS_SERVER_SIDE_ENCRYPTION = "x-oss-server-side-encryption";
static final String OSS_SERVER_SIDE_ENCRYPTION_KEY_ID = "x-oss-server-side-encryption-key-id";
+ static final String OSS_SERVER_SIDE_DATA_ENCRYPTION = "x-oss-server-side-data-encryption";
static final String GET_OBJECT_IF_MODIFIED_SINCE = "If-Modified-Since";
static final String GET_OBJECT_IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
diff --git a/src/main/java/com/aliyun/oss/internal/OSSMultipartOperation.java b/src/main/java/com/aliyun/oss/internal/OSSMultipartOperation.java
index b0145d40..67174570 100644
--- a/src/main/java/com/aliyun/oss/internal/OSSMultipartOperation.java
+++ b/src/main/java/com/aliyun/oss/internal/OSSMultipartOperation.java
@@ -363,6 +363,7 @@ public UploadPartResult uploadPart(UploadPartRequest uploadPartRequest) throws O
result.setETag(trimQuotes(response.getHeaders().get(OSSHeaders.ETAG)));
result.setRequestId(response.getRequestId());
result.setPartSize(uploadPartRequest.getPartSize());
+ result.setResponse(response);
ResponseParsers.setCRC(result, response);
if (getInnerClient().getClientConfiguration().isCrcCheckEnabled()) {
diff --git a/src/main/java/com/aliyun/oss/internal/ResponseParsers.java b/src/main/java/com/aliyun/oss/internal/ResponseParsers.java
index 8a652880..3c341d1d 100644
--- a/src/main/java/com/aliyun/oss/internal/ResponseParsers.java
+++ b/src/main/java/com/aliyun/oss/internal/ResponseParsers.java
@@ -771,6 +771,7 @@ public AppendObjectResult parse(ResponseMessage response) throws ResponseParseEx
result.setNextPosition(Long.valueOf(nextPosition));
}
result.setObjectCRC(response.getHeaders().get(OSSHeaders.OSS_HASH_CRC64_ECMA));
+ result.setResponse(response);
setCRC(result, response);
return result;
} finally {
@@ -904,6 +905,7 @@ public CopyObjectResult parse(ResponseMessage response) throws ResponseParseExce
CopyObjectResult result = parseCopyObjectResult(response.getContent());
result.setVersionId(response.getHeaders().get(OSSHeaders.OSS_HEADER_VERSION_ID));
result.setRequestId(response.getRequestId());
+ result.setResponse(response);
return result;
} finally {
safeCloseResponse(response);
@@ -999,6 +1001,7 @@ public InitiateMultipartUploadResult parse(ResponseMessage response) throws Resp
try {
InitiateMultipartUploadResult result = parseInitiateMultipartUpload(response.getContent());
result.setRequestId(response.getRequestId());
+ result.setResponse(response);
return result;
} finally {
safeCloseResponse(response);
@@ -1052,6 +1055,7 @@ public UploadPartCopyResult parse(ResponseMessage response) throws ResponseParse
result.setPartNumber(partNumber);
result.setETag(trimQuotes(parseUploadPartCopy(response.getContent())));
result.setRequestId(response.getRequestId());
+ result.setResponse(response);
return result;
} finally {
safeCloseResponse(response);
@@ -2382,6 +2386,9 @@ public static BucketInfo parseGetBucketInfo(InputStream responseBody) throws Res
if (sseElem.getChild("KMSMasterKeyID") != null) {
applyServerSideEncryptionByDefault.setKMSMasterKeyID(sseElem.getChildText("KMSMasterKeyID"));
}
+ if (sseElem.getChild("KMSDataEncryption") != null) {
+ applyServerSideEncryptionByDefault.setKMSDataEncryption(sseElem.getChildText("KMSDataEncryption"));
+ }
serverSideEncryptionConfiguration
.setApplyServerSideEncryptionByDefault(applyServerSideEncryptionByDefault);
@@ -2679,6 +2686,7 @@ public static ServerSideEncryptionConfiguration parseGetBucketEncryption(InputSt
Element sseElem = root.getChild("ApplyServerSideEncryptionByDefault");
sseByDefault.setSSEAlgorithm(sseElem.getChildText("SSEAlgorithm"));
sseByDefault.setKMSMasterKeyID(sseElem.getChildText("KMSMasterKeyID"));
+ sseByDefault.setKMSDataEncryption(sseElem.getChildText("KMSDataEncryption"));
configuration.setApplyServerSideEncryptionByDefault(sseByDefault);
return configuration;
diff --git a/src/main/java/com/aliyun/oss/model/DataEncryptionAlgorithm.java b/src/main/java/com/aliyun/oss/model/DataEncryptionAlgorithm.java
new file mode 100644
index 00000000..d0d5ab39
--- /dev/null
+++ b/src/main/java/com/aliyun/oss/model/DataEncryptionAlgorithm.java
@@ -0,0 +1,33 @@
+package com.aliyun.oss.model;
+
+/**
+ * Server-side Data Encryption Algorithm.
+ */
+public enum DataEncryptionAlgorithm {
+ SM4("SM4");
+
+ private final String algorithm;
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ private DataEncryptionAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ @Override
+ public String toString() {
+ return algorithm;
+ }
+
+ public static DataEncryptionAlgorithm fromString(String algorithm) {
+ if (algorithm == null)
+ return null;
+ for (DataEncryptionAlgorithm e: values()) {
+ if (e.getAlgorithm().equals(algorithm))
+ return e;
+ }
+ throw new IllegalArgumentException("Unsupported data encryption algorithm " + algorithm);
+ }
+}
diff --git a/src/main/java/com/aliyun/oss/model/ObjectMetadata.java b/src/main/java/com/aliyun/oss/model/ObjectMetadata.java
index 4e35ad14..b3d20520 100644
--- a/src/main/java/com/aliyun/oss/model/ObjectMetadata.java
+++ b/src/main/java/com/aliyun/oss/model/ObjectMetadata.java
@@ -310,6 +310,25 @@ public void setServerSideEncryptionKeyId(String serverSideEncryptionKeyId) {
metadata.put(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, serverSideEncryptionKeyId);
}
+ /**
+ * Sets the object's server side data encryption.
+ *
+ * @param serverSideDataEncryption
+ * The server side data encryption.
+ */
+ public void setServerSideDataEncryption(String serverSideDataEncryption) {
+ metadata.put(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION, serverSideDataEncryption);
+ }
+
+ /**
+ * Gets the object's server side data encryption.
+ *
+ * @return The server side data encryption. Null means no data encryption.
+ */
+ public String getServerSideDataEncryption() {
+ return (String) metadata.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION);
+ }
+
/**
* Gets the object's storage type, which only supports "normal" and
* "appendable" for now.
diff --git a/src/main/java/com/aliyun/oss/model/SSEAlgorithm.java b/src/main/java/com/aliyun/oss/model/SSEAlgorithm.java
index 455b0274..7817cf11 100755
--- a/src/main/java/com/aliyun/oss/model/SSEAlgorithm.java
+++ b/src/main/java/com/aliyun/oss/model/SSEAlgorithm.java
@@ -25,6 +25,7 @@
public enum SSEAlgorithm {
AES256("AES256"),
KMS("KMS"),
+ SM4("SM4"),
;
private final String algorithm;
diff --git a/src/main/java/com/aliyun/oss/model/ServerSideEncryptionByDefault.java b/src/main/java/com/aliyun/oss/model/ServerSideEncryptionByDefault.java
index 0fb29cfa..1d0fa195 100755
--- a/src/main/java/com/aliyun/oss/model/ServerSideEncryptionByDefault.java
+++ b/src/main/java/com/aliyun/oss/model/ServerSideEncryptionByDefault.java
@@ -27,7 +27,7 @@ public class ServerSideEncryptionByDefault {
private String sseAlgorithm;
private String kmsMasterKeyID;
-
+ private String kmsDataEncryption;
/**
* Creates a default instance.
*
@@ -126,5 +126,31 @@ public ServerSideEncryptionByDefault withKMSMasterKeyID(String kmsMasterKeyID) {
setKMSMasterKeyID(kmsMasterKeyID);
return this;
}
-
+
+ /**
+ * @return This parameter is allowed if SSEAlgorithm is kms.
+ */
+ public String getKMSDataEncryption() {
+ return kmsDataEncryption;
+ }
+
+ /**
+ * Sets the KMS data encryption. This parameter is allowed if SSEAlgorithm is kms.
+ *
+ * @param kmsDataEncryption KMS data encryption to use.
+ */
+ public void setKMSDataEncryption(String kmsDataEncryption) {
+ this.kmsDataEncryption = kmsDataEncryption;
+ }
+
+ /**
+ * Sets the KMS data encryption. This parameter is allowed if SSEAlgorithm is kms.
+ *
+ * @param kmsDataEncryption KMS data encryption to use.
+ * @return This object for method chaining.
+ */
+ public ServerSideEncryptionByDefault withKMSDataEncryption(String kmsDataEncryption) {
+ setKMSDataEncryption(kmsDataEncryption);
+ return this;
+ }
}
diff --git a/src/test/java/com/aliyun/oss/integrationtests/BucketEncryptionTest.java b/src/test/java/com/aliyun/oss/integrationtests/BucketEncryptionTest.java
index 153d48d9..d1cf8e6d 100644
--- a/src/test/java/com/aliyun/oss/integrationtests/BucketEncryptionTest.java
+++ b/src/test/java/com/aliyun/oss/integrationtests/BucketEncryptionTest.java
@@ -19,6 +19,8 @@
package com.aliyun.oss.integrationtests;
+import com.aliyun.oss.internal.OSSHeaders;
+import com.aliyun.oss.model.*;
import junit.framework.Assert;
import org.junit.Test;
@@ -26,21 +28,21 @@
import static com.aliyun.oss.integrationtests.TestUtils.waitForCacheExpiration;
import com.aliyun.oss.OSSException;
-import com.aliyun.oss.model.BucketInfo;
-import com.aliyun.oss.model.SSEAlgorithm;
-import com.aliyun.oss.model.ServerSideEncryptionByDefault;
-import com.aliyun.oss.model.ServerSideEncryptionConfiguration;
-import com.aliyun.oss.model.SetBucketEncryptionRequest;
+
+import java.io.File;
+import java.util.Map;
public class BucketEncryptionTest extends TestBase {
- @Test
- public void testSetBucketEncryption() {
+ private void testSetBucketEncryptionInternal(SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) {
try {
// set
ServerSideEncryptionByDefault applyServerSideEncryptionByDefault =
- new ServerSideEncryptionByDefault(SSEAlgorithm.AES256.toString());
+ new ServerSideEncryptionByDefault(algorithm.toString());
+ if (algorithm == SSEAlgorithm.KMS && dataEncryptionAlgorithm != null) {
+ applyServerSideEncryptionByDefault.setKMSDataEncryption(dataEncryptionAlgorithm.toString());
+ }
ServerSideEncryptionConfiguration setConfiguration = new ServerSideEncryptionConfiguration();
setConfiguration.setApplyServerSideEncryptionByDefault(applyServerSideEncryptionByDefault);
SetBucketEncryptionRequest setRequest = new SetBucketEncryptionRequest(bucketName, setConfiguration);
@@ -49,9 +51,20 @@ public void testSetBucketEncryption() {
// get
ServerSideEncryptionConfiguration getConfiguration = ossClient.getBucketEncryption(bucketName);
- Assert.assertEquals(SSEAlgorithm.AES256.toString(),
+ Assert.assertEquals(algorithm.toString(),
getConfiguration.getApplyServerSideEncryptionByDefault().getSSEAlgorithm());
Assert.assertNull(getConfiguration.getApplyServerSideEncryptionByDefault().getKMSMasterKeyID());
+ Assert.assertEquals(dataEncryptionAlgorithm,
+ DataEncryptionAlgorithm.fromString(getConfiguration.getApplyServerSideEncryptionByDefault().getKMSDataEncryption()));
+ String fileName = TestUtils.genFixedLengthFile(1024);
+ String objectName = "encryption-" + TestUtils.genRandomString(10);
+ ossClient.putObject(bucketName, objectName, new File(fileName));
+
+ Map headers = ossClient.getObject(bucketName, objectName).getResponse().getHeaders();
+ Assert.assertEquals(algorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm == SSEAlgorithm.KMS && dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
@@ -59,13 +72,24 @@ public void testSetBucketEncryption() {
}
@Test
- public void testDeleteBucketEncryption() {
+ public void testSetBucketEncryption() {
+ testSetBucketEncryptionInternal(SSEAlgorithm.AES256, null);
+ testSetBucketEncryptionInternal(SSEAlgorithm.SM4, null);
+ testSetBucketEncryptionInternal(SSEAlgorithm.KMS, null);
+ testSetBucketEncryptionInternal(SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ }
+
+ private void testDeleteBucketEncryptionInternal(SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) {
try {
// set
ServerSideEncryptionByDefault applyServerSideEncryptionByDefault =
- new ServerSideEncryptionByDefault().withSSEAlgorithm(SSEAlgorithm.KMS);
- applyServerSideEncryptionByDefault.setKMSMasterKeyID("test-kms-master-key-id");
+ new ServerSideEncryptionByDefault().withSSEAlgorithm(algorithm);
+ if (algorithm == SSEAlgorithm.KMS)
+ applyServerSideEncryptionByDefault.setKMSMasterKeyID("test-kms-master-key-id");
+ if (algorithm == SSEAlgorithm.KMS && dataEncryptionAlgorithm != null) {
+ applyServerSideEncryptionByDefault.setKMSDataEncryption(dataEncryptionAlgorithm.toString());
+ }
ServerSideEncryptionConfiguration setConfiguration = new ServerSideEncryptionConfiguration()
.withApplyServerSideEncryptionByDefault(applyServerSideEncryptionByDefault);
setConfiguration.setApplyServerSideEncryptionByDefault(applyServerSideEncryptionByDefault);
@@ -76,11 +100,13 @@ public void testDeleteBucketEncryption() {
// get
ServerSideEncryptionConfiguration getConfiguration = ossClient.getBucketEncryption(bucketName);
- Assert.assertEquals(SSEAlgorithm.KMS.toString(),
+ Assert.assertEquals(algorithm.toString(),
getConfiguration.getApplyServerSideEncryptionByDefault().getSSEAlgorithm());
- Assert.assertEquals("test-kms-master-key-id",
- getConfiguration.getApplyServerSideEncryptionByDefault().getKMSMasterKeyID());
-
+ if (algorithm == SSEAlgorithm.KMS)
+ Assert.assertEquals("test-kms-master-key-id",
+ getConfiguration.getApplyServerSideEncryptionByDefault().getKMSMasterKeyID());
+ Assert.assertEquals(dataEncryptionAlgorithm,
+ DataEncryptionAlgorithm.fromString(getConfiguration.getApplyServerSideEncryptionByDefault().getKMSDataEncryption()));
// delete
ossClient.deleteBucketEncryption(bucketName);
waitForCacheExpiration(3);
@@ -98,12 +124,22 @@ public void testDeleteBucketEncryption() {
}
@Test
- public void testBucketInfo() {
+ public void testDeleteBucketEncryption() {
+ testDeleteBucketEncryptionInternal(SSEAlgorithm.AES256, null);
+ testDeleteBucketEncryptionInternal(SSEAlgorithm.SM4, null);
+ testDeleteBucketEncryptionInternal(SSEAlgorithm.KMS, null);
+ testDeleteBucketEncryptionInternal(SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ }
+
+ public void testBucketInfoInternal(SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) {
try {
// set 1
ServerSideEncryptionByDefault applyServerSideEncryptionByDefault =
- new ServerSideEncryptionByDefault(SSEAlgorithm.AES256);
+ new ServerSideEncryptionByDefault(algorithm);
+ if (algorithm == SSEAlgorithm.KMS && dataEncryptionAlgorithm != null) {
+ applyServerSideEncryptionByDefault.setKMSDataEncryption(dataEncryptionAlgorithm.toString());
+ }
ServerSideEncryptionConfiguration setConfiguration = new ServerSideEncryptionConfiguration();
setConfiguration.setApplyServerSideEncryptionByDefault(applyServerSideEncryptionByDefault);
SetBucketEncryptionRequest setRequest = new SetBucketEncryptionRequest(bucketName, setConfiguration);
@@ -112,10 +148,14 @@ public void testBucketInfo() {
// get
BucketInfo bucketInfo = ossClient.getBucketInfo(bucketName);
- Assert.assertEquals(SSEAlgorithm.AES256.toString(), bucketInfo.getServerSideEncryptionConfiguration()
+ Assert.assertEquals(algorithm.toString(), bucketInfo.getServerSideEncryptionConfiguration()
.getApplyServerSideEncryptionByDefault().getSSEAlgorithm());
- Assert.assertNull(bucketInfo.getServerSideEncryptionConfiguration()
+ if (algorithm != SSEAlgorithm.KMS)
+ Assert.assertNull(bucketInfo.getServerSideEncryptionConfiguration()
.getApplyServerSideEncryptionByDefault().getKMSMasterKeyID());
+ Assert.assertEquals(dataEncryptionAlgorithm,
+ DataEncryptionAlgorithm.fromString(bucketInfo.getServerSideEncryptionConfiguration()
+ .getApplyServerSideEncryptionByDefault().getKMSDataEncryption()));
// delete
ossClient.deleteBucketEncryption(bucketName);
@@ -151,4 +191,11 @@ public void testBucketInfo() {
}
}
+ @Test
+ public void testBucketInfo() {
+ testBucketInfoInternal(SSEAlgorithm.AES256, null);
+ testBucketInfoInternal(SSEAlgorithm.SM4, null);
+ testBucketInfoInternal(SSEAlgorithm.KMS, null);
+ testBucketInfoInternal(SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ }
}
diff --git a/src/test/java/com/aliyun/oss/integrationtests/ObjectEncryptionTest.java b/src/test/java/com/aliyun/oss/integrationtests/ObjectEncryptionTest.java
new file mode 100644
index 00000000..de3ce8b1
--- /dev/null
+++ b/src/test/java/com/aliyun/oss/integrationtests/ObjectEncryptionTest.java
@@ -0,0 +1,364 @@
+package com.aliyun.oss.integrationtests;
+
+import com.aliyun.oss.internal.OSSHeaders;
+import com.aliyun.oss.model.AppendObjectRequest;
+import com.aliyun.oss.model.AppendObjectResult;
+import com.aliyun.oss.model.CompleteMultipartUploadRequest;
+import com.aliyun.oss.model.CompleteMultipartUploadResult;
+import com.aliyun.oss.model.CopyObjectRequest;
+import com.aliyun.oss.model.CopyObjectResult;
+import com.aliyun.oss.model.DataEncryptionAlgorithm;
+import com.aliyun.oss.model.InitiateMultipartUploadRequest;
+import com.aliyun.oss.model.InitiateMultipartUploadResult;
+import com.aliyun.oss.model.ObjectMetadata;
+import com.aliyun.oss.model.OSSObject;
+import com.aliyun.oss.model.PutObjectRequest;
+import com.aliyun.oss.model.PutObjectResult;
+import com.aliyun.oss.model.SSEAlgorithm;
+import com.aliyun.oss.model.UploadPartCopyRequest;
+import com.aliyun.oss.model.UploadPartCopyResult;
+import com.aliyun.oss.model.UploadPartRequest;
+import com.aliyun.oss.model.UploadPartResult;
+import junit.framework.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Map;
+
+import static com.aliyun.oss.integrationtests.TestUtils.buildObjectKey;
+import static com.aliyun.oss.integrationtests.TestUtils.genFixedLengthFile;
+import static com.aliyun.oss.integrationtests.TestUtils.removeFile;
+
+public class ObjectEncryptionTest extends TestBase {
+ private static final int ITERATIONS = 100;
+ @Test
+ public void testNormalObject() throws Exception {
+ testNormalObject(null, null);
+ testNormalObject(SSEAlgorithm.AES256, null);
+ testNormalObject(SSEAlgorithm.SM4, null);
+ testNormalObject(SSEAlgorithm.KMS, null);
+ testNormalObject(SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ }
+
+ private void testNormalObject(SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) throws Exception {
+ for (int i = 0; i < ITERATIONS; ++i) {
+ final String keyPrefix = "normal-file-encryption-";
+ final String filePath = genFixedLengthFile(i * 1024 * 100 + 1024); // 1KB
+ try {
+ // 1. put
+ ObjectMetadata metadata = new ObjectMetadata();
+ if (algorithm != null) {
+ metadata.setServerSideEncryption(algorithm.toString());
+ }
+ if (dataEncryptionAlgorithm != null) {
+ metadata.setServerSideDataEncryption(dataEncryptionAlgorithm.toString());
+ }
+ PutObjectRequest request = new PutObjectRequest(bucketName, buildObjectKey(keyPrefix, i), new File(filePath), metadata);
+ request.setProcess("");
+ PutObjectResult result = ossClient.putObject(request);
+ Map headers = result.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+ // 2. get
+ byte[] target = Files.readAllBytes(Paths.get(filePath));
+ checkObjectContent(target, buildObjectKey(keyPrefix, i), algorithm, dataEncryptionAlgorithm);
+ // 3. copy without encryption
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), null, null);
+ // 4. copy with the same encryption
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), algorithm, dataEncryptionAlgorithm);
+ // 5. copy with different encryption
+ if (dataEncryptionAlgorithm == null) {
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ } else {
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.KMS, null);
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.SM4, null);
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.AES256, null);
+ }
+ } catch (Exception ex) {
+ Assert.fail(ex.getMessage());
+ } finally {
+ removeFile(filePath);
+ }
+ }
+ }
+
+ private void copyObject(byte[] target, String srcKey, String dstKey, SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) throws Exception {
+ CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, srcKey, bucketName, dstKey);
+ ObjectMetadata metadata = new ObjectMetadata();
+ if (algorithm != null) {
+ metadata.setServerSideEncryption(algorithm.toString());
+ }
+ if (dataEncryptionAlgorithm != null) {
+ metadata.setServerSideDataEncryption(dataEncryptionAlgorithm.toString());
+ }
+ copyObjectRequest.setNewObjectMetadata(metadata);
+ CopyObjectResult copyObjectResult = ossClient.copyObject(copyObjectRequest);
+ checkObjectContent(target, dstKey, algorithm, dataEncryptionAlgorithm);
+ Map headers = copyObjectResult.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+ }
+
+ private void checkObjectContent(byte[] target, String key, SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) throws Exception {
+ OSSObject ossObject = ossClient.getObject(bucketName, key);
+ Assert.assertEquals(target.length, ossObject.getObjectMetadata().getContentLength());
+ byte[] source = new byte[target.length];
+ int read;
+ int len = 0;
+ while ((read = ossObject.getObjectContent().read(source, len, 1024 * 1024)) != -1) {
+ len += read;
+ }
+ Assert.assertEquals(new String(target), new String(source));
+ Assert.assertEquals(algorithm != null,
+ ossObject.getResponse().getHeaders().containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(ossObject.getResponse().getHeaders().get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ ossObject.getResponse().getHeaders().containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), ossObject.getResponse().getHeaders().get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+ }
+
+ @Test
+ public void testAppendObject() throws Exception {
+ testAppendObject(null, null);
+ testAppendObject(SSEAlgorithm.AES256, null);
+ testAppendObject(SSEAlgorithm.SM4, null);
+ testAppendObject(SSEAlgorithm.KMS, null);
+ testAppendObject(SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ }
+
+ private void testAppendObject(SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) throws Exception {
+ for (int i = 0; i < ITERATIONS; ++i) {
+ final String keyPrefix = "append-file-encryption-";
+ final String filePath = genFixedLengthFile(i * 1024 * 100 + 1024); // 1KB
+ try {
+ ObjectMetadata metadata = new ObjectMetadata();
+ if (algorithm != null) {
+ metadata.setServerSideEncryption(algorithm.toString());
+ }
+ if (dataEncryptionAlgorithm != null) {
+ metadata.setServerSideDataEncryption(dataEncryptionAlgorithm.toString());
+ }
+ // first append
+ AppendObjectRequest request = new AppendObjectRequest(bucketName, buildObjectKey(keyPrefix, i), new File(filePath), metadata);
+ request.setPosition(0L);
+ AppendObjectResult result = ossClient.appendObject(request);
+ Map headers = result.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+
+ // second append with different encryption
+ metadata = new ObjectMetadata();
+ if (dataEncryptionAlgorithm == null) {
+ metadata.setServerSideEncryption(SSEAlgorithm.KMS.toString());
+ metadata.setServerSideDataEncryption(DataEncryptionAlgorithm.SM4.toString());
+ } else {
+ metadata.setServerSideEncryption(SSEAlgorithm.KMS.toString());
+ }
+ request = new AppendObjectRequest(bucketName, buildObjectKey(keyPrefix, i), new File(filePath), metadata);
+ request.setPosition(i * 1024 * 100 + 1024L);
+ result = ossClient.appendObject(request);
+ headers = result.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+
+ // third append with the same encryption
+ if (algorithm != null) {
+ metadata.setServerSideEncryption(algorithm.toString());
+ }
+ if (dataEncryptionAlgorithm != null) {
+ metadata.setServerSideDataEncryption(dataEncryptionAlgorithm.toString());
+ }
+ request = new AppendObjectRequest(bucketName, buildObjectKey(keyPrefix, i), new File(filePath), metadata);
+ request.setPosition(2 * (i * 1024 * 100 + 1024L));
+ result = ossClient.appendObject(request);
+ headers = result.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+
+ // 2. get
+ byte[] content = Files.readAllBytes(Paths.get(filePath));
+ byte[] target = new byte[content.length * 3];
+ System.arraycopy(content, 0, target, 0, content.length);
+ System.arraycopy(content, 0, target, content.length, content.length);
+ System.arraycopy(content, 0, target, content.length * 2, content.length);
+ checkObjectContent(target, buildObjectKey(keyPrefix, i), algorithm, dataEncryptionAlgorithm);
+ // 3. copy without encryption
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), null, null);
+ // 4. copy with the same encryption
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), algorithm, dataEncryptionAlgorithm);
+ // 5. copy with different encryption
+ if (dataEncryptionAlgorithm == null) {
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ } else {
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.KMS, null);
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.SM4, null);
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.AES256, null);
+ }
+ } catch (Exception ex) {
+ Assert.fail(ex.getMessage());
+ } finally {
+ ossClient.deleteObject(bucketName, buildObjectKey(keyPrefix, i));
+ removeFile(filePath);
+ }
+ }
+ }
+
+ @Test
+ public void testMultipartObject() throws Exception {
+ testMultipartObject(null, null);
+ testMultipartObject(SSEAlgorithm.AES256, null);
+ testMultipartObject(SSEAlgorithm.SM4, null);
+ testMultipartObject(SSEAlgorithm.KMS, null);
+ testMultipartObject(SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ }
+
+ private void testMultipartObject(SSEAlgorithm algorithm, DataEncryptionAlgorithm dataEncryptionAlgorithm) throws Exception {
+ for (int i = 0; i < ITERATIONS; ++i) {
+ final String keyPrefix = "multipart-file-encryption-";
+ final String filePath = genFixedLengthFile(i * 1024 * 100 + 102400); // 1KB
+ try {
+ ObjectMetadata metadata = new ObjectMetadata();
+ if (algorithm != null) {
+ metadata.setServerSideEncryption(algorithm.toString());
+ }
+ if (dataEncryptionAlgorithm != null) {
+ metadata.setServerSideDataEncryption(dataEncryptionAlgorithm.toString());
+ }
+ InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, buildObjectKey(keyPrefix, i), metadata);
+ InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
+ Map headers = result.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+
+ UploadPartRequest uploadPartRequest = new UploadPartRequest(bucketName, buildObjectKey(keyPrefix, i),
+ result.getUploadId(), 1, new FileInputStream(new File(filePath)), i * 1024 * 100 + 102400);
+ UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
+ headers = uploadPartResult.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+
+ //String sourceBucketName, String sourceKey, String targetBucketName, String targetKey,
+ // String uploadId, int partNumber, Long beginIndex, Long partSize
+ ossClient.putObject(bucketName, buildObjectKey(keyPrefix, i) + ".normal", new File(filePath));
+ UploadPartCopyRequest uploadPartCopyRequest = new UploadPartCopyRequest(bucketName, buildObjectKey(keyPrefix, i) + ".normal", bucketName, buildObjectKey(keyPrefix, i),
+ result.getUploadId(), 2, 0L, i * 1024 * 100 + 102400L);
+ UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);
+ headers = uploadPartCopyResult.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+
+ CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, buildObjectKey(keyPrefix, i), result.getUploadId(),
+ Arrays.asList(uploadPartResult.getPartETag(), uploadPartCopyResult.getPartETag()));
+ completeMultipartUploadRequest.setProcess("");
+ CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
+ headers = completeMultipartUploadResult.getResponse().getHeaders();
+ Assert.assertEquals(algorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION));
+ if (algorithm != null) {
+ Assert.assertEquals(headers.get(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION), algorithm.toString());
+ }
+ Assert.assertEquals(dataEncryptionAlgorithm != null,
+ headers.containsKey(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ if (dataEncryptionAlgorithm != null) {
+ Assert.assertEquals(dataEncryptionAlgorithm.toString(), headers.get(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION));
+ }
+
+ // 2. get
+ byte[] content = Files.readAllBytes(Paths.get(filePath));
+ byte[] target = new byte[content.length * 2];
+ System.arraycopy(content, 0, target, 0, content.length);
+ System.arraycopy(content, 0, target, content.length, content.length);
+ checkObjectContent(target, buildObjectKey(keyPrefix, i), algorithm, dataEncryptionAlgorithm);
+ // 3. copy without encryption
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), null, null);
+ // 4. copy with the same encryption
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), algorithm, dataEncryptionAlgorithm);
+ // 5. copy with different encryption
+ if (dataEncryptionAlgorithm == null) {
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.KMS, DataEncryptionAlgorithm.SM4);
+ } else {
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.KMS, null);
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.SM4, null);
+ copyObject(target, buildObjectKey(keyPrefix, i), buildObjectKey(keyPrefix + "copy-", i), SSEAlgorithm.AES256, null);
+ }
+ } catch (Exception ex) {
+ Assert.fail(ex.getMessage());
+ } finally {
+ ossClient.deleteObject(bucketName, buildObjectKey(keyPrefix, i));
+ removeFile(filePath);
+ }
+ }
+ }
+}