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

Object Storage Service:クライアント側の暗号化

最終更新日:Feb 29, 2024

クライアント側の暗号化が有効になっている場合、オブジェクトはOSS (Object Storage Service) にアップロードされる前にローカルで暗号化されます。 オブジェクトを復号化できるのは、顧客マスターキー (CMK) の所有者だけです。 このようにして、データ伝送および記憶中のデータセキュリティが強化される。

免責事項

  • クライアント側の暗号化を使用する場合は、CMKの整合性と有効性を確保する必要があります。 不適切なメンテナンスのためにCMKが誤って使用されたり失われたりした場合、復号化の失敗によって引き起こされるすべての損失と結果に対して責任があります。

  • 暗号化されたデータをコピーまたは移行する場合、オブジェクトメタデータの整合性と有効性に責任があります。 暗号化されたメタデータが正しくないか、不適切なメンテナンスのために失われた場合、データの復号化の失敗によって引き起こされるすべての損失と結果に対して責任があります。

シナリオ

  • 機密性の高いデータ: 個人識別情報 (PII) 、金融取引記録、医療および健康データなどの非常に機密性の高い情報を含むデータの場合、ユーザーは、データがローカル環境を離れる前にデータを暗号化して、送信中に傍受されても元のデータが効果的に保護されます。

  • コンプライアンス要件: HIPAAやGDPRなどの特定の業界や規制では、サードパーティのプラットフォームに保存されているデータに対して厳格な暗号化管理が必要です。 CMKはユーザーによって管理され、ネットワークを経由したり、クラウドサービスプロバイダーが所有したりしないため、クライアント側の暗号化はこれらのコンプライアンス要件を満たしています。

  • 強力な権限管理: 企業または開発者は、暗号化アルゴリズムの選択、CMKの管理とローテーションなど、暗号化プロセスを完全に制御したい場合があります。 クライアント側の暗号化により、合法的に許可されたユーザーのみがデータを復号およびアクセスできます。

  • クロスリージョンデータ移行のセキュリティ: クライアント側の暗号化は、クロスリージョンデータ移行の前後でデータを暗号化された状態に維持するのに役立ちます。 これは、インターネット上のデータ伝送のセキュリティを増幅する。

背景情報

クライアント側の暗号化では、オブジェクトに対して対称暗号化を実行するために、オブジェクトごとにランダムなデータキーが生成されます。 クライアントはCMKを使用してランダムデータキーを暗号化します。 暗号化されたデータキーは、オブジェクトメタデータの一部としてアップロードされ、OSSサーバーに保存されます。 暗号化されたオブジェクトがダウンロードされると、クライアントはCMKを使用してランダムデータキーを復号し、次にデータキーを使用してオブジェクトを復号します。 データのセキュリティを確保するために、CMKはクライアントでのみ使用され、ネットワーク経由で送信されたり、サーバーに保存されたりすることはありません。

重要
  • クライアント側の暗号化は、サイズが5 GBを超えるオブジェクトのマルチパートアップロードをサポートします。 マルチパートアップロードを使用してオブジェクトをアップロードする場合、オブジェクトの合計サイズとパーツサイズを指定する必要があります。 最後の部分を除く各部分のサイズは同じでなければならず、16の整数倍でなければなりません。

  • ローカルクライアントで暗号化されたオブジェクトをアップロードすると、オブジェクトの暗号化されたメタデータは保護され、CopyObjectを呼び出して変更することはできません。

クライアント側の暗号化には2種類のCMKを使用できます。

クライアント側暗号化の完全なサンプルコードについては、『GitHub』をご参照ください。

KMSマネージドCMKの使用

クライアント側の暗号化にKMS管理CMKを使用する場合、オブジェクトをアップロードするときにCMK IDを指定するだけで済みます。 暗号化クライアントにデータキーを提供する必要はありません。 次の図は、暗号化プロセスを示しています。

image
  • オブジェクトの暗号化とアップロード

    1. データキーを取得します。

      クライアントは、指定されたCMK IDを使用して、KMSにデータキーを要求し、オブジェクトを暗号化します。 KMSはランダムキーを生成し、データキーの平文と暗号文を返します。

    2. オブジェクトを暗号化し、暗号化されたオブジェクトをOSSにアップロードします。

      クライアントは、KMSからデータキーの平文と暗号文を受け取り、データキーの平文を使用してクライアント側でオブジェクトを暗号化します。

  • オブジェクトのダウンロードと復号化

    1. オブジェクトのダウンロード

      クライアントはOSSから暗号化されたオブジェクトをダウンロードします。 データキーの暗号文は、オブジェクトのメタデータに含まれる。

    2. オブジェクトを复号化します。

      クライアントは、データキーの暗号文と対応するCMK IDをKMSに送信します。 KMSは、クライアントから送信されたCMKを使用して暗号化されたデータを復号し、データキーの平文をクライアントに返します。

説明
  • クライアントは、一意のデータキーを使用して、アップロードする各オブジェクトを暗号化します。

  • データのセキュリティを確保するため、CMKを定期的にローテーションまたは更新することを推奨します。

  • CMK IDと暗号化されたオブジェクトの間のマッピング関係を維持する必要があります。

顧客管理の CMK を使用

ユーザー管理CMKをクライアント側の暗号化に使用するには、CMKを手動で生成および管理する必要があります。 オブジェクト暗号化のために、対称CMKまたは非対称CMKを暗号化クライアントにアップロードする必要があります。 次の図は、暗号化プロセスを示しています。

image
  • オブジェクトの暗号化とアップロード

    1. クライアントに対称CMKまたは非対称CMKを提供します。

    2. クライアントはCMKを使用して、アップロードするオブジェクトの暗号化にのみ使用される1回限りの対称データキーを生成します。 クライアントは、アップロードするオブジェクトごとにランダムで一意のデータキーを生成します。

    3. クライアントはデータキーを使用してアップロードするオブジェクトを暗号化し、CMKを使用してデータキーを暗号化します。

    4. クライアントは、オブジェクトのメタデータに含まれる暗号化されたデータキーとともに、暗号化されたオブジェクトをOSSにアップロードします。

  • オブジェクトのダウンロードと復号化

    1. クライアントは、暗号化されたオブジェクトとそのメタデータをOSSからダウンロードします。

    2. クライアントは、対応するCMKを使用して、メタデータによって示されるキーマテリアルに基づいて暗号化されたデータキーを復号し、次いで、復号されたデータキーを使用してオブジェクトを復号する。

重要
  • クライアントはCMKと暗号化されていないデータをOSSに送信しません。 したがって、CMKを安全に保ちます。 CMKが失われた場合、このCMKを使用して生成されたデータキーを使用して暗号化されたオブジェクトは復号できません。

  • データキーはクライアントによってランダムに生成されます。

OSS SDKの使用

次のサンプルコードは、一般的なプログラミング言語のOSS SDKを使用してクライアント側の暗号化を設定する方法の例を示しています。 他のプログラミング言語のOSS SDKを使用してクライアント側の暗号化を設定する方法の詳細については、「概要」をご参照ください。

com.aliyun.oss.*;
impor t com.aliyun.oss.com mon.auth.*;
com.aliyun.oss.crypto.SimpleRSAEncryptionMaterialsをインポートします。com.aliyun.oss.mo del.OSSObjectをインポートします。java.io.BufferedReaderをインポートします。java.io.ByteArrayInputStreamをインポートします。java.io.InputStreamReaderをインポートします。java.security.KeyPairをインポートします。java.security.int erfaces.RSAPrivateKeyをインポートします。java.security.int erfaces.RSAPublicKeyをインポートします。java.util.HashMapをインポートします。java.util.Mapをインポートします。public classデモ {
    public static void main(String[] args) Throwable {
        // この例では、中国 (杭州) リージョンのエンドポイントが使用されます。 実際のエンドポイントを指定します。 
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 環境変数からアクセス資格情報を取得します。 サンプルコードを実行する前に、OSS_ACCESS_KEY_IDおよびOSS_ACCESS_KEY_SECRET環境変数が設定されていることを確認してください。 
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // バケットの名前を指定します。 例: examplebucket. 
        String bucketName = "examplebucket";
        // オブジェクトのフルパスを指定します。 例: exampleobject.txt。 バケット名をフルパスに含めないでください。 
        文字列objectName = "exampleobject.txt";
        String content = "Hello OSS!";

        // RSA秘密鍵文字列を指定します。 OpenSSLを使用して文字列を生成できます。 次のサンプルコードは、RSA秘密鍵文字列のサンプルを示しています。 
        final文字列PRIVATE_PKCS1_PEM=
                "----- BEGIN RSA PRIVATE KEY -----\n" +
                「MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n」 +
                "ttSx 8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO 1PByrE/MNd5AAfSVba93\n"
                「I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n」 +
                「AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n」 +
                "nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
                「JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n」 +
                「36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n」 +
                「6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw 4/a8vZm2tXXK/QfTQrJVXp\n」 +
                「VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n」
                "gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs + d5Tv4Cvquk0efOQJAd9OC\n" +
                「lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n」 +
                「Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG 7/S7Z74gyq5qZF4FUElOAZkz123E\n」 +
                "yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo ****\n" +
                "----- END RSAプライベートキー -----";
        // RSA公開キー文字列を指定します。 OpenSSLを使用して文字列を生成できます。 次のサンプルコードは、RSA公開キー文字列のサンプルを示しています。 
        final String PUBLIC_X509_PEM=
                「 ----- 公開キーを開始 ----- 」
                「MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw XO/UByW\n」 +
                "6mse2QsIgz3ZwBtMNu59fR5zttSx + 8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
                「5MFO 1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n」 +
                「1EKib1Id8hpooY5xaQID ****\n」 +
                "----- END PUBLIC KEY -----";

        // RSAキーペアを作成します。 
        RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
        RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
        KeyPair keyPair=新しいKeyPair(publicKey, privateKey);

        // CMKの説明を指定します。 記述は、指定後に変更することはできません。 CMKに指定できる説明は1つだけです。 
        // すべてのオブジェクトがCMKを共有する場合は、CMKの説明を空のままにすることができます。 この場合、CMKを置き換えることはできません。 
        // CMKの説明を空のままにすると、クライアントはどのCMKを復号化に使用するかを判断できません。 
        // CMKごとに説明を指定し、CMKと説明の間のマッピング関係をクライアントに保存することをお勧めします。 サーバーはマッピング関係を保存しません。 
        Map<String, String> matDesc = new HashMap<String, String>();
        matDesc.put("desc-key", "desc-value");

        // RSA暗号化マテリアルを作成します。 
        SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
        // 他のCMKを使用して暗号化されたオブジェクトをダウンロードして復号化するには、これらのCMKとその説明を暗号化マテリアルに追加します。 
        // encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);

        // クライアント側暗号化用のクライアントを作成します。 
        OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder() 。
                ビルド (endpoint, credentialsProvider, encryptionMaterials);

        try {
            // アップロードするオブジェクトを暗号化します。 
            ossEncryptionClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));

            // Download the object. オブジェクトは自動的に復号化されます。 
            OSSObject ossObject = ossEncryptionClient.getObject(bucketName, objectName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
            StringBuffer buffer = new StringBuffer();
            文字列ライン;
            while (((line = reader.readLine())) != null) {
                buffer.append (ライン);
            }
            reader.close();

            // 復号化されたコンテンツが、平文でアップロードされたオブジェクトと同じかどうかを確認します。 
            System.out.println("Put plain text: " + content);
            System.out.println("Get and decrypted text: " + buffer.toString());
        } catch (Exception e) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "しかし、何らかの理由でエラー応答で拒否されました。");
            System.out.println("エラーメッセージ:" + oe.getErrorMessage());
            System.out.println("エラーコード:" + oe.getErrorCode());
            System.out.println("リクエストID:" + oe.getRequestId());
            System.out.println("ホストID:" + oe.getHostId());
        } catch (ClientException e) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + 「ネットワークにアクセスできないなど」;
            System.out.println("エラーメッセージ:" + ce.getMessage());
        } 最後に{
            if (ossEncryptionClient != null) {
                ossEncryptionClient.shutdown();
            }
        }
    }
}
# -*-コーディング: utf-8 -*-
osのインポート
oss2のインポート
oss2.credentialsからEnvironmentVariableCredentialsProviderをインポート
oss2.cryptoからRsaProviderをインポート
oss2.cryptoimportAliKMSProviderから

# 環境変数からアクセス資格情報を取得します。 サンプルコードを実行する前に、OSS_ACCESS_KEY_IDおよびOSS_ACCESS_KEY_SECRET環境変数が設定されていることを確認してください。 
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())

kms_provider=AliKMSProvider(auth, 'yourRegion', 'yourCMKID')
bucket = oss2.CryptoBucket(auth, 'yourEndpoint', 'yourBucketName', crypto_provider = kms_provider)

キー='motto.txt'
content = b'a' * 1024*1024
filename = 'download.txt'


# オブジェクトをアップロードします。 
bucket.put_object (キー、コンテンツ、ヘッダー={'content-length ': str(1024*1024)})

# OSSからローカルメモリにオブジェクトをダウンロードします。 
result = bucket.get_object (キー)

# ダウンロードしたオブジェクトのコンテンツとアップロード前のオブジェクトのコンテンツのデータの整合性を確認します。 
content_got = b''
結果のチャンクの場合:
    content_got +=チャンク
assert content_got == content

# OSSからローカルメモリにオブジェクトをダウンロードします。 
result = bucket.get_object_to_file (キー、ファイル名)

# ダウンロードしたオブジェクトのコンテンツとアップロード前のオブジェクトのコンテンツのデータの整合性を確認します。 
with open(filename, 'rb') as fileobj:
    assert fileobj.read() == content 
package main

import (import (import)
「バイト」
"fmt"
"io/ioutil"
"os"

「github.com/aliyun/aliyun-oss-go-sdk/oss」
「github.com/aliyun/aliyun-oss-go-sdk/oss/crypto」
)

func main() {
// 環境変数からアクセス資格情報を取得します。 サンプルコードを実行する前に、OSS_ACCESS_KEY_IDおよびOSS_ACCESS_KEY_SECRET環境変数が設定されていることを確認してください。 
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err! =nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// OSSClientインスタンスを作成します。 
	// バケットが配置されているリージョンのエンドポイントを指定します。 たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントをhttps://oss-cn-hangzhou.aliyuncs.comに設定します。 実際のエンドポイントを指定します。 
	client, err := oss.New("yourEndpoint", ", " ", ", oss.SetCredentialsProvider(&provider))
if err! =nil {
fmt.Println("Error:", err)
os.Exit(-1)
}

// CMKの説明を指定します。 記述は、指定後に変更することはできません。 CMKに指定できる説明は1つだけです。 
	// すべてのオブジェクトがCMKを共有する場合は、CMKの説明を空のままにすることができます。 この場合、CMKは交換できません。 
	// CMKの説明が空の場合、クライアントはどのCMKを復号化に使用するかを判断できません。 
	// CMKごとにJSON文字列の形式で説明を構成し、CMKと説明の間のマッピング関係をクライアントに保存することをお勧めします。 サーバーはマッピング関係を保存しません。 

	// JSON文字列であるCMKの説明に基づいてマッピング関係を取得します。 
	materialDesc := make(map[string]string)
materialDesc["desc"] = "マスター暗号化キーマテリアル説明情報"

// CMKの説明に基づいてCMKオブジェクトを作成します。 
	// yourRsaPublicKeyを管理するCMKの公開鍵に設定し、yourRsaPrivateKeyを管理するCMKの秘密鍵に設定します。 
	masterRsaCipher, err := osscrypto.CreateMasterRsa(materialDesc, "yourRsaPublicKey", "yourRsaPrivateKey")
if err! =nil {
fmt.Println("Error:", err)
os.Exit(-1)
}

// CMKオブジェクトに基づいて暗号化操作を作成し、AES CTRモードで暗号化を実行します。 
	contentProvider := osscrypto.CreateAesCtrCipher(masterRsaCipher)

// クライアント側の暗号化に使用する既存のバケットを取得します。 
	// クライアント側の暗号化が設定されているバケットは、共通のバケットが使用されるのと同じ方法で使用されます。 
	cryptoBucket, err := osscrypto.GetCryptoBucket (クライアント, "yourBucketName", contentProvider)
if err! =nil {
fmt.Println("Error:", err)
os.Exit(-1)
}

// 暗号化は、PutObject操作を呼び出すと自動的に実行されます。 
	err = cryptoBucket.PutObject("yourObjectName", bytes.NewReader([]byte("yourObjectValueByteArrary"))))
if err! =nil {
fmt.Println("Error:", err)
os.Exit(-1)
}

// GetObject操作を呼び出すと、復号化が自動的に実行されます。 
	body, err := cryptoBucket.GetObject("yourObjectName")
if err! =nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
defer body.Close()

data, err := ioutil.ReadAll(body)
if err! =nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
fmt.Println("data:", string(data))
}
#include <alibabacloud/oss/OssEncryptionClient.h>
名前空間listaCloud::OSSを使用します。int main(void)
{
    /* OSSへのアクセスに使用されるアカウントに関する情報を初期化します。 */
    
    /* バケットが配置されているリージョンのエンドポイントを指定します。 たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントをhttps://oss-cn-hangzhou.aliyuncs.comに設定します。 */
    std::string Endpoint = "yourEndpoint";
    /* バケットの名前を指定します。 例: examplebucket. */
    std::string BucketName = "examplebucket";
    /* オブジェクトのフルパスを指定します。 バケット名をフルパスに含めないでください。 例: exampledir/exampleobject.txt。 */
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* CMKと説明を指定します。 */
    std::string RSAPublicKey = "rsa公開キー";
    std::string RSAPrivateKey = "rsaプライベートキー";
    std::map<std::string, std::string> desc;
    desc["comment"] = "あなたのコメント";

    /* ネットワークリソースなどのリソースを初期化します。 */
    InitializeSdk();
    
    ClientConfiguration conf;
    /* 環境変数からアクセス資格情報を取得します。 サンプルコードを実行する前に、OSS_ACCESS_KEY_IDおよびOSS_ACCESS_KEY_SECRET環境変数が設定されていることを確認してください。 */
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClientクライアント (Endpoint, credentialsProvider, conf);
  
    CryptoConfiguration cryptoConf;
    auto materials = std::make_shared<SimpleRSAEncryptionMaterials>(RSAPublicKey, RSAPrivateKey, desc);
    OssEncryptionClientクライアント (Endpoint、credentialsProvider、conf、materials、cryptoConf);
    /* オブジェクトをアップロードします。 */
    auto outcome = client.PutObject(BucketName, ObjectName, "yourLocalFilename");
    if (!outcome.isSuccess()) {
        /* 例外を処理します。 */
        std::cout << "PutObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }
    /* ネットワークリソースなどのリソースをリリースします。 */
    ShutdownSdk();
    0を返します。}