

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

# 适用于 Python 的 DynamoDB 加密客户端的示例代码
<a name="python-examples"></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)。

以下示例为您演示如何使用适用于 Python 的 DynamoDB 加密客户端来保护应用程序中的 DynamoDB 数据。你可以在上[aws-dynamodb-encryption-python](https://github.com/aws/aws-dynamodb-encryption-python/)存储库的示例目录中找到更多[示例](https://github.com/aws/aws-dynamodb-encryption-python/tree/master/examples)（并贡献自己的示例） GitHub。

**Topics**
+ [使用 EncryptedTable 客户端帮助器类](#python-example-table)
+ [使用项目加密程序](#python-example-item-encryptor)

## 使用 EncryptedTable 客户端帮助器类
<a name="python-example-table"></a>

以下示例为您演示如何结合使用 [Direct KMS 提供程序](direct-kms-provider.md)和此`EncryptedTable`[客户端帮助程序类](python-using.md#python-helpers)。此示例使用相同的[加密材料提供程序](DDBEC-legacy-concepts.md#concept-material-provider)，如[使用项目加密程序](#python-example-item-encryptor)示例所示。但是，它使用的是 `EncryptedTable` 类，而不是与低级别[项目加密程序](DDBEC-legacy-concepts.md#item-encryptor)直接交互。

通过比较这些示例，您可以看到客户端帮助程序类为您执行的工作。这包括创建 [DynamoDB 加密上下文](concepts.md#encryption-context)和确保始终为主键属性签名，但绝不加密。要创建加密上下文并发现主密钥，客户端帮助程序类会调用 DynamoDB 操作[DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)。要运行此代码，您必须具有调用此操作的权限。

**请参阅完整的代码示例**：[aws\$1kms\$1encrypted\$1table.py](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_table.py)

步骤 1：创建表  
首先使用表名称创建标准 DynamoDB 表的实例。  

```
table_name='test-table'
table = boto3.resource('dynamodb').Table(table_name)
```

步骤 2：创建加密材料提供程序  
创建您选择的[加密材料提供程序](crypto-materials-providers.md) (CMP) 的实例。  
此示例使用 [Direct KMS 提供程序](direct-kms-provider.md)，但您可以使用任何兼容的 CMP。要创建 Direct KMS 提供程序，请指定 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)。此示例使用的 Amazon 资源名称 (ARN) AWS KMS key，但您可以使用任何有效的密钥标识符。  

```
kms_key_id='arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=kms_key_id)
```

步骤 3：创建属性操作对象  
[属性操作](DDBEC-legacy-concepts.md#legacy-attribute-actions)告知项目加密程序将对项目的每个属性执行哪些操作。此示例中的 `AttributeActions` 对象加密并签名所有项目，除 `test` 属性以外，后者已被忽略。  
请勿在使用客户端帮助程序类时为主键属性指定属性操作。`EncryptedTable` 类会签名但绝不加密主键属性。  

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
    attribute_actions={'test': CryptoAction.DO_NOTHING}
)
```

步骤 4：创建加密表  
使用标准表、Direct KMS 提供程序和属性操作创建加密表。此步骤将完成配置。  

```
encrypted_table = EncryptedTable(
    table=table,
    materials_provider=kms_cmp,
    attribute_actions=actions
)
```

步骤 5：将明文项目放入表中  
在对 `encrypted_table` 调用 `put_item` 方法时，您的表项目会以透明方式加密、签名并添加到您的 DynamoDB 表。  
首先，定义表项目。  

```
plaintext_item = {
    'partition_attribute': 'value1',
    'sort_attribute': 55
    'example': 'data',
    'numbers': 99,
    'binary': Binary(b'\x00\x01\x02'),
    'test': 'test-value'
}
```
然后，请项目放入表中。  

```
encrypted_table.put_item(Item=plaintext_item)
```

要从采用加密形式的 DynamoDB 表中获取该项目，请对 `table` 对象调用 `get_item` 方法。要获取已解密的项目，请对 `get_item` 对象调用 `encrypted_table` 方法。

## 使用项目加密程序
<a name="python-example-item-encryptor"></a>

此示例向您展示在加密表项目时如何直接与 DynamoDB 加密客户端中的[项目加密程序](DDBEC-legacy-concepts.md#item-encryptor)交互，而不是使用与项目加密程序交互的[客户端帮助程序类](python-using.md#python-helpers)。

使用此方法时，将手动创建 DynamoDB 加密上下文和配置对象（`CryptoConfig`）。此外，您还会在加密一个调用中的项目并将它们放置在您在单独调用中的 DynamoDB 表中。这允许您自定义 `put_item` 调用并使用 DynamoDB 加密客户端来加密并签名绝不发送 DynamoDB 的结构化数据。

此示例使用 [Direct KMS 提供程序](direct-kms-provider.md)，但您可以使用任何兼容的 CMP。

**请参阅完整的代码示例**：[aws\$1kms\$1encrypted\$1item.py](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_item.py)

步骤 1：创建表  
首先使用表名称创建标准 DynamoDB 表资源的实例。  

```
table_name='test-table'
table = boto3.resource('dynamodb').Table(table_name)
```

步骤 2：创建加密材料提供程序  
创建您选择的[加密材料提供程序](crypto-materials-providers.md) (CMP) 的实例。  
此示例使用 [Direct KMS 提供程序](direct-kms-provider.md)，但您可以使用任何兼容的 CMP。要创建 Direct KMS 提供程序，请指定 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)。此示例使用的 Amazon 资源名称 (ARN) AWS KMS key，但您可以使用任何有效的密钥标识符。  

```
kms_key_id='arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=kms_key_id)
```

第 3 步：使用 TableInfo 辅助类  
要从 DynamoDB 获取有关表的信息，请创建帮助类的实例。[TableInfo](python-using.md#python-helpers)当您直接使用项目加密程序时，需要创建一个 `TableInfo` 实例并调用其方法：[客户端帮助程序类](python-using.md#python-helpers)可为您执行此操作。  
的`refresh_indexed_attributes`方法`TableInfo`使用 [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)DynamoDB 操作来获取有关表的实时、准确的信息。这包括其主键及其本地和全局二级索引。调用方需要具有调用 `DescribeTable` 的权限。  

```
table_info = TableInfo(name=table_name)
table_info.refresh_indexed_attributes(table.meta.client)
```

步骤 4：创建 DynamoDB 加密上下文  
[DynamoDB 加密上下文](concepts.md#encryption-context)包含有关表结构以及其如何加密和签名的信息。此示例明确创建 DynamoDB 密上下文，因为它与项目加密程序交互。[客户端帮助程序类](python-using.md#python-helpers)为您创建 DynamoDB 加密上下文。  
要获取分区键和排序键，可以使用[TableInfo](python-using.md#python-helpers)辅助类的属性。  

```
index_key = {
    'partition_attribute': 'value1',
    'sort_attribute': 55
}

encryption_context = EncryptionContext(
    table_name=table_name,
    partition_key_name=table_info.primary_index.partition,
    sort_key_name=table_info.primary_index.sort,
    attributes=dict_to_ddb(index_key)
)
```

步骤 5：创建属性操作对象  
[属性操作](DDBEC-legacy-concepts.md#legacy-attribute-actions)告知项目加密程序将对项目的每个属性执行哪些操作。此示例中的 `AttributeActions` 对象加密并签名所有项目，除已签名但未加密的主键属性和已被忽略的 `test` 属性以外。  
当您与项目加密程序直接交互且您的默认操作为 `ENCRYPT_AND_SIGN` 时，您必须为主键指定一个替代操作。您可以使用 `set_index_keys` 方法，该方法对主键使用 `SIGN_ONLY`；如果是默认操作，也可以使用 `DO_NOTHING`。  
为了指定主键，此示例使用[TableInfo](python-using.md#python-helpers)对象中的索引键，该索引键通过调用 DynamoDB 来填充。此方法要比硬编码主键名称更加安全。  

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
    attribute_actions={'test': CryptoAction.DO_NOTHING}
)
actions.set_index_keys(*table_info.protected_index_keys())
```

步骤 6：创建项目的配置  
要配置 DynamoDB 加密客户端，请使用您刚才在表项目的配置中[CryptoConfig](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/config.html)创建的对象。客户端帮助程序类 CryptoConfig 为您创建。  

```
crypto_config = CryptoConfig(
    materials_provider=kms_cmp,
    encryption_context=encryption_context,
    attribute_actions=actions
)
```

步骤 7：加密项目  
此步将加密并签名项目，但不会将项目放入 DynamoDB 表中。  
当您使用客户端帮助程序类时，您的项目会以透明方式加密并签名，然后在您调用帮助程序类的 `put_item` 方法时添加到您的 DynamoDB 表。当您直接使用项目加密程序时，encrypt 和 put 操作是相互独立的。  
首先，创建一个明文项目。  

```
plaintext_item = {
    'partition_attribute': 'value1',
    'sort_key': 55,
    'example': 'data',
    'numbers': 99,
    'binary': Binary(b'\x00\x01\x02'),
    'test': 'test-value'
}
```
然后，对该项目进行加密和签名。`encrypt_python_item` 方法需要 `CryptoConfig` 配置对象。  

```
encrypted_item = encrypt_python_item(plaintext_item, crypto_config)
```

步骤 8：将项目放入表中  
此步会将已加密且签名的项目放入 DynamoDB 表中。  

```
table.put_item(Item=encrypted_item)
```

要查看加密项目，请对原始 `get_item` 对象调用 `table` 方法，而不是对 `encrypted_table` 对象。它会从 DynamoDB 表获取该项目，无需验证和解密它。

```
encrypted_item = table.get_item(Key=partition_key)['Item']
```

下图展示了一个已加密且签名的示例表项目的一部分。

加密属性值为二进制数据。主键属性 (`partition_attribute` 和 `sort_attribute`) 和 `test` 属性的名称和值保持明文形式。输出还显示包含签名 (`*amzn-ddb-map-sig*`) 的属性和[材料描述属性](DDBEC-legacy-concepts.md#legacy-material-description) (`*amzn-ddb-map-desc*`)。

![\[已加密且签名的项目的摘要\]](http://docs.aws.amazon.com/zh_cn/database-encryption-sdk/latest/devguide/images/encrypted-item-closeup.png)
