すべてのプロダクト
Search
ドキュメントセンター

Object Storage Service:クライアントサイド暗号化 (Go SDK V2)

最終更新日:Nov 09, 2025

OSS クライアントサイド暗号化を使用すると、データを OSS にアップロードする前にローカルで暗号化できます。これにより、承認されたキー所有者のみがデータを復号化できるようになり、転送中およびストレージ中のデータセキュリティが強化されます。

注意事項

  • このトピックのサンプルコードでは、デフォルトで中国 (杭州) リージョン ID の cn-hangzhou とパブリックエンドポイントを使用します。同じリージョン内の他の Alibaba Cloud サービスから OSS にアクセスする場合は、内部エンドポイントを使用してください。OSS リージョンとエンドポイント間のマッピングの詳細については、「リージョンとエンドポイント」をご参照ください。

  • このトピックの例では、環境変数からアクセス資格情報を読み取ります。アクセス資格情報を構成する方法の詳細については、「アクセス資格情報を構成する」をご参照ください。

  • クライアントサイド暗号化機能を使用する場合、マスターキーの整合性はお客様の責任となります。

  • 暗号化されたデータをコピーまたは移行する場合、暗号化メタデータの整合性はお客様の責任となります。

メソッド定義

Go SDK V2 は、マスターキーを使用するための次のメソッドをサポートしています。

  • ユーザー管理のマスターキー (RSA) を使用する

    SDK は RSA のデフォルト実装を提供します。マスターキーの公開鍵と秘密鍵をパラメーターとして SDK に提供する必要があります。

  • カスタムマスターキーを使用する

    RSA マスターキーメソッドが要件を満たさない場合は、マスターキーのカスタム暗号化および復号化動作を実装できます。このトピックでは、Alibaba Cloud KMS 3.0 を例として、マスターキーの暗号化と復号化をカスタマイズする方法を示します。

これら 2 つの暗号化メソッドを使用すると、クライアントデータを漏洩から効果的に保護できます。暗号化されたデータが侵害された場合でも、復号化して生データを明らかにすることはできません。

重要

OSS クライアントサイド暗号化の原則の詳細については、「クライアントサイド暗号化」をご参照ください。

クライアントサイド暗号化を使用するには、まず暗号化クライアントをインスタンス化し、次にクライアントのインターフェイスを呼び出して操作を実行する必要があります。オブジェクトは、リクエストの一部として自動的に暗号化および復号化されます。

type EncryptionClient struct {
  ...
}

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

リクエストパラメーター

パラメーター

タイプ

説明

c

*Client

暗号化されていないクライアントインスタンス

masterCipher

crypto.MasterCipher

データキーの暗号化と復号化に使用されるマスターキーインスタンス。

optFns

...func(*EncryptionClientOptions)

(オプション) 暗号化クライアントの構成オプション。

次の表に、EncryptionClientOptions オプションを示します。

パラメーター

タイプ

説明

MasterCiphers

[]crypto.MasterCipher

データキーの復号化に使用されるマスターキーインスタンスグループ。

戻り値

戻り値

タイプ

説明

eclient

*EncryptionClient

暗号化クライアントインスタンス。このパラメーターは、err が nil の場合にのみ有効です。

err

error

暗号化クライアントの作成ステータス。操作が失敗した場合、err は nil ではありません。

次の表に、EncryptionClient インターフェイスを示します。

基本インターフェイス

説明

GetObjectMeta

オブジェクトのメタデータを取得します。

HeadObject

オブジェクトのメタデータを取得します。

GetObject

オブジェクトをダウンロードし、自動的に復号化します。

PutObject

オブジェクトをアップロードし、自動的に暗号化します。

InitiateMultipartUpload

マルチパートアップロードイベントとシャーディング暗号化コンテキスト (EncryptionMultiPartContext) を初期化します。

UploadPart

マルチパートアップロードイベントを初期化します。このインターフェイスを呼び出してパートデータをアップロードし、データを自動的に暗号化できます。このインターフェイスを呼び出すときは、シャーディング暗号化コンテキストを設定する必要があります。

CompleteMultipartUpload

すべてのパートデータがアップロードされた後、このインターフェイスを呼び出してパートをファイルにマージできます。

AbortMultipartUpload

マルチパートアップロードイベントをキャンセルし、対応するパートデータを削除します。

ListParts

指定されたアップロードイベントに属する、正常にアップロードされたすべてのパートをリストします。

高度なインターフェイス

説明

NewDownloader

ダウンロードマネージャーインスタンスを作成します。

NewUploader

アップロードマネージャーインスタンスを作成します。

OpenFile

ReadOnlyFile インスタンスを作成します。

ヘルパーインターフェイス

説明

Unwrap

暗号化されていないクライアントインスタンスを取得します。このインスタンスを使用して、他の基本インターフェイスにアクセスできます。

RSA マスターキーの使用

RSA マスターキーを使用したオブジェクトのシンプルなアップロードとダウンロード

次のサンプルコードは、RSA マスターキーを使用してオブジェクトのシンプルなアップロードとダウンロードを実行する方法を示しています。

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"
)

// グローバル変数
var (
	region     string // ストレージリージョン。
	bucketName string // バケット名。
	objectName string // オブジェクト名。
)

// init 関数は、コマンドラインパラメーターを初期化するために使用されます。
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを設定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSS クライアントを作成します。
	client := oss.NewClient(cfg)

	// マスターキーの説明を作成します。説明は作成後に変更できません。マスターキーの説明はマスターキーに対応します。
	// すべてのオブジェクトが同じマスターキーを使用する場合、マスターキーの説明は空にできますが、後でマスターキーを変更することはできません。
	// マスターキーの説明が空の場合、復号化にどのマスターキーが使用されているかを判断できません。
	// 各マスターキーの説明を構成し、マスターキーと説明のマッピングをクライアントに保存することをお勧めします。
	materialDesc := make(map[string]string)
	materialDesc["desc"] = "your master encrypt key material describe information"

	// マスターキーのみを含む暗号化クライアントを作成します。
	// ダウンロード操作が実行されない場合は、秘密鍵を空のままにすることができます。つまり、"" に設定します。
	mc, err := crypto.CreateMasterRsa(materialDesc, "yourRsaPublicKey", "yourRsaPrivateKey")
	if err != nil {
		log.Fatalf("failed to create master rsa %v", err)

	}

	// 暗号化クライアントを作成します。
	eclient, err := oss.NewEncryptionClient(client, mc)
	if err != nil {
		log.Fatalf("failed to create encryption client %v", err)
	}

	// シンプルなアップロードリクエストを作成します。
	putObjRequest := &oss.PutObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
		Body:   strings.NewReader("hi, simple put object"),
	}

	// 暗号化クライアントを使用してオブジェクトをアップロードします。
	putObjRequestResult, err := eclient.PutObject(context.TODO(), putObjRequest)
	if err != nil {
		log.Fatalf("failed to put object with encryption client %v", err)
	}
	log.Printf("put object with encryption client result:%#v\n", putObjRequestResult)

	// シンプルなダウンロードリクエストを作成します。
	getObjRequest := &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}

	// 暗号化クライアントを使用してオブジェクトをダウンロードします。
	getObjRequestResult, err := eclient.GetObject(context.TODO(), getObjRequest)
	if err != nil {
		log.Fatalf("failed to put object with encryption client %v", err)
	}
	log.Printf("put object with encryption client result:%#v\n", getObjRequestResult)

}

RSA マスターキーを使用したオブジェクトのマルチパートアップロード

次のサンプルコードは、RSA マスターキーを使用してオブジェクトのマルチパートアップロードを実行する方法を示しています。

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"
)

// グローバル変数
var (
	region     string                                                                     // ストレージリージョン。
	bucketName string                                                                     // バケット名。
	objectName string                                                                     // オブジェクト名。
	letters    = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") // ランダムな文字列を生成するために使用される文字セット。
)

// init 関数は、コマンドラインパラメーターを初期化するために使用されます。
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを設定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSS クライアントを作成します。
	client := oss.NewClient(cfg)

	// マスターキーの説明を作成します。説明は作成後に変更できません。マスターキーの説明はマスターキーに対応します。
	// すべてのオブジェクトが同じマスターキーを使用する場合、マスターキーの説明は空にできますが、後でマスターキーを変更することはできません。
	// マスターキーの説明が空の場合、復号化にどのマスターキーが使用されているかを判断できません。
	// 各マスターキーの説明を構成し、マスターキーと説明のマッピングをクライアントに保存することをお勧めします。
	materialDesc := make(map[string]string)
	materialDesc["desc"] = "your master encrypt key material describe information"

	// マスターキーのみを含む暗号化クライアントを作成します。
	// ダウンロード操作が実行されない場合は、秘密鍵を空のままにすることができます。つまり、"" に設定します。
	mc, err := crypto.CreateMasterRsa(materialDesc, "yourRsaPublicKey", "yourRsaPrivateKey")
	if err != nil {
		log.Fatalf("failed to create master rsa %v", err)

	}

	// 暗号化クライアントを作成します。
	eclient, err := oss.NewEncryptionClient(client, mc)
	if err != nil {
		log.Fatalf("failed to create encryption client %v", err)
	}

	// マルチパートアップロードを初期化するリクエストを作成します。
	initRequest := &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}
	initResult, err := eclient.InitiateMultipartUpload(context.TODO(), initRequest)
	if err != nil {
		log.Fatalf("failed to initiate multi part upload %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),                                             // バケット名。
				Key:                 oss.Ptr(objectName),                                             // オブジェクト名。
				PartNumber:          int32(partNumber),                                               // パート番号。
				UploadId:            oss.Ptr(*initResult.UploadId),                                   // アップロード ID。
				Body:                strings.NewReader(string(content[i*partSize : (i+1)*partSize])), // パートコンテンツ。
				CSEMultiPartContext: initResult.CSEMultiPartContext,                                  // マルチパートコンテキスト。
			}
			partResult, err := eclient.UploadPart(context.TODO(), partRequest)
			if err != nil {
				log.Fatalf("failed to upload part %d: %v", partNumber, err)
			}
			part := oss.UploadPart{
				PartNumber: partRequest.PartNumber, // パート番号。
				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),           // バケット名。
		Key:      oss.Ptr(objectName),           // オブジェクト名。
		UploadId: oss.Ptr(*initResult.UploadId), // アップロード ID。
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts, // アップロードされたパートのリスト。
		},
	}
	result, err := eclient.CompleteMultipartUpload(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to complete multipart upload %v", err)
	}
	log.Printf("complete multipart upload result:%#v\n", result)
}

// ランダムな文字列を生成します。
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)
}

カスタムマスターキーの使用

カスタムマスターキーを使用したオブジェクトのシンプルなアップロードとダウンロード

SDK は RSA のデフォルト実装を提供します。このメソッドが要件を満たさない場合は、マスターキーのカスタム暗号化および復号化動作を実装できます。次のサンプルコードでは、Alibaba Cloud KMS 3.0 を例として、マスターキーをカスタマイズしてオブジェクトのシンプルなアップロードとダウンロードを実行する方法を示します。

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 は、Alibaba Cloud KMS 3.0 によって実装されたマスターキーインターフェイスを作成します。
// matDesc は 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 is empty or kmsClient is 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
}

// Alibaba Cloud KMS マスターキーインターフェイス。
type MasterAliKms3Cipher struct {
	MatDesc   string                    // キーの説明。
	KmsID     string                    // KMS キー ID。
	KmsClient *kmssdk.KmsTransferClient // KMS クライアント。
}

// マスターキーのラッピングアルゴリズムを取得します。
func (mrc MasterAliKms3Cipher) GetWrapAlgorithm() string {
	return "KMS/ALICLOUD"
}

// マスターキーの説明を取得します。
func (mkms MasterAliKms3Cipher) GetMatDesc() string {
	return mkms.MatDesc
}

// Alibaba Cloud KMS を使用してデータを暗号化します。これは主に、オブジェクトの対称キーと IV を暗号化するために使用されます。
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)
}

// Alibaba Cloud KMS を使用してデータを復号化します。これは主に、オブジェクトの対称キーと IV を復号化するために使用されます。
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 // ストレージリージョン。
	bucketName string // バケット名。
	objectName string // オブジェクト名。
)

// init 関数は、コマンドラインパラメーターを初期化するために使用されます。
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// ストレージリージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// デフォルトの構成をロードし、資格情報プロバイダーとリージョンを設定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSS クライアントを作成します。
	client := oss.NewClient(cfg)

	// KMS クライアントを作成します。
	kmsRegion := "cn-hangzhou"                // KMS リージョン。
	kmsAccessKeyId := "access key id"         // KMS AccessKey ID。
	kmsAccessKeySecret := "access key secret" // KMS AccessKey Secret。
	kmsKeyId := "kms id"                      // KMS キー ID。

	kmsClient, err := kmssdk.NewClientWithAccessKey(kmsRegion, kmsAccessKeyId, kmsAccessKeySecret, nil)
	if err != nil {
		log.Fatalf("failed to create kms sdk client %v", err)
	}

	// キーの説明を作成します。
	materialDesc := make(map[string]string)
	materialDesc["desc"] = "your kms encrypt key material describe information"

	// マスターキーインスタンスを作成します。
	masterKmsCipher, err := CreateMasterAliKms3(materialDesc, kmsKeyId, kmsClient)
	if err != nil {
		log.Fatalf("failed to create master AliKms3 %v", err)
	}

	// 暗号化クライアントを作成します。
	eclient, err := oss.NewEncryptionClient(client, masterKmsCipher)
	if err != nil {
		log.Fatalf("failed to create encryption client %v", err)
	}

	// オブジェクトをアップロードするリクエストを作成します。
	request := &oss.PutObjectRequest{
		Bucket: oss.Ptr(bucketName),         // バケット名。
		Key:    oss.Ptr(objectName),         // オブジェクト名。
		Body:   strings.NewReader("hi kms"), // アップロードするデータ。
	}

	// オブジェクトをアップロードします。
	result, err := eclient.PutObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to put object with encryption client %v", err)
	}
	log.Printf("put object with encryption client result:%#v\n", result)

	// オブジェクトをダウンロードするリクエストを作成します。
	getRequest := &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName), // バケット名。
		Key:    oss.Ptr(objectName), // オブジェクト名。
	}

	// オブジェクトをダウンロードします。
	getResult, err := eclient.GetObject(context.TODO(), getRequest)
	if err != nil {
		log.Fatalf("failed to get object with encryption client %v", err)
	}
	defer getResult.Body.Close()

	// ダウンロードしたデータを読み取ります。
	data, err := io.ReadAll(getResult.Body)
	if err != nil {
		log.Fatalf("failed to read all %v", err)
	}
	log.Printf("get object data:%s\n", data)
}

関連情報

  • OSS クライアントサイド暗号化の原則の詳細については、「クライアントサイド暗号化」をご参照ください。

  • クライアントサイド暗号化用の Go SDK ユーザーガイドの詳細については、「ユーザーガイド」をご参照ください。

  • RSA マスターキーを使用したオブジェクトのシンプルなアップロードとダウンロードを実行するための完全なサンプルコードについては、「GitHub サンプル」をご参照ください。

  • KMS マスターキーを使用したオブジェクトのシンプルなアップロードとダウンロードを実行するための完全なサンプルコードについては、「GitHub サンプル」をご参照ください。