

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

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

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

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

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

Amazon S3 加密用戶端第 3 版推出具有金鑰承諾的 AES GCM，以提高安全性。這個新的加密演算法提供保護，防止資料金鑰遭到竄改，並確保加密資料的完整性。遷移至 V3 需要仔細規劃，以在整個過程中維持應用程式的可用性和資料可存取性。

此遷移分為兩個階段：

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

2. **將加密和解密用戶端遷移至 V3。**一旦所有 V2 加密用戶端都可以讀取新的格式，您就可以將現有的加密和解密用戶端遷移到各自的 V3 版本。這包括設定承諾政策並更新您的程式碼，以使用新的用戶端組態選項。

如果您尚未從 V1 遷移至 V2，您必須先完成該遷移。如需從 V1 遷移至 V2 的詳細說明[Amazon S3 加密用戶端遷移 (V1 至 V2)](s3-encryption-migration-v1-v2.md)，請參閱 。

## 了解 V3 功能
<a name="s3-encryption-migration-v2-v3-understanding"></a>

Amazon S3 加密用戶端第 3 版推出兩個金鑰安全功能：承諾政策和具有金鑰承諾的 AES GCM。了解這些功能對於規劃遷移策略並確保加密資料的安全性至關重要。

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

承諾政策控制加密用戶端在加密和解密操作期間處理金鑰承諾的方式。金鑰承諾可確保加密的資料只能使用用來加密的確切金鑰進行解密，以防止特定類型的密碼編譯攻擊。

V3 加密用戶端支援三個承諾政策選項：

 **`FORBID_ENCRYPT_ALLOW_DECRYPT`** 

此政策會加密沒有金鑰承諾的物件，並允許使用和不使用金鑰承諾的兩個物件進行解密。
+  **加密行為：**使用與 V2 相同的演算法套件來加密物件，無需金鑰承諾。
+  **解密行為：**可以解密有或沒有金鑰承諾的加密物件。
+  **安全性影響：**此政策不會強制執行金鑰承諾，並可能允許竄改。使用此政策加密的物件不會受益於金鑰承諾的增強型安全保護。當您需要維持與 V2 加密行為的相容性時，請僅在遷移期間使用此政策。
+  **版本相容性：**使用此政策加密的物件可由 S3 加密用戶端的所有 V2 和 V3 實作讀取。 V3 

 **`REQUIRE_ENCRYPT_ALLOW_DECRYPT`**

此政策會使用金鑰承諾來加密物件，並允許使用和不使用金鑰承諾來解密這兩個物件。
+  **加密行為：**使用 AES GCM 搭配金鑰承諾，以金鑰承諾加密物件。
+  **解密行為：**可以解密使用或不使用金鑰承諾加密的物件，提供回溯相容性。
+  **安全影響：**新物件受益於金鑰承諾保護，而沒有金鑰承諾的現有物件仍可讀取。這可在遷移期間提供安全與回溯相容性之間的平衡。
+  **版本相容性：**使用此政策加密的物件只能由 SV3 加密用戶端的 V3 和最新的 V2 實作讀取。 S3 

 **`REQUIRE_ENCRYPT_REQUIRE_DECRYPT`** 

此政策會加密具有金鑰承諾的物件，並僅允許解密使用金鑰承諾加密的物件。
+  **加密行為：**使用 AES GCM 搭配金鑰承諾，以金鑰承諾加密物件。
+  **解密行為：**只能解密以金鑰承諾加密的物件。嘗試在沒有金鑰承諾的情況下解密物件將會失敗。
+  **安全性影響：**此政策會強制執行所有操作的金鑰承諾，以提供最高層級的安全性。只有在所有物件都已透過金鑰承諾重新加密，且所有用戶端都已升級至 V3 之後，才能使用此政策。
+  **版本相容性：**使用此政策加密的物件只能由 SV3 加密用戶端的 V3 和最新的 V2 實作讀取。 S3 此政策也可防止讀取由 V2 或 V1 用戶端加密的物件。

**注意**  
規劃遷移時，請從 開始`REQUIRE_ENCRYPT_ALLOW_DECRYPT`，以維持回溯相容性，同時獲得新物件金鑰承諾的安全優勢。只有在所有物件都重新加密且所有用戶端都升級至 V3 `REQUIRE_ENCRYPT_REQUIRE_DECRYPT`之後，才能移至 。

### 具有金鑰承諾的 AES GCM
<a name="s3-encryption-migration-v2-v3-aes-gcm-kc"></a>

具有金鑰承諾的 AES GCM (`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`) 是 V3 中引入的新加密演算法，可透過防止資料金鑰竄改來提供增強的安全性。了解此演算法的運作方式及其套用時間對於規劃遷移至關重要。

 **與先前演算法`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`的差異** 

舊版 S3 加密用戶端使用 AES CBC 或 AES GCM，無需金鑰承諾即可加密指令檔案中的資料金鑰。 會將密碼編譯承諾`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`新增至加密程序，將加密的資料繫結至特定金鑰。這可防止攻擊者竄改指令檔案中的加密資料金鑰，並導致用戶端使用不正確的金鑰解密資料。

如果沒有金鑰承諾，攻擊者可能會修改指令檔案中的加密資料金鑰，使其解密為不同的金鑰，從而可能允許未經授權的存取或資料損毀。 會確保加密的資料金鑰只能解密為加密期間使用的原始金鑰，`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`以防止此攻擊。

 **版本相容性** 

使用 加密的物件`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`只能由 SV3 加密用戶端的 V3 實作和包含支援讀取 V3 格式的特定 V2 轉換版本解密。 S3 沒有此轉換支援的 V2 用戶端無法解密使用 加密的指令檔案`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`。

**警告**  
在啟用 加密 `ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`（使用 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`或 `REQUIRE_ENCRYPT_REQUIRE_DECRYPT`承諾政策） 之前，請確保需要讀取加密物件的所有用戶端都已升級至 V3 或支援 V3 格式的轉換版本。如果任何沒有轉換支援的 V2 用戶端嘗試讀取使用 加密的物件`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`，解密將會失敗。

在遷移期間，您可以使用 `FORBID_ENCRYPT_ALLOW_DECRYPT` 承諾政策繼續加密，而無需 ，`ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY`同時仍然允許 V3 用戶端讀取使用金鑰承諾加密的物件。這提供安全的遷移路徑，您可以在其中先升級所有讀取器，然後切換到使用金鑰承諾加密。

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

V3 加密用戶端使用 V2 用戶端預設不支援的加密演算法和金鑰承諾功能。遷移的第一步是將您的 V2 解密用戶端更新為可讀取 V3 加密物件的適用於 Ruby 的 AWS SDK 版本。完成此步驟後，應用程式的 V2 用戶端將能夠解密由 V3 加密用戶端加密的物件。

若要讀取 V3 用戶端加密的物件 （使用 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`或 `REQUIRE_ENCRYPT_REQUIRE_DECRYPT`承諾政策的物件），您需要使用 1.93.0 版或更新版本的 `aws-sdk-s3` Gem 套件。此版本包含支援解密使用 AES GCM 與金鑰承諾加密的物件。

 **從命令列安裝** 

對於從命令列安裝 `aws-sdk-s3` Gem 的專案，請使用版本選項來驗證已安裝最低版本 1.208.0。

```
gem install aws-sdk-s3 -v '>= 1.208.0'
```

 **使用 Gemfile** 

對於使用 Gemfile 管理相依性的專案，請將 `aws-sdk-s3` Gem 的最低版本設定為 1.208.0。例如：

```
gem 'aws-sdk-s3', '>= 1.208.0'
```

1. 修改 Gemfile 以指定最低版本。

1. 執行 `bundle update aws-sdk-s3`以更新 Gem。

1. 若要驗證您的版本，請執行 `bundle info aws-sdk-s3`。

**注意**  
更新至最新版本後，您現有的 V2 加密用戶端將能夠解密 V3 用戶端加密的物件。不過，它們將繼續使用 V2 演算法加密新物件，直到您將其遷移至 V3，如下一節所述。

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

更新用戶端以讀取新的加密格式後，您可以將應用程式更新為 V3 加密和解密用戶端。下列步驟說明如何成功將程式碼從 V2 遷移至 V3。

在更新您的程式碼以使用 V3 加密用戶端之前，請確定您已遵循上述步驟，並使用 `aws-sdk-s3` Gem 1.93.0 版或更新版本。

**注意**  
使用 AES-GCM 解密時，請先將整個物件讀到結尾，再開始使用解密的資料。這是為了驗證物件在加密後尚未修改。

### 設定 V3 用戶端
<a name="s3-encryption-migration-v2-v3-configure"></a>

V3 加密用戶端推出新的組態選項，可控制金鑰承諾行為和回溯相容性。了解這些選項對於成功遷移至關重要。

 **commitment\_policy** 

`commitment_policy` 參數控制加密用戶端在加密和解密操作期間處理金鑰承諾的方式。這是 V3 用戶端最重要的組態選項。
+  `:require_encrypt_allow_decrypt` - 加密具有金鑰承諾的新物件，並允許解密具有或不具有金鑰承諾的物件。這是建議的遷移設定，因為它可為新物件提供增強的安全性，同時保持與現有 V2 物件的回溯相容性。
+  `:forbid_encrypt_allow_decrypt` - 加密沒有金鑰承諾的新物件 （使用 V2 演算法），並允許解密有或沒有金鑰承諾的物件。只有在您需要在遷移期間維護 V2 加密行為時，例如某些用戶端尚無法讀取 V3 加密物件時，才使用此設定。
+  `:require_encrypt_require_decrypt` - 使用金鑰承諾加密新物件，並僅允許使用金鑰承諾加密的物件進行解密。只有在所有物件都已透過金鑰承諾重新加密，且所有用戶端都已升級至 V3 之後，才能使用此設定。

 **security\_profile** 

`security_profile` 參數決定對讀取較舊加密用戶端版本所寫入物件的支援。此參數對於在遷移期間維持回溯相容性至關重要。
+  `:v3_and_legacy` - 允許 V3 用戶端解密 V1 和 V2 加密用戶端加密的物件。在遷移期間使用此設定，以確保您的 V3 用戶端可以讀取所有現有的加密物件。
+  `:v3` - 允許 V3 用戶端僅解密 V2 加密用戶端加密的物件。如果您已將所有 V1 物件遷移至 V2 格式，請使用此設定。
+ 如果未指定，用戶端只會解密 V3 用戶端加密的物件。僅將此用於不存在舊版物件的新應用程式開發。

 **envelope\_location** 

`envelope_location` 參數會決定加密中繼資料 （包括加密的資料金鑰） 的存放位置。此參數會影響哪些物件受到具有金鑰承諾的 AES GCM 保護。
+  `:metadata` （預設） - 將加密中繼資料存放在 S3 物件的中繼資料標頭中。這是預設行為，建議大多數使用案例使用。使用中繼資料儲存體時，不適用具有金鑰承諾的 AES GCM。
+  `:instruction_file` - 將加密中繼資料存放在具有可設定尾碼的個別 S3 物件 （指令檔案） 中。使用指示檔案時，AES GCM 與金鑰承諾可防止加密的資料金鑰遭到竄改。如果您需要資料金鑰本身的金鑰承諾提供的額外安全性，請使用此設定。

使用 時`:instruction_file`，您可以選擇指定 `instruction_file_suffix` 參數來自訂用於指令檔案物件的尾碼。預設尾碼為 `.instruction`。

 **何時使用每個組態選項** 

在遷移期間，請遵循以下建議的組態策略：

1.  **初始遷移：**設定 `commitment_policy: :require_encrypt_allow_decrypt`和 `security_profile: :v3_and_legacy`。這可讓您的 V3 用戶端使用金鑰承諾來加密新物件，同時仍然能夠解密所有現有的 V1 和 V2 物件。

1.  **升級所有用戶端之後：繼續使用 **`commitment_policy: :require_encrypt_allow_decrypt`和 ，`security_profile: :v3_and_legacy`直到您重新加密所有需要金鑰承諾保護的物件為止。

1.  **完整 V3 強制執行：**只有在所有物件都已透過金鑰承諾重新加密，而且您不再需要讀取 V1/V2 物件之後，您可以選擇切換到 `commitment_policy: :require_encrypt_require_decrypt` 並移除 `security_profile` 參數 （如果 V2 物件仍然存在`:v2`，則將其設定為 )。

對於 `envelope_location`，除非您有特定的變更原因，否則請繼續使用現有的儲存方法 (`:metadata` 或 `:instruction_file`)。如果您目前正在使用中繼資料儲存體，並希望對資料金鑰具有金鑰承諾的 AES GCM 具有額外的安全性，您可以切換到 `:instruction_file`，但請注意，這將需要更新讀取這些物件的所有用戶端。

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

更新用戶端以讀取新的加密格式後，您可以將應用程式更新為 V3 加密和解密用戶端。下列範例示範如何成功將程式碼從 V2 遷移至 V3。

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

 **預遷移 (V2)** 

```
require 'aws-sdk-s3'

# Create V2 encryption client with KMS
client = Aws::S3::EncryptionV2::Client.new(
  kms_key_id: kms_key_id,
  key_wrap_schema: :kms_context,
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v2_and_legacy,
  commitment_policy: :forbid_encrypt_allow_decrypt
)

# Encrypt and upload object
client.put_object(bucket: 'my-bucket', key: 'my-object', body: 'secret data')

# Download and decrypt object
resp = client.get_object(bucket: 'my-bucket', key: 'my-object')
decrypted_data = resp.body.read
```

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

```
require 'aws-sdk-s3'

# Create V3 encryption client with KMS
client = Aws::S3::EncryptionV3::Client.new(
  kms_key_id: kms_key_id,
  key_wrap_schema: :kms_context,
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v3_and_legacy,
  commitment_policy: :require_encrypt_allow_decrypt
)

# Encrypt and upload object
client.put_object(bucket: 'my-bucket', key: 'my-object', body: 'secret data')

# Download and decrypt object
resp = client.get_object(bucket: 'my-bucket', key: 'my-object')
decrypted_data = resp.body.read
```

 **遷移後 (V3)** 

```
require 'aws-sdk-s3'

# Create V3 encryption client with KMS
client = Aws::S3::EncryptionV3::Client.new(
  kms_key_id: kms_key_id,
  key_wrap_schema: :kms_context,
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v3,
  # Use the commitment policy (REQUIRE_ENCRYPT_REQUIRE_DECRYPT)
  # This encrypts with key commitment and does not decrypt V2 objects
  commitment_policy: :require_encrypt_require_decrypt
)

# Encrypt and upload object
client.put_object(bucket: 'my-bucket', key: 'my-object', body: 'secret data')

# Download and decrypt object
resp = client.get_object(bucket: 'my-bucket', key: 'my-object')
decrypted_data = resp.body.read
```

V3 的關鍵差異是新增 `commitment_policy` 參數。將其設定為 `:require_encrypt_require_decrypt`可確保使用金鑰承諾加密新物件，而且用戶端只會解密使用金鑰承諾加密的物件，從而增強資料金鑰竄改的安全性。

`put_object` 呼叫本身保持不變。所有安全性增強功能都是在用戶端層級設定。

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

本節提供特定遷移案例的其他範例，以及在 V2 到 V3 遷移期間可能有用的組態選項。

#### 指示檔案與中繼資料儲存
<a name="s3-encryption-migration-v2-v3-example-storage"></a>

S3 加密用戶端可以將加密中繼資料 （包括加密的資料金鑰） 存放在兩個不同的位置：S3 物件的中繼資料標頭或單獨的指令檔案中。儲存方法的選擇會影響哪些物件受益於具有金鑰承諾保護的 AES GCM。

 **中繼資料儲存 （預設）** 

根據預設，加密用戶端會將加密中繼資料存放在 S3 物件的中繼資料標頭中。這是大多數使用案例的建議方法，因為它會將加密中繼資料與 物件一起保留，而且不需要管理個別的指令檔案物件。

```
require 'aws-sdk-s3'

# Create V3 encryption client with metadata storage (default)
client = Aws::S3::EncryptionV3::Client.new(
  kms_key_id: kms_key_id,
  key_wrap_schema: :kms_context,
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v3_and_legacy,
  commitment_policy: :require_encrypt_allow_decrypt,
  envelope_location: :metadata # Explicitly set to metadata (this is the default)
)

# Encrypt and upload object
# Encryption metadata is stored in the object's metadata headers
client.put_object(bucket: 'my-bucket', key: 'my-object',body: 'secret data')
```

使用中繼資料儲存時，具有金鑰承諾的 AES GCM 不適用於加密的資料金鑰。不過，使用 `commitment_policy: :require_encrypt_allow_decrypt`或 時，內容加密仍然受益於金鑰承諾`:require_encrypt_require_decrypt`。

 **指令檔案儲存** 

或者，您可以設定加密用戶端，將加密中繼資料存放在稱為 指令檔案的個別 S3 物件中。搭配 V3 使用指令檔案時，加密的資料金鑰受到 AES GCM 與金鑰承諾的保護，可提供額外的安全性，避免資料金鑰遭到竄改。

```
require 'aws-sdk-s3'

# Create V3 encryption client with instruction file storage
client = Aws::S3::EncryptionV3::Client.new(
  kms_key_id: kms_key_id,
  key_wrap_schema: :kms_context,
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v3_and_legacy,
  commitment_policy: :require_encrypt_allow_decrypt,
  envelope_location: :instruction_file, # Store metadata in separate instruction file
  instruction_file_suffix: '.instruction' # Optional: customize the suffix (default is '.instruction')
)

# Encrypt and upload object
# Encryption metadata is stored in a separate object: 'my-object.instruction'
client.put_object(bucket: 'my-bucket', key: 'my-object', body: 'secret data')

# When retrieving the object, the client automatically reads the instruction file
resp = client.get_object(bucket: 'my-bucket', key: 'my-object')
decrypted_data = resp.body.read
```

使用 時`envelope_location: :instruction_file`，加密用戶端會建立兩個 S3 物件：

1. 加密的資料物件 （例如 `my-object`)

1. 包含加密中繼資料的指示檔案 （例如 `my-object.instruction`)

`instruction_file_suffix` 參數可讓您自訂用於指令檔案的尾碼。預設值為 `.instruction`。

 **何時使用每種儲存方法** 
+  針對大多數案例**使用中繼資料儲存**。其可簡化物件管理，因為加密中繼資料會隨著物件移動。
+  當需要考慮物件中繼資料大小，或您需要將加密中繼資料與加密物件分開時，**請使用指令檔案儲存**。請注意，使用指令檔案需要管理兩個 S3 物件 （加密的物件及其指令檔案），而不是一個。

**警告**  
如果您從中繼資料儲存變更為指令檔案儲存 （反之亦然），使用新儲存方法設定的用戶端將無法讀取使用舊儲存方法加密的現有物件。仔細規劃您的儲存方法，並保持整個應用程式的一致性。