

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

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

**注意**  
如果您使用的是 S3 加密客户端的 V2，并且想要迁移到 V3，请参阅[亚马逊 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 的 AWS SDK 的更新版本部署到您的应用程序。这将允许现有 V1 加密客户端解密由新的 V2 客户端写入的对象。如果您的应用程序使用多个 SDK AWS SDKs，则必须单独升级每个 SDK。

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

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

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

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

版本 3 是适用于 Ruby 的 AWS 软件开发工具包的最新版本。要完成此迁移，您需要使用版本 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`。

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

适用于 Ruby 的 AWS SDK 第 2 版将于 2021 年 11 月 21 日进入[维护模式](https://aws.amazon.com/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.aws.amazon.com/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`-如果您正在使用 AWS 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. **AWS KMS key 默认情况下强制使用 ID。**在 V1 中`Encryption::Client`，`kms_key_id`用于创建客户端的未提供给。 AWS KMS `Decrypt call` AWS KMS 可以从元数据中获取这些信息并将其添加到对称密文 blob 中。在 V2 中，e`nCryptionV2:: Client`，*kms\_key\_id 被传递给 AWS KMS Decrypt 调用，如果它与用于加密对象的密钥*不匹配，则调用将失败。如果代码以前依赖于不设置特定的 `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>

 **迁移前** 

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

 **迁移后** 

```
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
```

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

 **迁移前** 

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

 **迁移后** 

```
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
```

### 示例：在没有 kms\_ke AWS KMS y\_id 的情况下使用
<a name="example-using-aws-kms-without-kms-key-id-v1-v2"></a>

 **迁移前** 

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

 **迁移后** 

```
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
```

 **迁移后替代方案** 

如果仅使用 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
```