

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

# Direct KMS 材料提供程序
<a name="direct-kms-provider"></a>

**注意**  
我们的客户端加密库已[重命名为 AWS 数据库加密 SDK](DDBEC-rename.md)。以下主题提供有关适用于 Java 的 DynamoDB 加密客户端版本 1.*x*—2.*x* 以及适用于 Python 的 DynamoDB 加密客户端版本 1.*x*—3.*x* 的信息。有关更多信息，请参阅[适用于 DynamoDB 的AWS 数据库加密 SDK 版本支持](legacy-dynamodb-encryption-client.md#legacy-support)。

*Direct KMS 材料提供程序*（Direct KMS 提供程序）借助从不让 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)（AWS KMS）处于不加密状态的 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys) 保护您的表项目。此[加密材料提供程序](DDBEC-legacy-concepts.md#concept-material-provider)为每个表项目返回唯一的加密密钥和签名密钥。为此，它会在您 AWS KMS 每次加密或解密项目时调用。

如果您以高频率和大规模处理 DynamoDB 项目，则可能会超出限制，从而导致处理 AWS KMS [requests-per-second延](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html#requests-per-second)迟。如果需要超出限制，请在 [AWS 支持 中心](https://console.aws.amazon.com/support/home)并创建案例。您也可以考虑使用密钥重复次数使用有限的加密材料提供程序，例如[最新提供程序](most-recent-provider.md)。

要使用 Direcrypt KMS 提供程序 AWS 账户，调用者必须至少拥有[一个](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)权限 AWS KMS key，才能在上调用[GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html)和[解密](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html)操作。 AWS KMS key AWS KMS key 必须是对称加密密钥；DynamoDB 加密客户端不支持非对称加密。如果您使用的是 [DynamoDB 全局表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GlobalTables.html)，则可能需要指定一个 [AWS KMS 多区域密钥](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)。有关更多信息，请参阅 [使用方法](#provider-kms-how-to-use)。

**注意**  
当您使用 Direct KMS 提供程序时，您的主密钥属性的名称和值将以纯文本形式显示在[AWS KMS 加密上下文](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)和相关 AWS CloudTrail AWS KMS 操作日志中。但是，DynamoDB 加密客户端从不公开任意加密属性值的明文。

直接 KMS 提供程序是 DynamoDB [加密客户端支持的几个加密材料提供商](DDBEC-legacy-concepts.md#concept-material-provider) (CMPs) 之一。有关另一个的信息 CMPs，请参阅[加密材料提供程序](crypto-materials-providers.md)。

**有关示例代码，请参阅：**
+ Java：[AwsKmsEncryptedItem](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedItem.java)
+ Python: [aws-kms-encrypted-table](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_table.py)，[aws-kms-encrypted-item](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_item.py)

**Topics**
+ [使用方法](#provider-kms-how-to-use)
+ [工作原理](#provider-kms-how-it-works)

## 使用方法
<a name="provider-kms-how-to-use"></a>

要创建 Direct KMS 提供程序，请使用密钥 ID 参数在您的账户中指定对称加密 [KMS 密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)。密钥 ID 参数的值可以是 AWS KMS key的密钥 ID、密钥 ARN、别名名称或别名 ARN。有关密钥标识符的详细信息，请参阅《AWS Key Management Service 开发人员指南》**中的[密钥标识符](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id)。

Direct KMS 提供程序需要对称的加密 KMS 密钥。不能使用非对称 KMS 密钥。但是，可以使用多区域 KMS 键、包含导入的密钥材料的 KMS 密钥，或自定义密钥存储中的 KMS 密钥。您必须拥有 [KMS 密钥的 kms: GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 和 [kms: decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 权限。因此，您必须使用客户托管的密钥，而不是托 AWS 管或 AWS 拥有的 KMS 密钥。

适用于 Python 的 DynamoDB 加密客户端在密钥 ID 参数值（如果包含密钥 ID 参数值）中确定从该区域 AWS KMS 调用的区域。否则，它将使用 AWS KMS 客户端中的区域（如果您指定）或您在中配置的区域 适用于 Python (Boto3) 的 AWS SDK。有关 Python 中区域选择的信息，请参阅 Python AWS 开发工具包 (Boto3) API 参考中的[配置](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html)。

如果您指定的客户端包含区域，则适用于 Java 的 DynamoDB 加密客户端 AWS KMS 会确定从客户端中的区域进行 AWS KMS 调用的区域。否则，它将使用您在 适用于 Java 的 AWS SDK中配置的区域。有关中区域选择的信息 适用于 Java 的 AWS SDK，请参阅《 适用于 Java 的 AWS SDK 开发者指南》中的[AWS 区域 选择](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-region-selection.html)。

------
#### [ Java ]

```
// Replace the example key ARN and Region with valid values for your application
final String keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
final String region = 'us-west-2'
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
```

------
#### [ Python ]

以下示例使用密钥 ARN 指定 AWS KMS key。如果您的密钥标识符不包括 AWS 区域，则 DynamoDB 加密客户端将从已配置的 Botocore 会话（如果有）或 Boto 默认会话中获取区域。

```
# Replace the example key ID with a valid value
kms_key = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=kms_key)
```

------

如果您使用的是 [Amazon DynamoDB 全局](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GlobalTables.html)表，我们建议您使用多区域密钥对数据进行 AWS KMS 加密。多区域密钥不同 AWS 区域 ，可以互换使用，因为它们具有相同的密钥 ID 和密钥材料。 AWS KMS keys 有关详细信息，请参阅《AWS Key Management Service 开发人员指南》**中的[使用多区域密钥](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)。

**注意**  
如果您使用的是全局表[版本 2017.11.29](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/globaltables.V1.html)，则必须设置属性操作，这样，保留的复制字段就不会被加密或签名。有关更多信息，请参阅 [旧版本全局表存在的问题](troubleshooting.md#fix-global-tables)。

要在 DynamoDB 加密客户端中使用多区域密钥，请创建多区域密钥并将其复制到应用程序运行所在的区域。然后将 Direct KMS 提供程序配置为使用 DynamoDB 加密客户端调用 AWS KMS所在区域中的多区域密钥。

以下示例将 DynamoDB 加密客户端配置为在美国东部（弗吉尼亚州北部）（us-east-1）区域中的加密数据，并使用多区域密钥，在美国西部（俄勒冈州）（us-west-2）区域中对其进行解密。

------
#### [ Java ]

在此示例中，DynamoDB 加密客户端在客户端中获取从该区域进行 AWS KMS 调用的区域。 AWS KMS `keyArn` 值标识同一区域中的多区域密钥。

```
// Encrypt in us-east-1

// Replace the example key ARN and Region with valid values for your application
final String usEastKey = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
final String region = 'us-east-1'
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, usEastKey);
```

```
// Decrypt in us-west-2

// Replace the example key ARN and Region with valid values for your application
final String usWestKey = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
final String region = 'us-west-2'
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, usWestKey);
```

------
#### [ Python ]

在此示例中，DynamoDB 加密客户端在密钥 ARN 中获取了从该区域进行 AWS KMS 呼叫的区域。

```
# Encrypt in us-east-1

# Replace the example key ID with a valid value
us_east_key = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=us_east_key)
```

```
# Decrypt in us-west-2

# Replace the example key ID with a valid value
us_west_key = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=us_west_key)
```

------

## 工作原理
<a name="provider-kms-how-it-works"></a>

Direct KMS 提供程序返回受您指定的 AWS KMS key 保护的加密密钥和签名密钥，如下图所示。

![\[DynamoDB 加密客户端中 Direct KMS 提供程序的输入、处理和输出\]](http://docs.aws.amazon.com/zh_cn/database-encryption-sdk/latest/devguide/images/directKMS.png)

+ 要生成加密材料，Direct KMS 提供程序会要求 AWS KMS 使用您指定的为每个项目[生成一个 AWS KMS key 唯一的数据密钥](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html)。它从[数据密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#data-keys)的明文副本中派生项目的加密密钥和签名密钥，然后返回加密密钥和签名密钥以及加密的数据密钥，后者存储在项目的[材料说明属性](DDBEC-legacy-concepts.md#legacy-material-description)中。

  项目加密程序使用加密密钥和签名密钥并尽快将它们从内存中删除。仅其派生自的数据密钥的加密副本保存在加密项目中。
+ 要生成解密材料，Direct KMS 提供商会要求 AWS KMS 解密加密的数据密钥。然后，它从明文数据密钥派生验证密钥和签名密钥，然后将这些密钥返回至项目加密程序。

  项目加密程序会验证项目，而且如果验证成功，会解密加密的值。然后，它会尽快从内存中删除这些密钥。

### 获取加密材料
<a name="direct-kms-get-encryption-materials"></a>

本部分详细介绍了 Direct KMS 提供程序收到来自[项目加密程序](DDBEC-legacy-concepts.md#item-encryptor)的加密材料请求时的输入、输出和处理。

**输入**（来自应用程序）
+ 的密钥 ID AWS KMS key。

**输入**（来自项目加密程序）
+ [DynamoDB 加密上下文](concepts.md#encryption-context)

**输出**（至项目加密程序）
+ 加密密钥（明文）
+ 签名密钥
+ 在[实际材料描述](DDBEC-legacy-concepts.md#legacy-material-description)中：这些值保存在客户端将添加到项目的材料描述属性中。
  + amzn-ddb-env-key: Base64 编码的数据密钥由加密 AWS KMS key
  + amzn-ddb-env-alg: 加密算法，默认为 [AES/256](https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/archived-crypto-projects/aes-development)
  + amzn-ddb-sig-alg: 签名算法，默认情况下，[Hmac /256 SHA256](https://en.wikipedia.org/wiki/HMAC)
  + amzn-ddb-wrap-alg: kms

**Processing**

1. Direct KMS 提供者发送 AWS KMS 请求，要求使用指定的 AWS KMS key 为该项目[生成唯一的数据密钥](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html)。该操作会返回明文密钥以及由 AWS KMS key加密的副本。这称为*初始密钥材料*。

   请求包括 [AWS KMS 加密上下文](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)中的以下明文值。这些非密钥值以加密方式绑定到加密对象，因此，解密时需要相同的加密上下文。您可以使用这些值 AWS KMS 在[AWS CloudTrail 日志](https://docs.aws.amazon.com/kms/latest/developerguide/monitoring-overview.html)中标识对的调用。
   + amzn-ddb-env-alg — 加密算法，默认为 AES/256
   + amzn-ddb-sig-alg — 签名算法，默认为 Hmac /256 SHA256
   + （可选） aws-kms-table— *table name*
   + （可选）*partition key name*—*partition key value*（二进制值采用 Base64 编码）
   + （可选）*sort key name*—*sort key value*（二进制值采用 Base64 编码）

   直接 KMS 提供程序从该项目的 [DynamoDB AWS KMS 加密上下文中获取加密](concepts.md#encryption-context)上下文的值。如果 DynamoDB 加密上下文不包含值（例如表名），则加密上下文中将省略该名称/值对。 AWS KMS 

1. Direct KMS 提供程序从数据密钥派生对称加密密钥和签名密钥。默认情况下，它使用[安全哈希算法 (SHA) 256](https://en.wikipedia.org/wiki/SHA-2) 和[RFC5869 基于 HMAC 的密钥派生函数来派](https://tools.ietf.org/html/rfc5869)生 256 位 AES 对称加密密钥和 256 位 HMAC-SHA-256 签名密钥。

1. Direct KMS 提供程序将输出返回到项目加密程序。

1. 项目加密程序通过使用在实际材料说明中指定的算法，使用加密密钥加密指定的属性并使用签名密钥签署它们。它会尽快从内存中删除明文密钥。

### 获取解密材料
<a name="direct-kms-get-decryption-materials"></a>

本部分详细介绍了 Direct KMS 提供程序在从[项目加密程序](DDBEC-legacy-concepts.md#item-encryptor)收到解密材料的请求时的输入、输出和处理。

**输入**（来自应用程序）
+ 的密钥 ID AWS KMS key。

  密钥 ID 的值可以是 AWS KMS key的密钥 ID、密钥 ARN、别名名称或别名 ARN。未包含在密钥 ID 中的任何值，如区域，必须在 [AWS 命名配置文件](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-using-profiles)中可用。密钥 ARN 提供了 AWS KMS 需要的所有值。

**输入**（来自项目加密程序）
+ 包含材料描述属性内容的 [DynamoDB 加密上下文](concepts.md#encryption-context)的副本。

**输出**（至项目加密程序）
+ 加密密钥（明文）
+ 签名密钥

**Processing**

1. Direct KMS 提供程序从加密项目中的材料描述属性获取加密数据密钥。

1. 它要求 AWS KMS 使用指定的 AWS KMS key 来[解密加密的数据密](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html)钥。此操作会返回明文密钥。

   此请求必须使用用于生成和加密数据密钥的相同的 [AWS KMS 加密上下文](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)。
   + aws-kms-table – *table name*
   + *partition key name*—*partition key value*（二进制值采用 Base64 编码）
   + （可选）*sort key name*—*sort key value*（二进制值采用 Base64 编码）
   + amzn-ddb-env-alg — 加密算法，默认为 AES/256
   + amzn-ddb-sig-alg — 签名算法，默认为 Hmac /256 SHA256

1. Direct KMS 提供商使用[安全哈希算法 (SHA) 256](https://en.wikipedia.org/wiki/SHA-2) 和[RFC5869 基于 HMAC 的密钥派生函数](https://tools.ietf.org/html/rfc5869)从数据密钥中派生 256 位 AES 对称加密密钥和 256 位 HMAC-SHA-256 签名密钥。

1. Direct KMS 提供程序将输出返回到项目加密程序。

1. 项目加密程序将使用此签名密钥验证项目。如果它成功，则会使用对称加密密钥来解决加密的属性值。这些操作使用在实际材料说明中指定的加密和签名算法。项目加密程序它会尽快从内存中删除明文密钥。