全部产品
Search
文档中心

Object Storage Service:Enkripsi sisi klien (Go SDK V2)

更新时间:Nov 09, 2025

Enkripsi sisi klien OSS memungkinkan Anda mengenkripsi data secara lokal sebelum mengunggahnya ke OSS. Hal ini memastikan bahwa hanya pemegang kunci yang berwenang yang dapat mendekripsi data, meningkatkan keamanan selama transmisi dan penyimpanan.

Peringatan

  • Kode contoh dalam topik ini menggunakan ID Wilayah China (Hangzhou), cn-hangzhou, dan titik akhir publik secara default. Jika Anda ingin mengakses OSS dari layanan Alibaba Cloud lain di wilayah yang sama, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang pemetaan antara Wilayah OSS dan titik akhir, lihat Wilayah dan Titik Akhir.

  • Contoh-contoh dalam topik ini membaca kredensial akses dari variabel lingkungan. Untuk informasi lebih lanjut tentang cara mengonfigurasi kredensial akses, lihat Konfigurasi Kredensial Akses.

  • Saat menggunakan fitur enkripsi sisi klien, Anda bertanggung jawab atas integritas kunci utama.

  • Saat menyalin atau memigrasi data terenkripsi, Anda bertanggung jawab atas integritas metadata enkripsi.

Definisi Metode

Go SDK V2 mendukung metode berikut untuk menggunakan kunci master:

  • Menggunakan kunci master yang dikelola pengguna (RSA)

    SDK menyediakan implementasi default dari RSA. Anda harus memberikan kunci publik dan kunci privat dari kunci master ke SDK sebagai parameter.

  • Menggunakan kunci master kustom

    Jika metode kunci master RSA tidak memenuhi kebutuhan Anda, Anda dapat mengimplementasikan perilaku enkripsi dan dekripsi kustom untuk kunci master. Topik ini menggunakan Alibaba Cloud KMS 3.0 sebagai contoh untuk menunjukkan cara menyesuaikan enkripsi dan dekripsi kunci master.

Dengan menggunakan dua metode enkripsi ini, data klien dapat dilindungi secara efektif dari kebocoran. Bahkan jika data terenkripsi disusupi, data tersebut tidak dapat didekripsi untuk mengungkapkan data mentah.

Penting

Untuk informasi lebih lanjut tentang prinsip enkripsi sisi klien OSS, lihat Enkripsi Sisi Klien.

Untuk menggunakan enkripsi sisi klien, Anda harus terlebih dahulu membuat instance klien enkripsi dan kemudian memanggil antarmuka klien untuk melakukan operasi. Objek Anda akan dienkripsi dan didekripsi secara otomatis sebagai bagian dari permintaan.

type EncryptionClient struct {
  ...
}

func NewEncryptionClient(c *Client, masterCipher crypto.MasterCipher, optFns ...func(*EncryptionClientOptions)) (eclient *EncryptionClient, err error)

Parameter permintaan

Parameter

Tipe

Deskripsi

c

*Client

Sebuah instance klien non-terenkripsi

masterCipher

crypto.MasterCipher

Instance kunci master, yang digunakan untuk mengenkripsi dan mendekripsi kunci data.

optFns

...func(*EncryptionClientOptions)

(Opsional) Opsi konfigurasi untuk klien enkripsi.

Tabel berikut menjelaskan opsi EncryptionClientOptions.

Parameter

Tipe

Deskripsi

MasterCiphers

[]crypto.MasterCipher

Kelompok instance kunci master, yang digunakan untuk mendekripsi kunci data.

Nilai Pengembalian

Nilai Pengembalian

Tipe

Deskripsi

eclient

*EncryptionClient

Instance klien enkripsi. Parameter ini valid hanya ketika err adalah nil.

err

error

Status pembuatan klien enkripsi. Jika operasi gagal, err tidak nil.

Tabel berikut mencantumkan antarmuka EncryptionClient.

Antarmuka Dasar

Deskripsi

GetObjectMeta

Mendapatkan beberapa metadata dari sebuah objek.

HeadObject

Mendapatkan beberapa metadata dari sebuah objek.

GetObject

Mengunduh sebuah objek dan secara otomatis mendekripsinya.

PutObject

Mengunggah sebuah objek dan secara otomatis mengenkripsinya.

InitiateMultipartUpload

Menginisialisasi event unggah multi-bagian dan konteks enkripsi sharding (EncryptionMultiPartContext).

UploadPart

Menginisialisasi event unggah multi-bagian. Anda dapat memanggil antarmuka ini untuk mengunggah data bagian dan secara otomatis mengenkripsi data tersebut. Saat memanggil antarmuka ini, Anda harus menetapkan konteks enkripsi sharding.

CompleteMultipartUpload

Setelah semua data bagian diunggah, Anda dapat memanggil antarmuka ini untuk menggabungkan bagian-bagian menjadi satu file.

AbortMultipartUpload

Membatalkan event unggah multi-bagian dan menghapus data bagian yang sesuai.

ListParts

Mendaftarkan semua bagian yang berhasil diunggah yang termasuk dalam event unggah tertentu.

Antarmuka Lanjutan

Deskripsi

NewDownloader

Membuat instance manajer unduhan.

NewUploader

Membuat instance manajer unggahan.

OpenFile

Membuat instance ReadOnlyFile.

Antarmuka Pembantu

Deskripsi

Unwrap

Mendapatkan instance klien non-terenkripsi. Anda dapat menggunakan instance ini untuk mengakses antarmuka dasar lainnya.

Gunakan kunci master RSA

Gunakan kunci master RSA untuk melakukan unggah dan unduhan sederhana objek

Kode sampel berikut menunjukkan cara menggunakan kunci master RSA untuk melakukan unggah dan unduhan sederhana objek:

package main

import (
	"context"
	"flag"
	"log"
	"strings"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/crypto"
)

// Variabel global
var (
	region     string // Wilayah penyimpanan.
	bucketName string // Nama bucket.
	objectName string // Nama objek.
)

// Fungsi init digunakan untuk menginisialisasi parameter baris perintah.
func init() {
	flag.StringVar(&region, "region", "", "Wilayah tempat bucket berada.")
	flag.StringVar(&bucketName, "bucket", "", "Nama bucket.")
	flag.StringVar(&objectName, "object", "", "Nama objek.")
}

func main() {
	// Parsing parameter baris perintah.
	flag.Parse()

	// Periksa apakah nama bucket kosong.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, nama bucket diperlukan")
	}

	// Periksa apakah wilayah kosong.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, wilayah diperlukan")
	}

	// Periksa apakah nama objek kosong.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, nama objek diperlukan")
	}

	// Muat konfigurasi default dan atur penyedia kredensial serta wilayah.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Buat klien OSS.
	client := oss.NewClient(cfg)

	// Buat deskripsi untuk kunci master. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master sesuai dengan kunci master.
	// Jika semua objek menggunakan kunci master yang sama, deskripsi kunci master dapat kosong, tetapi Anda tidak dapat mengubah kunci master nanti.
	// Jika deskripsi kunci master kosong, Anda tidak dapat menentukan kunci master mana yang digunakan untuk dekripsi.
	// Kami sarankan Anda mengonfigurasi deskripsi untuk setiap kunci master dan menyimpan pemetaan antara kunci master dan deskripsinya di klien.
	materialDesc := make(map[string]string)
	materialDesc["desc"] = "deskripsi informasi bahan kunci enkripsi master Anda"

	// Buat klien enkripsi yang hanya berisi kunci master.
	// Jika tidak ada operasi unduhan yang dilakukan, Anda dapat membiarkan kunci privat kosong. Yaitu, atur ke "".
	mc, err := crypto.CreateMasterRsa(materialDesc, "yourRsaPublicKey", "yourRsaPrivateKey")
	if err != nil {
		log.Fatalf("gagal membuat master rsa %v", err)

	}

	// Buat klien enkripsi.
	eclient, err := oss.NewEncryptionClient(client, mc)
	if err != nil {
		log.Fatalf("gagal membuat klien enkripsi %v", err)
	}

	// Buat permintaan unggah sederhana.
	putObjRequest := &oss.PutObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
		Body:   strings.NewReader("hi, simple put object"),
	}

	// Gunakan klien enkripsi untuk mengunggah objek.
	putObjRequestResult, err := eclient.PutObject(context.TODO(), putObjRequest)
	if err != nil {
		log.Fatalf("gagal mengunggah objek dengan klien enkripsi %v", err)
	}
	log.Printf("hasil unggah objek dengan klien enkripsi:%#v\n", putObjRequestResult)

	// Buat permintaan unduhan sederhana.
	getObjRequest := &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}

	// Gunakan klien enkripsi untuk mengunduh objek.
	getObjRequestResult, err := eclient.GetObject(context.TODO(), getObjRequest)
	if err != nil {
		log.Fatalf("gagal mengunggah objek dengan klien enkripsi %v", err)
	}
	log.Printf("hasil unggah objek dengan klien enkripsi:%#v\n", getObjRequestResult)

}

Gunakan kunci master RSA untuk melakukan unggah multi-bagian objek

Kode sampel berikut menunjukkan cara menggunakan kunci master RSA untuk melakukan unggah multi-bagian objek:

package main

import (
	"bufio"
	"context"
	"flag"
	"io"
	"log"
	"math/rand"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/crypto"
)

// Variabel global
var (
	region     string                                                                     // Wilayah penyimpanan.
	bucketName string                                                                     // Nama bucket.
	objectName string                                                                     // Nama objek.
	letters    = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") // Set karakter yang digunakan untuk menghasilkan string acak.
)

// Fungsi init digunakan untuk menginisialisasi parameter baris perintah.
func init() {
	flag.StringVar(&region, "region", "", "Wilayah tempat bucket berada.")
	flag.StringVar(&bucketName, "bucket", "", "Nama bucket.")
	flag.StringVar(&objectName, "object", "", "Nama objek.")
}

func main() {
	// Parsing parameter baris perintah.
	flag.Parse()

	// Periksa apakah nama bucket kosong.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, nama bucket diperlukan")
	}

	// Periksa apakah wilayah kosong.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, wilayah diperlukan")
	}

	// Periksa apakah nama objek kosong.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, nama objek diperlukan")
	}

	// Muat konfigurasi default dan atur penyedia kredensial serta wilayah.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Buat klien OSS.
	client := oss.NewClient(cfg)

	// Buat deskripsi untuk kunci master. Deskripsi tidak dapat diubah setelah dibuat. Deskripsi kunci master sesuai dengan kunci master.
	// Jika semua objek menggunakan kunci master yang sama, deskripsi kunci master dapat kosong, tetapi Anda tidak dapat mengubah kunci master nanti.
	// Jika deskripsi kunci master kosong, Anda tidak dapat menentukan kunci master mana yang digunakan untuk dekripsi.
	// Kami sarankan Anda mengonfigurasi deskripsi untuk setiap kunci master dan menyimpan pemetaan antara kunci master dan deskripsinya di klien.
	materialDesc := make(map[string]string)
	materialDesc["desc"] = "deskripsi informasi bahan kunci enkripsi master Anda"

	// Buat klien enkripsi yang hanya berisi kunci master.
	// Jika tidak ada operasi unduhan yang dilakukan, Anda dapat membiarkan kunci privat kosong. Yaitu, atur ke "".
	mc, err := crypto.CreateMasterRsa(materialDesc, "yourRsaPublicKey", "yourRsaPrivateKey")
	if err != nil {
		log.Fatalf("gagal membuat master rsa %v", err)

	}

	// Buat klien enkripsi.
	eclient, err := oss.NewEncryptionClient(client, mc)
	if err != nil {
		log.Fatalf("gagal membuat klien enkripsi %v", err)
	}

	// Buat permintaan untuk memulai unggah multi-bagian.
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}
	initResult, err := eclient.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("gagal memulai unggah multi-bagian %v", err)
	}

	var wg sync.WaitGroup
	var parts oss.UploadParts
	count := 3
	body := randStr(400000)
	reader := strings.NewReader(body)
	bufReader := bufio.NewReader(reader)
	content, _ := io.ReadAll(bufReader)
	partSize := len(body) / count
	var mu sync.Mutex

	for i := 0; i < count; i++ {
		wg.Add(1)
		go func(partNumber int, partSize int, i int) {
			defer wg.Done()
			partRequest := &oss.UploadPartRequest{
				Bucket:              oss.Ptr(bucketName),                                             // Nama bucket.
				Key:                 oss.Ptr(objectName),                                             // Nama objek.
				PartNumber:          int32(partNumber),                                               // Nomor bagian.
				UploadId:            oss.Ptr(*initResult.UploadId),                                   // ID unggah.
				Body:                strings.NewReader(string(content[i*partSize : (i+1)*partSize])), // Konten bagian.
				CSEMultiPartContext: initResult.CSEMultiPartContext,                                  // Konteks multi-bagian.
			}
			partResult, err := eclient.UploadPart(context.TODO(), partRequest)
			if err != nil {
				log.Fatalf("gagal mengunggah bagian %d: %v", partNumber, err)
			}
			part := oss.UploadPart{
				PartNumber: partRequest.PartNumber, // Nomor bagian.
				ETag:       partResult.ETag,        // ETag.
			}
			mu.Lock()
			parts = append(parts, part)
			mu.Unlock()
		}(i+1, partSize, i)
	}
	wg.Wait()
	sort.Sort(parts)

	request := &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucketName),           // Nama bucket.
		Key:      oss.Ptr(objectName),           // Nama objek.
		UploadId: oss.Ptr(*initResult.UploadId), // ID unggah.
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts, // Daftar bagian yang diunggah.
		},
	}
	result, err := eclient.CompleteMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("gagal menyelesaikan unggah multi-bagian %v", err)
	}
	log.Printf("hasil unggah multi-bagian selesai:%#v\n", result)
}

// Hasilkan string acak.
func randStr(n int) string {
	b := make([]rune, n)
	randMarker := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := range b {
		b[i] = letters[randMarker.Intn(len(letters))]
	}
	return string(b)
}

Gunakan kunci master kustom

Gunakan kunci master kustom untuk melakukan unggah dan unduh objek sederhana

SDK menyediakan implementasi default dari RSA. Jika metode ini tidak memenuhi kebutuhan Anda, Anda dapat mengimplementasikan perilaku enkripsi dan dekripsi kustom untuk kunci master. Contoh kode berikut menggunakan Alibaba Cloud KMS 3.0 sebagai contoh untuk menunjukkan cara menyesuaikan kunci master untuk melakukan unggah dan unduh objek sederhana.

package main

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"strings"

	kms "github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
	kmssdk "github.com/aliyun/alibabacloud-dkms-transfer-go-sdk/sdk"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
	osscrypto "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/crypto"
)

// CreateMasterAliKms3 membuat antarmuka kunci master yang diimplementasikan oleh Alibaba Cloud KMS 3.0.
// matDesc dikonversi menjadi string JSON.
func CreateMasterAliKms3(matDesc map[string]string, kmsID string, kmsClient *kmssdk.KmsTransferClient) (osscrypto.MasterCipher, error) {
	var masterCipher MasterAliKms3Cipher
	if kmsID == "" || kmsClient == nil {
		return masterCipher, fmt.Errorf("kmsID kosong atau kmsClient nil")
	}

	var jsonDesc string
	if len(matDesc) > 0 {
		b, err := json.Marshal(matDesc)
		if err != nil {
			return masterCipher, err
		}
		jsonDesc = string(b)
	}

	masterCipher.MatDesc = jsonDesc
	masterCipher.KmsID = kmsID
	masterCipher.KmsClient = kmsClient
	return masterCipher, nil
}

// Antarmuka kunci master Alibaba Cloud KMS.
type MasterAliKms3Cipher struct {
	MatDesc   string                    // Deskripsi kunci.
	KmsID     string                    // ID kunci KMS.
	KmsClient *kmssdk.KmsTransferClient // Klien KMS.
}

// Dapatkan algoritma pembungkus kunci master.
func (mrc MasterAliKms3Cipher) GetWrapAlgorithm() string {
	return "KMS/ALICLOUD"
}

// Dapatkan deskripsi kunci master.
func (mkms MasterAliKms3Cipher) GetMatDesc() string {
	return mkms.MatDesc
}

// Gunakan Alibaba Cloud KMS untuk mengenkripsi data. Ini terutama digunakan untuk mengenkripsi kunci simetris dan IV objek.
func (mkms MasterAliKms3Cipher) Encrypt(plainData []byte) ([]byte, error) {
	base64Plain := base64.StdEncoding.EncodeToString(plainData)
	request := kms.CreateEncryptRequest()
	request.RpcRequest.Scheme = "https"
	request.RpcRequest.Method = "POST"
	request.RpcRequest.AcceptFormat = "json"

	request.KeyId = mkms.KmsID
	request.Plaintext = base64Plain

	response, err := mkms.KmsClient.Encrypt(request)
	if err != nil {
		return nil, err
	}
	return base64.StdEncoding.DecodeString(response.CiphertextBlob)
}

// Gunakan Alibaba Cloud KMS untuk mendekripsi data. Ini terutama digunakan untuk mendekripsi kunci simetris dan IV objek.
func (mkms MasterAliKms3Cipher) Decrypt(cryptoData []byte) ([]byte, error) {
	base64Crypto := base64.StdEncoding.EncodeToString(cryptoData)
	request := kms.CreateDecryptRequest()
	request.RpcRequest.Scheme = "https"
	request.RpcRequest.Method = "POST"
	request.RpcRequest.AcceptFormat = "json"
	request.CiphertextBlob = string(base64Crypto)
	response, err := mkms.KmsClient.Decrypt(request)
	if err != nil {
		return nil, err
	}
	return base64.StdEncoding.DecodeString(response.Plaintext)
}

var (
	region     string // Wilayah penyimpanan.
	bucketName string // Nama bucket.
	objectName string // Nama objek.
)

// Fungsi init digunakan untuk menginisialisasi parameter baris perintah.
func init() {
	flag.StringVar(&region, "region", "", "Wilayah tempat bucket berada.")
	flag.StringVar(&bucketName, "bucket", "", "Nama bucket.")
	flag.StringVar(&objectName, "object", "", "Nama objek.")
}

func main() {
	// Parsing parameter baris perintah.
	flag.Parse()

	// Periksa apakah wilayah penyimpanan kosong.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, wilayah diperlukan")
	}

	// Periksa apakah nama bucket kosong.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, nama bucket diperlukan")
	}

	// Periksa apakah nama objek kosong.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("parameter tidak valid, nama objek diperlukan")
	}

	// Muat konfigurasi default dan atur penyedia kredensial serta wilayah.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Buat klien OSS.
	client := oss.NewClient(cfg)

	// Buat klien KMS.
	kmsRegion := "cn-hangzhou"                // Wilayah KMS.
	kmsAccessKeyId := "access key id"         // ID AccessKey KMS.
	kmsAccessKeySecret := "access key secret" // Rahasia AccessKey KMS.
	kmsKeyId := "kms id"                      // ID kunci KMS.

	kmsClient, err := kmssdk.NewClientWithAccessKey(kmsRegion, kmsAccessKeyId, kmsAccessKeySecret, nil)
	if err != nil {
		log.Fatalf("gagal membuat klien sdk kms %v", err)
	}

	// Buat deskripsi kunci.
	materialDesc := make(map[string]string)
	materialDesc["desc"] = "informasi deskripsi bahan kunci enkripsi kms Anda"

	// Buat instance kunci master.
	masterKmsCipher, err := CreateMasterAliKms3(materialDesc, kmsKeyId, kmsClient)
	if err != nil {
		log.Fatalf("gagal membuat master AliKms3 %v", err)
	}

	// Buat klien enkripsi.
	eclient, err := oss.NewEncryptionClient(client, masterKmsCipher)
	if err != nil {
		log.Fatalf("gagal membuat klien enkripsi %v", err)
	}

	// Buat permintaan untuk mengunggah objek.
	request := &oss.PutObjectRequest{
		Bucket: oss.Ptr(bucketName),         // Nama bucket.
		Key:    oss.Ptr(objectName),         // Nama objek.
		Body:   strings.NewReader("hi kms"), // Data untuk diunggah.
	}

	// Unggah objek.
	result, err := eclient.PutObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("gagal menaruh objek dengan klien enkripsi %v", err)
	}
	log.Printf("hasil menaruh objek dengan klien enkripsi:%#v\n", result)

	// Buat permintaan untuk mengunduh objek.
	getRequest := &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName), // Nama bucket.
		Key:    oss.Ptr(objectName), // Nama objek.
	}

	// Unduh objek.
	getResult, err := eclient.GetObject(context.TODO(), getRequest)
	if err != nil {
		log.Fatalf("gagal mendapatkan objek dengan klien enkripsi %v", err)
	}
	defer getResult.Body.Close()

	// Baca data yang diunduh.
	data, err := io.ReadAll(getResult.Body)
	if err != nil {
		log.Fatalf("gagal membaca semua %v", err)
	}
	log.Printf("data objek yang diunduh:%s\n", data)
}

Referensi

  • Untuk informasi lebih lanjut tentang prinsip enkripsi sisi klien OSS, lihat Enkripsi Sisi Klien.

  • Untuk informasi lebih lanjut tentang panduan pengguna Go SDK untuk enkripsi sisi klien, lihat Panduan Pengguna.

  • Untuk kode sampel lengkap untuk melakukan unggah dan unduh sederhana objek menggunakan kunci utama RSA, lihat Contoh GitHub.

  • Untuk kode sampel lengkap untuk melakukan unggah dan unduh sederhana objek menggunakan kunci utama KMS, lihat Contoh GitHub.