

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# Amazon S3 加密用戶端遷移 (V2 到 V3)
<a name="s3-encryption-migration-v2-v3"></a>

**注意**  
如果您使用的是 Amazon S3 加密用戶端的 V1，您必須先遷移至 V2，才能遷移至 V3。請參閱 [Amazon S3 加密用戶端遷移 (V1 至 V2)](s3-encryption-migration-v1-v2.md)。

本主題說明如何將應用程式從 Amazon Simple Storage Service (Amazon S3) 加密用戶端的第 2 版 (V2) 遷移到第 3 版 (V3)，並確保在整個遷移過程中的應用程式可用性。V3 推出`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法和承諾政策，透過防止指令檔案中的資料金鑰竄改來增強安全性。

## 遷移概觀
<a name="s3-encryption-migration-v2-v3-overview"></a>

此遷移分為兩個階段：

1. **更新現有用戶端以讀取新格式。**首先，將更新的 適用於 C\+\+ 的 AWS SDK 版本部署到您的應用程式。這可讓現有的 V2 加密用戶端解密新 V3 用戶端寫入的物件。如果您的應用程式使用多個 AWS SDKs，您必須分別升級每個 SDK。

2. **將加密和解密用戶端遷移至 V3。**一旦所有 V2 加密用戶端都可以讀取新的格式，您就可以將現有的加密和解密用戶端遷移到各自的 V3 版本。

## 了解 V3 概念
<a name="s3-encryption-migration-v2-v3-concepts"></a>

Amazon S3 加密用戶端第 3 版推出新的安全功能，可增強對資料金鑰竄改的保護。了解這些概念對於成功遷移至關重要。

### 承諾政策
<a name="s3-encryption-migration-v2-v3-commitment-policy"></a>

承諾政策控制加密用戶端在加密和解密操作期間處理金鑰承諾的方式。V3 提供三種政策選項，以支援不同的遷移案例和安全需求：

**`FORBID_ENCRYPT_ALLOW_DECRYPT`**  
**加密行為：**使用與 V2 相同的演算法加密物件，無需金鑰承諾。  
**解密行為：**允許解密使用和不使用金鑰承諾加密的物件。  
**安全性影響：**此政策不會強制執行金鑰承諾，並可能允許竄改指令檔案中的加密資料金鑰。當您需要 V2 用戶端讀取新加密的物件時，請只在初始遷移階段使用此政策。  
**版本相容性：**所有 V2 和 V3 實作都可以讀取使用此政策加密的物件。

**`REQUIRE_ENCRYPT_ALLOW_DECRYPT` (預設值)**  
**加密行為：**使用`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法加密具有金鑰承諾的物件。  
**解密行為：**允許解密使用金鑰承諾加密的物件，以及不使用金鑰承諾加密的物件。  
**安全性影響：**此政策為新加密的物件提供強大的安全性，同時保持讀取舊物件的回溯相容性。這是大多數遷移案例的建議政策。  
**版本相容性：**使用此政策加密的物件只能由 V3 和最新的 V2 實作讀取。V2 用戶端無法解密這些物件。不過，使用此政策的 V3 用戶端仍然可以解密 V2 用戶端加密的物件。

**`REQUIRE_ENCRYPT_REQUIRE_DECRYPT`**  
**加密行為：**使用`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法加密具有金鑰承諾的物件。  
**解密行為：**僅允許解密以金鑰承諾加密的物件。拒絕在沒有金鑰承諾的情況下加密的物件。  
**安全性影響：**此政策會強制執行所有操作的金鑰承諾，以提供最高層級的安全性。只有在所有物件都已透過金鑰承諾重新加密，而且您不再需要讀取舊版 V1 或 V2 加密物件之後，才使用此政策。  
**版本相容性：**使用此政策加密的物件只能由 V3 和最新的 V2 實作讀取。此外，使用此政策的用戶端無法解密 V1 或 V2 用戶端加密的物件。

**遷移考量：**在遷移期間，`FORBID_ENCRYPT_ALLOW_DECRYPT`如果您需要 V2 用戶端讀取新物件，請從 開始，然後在所有用戶端升級至 V3 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`後移至 。最後，`REQUIRE_ENCRYPT_REQUIRE_DECRYPT`僅在重新加密所有舊版物件之後才考慮。

### ALG\_AES\_256\_GCM\_HKDF\_SHA512\_COMMIT\_KEY 演算法
<a name="s3-encryption-migration-v2-v3-aes-gcm-kc"></a>

`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY` 演算法是 V3 中引入的新加密演算法，可為存放在指令檔案中的加密資料金鑰提供增強的安全性。

**指令檔案影響：**`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法只會影響指令檔案，也就是存放加密中繼資料的個別 S3 物件，包括加密的資料金鑰。將加密中繼資料存放在物件中繼資料 （預設儲存方法） 的物件不受此演算法變更的影響。

**防止竄改：**`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法會以密碼編譯方式將加密的資料金鑰繫結至加密內容，以防止資料金鑰遭到竄改。這可防止攻擊者在指令檔案中替換不同的加密資料金鑰，這可能會導致使用非預期的金鑰進行解密。

**版本相容性：**使用`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法加密的物件只能由 V3 實作和包含 V3 解密支援之 SDK 的最新 V3 V2 轉換版本解密。

**警告**  
**重要：**使用`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法啟用加密 （使用 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`或 `REQUIRE_ENCRYPT_REQUIRE_DECRYPT`承諾政策） 之前，您必須確保所有將讀取這些物件的用戶端都已升級至 V3 或支援 V3 解密的最新 V2 轉換版本。未先升級所有讀取器會導致新加密物件的解密失敗。

## 更新現有用戶端以讀取新格式
<a name="s3-encryption-migration-v2-v3-update-clients"></a>

您必須先將現有用戶端更新為最新的 SDK 版本。完成此步驟後，您應用程式的 V2 用戶端將能夠解密由 V3 加密用戶端加密的物件，而無需更新應用程式的程式碼基底。

### 建置和安裝最新版本的 適用於 C\+\+ 的 AWS SDK
<a name="s3-encryption-migration-v2-v3-build-install-sdk"></a>

 **從來源使用 SDK 的應用程式** 

如果您 適用於 C\+\+ 的 AWS SDK 從來源建置和安裝 ，請在 GitHub [`aws/aws-sdk-cpp`](https://github.com/aws/aws-sdk-cpp)上從 下載或複製 SDK 來源。然後重複正常的建置和安裝步驟。

如果您是 適用於 C\+\+ 的 AWS SDK 從早於 1.11.x 的版本升級，請參閱此 [CHANGELOG](https://github.com/aws/aws-sdk-cpp/blob/main/CHANGELOG.md)，了解在每個主要版本中引進的重大變更。如需如何建置和安裝 的詳細資訊 適用於 C\+\+ 的 AWS SDK，請參閱 [適用於 C\+\+ 的 AWS SDK 從原始程式碼取得](sdk-from-source.md)。

 **從 Vcpkg 使用 SDK 的應用程式** 

如果您的應用程式使用 [Vcpkg](https://github.com/microsoft/vcpkg) 來追蹤 SDK 更新，只需使用現有的 Vcpkg 升級方法來將 SDK 升級到最新版本。請記住，發行版本與透過套件管理員取得版本之間存在延遲。透過[從來源安裝](sdk-from-source.md) ，一律可使用最新版本。

您可以執行下列命令來升級套件 `aws-sdk-cpp`：

```
vcpkg upgrade aws-sdk-cpp
```

並驗證套件 的版本`aws-sdk-cpp`：

```
vcpkg list aws-sdk-cpp
```

版本至少應為 1.11.x，以支援 V3-encrypted解密。

如需搭配 使用 Vcpkg 的詳細資訊 適用於 C\+\+ 的 AWS SDK，請參閱 [適用於 C\+\+ 的 AWS SDK 從套件管理員取得](sdk-from-pm.md)。

### 建置、安裝和部署您的應用程式
<a name="s3-encryption-migration-v2-v3-build-deploy-apps"></a>

如果您的應用程式靜態連結至 適用於 C\+\+ 的 AWS SDK，則不需要在您的應用程式中進行程式碼變更，但您必須再次建置應用程式，才能使用最新的 SDK 變更。動態連結不需要此步驟。

升級應用程式的相依性版本並驗證應用程式功能後，請繼續將應用程式部署到機群。一旦應用程式部署完成，您就可以繼續進行下一個階段，遷移應用程式以使用 V3 加密和解密用戶端。

## 將加密和解密用戶端遷移至 V3
<a name="s3-encryption-migration-v2-v3-migrate"></a>

下列步驟說明如何成功將程式碼從 Amazon S3 加密用戶端的 V2 V3Amazon S3。由於程式碼需要變更，因此無論應用程式是靜態還是動態連結，您都需要重建應用程式 適用於 C\+\+ 的 AWS SDK。

### 使用 V3 加密用戶端
<a name="s3-encryption-migration-v2-v3-using-v3-clients"></a>

V3 引入 `S3EncryptionClientV3`類別，並`CryptoConfigurationV3`取代 V2 對等項目。V3 中的主要差異為：
+ V3 使用 `KMSWithContextEncryptionMaterials`（與 V2 相同），但在 中需要明確組態`CryptoConfigurationV3`。
+ 所有`PutObject`操作都需要加密內容映射 （可以是空的）。
+ V3 推出承諾政策來控制加密和解密行為。
+ 根據預設，V3 會使用`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`演算法以金鑰承諾加密。
+ 舊版演算法解密組態 API 從 變更為 `config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY);` `config.AllowLegacy();`。

 **範例：使用 KMS 加密從 V2 遷移至 V3 ** 

 *預遷移 (V2)* 

```
// Create encryption materials
auto materials = Aws::MakeShared<KMSWithContextEncryptionMaterials>("s3EncryptionV2", CUSTOMER_MASTER_KEY_ID);

// Create V2 crypto configuration
CryptoConfigurationV2 cryptoConfig(materials);

// Create V2 encryption client
S3EncryptionClientV2 encryptionClient(cryptoConfig);

// Put object with encryption context
Aws::Map<Aws::String, Aws::String> encryptionContext;
encryptionContext.emplace("client", "aws-sdk-cpp");
encryptionContext.emplace("version", "1.11.0");

PutObjectRequest putObjectRequest;
putObjectRequest.SetBucket(BUCKET_NAME);
putObjectRequest.SetKey(OBJECT_KEY);
// Set object body...

auto putOutcome = encryptionClient.PutObject(putObjectRequest, encryptionContext);

// Get object with encryption context
GetObjectRequest getObjectRequest;
getObjectRequest.SetBucket(BUCKET_NAME);
getObjectRequest.SetKey(OBJECT_KEY);

auto getOutcome = encryptionClient.GetObject(getObjectRequest, encryptionContext);
```

 *在遷移期間 （具有回溯相容性的 V3)* 

```
// Create encryption materials
auto materials = Aws::MakeShared<KMSWithContextEncryptionMaterials>("s3EncryptionV3", CUSTOMER_MASTER_KEY_ID);

// Create V3 crypto configuration with materials
CryptoConfigurationV3 cryptoConfig(materials);

// Set commitment policy to maintain compatibility with V2 encrypted objects
// This allows V3 clients to decrypt objects encrypted by the V2 client
cryptoConfig.SetCommitmentPolicy(CommitmentPolicy::REQUIRE_ENCRYPT_ALLOW_DECRYPT);

// Create V3 encryption client
S3EncryptionClientV3 encryptionClient(cryptoConfig);

// Put object with encryption context
Aws::Map<Aws::String, Aws::String> encryptionContext;
encryptionContext.emplace("client", "aws-sdk-cpp");
encryptionContext.emplace("version", "1.11.0");

PutObjectRequest putObjectRequest;
putObjectRequest.SetBucket(BUCKET_NAME);
putObjectRequest.SetKey(OBJECT_KEY);
// Set object body...

auto putOutcome = encryptionClient.PutObject(putObjectRequest, encryptionContext);

// Get object with encryption context
GetObjectRequest getObjectRequest;
getObjectRequest.SetBucket(BUCKET_NAME);
getObjectRequest.SetKey(OBJECT_KEY);

auto getOutcome = encryptionClient.GetObject(getObjectRequest, encryptionContext);
```

 *遷移後 (V3 與金鑰承諾）* 

```
// Create encryption materials
auto materials = Aws::MakeShared<KMSWithContextEncryptionMaterials>("s3EncryptionV3", CUSTOMER_MASTER_KEY_ID);

// Create V3 crypto configuration with materials
CryptoConfigurationV3 cryptoConfig(materials);

// Use the default commitment policy (REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
// This encrypts with key commitment and does not decrypt V2 objects
// cryptoConfig.SetCommitmentPolicy(CommitmentPolicy::REQUIRE_ENCRYPT_ALLOW_DECRYPT);

// Create V3 encryption client
S3EncryptionClientV3 encryptionClient(cryptoConfig);

// Put object with encryption context
Aws::Map<Aws::String, Aws::String> encryptionContext;
encryptionContext.emplace("client", "aws-sdk-cpp");
encryptionContext.emplace("version", "1.11.0");

PutObjectRequest putObjectRequest;
putObjectRequest.SetBucket(BUCKET_NAME);
putObjectRequest.SetKey(OBJECT_KEY);
// Set object body...

auto putOutcome = encryptionClient.PutObject(putObjectRequest, encryptionContext);

// Get object with encryption context
GetObjectRequest getObjectRequest;
getObjectRequest.SetBucket(BUCKET_NAME);
getObjectRequest.SetKey(OBJECT_KEY);

auto getOutcome = encryptionClient.GetObject(getObjectRequest, encryptionContext);
```

## 其他範例
<a name="s3-encryption-migration-v2-v3-examples"></a>

本節提供設定 V3 加密用戶端選項以支援各種遷移案例和要求的其他範例。

### 啟用舊版支援
<a name="s3-encryption-migration-v2-v3-examples-legacy-support"></a>

只有在使用 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`或 `FORBID_ENCRYPT_ALLOW_DECRYPT`承諾政策時，V3 用戶端才能解密 V2 用戶端加密的物件。不過，如果您需要解密 V1 用戶端加密的物件，您必須使用 `AllowLegacy()`方法明確啟用舊版支援。

**何時使用舊版支援：**
+ 您在 S3 中有使用 S3 加密用戶端的 V1 S3加密的物件。
+ 在遷移過程中，您需要使用 V3 用戶端讀取這些 V1-encrypted的物件。
+ 您正在使用 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`或 `FORBID_ENCRYPT_ALLOW_DECRYPT`承諾政策。

**警告**  
舊版支援只能在遷移期間暫時啟用。使用 V2 或 V3 重新加密所有 V1 物件後，請停用舊版支援以確保最大安全性。

**範例：啟用舊版支援**

```
// Create encryption materials
auto materials = Aws::MakeShared<KMSWithContextEncryptionMaterials>("s3EncryptionV3", CUSTOMER_MASTER_KEY_ID);

// Create V3 crypto configuration
CryptoConfigurationV3 cryptoConfig(materials);

// Enable legacy support to read V1 encrypted objects
cryptoConfig.AllowLegacy();

// Set commitment policy (default is REQUIRE_ENCRYPT_REQUIRE_DECRYPT but we need to allow decryption)
cryptoConfig.SetCommitmentPolicy(CommitmentPolicy::REQUIRE_ENCRYPT_ALLOW_DECRYPT);

// Create V3 encryption client with legacy support enabled
S3EncryptionClientV3 encryptionClient(cryptoConfig);

// Now you can decrypt objects encrypted by V1, V2, and V3 clients
GetObjectRequest getObjectRequest;
getObjectRequest.SetBucket(BUCKET_NAME);
getObjectRequest.SetKey(LEGACY_OBJECT_KEY);

Aws::Map<Aws::String, Aws::String> encryptionContext;
auto getOutcome = encryptionClient.GetObject(getObjectRequest, encryptionContext);
```

### 設定儲存方法
<a name="s3-encryption-migration-v2-v3-examples-storage-method"></a>

S3 加密用戶端可以透過兩種方式存放加密中繼資料：做為物件中繼資料 （預設） 或存放在單獨的指示檔案中。您可以使用 上的 方法設定儲存`SetStorageMethod()`方法`CryptoConfigurationV3`。

**儲存方法選項：**

**`METADATA` (預設值)**  
加密中繼資料會存放在物件的中繼資料標頭中。這是最常見且方便的方法，因為所有加密資訊都會與物件本身一起存放。  
**使用時機：**在大多數情況下使用此方法。其可簡化物件管理，因為加密中繼資料會隨著物件移動。

**`INSTRUCTION_FILE`**  
加密中繼資料存放在具有尾碼 的個別 S3 物件 （指令檔案） 中`.instruction`。  
**使用時機：**當需要考慮物件中繼資料大小，或您需要將加密中繼資料與加密物件分開時，請使用此方法。請注意，使用指令檔案需要管理兩個 S3 物件 （加密的物件及其指令檔案），而不是一個。

**範例：設定儲存方法**

```
// Create encryption materials
auto materials = Aws::MakeShared<KMSWithContextEncryptionMaterials>("s3EncryptionV3", CUSTOMER_MASTER_KEY_ID);

// Create V3 crypto configuration
CryptoConfigurationV3 cryptoConfig(materials);

// Option 1: Use metadata storage (default, can be omitted)
cryptoConfig.SetStorageMethod(StorageMethod::METADATA);

// Option 2: Use instruction file storage
cryptoConfig.SetStorageMethod(StorageMethod::INSTRUCTION_FILE);

// Create V3 encryption client with the configured storage method
S3EncryptionClientV3 encryptionClient(cryptoConfig);

// Put object - encryption metadata will be stored according to the configured method
Aws::Map<Aws::String, Aws::String> encryptionContext;
encryptionContext.emplace("client", "aws-sdk-cpp");

PutObjectRequest putObjectRequest;
putObjectRequest.SetBucket(BUCKET_NAME);
putObjectRequest.SetKey(OBJECT_KEY);
// Set object body...

auto putOutcome = encryptionClient.PutObject(putObjectRequest, encryptionContext);

// If using INSTRUCTION_FILE, a separate object with key "OBJECT_KEY.instruction" will be created
```

**注意**  
使用`INSTRUCTION_FILE`儲存方法時，請記住，刪除加密的物件不會自動刪除指令檔案。您必須分別管理這兩個物件。