Enkripsi sisi klien OSS memungkinkan Anda mengenkripsi data secara lokal sebelum mengunggahnya ke OSS, sehingga hanya pemegang kunci yang dapat mendekripsi data tersebut. Hal ini meningkatkan keamanan data selama transmisi dan penyimpanan.
Penafian
Saat menggunakan enkripsi sisi klien, Anda harus memastikan integritas dan validitas CMK. Jika CMK digunakan secara tidak tepat atau hilang akibat pemeliharaan yang tidak sesuai, Anda bertanggung jawab atas seluruh kerugian dan konsekuensi yang disebabkan oleh kegagalan dekripsi.
Saat menyalin atau memigrasikan data terenkripsi, Anda bertanggung jawab atas integritas dan validitas metadata objek. Jika metadata terenkripsi salah atau hilang akibat pemeliharaan yang tidak sesuai, Anda bertanggung jawab atas seluruh kerugian dan konsekuensi yang disebabkan oleh kegagalan dekripsi data.
Skenario
Data sangat sensitif: Untuk data yang berisi informasi sangat sensitif, seperti informasi identitas pribadi (PII), catatan transaksi keuangan, atau data kesehatan medis, Anda dapat mengenkripsi data sebelum meninggalkan lingkungan lokal Anda. Hal ini memastikan data mentah tetap terlindungi bahkan jika disadap selama transmisi.
Persyaratan kepatuhan: Beberapa industri dan regulasi, seperti HIPAA dan GDPR, mewajibkan kontrol enkripsi ketat untuk data yang disimpan di platform pihak ketiga. Enkripsi sisi klien membantu memenuhi persyaratan kepatuhan ini karena Anda mengelola kuncinya sendiri. Kunci tersebut tidak dikirim melalui jaringan atau dikendalikan langsung oleh penyedia layanan cloud.
Kontrol otonom yang lebih kuat: Bisnis atau pengembang mungkin menginginkan kontrol penuh atas proses enkripsi, termasuk memilih algoritma enkripsi serta mengelola dan memutar kunci. Enkripsi sisi klien memberikan tingkat kontrol ini dan memastikan hanya pengguna yang berwenang yang dapat mendekripsi dan mengakses data.
Keamanan migrasi data lintas wilayah: Saat memigrasikan data dari satu wilayah ke wilayah lain, enkripsi sisi klien memastikan data tetap terenkripsi sebelum, selama, dan setelah migrasi. Hal ini meningkatkan keamanan data selama transmisi melalui Internet.
Catatan
Dalam topik ini, titik akhir publik wilayah Tiongkok (Hangzhou) digunakan. Untuk mengakses OSS dari layanan Alibaba Cloud lainnya dalam wilayah yang sama, gunakan titik akhir internal. Untuk detail tentang wilayah dan titik akhir yang didukung, lihat Wilayah dan titik akhir.
Dalam topik ini, kredensial akses diperoleh dari variabel lingkungan. Untuk informasi lebih lanjut tentang cara mengonfigurasi kredensial akses, lihat Konfigurasi kredensial akses.
Dalam topik ini, instans OSSClient dibuat menggunakan titik akhir OSS. Jika ingin membuat instans OSSClient menggunakan nama domain kustom atau Security Token Service (STS), lihat Contoh konfigurasi untuk skenario umum.
Informasi latar belakang
Dalam enkripsi sisi klien, kunci data acak dihasilkan untuk setiap objek guna melakukan enkripsi simetris pada objek tersebut. Klien menggunakan CMK untuk mengenkripsi kunci data acak tersebut. Kunci data terenkripsi diunggah sebagai bagian dari metadata objek dan disimpan di server OSS. Saat objek terenkripsi diunduh, klien menggunakan CMK untuk mendekripsi kunci data acak, lalu menggunakan kunci data yang telah didekripsi tersebut untuk mendekripsi objek. Untuk memastikan keamanan data, CMK hanya digunakan di sisi klien dan tidak dikirim melalui jaringan atau disimpan di server.
Enkripsi sisi klien mendukung unggah multi-bagian untuk file yang lebih besar dari 5 GB. Saat menggunakan unggah multi-bagian, Anda harus menentukan ukuran total file dan ukuran bagian. Ukuran setiap bagian, kecuali bagian terakhir, harus sama. Ukuran bagian harus kelipatan 16.
Setelah mengunggah file menggunakan enkripsi sisi klien, metadata enkripsi dilindungi. Anda tidak dapat menggunakan CopyObject untuk memodifikasi metadata objek.
Metode enkripsi
Anda dapat menggunakan dua jenis CMK untuk enkripsi sisi klien:
CMK yang dikelola oleh KMS
Saat menggunakan CMK yang dikelola di Key Management Service (KMS) untuk enkripsi sisi klien, Anda harus memberikan ID CMK ke OSS SDK for Python.
CMK berbasis RSA yang dikelola sendiri
Saat menggunakan CMK yang dikelola sendiri untuk enkripsi sisi klien, Anda harus mengirim kunci publik dan kunci privat CMK Anda sebagai parameter ke OSS SDK for Python.
Anda dapat menggunakan metode enkripsi di atas untuk mencegah kebocoran data dan melindungi data Anda di sisi klien. Bahkan jika data Anda bocor, data tersebut tidak dapat didekripsi oleh pihak lain.
Metadata enkripsi
Parameter | Deskripsi | Wajib |
x-oss-meta-client-side-encryption-key | Kunci terenkripsi. String Base64 yang dienkripsi dengan kunci master. | Ya |
x-oss-meta-client-side-encryption-start | Nilai awal acak yang digunakan untuk mengenkripsi data. String Base64 yang dienkripsi dengan kunci master. | Ya |
x-oss-meta-client-side-encryption-cek-alg | Algoritma enkripsi untuk data. | Ya |
x-oss-meta-client-side-encryption-wrap-alg | Algoritma enkripsi untuk kunci data. | Ya |
x-oss-meta-client-side-encryption-matdesc | Deskripsi kunci master. Formatnya JSON. Peringatan Konfigurasikan deskripsi untuk setiap kunci master. Simpan pemetaan antara kunci master dan deskripsinya. Jika tidak, Anda tidak dapat mengubah kunci master untuk enkripsi setelah data dienkripsi. | Tidak |
x-oss-meta-client-side-encryption-unencrypted-content-length | Panjang data sebelum enkripsi. Parameter ini tidak dihasilkan jika `content-length` tidak ditentukan. | Tidak |
x-oss-meta-client-side-encryption-unencrypted-content-md5 | Hash MD5 dari data sebelum enkripsi. Parameter ini tidak dihasilkan jika hash MD5 tidak ditentukan. | Tidak |
x-oss-meta-client-side-encryption-data-size | Jika Anda mengenkripsi file menggunakan unggah multi-bagian, Anda harus meneruskan ukuran total file besar selama `init_multipart`. | Ya (untuk unggah multi-bagian) |
x-oss-meta-client-side-encryption-part-size | Jika Anda mengenkripsi file menggunakan unggah multi-bagian, Anda harus meneruskan ukuran bagian selama `init_multipart`. Penting Ukuran bagian harus kelipatan 16. | Ya (untuk unggah multi-bagian) |
Deskripsi tool OpenSSL
Tool OpenSSL 3.x menghasilkan PRIVATE_PKCS8_PEM secara default. Untuk menghasilkan PRIVATE_PKCS1_PEM, gunakan opsi -traditional. Untuk informasi lebih lanjut, lihat OpenSSL.
Buat klien enkripsi
Saat membuat klien enkripsi RSA atau KMS, Anda harus menggunakan OSS Java SDK versi 3.9.1 atau lebih baru. Anda juga harus mengimpor library Java Bouncy Castle (bcprov-jdk15on) ke proyek Maven Anda.
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
</dependency>Jika terjadi error java.security.InvalidKeyException: Illegal key size or default parameters saat runtime, Anda harus menambahkan file Oracle JCE ke lingkungan JRE Anda.
Unduh file yang sesuai dengan versi JDK Anda. Ekstrak file tersebut dan letakkan di direktori jre/lib/security.
JCE Unlimited Strength Jurisdiction Policy Files untuk JDK 6
JCE Unlimited Strength Jurisdiction Policy Files untuk JDK 7
JCE Unlimited Strength Jurisdiction Policy Files untuk JDK 8
Buat klien enkripsi RSA
Sebelum membuat klien enkripsi RSA, Anda harus membuat objek KeyPair asimetris. OSS Java SDK menyediakan metode untuk mengonversi string kunci privat dalam format PEM PKCS#1 atau PKCS#8 menjadi objek RSAPrivateKey. SDK ini juga menyediakan metode untuk mengonversi string kunci publik dalam format PEM X.509 menjadi objek RSAPublicKey.
Metode konversi kunci tersebut adalah sebagai berikut:
RSAPrivateKey SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(String privateKeyStr);
RSAPrivateKey SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS8(String privateKeyStr);
RSAPublicKey SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(String publicKeyStr);
Kode berikut memberikan contoh cara membuat klien enkripsi RSA:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// Titik akhir diatur ke Tiongkok (Hangzhou) sebagai contoh. Atur ke wilayah aktual Anda.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Anda dapat menggunakan perintah berikut untuk menghasilkan file PEM kunci privat dan publik. Lalu, salin string dari file PEM ke variabel PRIVATE_PKCS1_PEM dan PUBLIC_X509_PEM.
// openssl genrsa -out private_key.pem 2048
// openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout
// Tentukan string kunci privat RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci privat RSA.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Tentukan string kunci publik RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci publik RSA.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Buat pasangan kunci RSA.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Buat deskripsi untuk kunci master RSA. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master dan kunci master memiliki pemetaan satu-ke-satu.
// Jika semua objek menggunakan kunci master yang sama, deskripsinya dapat dikosongkan. Namun, Anda tidak dapat mengubah kunci master nanti.
// Jika deskripsi kunci master kosong, klien tidak dapat menentukan kunci master mana yang digunakan untuk mengenkripsi file selama dekripsi.
// Konfigurasikan deskripsi untuk setiap kunci master. Klien harus menyimpan pemetaan antara kunci master dan deskripsinya. Server tidak menyimpan pemetaan ini.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Buat material enkripsi RSA.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan kunci RSA lain, tambahkan kunci master lain dan deskripsinya ke material enkripsi.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Buat klien enkripsi RSA.
// Saat klien enkripsi RSA tidak lagi diperlukan, panggil metode shutdown untuk melepaskan sumber dayanya.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Tambahkan kode bisnis Anda di sini.
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan tanggapan error karena suatu alasan.");
System.out.println("Pesan Error:" + oe.getErrorMessage());
System.out.println("Kode Error:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("ID Host:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti klien mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Error:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}Buat klien enkripsi KMS
Saat membuat klien enkripsi KMS, Anda harus mengimpor library Java Bouncy Castle (bcprov-jdk15on) dan library Java Alibaba Cloud KMS (kms-transfer-client) ke proyek Maven Anda.
<dependency>
<groupId>com.aliyun.kms</groupId>
<artifactId>kms-transfer-client</artifactId>
<version>0.1.0</version>
<scope>test</scope>
</dependency>Kode berikut memberikan contoh cara membuat klien enkripsi KMS:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.crypto.ContentCryptoMaterialRW;
import com.aliyun.oss.crypto.EncryptionMaterials;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.kms.model.v20160120.DecryptRequest;
import com.aliyuncs.kms.model.v20160120.DecryptResponse;
import com.aliyuncs.kms.model.v20160120.EncryptRequest;
import com.aliyuncs.kms.model.v20160120.EncryptResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// Titik akhir diatur ke Tiongkok (Hangzhou) sebagai contoh. Atur ke wilayah aktual Anda.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Kunci master pelanggan (CMK), misalnya e1935511-cf88-1123-a0f8-1be8d251****.
String cmk = "e1935511-cf88-1123-a0f8-1be8d251****";
// Wilayah tempat CMK berada, misalnya cn-hangzhou.
String region = "cn-hangzhou";
// Buat deskripsi untuk kunci master KMS. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master, wilayah, dan CMK memiliki pemetaan satu-ke-satu.
// Jika semua objek menggunakan CMK yang sama, deskripsinya dapat dikosongkan. Namun, Anda tidak dapat mengubah kunci master nanti.
// Jika deskripsi kunci master kosong, klien tidak dapat menentukan kunci master mana yang digunakan untuk mengenkripsi file selama dekripsi.
// Konfigurasikan deskripsi untuk setiap kunci master. Klien harus menyimpan pemetaan antara kunci master dan deskripsinya. Server tidak menyimpan pemetaan ini.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Buat material enkripsi KMS.
KmsEncryptionMaterialsV3 encryptionMaterials = new KmsEncryptionMaterialsV3(region, cmk, matDesc);
encryptionMaterials.setKmsCredentialsProvider(credentialsProvider);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan CMK lain, tambahkan nama wilayah dan deskripsi CMK ke material enkripsi KMS.
// encryptionMaterials.addKmsDescMaterial(<otherKmsRegion>, <otherKmsMatDesc>);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan CMK lain saat akun KMS berbeda dengan akun klien OSS, tambahkan nama wilayah KMS, kredensial, dan deskripsi ke material enkripsi.
// encryptionMaterials.addKmsDescMaterial(<otherKmsRegion>, <otherKmsCredentialsProvider>, <otherKmsMatDesc>);
// Buat klien enkripsi.
// Saat klien enkripsi tidak lagi diperlukan, panggil metode shutdown untuk melepaskan sumber dayanya.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Tambahkan kode bisnis Anda di sini.
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan tanggapan error karena suatu alasan.");
System.out.println("Pesan Error:" + oe.getErrorMessage());
System.out.println("Kode Error:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("ID Host:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti klien mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Error:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
class KmsEncryptionMaterialsV3 implements EncryptionMaterials {
private static final String KEY_WRAP_ALGORITHM = "KMS/ALICLOUD";
private String region;
private String cmk;
CredentialsProvider credentialsProvider;
private final Map<String, String> desc;
private final LinkedHashMap<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>> kmsDescMaterials =
new LinkedHashMap<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>>();
public KmsEncryptionMaterialsV3(String region, String cmk) {
assertParameterNotNull(region, "kms region");
assertParameterNotNull(cmk, "kms cmk");
this.region = region;
this.cmk = cmk;
this.desc = new HashMap<String, String>();
}
public KmsEncryptionMaterialsV3(String region, String cmk, Map<String, String> desc) {
assertParameterNotNull(region, "kms region");
assertParameterNotNull(region, "kms cmk");
this.region = region;
this.cmk = cmk;
this.desc = (desc == null) ? new HashMap<String, String>() : new HashMap<String, String>(desc);
}
private final class KmsClientSuite {
private String region;
private CredentialsProvider credentialsProvider;
KmsClientSuite(String region, CredentialsProvider credentialsProvider) {
this.region = region;
this.credentialsProvider = credentialsProvider;
}
}
public void setKmsCredentialsProvider(CredentialsProvider credentialsProvider) {
this.credentialsProvider = credentialsProvider;
kmsDescMaterials.put(new KmsEncryptionMaterialsV3.KmsClientSuite(region, credentialsProvider), desc);
}
private DefaultAcsClient createKmsClient(String region, CredentialsProvider credentialsPorvider) {
Credentials credentials = credentialsPorvider.getCredentials();
IClientProfile profile = DefaultProfile.getProfile(region, credentials.getAccessKeyId(),
credentials.getSecretAccessKey(), credentials.getSecurityToken());
return new KmsTransferAcsClient(profile);
}
private EncryptResponse encryptPlainText(String keyId, String plainText) throws ClientException {
DefaultAcsClient kmsClient = createKmsClient(region, credentialsProvider);
final EncryptRequest encReq = new EncryptRequest();
encReq.setSysProtocol(ProtocolType.HTTPS);
encReq.setAcceptFormat(FormatType.JSON);
encReq.setSysMethod(MethodType.POST);
encReq.setKeyId(keyId);
encReq.setPlaintext(plainText);
final EncryptResponse encResponse;
try {
encResponse = kmsClient.getAcsResponse(encReq);
} catch (Exception e) {
throw new ClientException("Klien KMS gagal mengenkripsi data. " + e.getMessage(), e);
}
return encResponse;
}
private DecryptResponse decryptCipherBlob(KmsEncryptionMaterialsV3.KmsClientSuite kmsClientSuite, String cipherBlob)
throws ClientException {
final DefaultAcsClient kmsClient = createKmsClient(kmsClientSuite.region, kmsClientSuite.credentialsProvider);
final DecryptRequest decReq = new DecryptRequest();
decReq.setSysProtocol(ProtocolType.HTTPS);
decReq.setAcceptFormat(FormatType.JSON);
decReq.setSysMethod(MethodType.POST);
decReq.setCiphertextBlob(cipherBlob);
final DecryptResponse decResponse;
try {
decResponse = kmsClient.getAcsResponse(decReq);
} catch (Exception e) {
throw new ClientException("Klien KMS gagal mendekripsi data. " + e.getMessage(), e);
}
return decResponse;
}
public void addKmsDescMaterial(String region, Map<String, String> description) {
addKmsDescMaterial(region, credentialsProvider, description);
}
public synchronized void addKmsDescMaterial(String region, CredentialsProvider credentialsProvider, Map<String, String> description) {
assertParameterNotNull(region, "region");
assertParameterNotNull(credentialsProvider, "credentialsProvider");
KmsEncryptionMaterialsV3.KmsClientSuite kmsClientSuite = new KmsEncryptionMaterialsV3.KmsClientSuite(region, credentialsProvider);
if (description != null) {
kmsDescMaterials.put(kmsClientSuite, new HashMap<String, String>(description));
} else {
kmsDescMaterials.put(kmsClientSuite, new HashMap<String, String>());
}
}
private KmsEncryptionMaterialsV3.KmsClientSuite findKmsClientSuiteByDescription(Map<String, String> desc) {
if (desc == null) {
return null;
}
for (Map.Entry<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>> entry : kmsDescMaterials.entrySet()) {
if (desc.equals(entry.getValue())) {
return entry.getKey();
}
}
return null;
}
private <K, V> Map.Entry<K, V> getTailByReflection(LinkedHashMap<K, V> map)
throws NoSuchFieldException, IllegalAccessException {
Field tail = map.getClass().getDeclaredField("tail");
tail.setAccessible(true);
return (Map.Entry<K, V>) tail.get(map);
}
@Override
public void encryptCEK(ContentCryptoMaterialRW contentMaterialRW) {
try {
assertParameterNotNull(contentMaterialRW, "contentMaterialRW");
assertParameterNotNull(contentMaterialRW.getIV(), "contentMaterialRW#getIV");
assertParameterNotNull(contentMaterialRW.getCEK(), "contentMaterialRW#getCEK");
byte[] iv = contentMaterialRW.getIV();
EncryptResponse encryptresponse = encryptPlainText(cmk, BinaryUtil.toBase64String(iv));
byte[] encryptedIV = BinaryUtil.fromBase64String(encryptresponse.getCiphertextBlob());
SecretKey cek = contentMaterialRW.getCEK();
encryptresponse = encryptPlainText(cmk, BinaryUtil.toBase64String(cek.getEncoded()));
byte[] encryptedCEK = BinaryUtil.fromBase64String(encryptresponse.getCiphertextBlob());
contentMaterialRW.setEncryptedCEK(encryptedCEK);
contentMaterialRW.setEncryptedIV(encryptedIV);
contentMaterialRW.setKeyWrapAlgorithm(KEY_WRAP_ALGORITHM);
contentMaterialRW.setMaterialsDescription(desc);
} catch (Exception e) {
throw new ClientException("Gagal mengenkripsi CEK dan IV dengan KMS. "
+ "Periksa CMK, wilayah, ID AccessKey, dan Rahasia AccessKey Anda." + e.getMessage(), e);
}
}
@Override
public void decryptCEK(ContentCryptoMaterialRW contentMaterialRW) {
assertParameterNotNull(contentMaterialRW, "ContentCryptoMaterialRW");
assertParameterNotNull(contentMaterialRW.getEncryptedCEK(), "ContentCryptoMaterialRW#getEncryptedCEK");
assertParameterNotNull(contentMaterialRW.getEncryptedIV(), "ContentCryptoMaterialRW#getEncryptedIV");
assertParameterNotNull(contentMaterialRW.getKeyWrapAlgorithm(), "ContentCryptoMaterialRW#getKeyWrapAlgorithm");
if (!contentMaterialRW.getKeyWrapAlgorithm().toLowerCase().equals(KEY_WRAP_ALGORITHM.toLowerCase())) {
throw new ClientException(
"Algoritma pembungkus kunci objek tidak dikenali: " + contentMaterialRW.getKeyWrapAlgorithm());
}
try {
KmsEncryptionMaterialsV3.KmsClientSuite kmsClientSuite = findKmsClientSuiteByDescription(contentMaterialRW.getMaterialsDescription());
if (kmsClientSuite == null) {
Map.Entry<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>> entry = getTailByReflection(kmsDescMaterials);
kmsClientSuite = entry.getKey();
}
DecryptResponse decryptIvResp = decryptCipherBlob(kmsClientSuite,
BinaryUtil.toBase64String(contentMaterialRW.getEncryptedIV()));
byte[] iv = BinaryUtil.fromBase64String(decryptIvResp.getPlaintext());
DecryptResponse decryptCEKResp = decryptCipherBlob(kmsClientSuite,
BinaryUtil.toBase64String(contentMaterialRW.getEncryptedCEK()));
byte[] cekBytes = BinaryUtil.fromBase64String(decryptCEKResp.getPlaintext());
SecretKey cek = new SecretKeySpec(cekBytes, "");
contentMaterialRW.setCEK(cek);
contentMaterialRW.setIV(iv);
} catch (Exception e) {
throw new ClientException("Tidak dapat mendekripsi kunci dan IV yang diamankan konten. "
+ "Periksa wilayah KMS dan deskripsi material Anda." + e.getMessage(), e);
}
}
private void assertParameterNotNull(Object parameterValue, String errorMessage) {
if (parameterValue == null)
throw new IllegalArgumentException(errorMessage);
}
}Bagian berikut memberikan contoh lengkap cara menggunakan kunci master yang dikelola pengguna (RSA) untuk skenario seperti mengunggah dan mengunduh file, unggah multi-bagian, serta unduhan rentang.
Satu-satunya perbedaan antara penggunaan kunci master KMS dan kunci master RSA adalah cara membuat OSSEncryptionClient.
Unggah dan unduh file
Kode berikut memberikan contoh cara mengunggah dan mengunduh objek menggunakan kunci master RSA:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.OSSObject;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// Titik akhir diatur ke Tiongkok (Hangzhou) sebagai contoh. Atur ke wilayah aktual Anda.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Tentukan nama bucket, misalnya examplebucket.
String bucketName = "examplebucket";
// Tentukan path lengkap objek, misalnya exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
String objectName = "exampleobject.txt";
String content = "Hello OSS!";
// Tentukan string kunci privat RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci privat RSA.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Tentukan string kunci publik RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci publik RSA.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Buat pasangan kunci RSA.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Buat deskripsi untuk kunci master RSA. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master dan kunci master memiliki pemetaan satu-ke-satu.
// Jika semua objek menggunakan kunci master yang sama, deskripsinya dapat dikosongkan. Namun, Anda tidak dapat mengubah kunci master nanti.
// Jika deskripsi kunci master kosong, klien tidak dapat menentukan kunci master mana yang digunakan untuk mengenkripsi file selama dekripsi.
// Konfigurasikan deskripsi untuk setiap kunci master. Klien harus menyimpan pemetaan antara kunci master dan deskripsinya. Server tidak menyimpan pemetaan ini.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Buat material enkripsi RSA.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan kunci RSA lain, tambahkan kunci master lain dan deskripsinya ke material enkripsi.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Buat klien enkripsi.
// Saat klien enkripsi tidak lagi diperlukan, panggil metode shutdown untuk melepaskan sumber dayanya.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Enkripsi dan unggah file.
ossEncryptionClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
// File secara otomatis didekripsi selama pengunduhan.
OSSObject ossObject = ossEncryptionClient.getObject(bucketName, objectName);
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
// Periksa apakah konten yang didekripsi cocok dengan teks biasa yang diunggah.
System.out.println("Teks biasa yang diunggah: " + content);
System.out.println("Teks yang diunduh dan didekripsi: " + buffer.toString());
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan tanggapan error karena suatu alasan.");
System.out.println("Pesan Error:" + oe.getErrorMessage());
System.out.println("Kode Error:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("ID Host:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti klien mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Error:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}Unggah multi-bagian
Kode berikut memberikan contoh cara melakukan unggah multi-bagian menggunakan kunci master RSA:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.MultipartUploadCryptoContext;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.io.*;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// Titik akhir diatur ke Tiongkok (Hangzhou) sebagai contoh. Atur ke wilayah aktual Anda.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Tentukan nama bucket, misalnya examplebucket.
String bucketName = "examplebucket";
// Tentukan path lengkap objek, misalnya exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
String objectName = "exampleobject.txt";
// Path file. Misalnya, D:\\localpath\\examplefile.txt
String localFile = "D:\\localpath\\examplefile.txt";
// Tentukan string kunci privat RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci privat RSA.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Tentukan string kunci publik RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci publik RSA.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Buat pasangan kunci RSA.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Buat deskripsi untuk kunci master RSA. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master dan kunci master memiliki pemetaan satu-ke-satu.
// Jika semua objek menggunakan kunci master yang sama, deskripsinya dapat dikosongkan. Namun, Anda tidak dapat mengubah kunci master nanti.
// Jika deskripsi kunci master kosong, klien tidak dapat menentukan kunci master mana yang digunakan untuk mengenkripsi file selama dekripsi.
// Konfigurasikan deskripsi untuk setiap kunci master. Klien harus menyimpan pemetaan antara kunci master dan deskripsinya. Server tidak menyimpan pemetaan ini.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Buat material enkripsi RSA.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan kunci RSA lain, tambahkan kunci master lain dan deskripsinya ke material enkripsi.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Buat klien enkripsi.
// Saat klien enkripsi tidak lagi diperlukan, panggil metode shutdown untuk melepaskan sumber dayanya.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Buat objek MultipartUploadCryptoContext dan tentukan ukuran bagian serta ukuran file. Ukuran bagian harus kelipatan 16.
File file = new File(localFile);
long fileLength = file.length();
final long partSize = 100 * 1024L; // 100K
MultipartUploadCryptoContext context = new MultipartUploadCryptoContext();
context.setPartSize(partSize);
context.setDataSize(fileLength);
// Inisialisasi event unggah multi-bagian.
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName, objectName);
// Teruskan objek MultipartUploadCryptoContext.
InitiateMultipartUploadResult upresult = ossEncryptionClient.initiateMultipartUpload(initiateMultipartUploadRequest, context);
String uploadId = upresult.getUploadId();
// Buat daftar PartETags. PartETag terdiri dari ETag dan nomor bagian dari suatu bagian.
List<PartETag> partETags = new ArrayList<PartETag>();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// Unggah bagian dalam loop.
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
InputStream instream = new FileInputStream(file);
instream.skip(startPos);
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(objectName);
uploadPartRequest.setUploadId(uploadId);
uploadPartRequest.setInputStream(instream);
uploadPartRequest.setPartSize(curPartSize);
uploadPartRequest.setPartNumber( i + 1);
// Teruskan objek MultipartUploadCryptoContext.
UploadPartResult uploadPartResult = ossEncryptionClient.uploadPart(uploadPartRequest, context);
partETags.add(uploadPartResult.getPartETag());
}
// Selesaikan unggah multi-bagian.
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
ossEncryptionClient.completeMultipartUpload(completeMultipartUploadRequest);
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan tanggapan error karena suatu alasan.");
System.out.println("Pesan Error:" + oe.getErrorMessage());
System.out.println("Kode Error:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("ID Host:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti klien mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Error:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}Unggah yang dapat dilanjutkan
Kode berikut memberikan contoh cara melakukan unggah yang dapat dilanjutkan menggunakan kunci master RSA:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// Titik akhir diatur ke Tiongkok (Hangzhou) sebagai contoh. Atur ke wilayah aktual Anda.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Tentukan nama bucket, misalnya examplebucket.
String bucketName = "examplebucket";
// Tentukan path lengkap objek, misalnya exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
String objectName = "exampleobject.txt";
// Path file. Misalnya, D:\\localpath\\examplefile.txt
String localFile = "D:\\localpath\\examplefile.txt";
// Tentukan string kunci privat RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci privat RSA.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Tentukan string kunci publik RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci publik RSA.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Buat pasangan kunci RSA.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Buat deskripsi untuk kunci master RSA. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master dan kunci master memiliki pemetaan satu-ke-satu.
// Jika semua objek menggunakan kunci master yang sama, deskripsinya dapat dikosongkan. Namun, Anda tidak dapat mengubah kunci master nanti.
// Jika deskripsi kunci master kosong, klien tidak dapat menentukan kunci master mana yang digunakan untuk mengenkripsi file selama dekripsi.
// Konfigurasikan deskripsi untuk setiap kunci master. Klien harus menyimpan pemetaan antara kunci master dan deskripsinya. Server tidak menyimpan pemetaan ini.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Buat material enkripsi RSA.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan kunci RSA lain, tambahkan kunci master lain dan deskripsinya ke material enkripsi.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Buat klien enkripsi.
// Saat klien enkripsi tidak lagi diperlukan, panggil metode shutdown untuk melepaskan sumber dayanya.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Buat objek UploadFileRequest.
UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, objectName);
// Atur path file yang akan diunggah.
uploadFileRequest.setUploadFile(localFile);
// Tentukan ukuran bagian untuk unggah. Nilainya harus dalam rentang 100 KB hingga 5 GB. Nilai default adalah 1/10.000 dari ukuran file.
uploadFileRequest.setPartSize(100 * 1024);
// Aktifkan unggah yang dapat dilanjutkan. Fitur ini dinonaktifkan secara default.
uploadFileRequest.setEnableCheckpoint(true);
// Atur file titik pemeriksaan. Jika tidak ditentukan, nama default adalah localfile + ".ucp" di direktori yang sama dengan file lokal.
// Progres unggah disimpan ke file ini. Jika suatu bagian gagal diunggah, unggah dilanjutkan dari titik putus yang tercatat saat Anda mencoba lagi. File ini dihapus setelah unggah selesai.
uploadFileRequest.setCheckpointFile("test-upload.ucp");
// Mulai unggah yang dapat dilanjutkan.
ossEncryptionClient.uploadFile(uploadFileRequest);
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan tanggapan error karena suatu alasan.");
System.out.println("Pesan Error:" + oe.getErrorMessage());
System.out.println("Kode Error:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("ID Host:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti klien mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Error:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}Unduhan yang dapat dilanjutkan
Kode berikut memberikan contoh cara melakukan unduhan yang dapat dilanjutkan menggunakan kunci master RSA:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// Titik akhir diatur ke Tiongkok (Hangzhou) sebagai contoh. Atur ke wilayah aktual Anda.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Tentukan nama bucket, misalnya examplebucket.
String bucketName = "examplebucket";
// Tentukan path lengkap objek, misalnya exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
String objectName = "exampleobject.txt";
// Tentukan string kunci privat RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci privat RSA.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Tentukan string kunci publik RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci publik RSA.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Buat pasangan kunci RSA.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Buat deskripsi untuk kunci master RSA. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master dan kunci master memiliki pemetaan satu-ke-satu.
// Jika semua objek menggunakan kunci master yang sama, deskripsinya dapat dikosongkan. Namun, Anda tidak dapat mengubah kunci master nanti.
// Jika deskripsi kunci master kosong, klien tidak dapat menentukan kunci master mana yang digunakan untuk mengenkripsi file selama dekripsi.
// Konfigurasikan deskripsi untuk setiap kunci master. Klien harus menyimpan pemetaan antara kunci master dan deskripsinya. Server tidak menyimpan pemetaan ini.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Buat material enkripsi RSA.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan kunci RSA lain, tambahkan kunci master lain dan deskripsinya ke material enkripsi.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Buat klien enkripsi.
// Saat klien enkripsi tidak lagi diperlukan, panggil metode shutdown untuk melepaskan sumber dayanya.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Inisialisasi permintaan unduh. Tentukan 10 tugas unduh konkuren dan aktifkan unduhan yang dapat dilanjutkan.
DownloadFileRequest downloadFileRequest = new DownloadFileRequest(bucketName, objectName);
downloadFileRequest.setDownloadFile("<yourDownloadFile>");
downloadFileRequest.setPartSize(1 * 1024 * 1024);
downloadFileRequest.setTaskNum(10);
downloadFileRequest.setEnableCheckpoint(true);
downloadFileRequest.setCheckpointFile("<yourCheckpointFile>");
// Mulai unduhan yang dapat dilanjutkan.
DownloadFileResult downloadRes = ossEncryptionClient.downloadFile(downloadFileRequest);
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan tanggapan error karena suatu alasan.");
System.out.println("Pesan Error:" + oe.getErrorMessage());
System.out.println("Kode Error:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("ID Host:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti klien mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Error:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}Unduhan rentang
Kode berikut memberikan contoh cara melakukan unduhan rentang dan mendekripsi data yang diunduh menggunakan kunci master RSA:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// Titik akhir diatur ke Tiongkok (Hangzhou) sebagai contoh. Atur ke wilayah aktual Anda.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Tentukan nama bucket, misalnya examplebucket.
String bucketName = "examplebucket";
// Tentukan path lengkap objek, misalnya exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket.
String objectName = "exampleobject.txt";
String content = "test-range-get-content-82042795hlnf12s8yhfs976y2nfoshhnsdfsf235bvsmnhtskbcfd!";
// Tentukan string kunci privat RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci privat RSA.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Tentukan string kunci publik RSA Anda. Anda dapat menghasilkannya menggunakan OpenSSL. Nilai berikut adalah contoh string kunci publik RSA.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Buat pasangan kunci RSA.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Buat deskripsi untuk kunci master RSA. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master dan kunci master memiliki pemetaan satu-ke-satu.
// Jika semua objek menggunakan kunci master yang sama, deskripsinya dapat dikosongkan. Namun, Anda tidak dapat mengubah kunci master nanti.
// Jika deskripsi kunci master kosong, klien tidak dapat menentukan kunci master mana yang digunakan untuk mengenkripsi file selama dekripsi.
// Konfigurasikan deskripsi untuk setiap kunci master. Klien harus menyimpan pemetaan antara kunci master dan deskripsinya. Server tidak menyimpan pemetaan ini.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Buat material enkripsi RSA.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// Untuk mengunduh dan mendekripsi file yang dienkripsi dengan kunci RSA lain, tambahkan kunci master lain dan deskripsinya ke material enkripsi.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Buat klien enkripsi.
// Saat klien enkripsi tidak lagi diperlukan, panggil metode shutdown untuk melepaskan sumber dayanya.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Enkripsi dan unggah file.
ossEncryptionClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
// Lakukan unduhan rentang.
int start = 17;
int end = 35;
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectName);
getObjectRequest.setRange(start, end);
OSSObject ossObject = ossEncryptionClient.getObject(getObjectRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
// Lihat hasil unduhan rentang.
System.out.println("Teks biasa Unduhan Rentang:" + content.substring(start, end + 1));
System.out.println("Teks yang didekripsi Unduhan Rentang: " + buffer.toString());
} catch (OSSException oe) {
System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
+ "tetapi ditolak dengan tanggapan error karena suatu alasan.");
System.out.println("Pesan Error:" + oe.getErrorMessage());
System.out.println("Kode Error:" + oe.getErrorCode());
System.out.println("ID Permintaan:" + oe.getRequestId());
System.out.println("ID Host:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Terjadi ClientException, yang berarti klien mengalami "
+ "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
+ "seperti tidak dapat mengakses jaringan.");
System.out.println("Pesan Error:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}Referensi
Untuk kode contoh lengkap enkripsi sisi klien, lihat contoh GitHub.