

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon S3 加密客户端迁移（V1 到 V2）
<a name="s3-encryption-migration-v1-v2"></a>

**注意**  
如果您使用的是 S3 加密客户端的 V2 并想迁移到 V3，请参阅[Amazon S3 加密客户端迁移（V2 到 V3）](s3-encryption-migration-v2-v3.md)。

此主题介绍了如何将应用程序从 Amazon Simple Storage Service (Amazon S3) 加密客户端的版本 1 (V1) 迁移到版本 2 (V2)，并确保应用程序在整个迁移过程中的可用性。

## 迁移概述
<a name="migration-overview-v1-v2"></a>

此迁移分为两个阶段：

1. **更新现有客户端以读取新格式。**首先，将 Ruby Amazon 软件开发工具包的更新版本部署到您的应用程序。这将允许现有 V1 加密客户端解密由新的 V2 客户端写入的对象。如果您的应用程序使用多个 Amazon SDK，则必须单独升级每个 SDK。

2. **将加密和解密客户端迁移到 V2。**一旦所有 V1 加密客户端都能读取新格式，就可以将现有加密和解密客户端迁移到各自的 V2 版本。

## 更新现有客户端以读取新格式
<a name="update-existing-clients-to-read-new-formats-v1-v2"></a>

V2 加密客户端使用旧版本客户端不支持的加密算法。迁移的第一步是将 V1 解密客户端更新到最新 SDK 版本。完成此步骤后，应用程序的 V1 客户端就能够解密由 V2 加密客户端加密的对象。有关适用于 Ruby 的 Amazon SDK 的每个主要版本的详细信息，请参见下文。

### 更新 Amazon 适用于 Ruby 的 SDK 版本 3
<a name="update-aws-sdk-for-ruby-version-3-v1-v2"></a>

版本 3 是 Ruby Amazon 软件开发工具包的最新版本。要完成此迁移，您需要使用版本 1.76.0 或更高版本的 `aws-sdk-s3` Gem。

 **从命令行安装** 

对于安装 `aws-sdk-s3` Gem 的项目，请使用版本选项来验证是否安装了不低于 1.76.0 的版本。

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

 **使用 Gemfile** 

对于使用 Gemfile 管理依赖项的项目，请将 `aws-sdk-s3` Gem 的最低版本设置为 1.76.0。例如：

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

1. 修改 Gemfile。

1. 运行 `bundle update aws-sdk-s3`。要验证您的版本，请运行 `bundle info aws-sdk-s3`。

### 升级 Amazon 适用于 Ruby 的 SDK 版本 2
<a name="upgdate-aws-sdk-for-ruby-version-2-v1-v2"></a>

 Amazon 适用于 Ruby 的 SDK 版本 2 将于 2021 年 11 月 21 [ 日进入](https://www.amazonaws.cn/blogs/developer/deprecation-schedule-for-aws-sdk-for-ruby-v2/)维护模式。要完成此迁移，您需要使用版本 2.11.562 或更高版本的 aws-sdk Gem。

 **从命令行安装** 

对于安装 `aws-sdk` Gem 的项目，请从命令行使用版本选项来验证是否安装了不低于 2.11.562 的版本。

```
gem install aws-sdk -v '>= 2.11.562'
```

 **使用 Gemfile** 

对于使用 Gemfile 管理依赖项的项目，请将 `aws-sdk` Gem 的最低版本设置为 2.11.562。例如：

```
gem 'aws-sdk', '>= 2.11.562'
```

1. 修改 Gemfile。如果您有 Gemfile.lock 文件，请将其删除或更新。

1. 运行 `bundle update aws-sdk`。要验证您的版本，请运行 `bundle info aws-sdk`。

## 将加密和解密客户端迁移到 V2
<a name="migrate-encryption-and-decryption-clients-to-v2-v1-v2"></a>

更新客户端以读取新的加密格式后，您可以将应用程序更新到 V2 加密和解密客户端。以下步骤展示了如何成功地将代码从 V1 迁移到 V2。

在更新代码以使用 V2 加密客户端之前，确保您已按照上述步骤操作且使用的是 `aws-sdk-s3` Gem 版本 2.11.562 或更高版本。

**注意**  
使用解密时 AES-GCM，请先将整个对象读取到最后，然后再开始使用解密后的数据。这是为了验证自加密以来是否未对对象进行过修改。

### 配置 V2 加密客户端
<a name="configuring-v2-encryption-clients-v1-v2"></a>

*EncryptionV2::Client* 需要额外的配置。有关详细的配置信息，请参阅 [EncryptionV2::Client 文档](https://docs.amazonaws.cn/sdk-for-ruby/v3/api/Aws/S3/EncryptionV2/Client.html#initialize-instance_method)或本主题后面提供的示例。

1. **必须在构造客户端时指定密钥包装方法和内容加密算法。**在创建新的 `EncryptionV2::Client` 时，需要为 `key_wrap_schema` 和 `content_encryption_schema` 提供值。

 `key_wrap_schema`-如果您正在使用 Amazon KMS，则必须将其设置为`:kms_context`。如果您使用的是对称 (AES) 密钥，则必须将其设置为 `:aes_gcm`。如果您使用的是非对称 (RSA) 密钥，则必须将其设置为 `:rsa_oaep_sha1`。

 `content_encryption_schema`：必须将其设置为 *:aes\_gcm\_no\_padding*。

2. **必须在构造客户端时指定 security\_profile。**在创建新的 `EncryptionV2::Client` 时，需要为 `security_profile` 提供值。*security\_profile* 参数决定了是否支持读取使用旧版 V1 `Encryption::Client` 写入的对象。有两个值：*:v2* 和 *:v2\_and\_legacy*。要支持迁移，请将 `security_profile` 设置为 *:v2\_and\_legacy*。*:v2* 仅适用于新应用程序开发。

3. **Amazon KMS key 默认情况下强制使用 ID。**在 V1 中`Encryption::Client`，`kms_key_id`用于创建客户端的未提供给。 Amazon KMS `Decrypt call` Amazon KMS 可以从元数据中获取此信息并将其添加到对称密文 blob 中。在 V2 e`nCryptionV2:: Client` 中，*kms\_key\_id * 被传递给解密调用，如果它与用于加密对象的 Amazon KMS 密钥不匹配，则调用将失败。如果代码以前依赖于不设置特定的 `kms_key_id`，则要么在创建客户端时设置 `kms_key_id: :kms_allow_decrypt_with_any_cmk`，要么在调用 `get_object` 时设置 `kms_allow_decrypt_with_any_cmk: true`。

### 示例：使用对称 (AES) 密钥
<a name="example-using-a-symmetric-aes-key-v1-v2"></a>

 **Pre-migration** 

```
client = Aws::S3::Encryption::Client.new(encryption_key: aes_key)
client.put_object(bucket: bucket, key: key, body: secret_data)
resp = client.get_object(bucket: bucket, key: key)
```

 **Post-migration** 

```
client = Aws::S3::EncryptionV2::Client.new(
  encryption_key: rsa_key,
  key_wrap_schema: :rsa_oaep_sha1, # the key_wrap_schema must be rsa_oaep_sha1 for asymmetric keys
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v2_and_legacy # to allow reading/decrypting objects encrypted by the V1 encryption client
 )
client.put_object(bucket: bucket, key: key, body: secret_data)  # No changes
resp = client.get_object(bucket: bucket, key: key) # No changes
```

### 示例：使用 Amazon KMS 使用 kms\_key\_id
<a name="example-using-aws-kms-with-kms-key-id-v1-v2"></a>

 **Pre-migration** 

```
client = Aws::S3::Encryption::Client.new(kms_key_id: kms_key_id)
client.put_object(bucket: bucket, key: key, body: secret_data)
resp = client.get_object(bucket: bucket, key: key)
```

 **Post-migration** 

```
client = Aws::S3::EncryptionV2::Client.new(
  kms_key_id: kms_key_id,
  key_wrap_schema: :kms_context, # the key_wrap_schema must be kms_context for KMS keys
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v2_and_legacy # to allow reading/decrypting objects encrypted by the V1 encryption client
)
client.put_object(bucket: bucket, key: key, body: secret_data)  # No changes
resp = client.get_object(bucket: bucket, key: key) # No change
```

### 示例：使用 Amazon KMS 没有 kms\_key\_id
<a name="example-using-aws-kms-without-kms-key-id-v1-v2"></a>

 **Pre-migration** 

```
client = Aws::S3::Encryption::Client.new(kms_key_id: kms_key_id)
client.put_object(bucket: bucket, key: key, body: secret_data)
resp = client.get_object(bucket: bucket, key: key)
```

 **Post-migration** 

```
client = Aws::S3::EncryptionV2::Client.new(
  kms_key_id: kms_key_id,
  key_wrap_schema: :kms_context, # the key_wrap_schema must be kms_context for KMS keys
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v2_and_legacy # to allow reading/decrypting objects encrypted by the V1 encryption client
)
client.put_object(bucket: bucket, key: key, body: secret_data)  # No changes
resp = client.get_object(bucket: bucket, key: key, kms_allow_decrypt_with_any_cmk: true) # To allow decrypting with any cmk
```

 **Post-Migration 替代方案 ** 

如果仅使用 S2 加密客户端读取和解密（从不写入和加密）对象，请使用此代码。

```
client = Aws::S3::EncryptionV2::Client.new(
  kms_key_id: :kms_allow_decrypt_with_any_cmk, # set kms_key_id to allow all get_object requests to use any cmk
  key_wrap_schema: :kms_context, # the key_wrap_schema must be kms_context for KMS keys
  content_encryption_schema: :aes_gcm_no_padding,
  security_profile: :v2_and_legacy # to allow reading/decrypting objects encrypted by the V1 encryption client
)
resp = client.get_object(bucket: bucket, key: key) # No change
```