

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

# Amazon DynamoDB Encryption Client 可用的编程语言
<a name="programming-languages"></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)。

Amazon DynamoDB Encryption Client 适用于以下编程语言。特定于语言的库各不相同，但生成的实现是可互操作的。例如，您可以使用 Java 客户端加密（和签署）项目，并使用 Python 客户端解密项目。

有关更多信息，请参阅相应主题。

**Topics**
+ [Java](java.md)
+ [Python](python.md)

# 适用于 Java 的 Amazon DynamoDB Encryption Client
<a name="java"></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)。

本主题介绍了如何安装和使用适用于 Java 的 Amazon DynamoDB Encryption Client。[https://github.com/aws/aws-dynamodb-encryption-java/tree/master/examples](https://github.com/aws/aws-dynamodb-encryption-java/tree/master/examples)

**注意**  
版本 1. *x*。 适用于 Java 的 DynamoDB 加密客户端中的 *x* 已于 2022 [end-of-support 年](what-is-database-encryption-sdk.md#support) 7 月开始分阶段生效。请尽快升级到更新的版本。

**Topics**
+ [先决条件](#java-prerequisites)
+ [安装](#java-installation)
+ [使用适用于 Java 的 DynamoDB 加密客户端](java-using.md)
+ [Java 示例](java-examples.md)

## 先决条件
<a name="java-prerequisites"></a>

在安装适用于 Java 的 Amazon DynamoDB Encryption Client 之前，请确保满足以下先决条件。

**Java 开发环境**  
您需要使用 Java 8 或更高版本。在 Oracle 网站上，转到 [Java SE 下载](https://www.oracle.com/java/technologies/downloads/)，然后下载并安装 Java SE Development Kit (JDK)。  
如果使用 Oracle JDK，您还必须下载并安装 [Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files](http://www.oracle.com/java/technologies/javase-jce8-downloads.html)。

**适用于 Java 的 AWS SDK**  
即使您的应用程序未与 DynamoDB 交互，DynamoDB 加密客户端也需要的 DynamoDB 模块。 适用于 Java 的 AWS SDK 可以安装整个开发工具包或仅安装此模块。如果使用的是 Maven，则将 `aws-java-sdk-dynamodb` 添加到 `pom.xml` 文件。  
有关安装和配置的更多信息 适用于 Java 的 AWS SDK，请参阅[适用于 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/getting-started.html)。

## 安装
<a name="java-installation"></a>

您可以通过下列方式安装适用于 Java 的 Amazon DynamoDB Encryption Client。

**手动方式**  
要安装适用于 Java 的 Amazon DynamoDB 加密客户端，请克隆或下载存储库。[aws-dynamodb-encryption-java](https://github.com/aws/aws-dynamodb-encryption-java/) GitHub 

**使用 Apache Maven**  
适用于 Java 的 Amazon DynamoDB Encryption Client 通过 [Apache Maven](https://maven.apache.org/) 提供，并具有以下依赖项定义。  

```
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-dynamodb-encryption-java</artifactId>
  <version>version-number</version>
</dependency>
```

安装完软件开发工具包后，请先查看本指南中的示例代码并打开 D [ynamoDB 加密客户端 Jav](https://aws.github.io/aws-dynamodb-encryption-java/) adoc。 GitHub

# 使用适用于 Java 的 DynamoDB 加密客户端
<a name="java-using"></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)。

本主题介绍了 Java 中的 DynamoDB 加密客户端的可能在其他编程语言实施中找不到的一些功能。

[https://github.com/aws/aws-dynamodb-encryption-java/tree/master/examples](https://github.com/aws/aws-dynamodb-encryption-java/tree/master/examples)



**Topics**
+ [项目加密程序](#attribute-encryptor)
+ [配置保存行为](#save-behavior)
+ [Java 中的属性操作](#attribute-actions-java)
+ [覆盖表名称](#override-table-name)

## 物品加密器： AttributeEncryptor 和 Dynamo DBEncryptor
<a name="attribute-encryptor"></a>

[Java 中的 DynamoDB 加密客户端有[两个项目](DDBEC-legacy-concepts.md#item-encryptor)加密器：较低级别的 Dynamo 和。DBEncryptor [AttributeEncryptor](#attribute-encryptor)](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html)

`AttributeEncryptor`是一个帮助程序类，可帮助您在 [DynamoD](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html) B DBMapper 加密客户端`DynamoDB Encryptor`中 适用于 Java 的 AWS SDK 使用 Dynamo。如果您结合使用 `AttributeEncryptor` 和 `DynamoDBMapper`，则当您保存项目时，它会透明对项目进行加密并签名。当您加载项目时，它还会透明地验证和解密您的项目。

## 配置保存行为
<a name="save-behavior"></a>

您可以使用 `AttributeEncryptor` 和 `DynamoDBMapper` 来添加或替换具有仅已签名（或已加密和签名）的属性的表项目。对于这些任务，我们建议您将其配置为使用 `PUT` 保存行为，如以下示例所示。否则，您可能无法解密您的数据。

```
DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder().withSaveBehavior(SaveBehavior.PUT).build();
DynamoDBMapper mapper = new DynamoDBMapper(ddb, mapperConfig, new AttributeEncryptor(encryptor));
```

如果您使用默认保存行为（仅更新在表项目中建模的属性），则未建模的属性将不会包含在签名中，且不会由表写入更改。因此，在以后读取所有的属性时，签名将无法验证，因为它不包括未建模的属性。

您也可以使用 `CLOBBER` 保存行为。该行为与 `PUT` 保存行为相同，只不过它将禁用乐观锁并覆盖表中的项目。

为防止签名错误，如果 `AttributeEncryptor` 与未配置 `CLOBBER` 或 `PUT` 保存行为的 `DynamoDBMapper` 一起使用，则 DynamoDB 加密客户端会抛出运行时系统异常。

要查看示例中使用的此代码，请参阅[使用发电机 DBMapper](java-examples.md#java-example-dynamodb-mapper)和中`aws-dynamodb-encryption-java`存储库中的 [AwsKmsEncryptedObject GitHub.java](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedObject.java) 示例。

## Java 中的属性操作
<a name="attribute-actions-java"></a>

[属性操作](DDBEC-legacy-concepts.md#legacy-attribute-actions)确定加密并签名的属性值、仅签名的属性值以及忽略的属性值。用于指定属性操作的方法取决于您使用的是`DynamoDBMapper`和`AttributeEncryptor`还是较低级别的 [Dynam DBEncryptor](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html) o。

**重要**  
使用属性操作对表项进行加密后，在数据模型中添加或删除属性可能会导致签名验证错误，从而使您无法解密数据。有关详细说明，请参阅[更改数据模型](data-model.md)。

### Dynamo 的属性动作 DBMapper
<a name="attribute-action-java-mapper"></a>

当您使用 `DynamoDBMapper` 和 `AttributeEncryptor` 时，使用注释指定属性操作。DynamoDB 加密客户端使用[标准 DynamoDB 属性注释](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Annotations.html)，该注释可定义属性类型以确定如何保护属性。默认情况下，除主键以外的所有属性均加密并签名，主键已签名但未加密。

**注意**  
不要使用 [@Dynamo Attribut DBVersion e 注解](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptimisticLocking.html)对属性的值进行加密，尽管你可以（也应该）对它们进行签名。否则，使用其值的情况将产生意外后果。

```
// Attributes are encrypted and signed
@DynamoDBAttribute(attributeName="Description")

// Partition keys are signed but not encrypted
@DynamoDBHashKey(attributeName="Title")

// Sort keys are signed but not encrypted
@DynamoDBRangeKey(attributeName="Author")
```

要指定例外情况，请使用在适用于 Java 的 DynamoDB 加密客户端中定义的加密注释。如果您在类级别指定这些注释，它们将成为该类的默认值。

```
// Sign only
@DoNotEncrypt

// Do nothing; not encrypted or signed
@DoNotTouch
```

例如，这些注释签署但未加密 `PublicationYear` 属性，而且未加密或签署 `ISBN` 属性值。

```
// Sign only (override the default)
@DoNotEncrypt
@DynamoDBAttribute(attributeName="PublicationYear")

// Do nothing (override the default)
@DoNotTouch
@DynamoDBAttribute(attributeName="ISBN")
```

### Dynamo 的属性动作 DBEncryptor
<a name="attribute-action-default"></a>

要在DBEncryptor直接使用 [Dynamo](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html) 时指定属性操作，请创建一个`HashMap`对象，其中名称/值对表示属性名称和指定操作。

有效值适用于在 `EncryptionFlags` 枚举类型中定义的属性操作。您可以结合使用 `ENCRYPT` 和 `SIGN`，单独使用 `SIGN`，或同时忽略。但是，如果您单独使用 `ENCRYPT`，则 DynamoDB 加密客户端会抛出错误。您无法加密未签名的属性。

```
ENCRYPT
SIGN
```

**警告**  
请勿加密主键属性。它们必须保留为明文，以便 DynamoDB 查找项目而无需运行全表扫描。

如果您在加密上下文中指定一个主键，然后为主键属性的属性操作指定 `ENCRYPT`，则 DynamoDB 加密客户端会抛出异常。

例如，以下 Java 代码创建了一个`actions` HashMap 对`record`项目中的所有属性进行加密和签名。例外是分区键和排序键属性（这些属性已签名但未加密）以及 `test` 属性（该属性未签名或未加密）。

```
final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN);
final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN);
final Map<String, Set<EncryptionFlags>> actions = new HashMap<>();

for (final String attributeName : record.keySet()) {
  switch (attributeName) {
    case partitionKeyName: // no break; falls through to next case
    case sortKeyName:
      // Partition and sort keys must not be encrypted, but should be signed
      actions.put(attributeName, signOnly);
      break;
    case "test":
      // Don't encrypt or sign
      break;
    default:
      // Encrypt and sign everything else
      actions.put(attributeName, encryptAndSign);
      break;
  }
}
```

然后，当您调用 `DynamoDBEncryptor` 的 [encryptRecord](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html#encryptRecord-java.util.Map-java.util.Map-com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext-) 方法时，将映射指定为 `attributeFlags` 参数的值。例如，这个对 `encryptRecord` 的调用使用 `actions` 映射。

```
// Encrypt the plaintext record
final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
```

## 覆盖表名称
<a name="override-table-name"></a>

在 DynamoDB 加密客户端中，DynamoDB 表的名称是传递到加密和解密方法的 [DynamoDB 加密上下文](concepts.md#encryption-context)的元素。对表项目进行加密或签名时，DynamoDB 加密上下文（包括表名称）以加密方式绑定到加密文字。如果传递给解密方法的 DynamoDB 加密上下文与传递给加密方法的 DynamoDB 加密上下文不匹配，则解密操作将失败。

有时，表的名称会发生变化，例如备份表或执行[point-in-time 恢复](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html)时。解密或验证这些项目的签名时，必须传递用于对项目进行加密和签名的相同 DynamoDB 加密上下文，包括原始表名称。不需要当前表名称。

使用 `DynamoDBEncryptor` 时，您将手动汇编 DynamoDB 加密上下文。但是，如果使用 `DynamoDBMapper`，`AttributeEncryptor` 会为您创建 DynamoDB 加密上下文，包括当前表名称。要告知 `AttributeEncryptor` 使用其他表名称创建加密上下文，请使用 `EncryptionContextOverrideOperator`。

例如，以下代码创建加密材料提供程序 (CMP) 和 `DynamoDBEncryptor` 的实例。然后，它调用 `DynamoDBEncryptor` 的 `setEncryptionContextOverrideOperator` 方法。它使用 `overrideEncryptionContextTableName` 运算符，该运算符将覆盖一个表名称。通过这种方式配置它后，`AttributeEncryptor` 会创建一个 DynamoDB 加密上下文，其中包含 `newTableName` 以代替 `oldTableName`。有关完整的示例，请参阅 [EncryptionContextOverridesWithDynamoDBMapper.java。](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/EncryptionContextOverridesWithDynamoDBMapper.java)

```
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);

encryptor.setEncryptionContextOverrideOperator(EncryptionContextOperators.overrideEncryptionContextTableName(
                oldTableName, newTableName));
```

当您调用 `DynamoDBMapper` 的加载方法（该方法解密并验证项目）时，您指定原始表名称。

```
mapper.load(itemClass, DynamoDBMapperConfig.builder()
                .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement(oldTableName))
                .build());
```

您还可以使用 `overrideEncryptionContextTableNameUsingMap` 运算符，该运算符将覆盖多个表名称。

表名称覆盖运算符通常在解密数据和验证签名时使用。但是，您可以使用它们在加密和签名时将 DynamoDB 加密上下文中的表名称设置为其他值。

如果使用 `DynamoDBEncryptor`，请不要使用表名称覆盖运算符。而是使用原始表名称创建一个加密上下文，并将其提交给解密方法。

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

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

**Topics**
+ [使用发电机 DBEncryptor](#java-example-ddb-encryptor)
+ [使用发电机 DBMapper](#java-example-dynamodb-mapper)

## 使用发电机 DBEncryptor
<a name="java-example-ddb-encryptor"></a>

此示例说明如何将较低级别的 [Dynamo DBEncryptor](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html) 与 Di [rect KMS](direct-kms-provider.md) 提供程序配合使用。直接 KMS 提供商在您指定的 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)in AWS Key Management Service (AWS KMS) 下生成并保护其加密材料。

您可以将任何兼容的[加密材料提供程序](DDBEC-legacy-concepts.md#concept-material-provider) (CMP) 与一起使用`DynamoDBEncryptor`，也可以将直接 KMS 提供程序与`DynamoDBMapper`和[AttributeEncryptor](java-using.md#attribute-encryptor)一起使用。

**查看完整的代码示例**：[AwsKmsEncryptedItem.java](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedItem.java)

步骤 1：创建 Direct KMS 提供程序  
创建指定区域的 AWS KMS 客户端实例。然后，使用客户端实例借助您的首选 AWS KMS key创建 Direct KMS 提供程序的实例。  
此示例使用 Amazon 资源名称 (ARN) 来标识 AWS KMS key，但您可以使用[任何有效的密钥](https://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html#find-cmk-id-arn)标识符。  

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

步骤 2：创建项目  
此示例定义了`record` HashMap 表示示例表项的。  

```
final String partitionKeyName = "partition_attribute";
final String sortKeyName = "sort_attribute";

final Map<String, AttributeValue> record = new HashMap<>();
record.put(partitionKeyName, new AttributeValue().withS("value1"));
record.put(sortKeyName, new AttributeValue().withN("55"));
record.put("example", new AttributeValue().withS("data"));
record.put("numbers", new AttributeValue().withN("99"));
record.put("binary", new AttributeValue().withB(ByteBuffer.wrap(new byte[]{0x00, 0x01, 0x02})));
record.put("test", new AttributeValue().withS("test-value"));
```

步骤 3：创建发电机 DBEncryptor  
使用 Direct KMS 提供程序创建 `DynamoDBEncryptor` 的实例。  

```
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);
```

步骤 4：创建 DynamoDB 加密上下文  
[DynamoDB 加密上下文](concepts.md#encryption-context)包含有关表结构以及其如何加密和签名的信息。如果使用的是 `DynamoDBMapper`，则 `AttributeEncryptor` 会为您创建加密上下文。  

```
final String tableName = "testTable";

final EncryptionContext encryptionContext = new EncryptionContext.Builder()
    .withTableName(tableName)
    .withHashKeyName(partitionKeyName)
    .withRangeKeyName(sortKeyName)
    .build();
```

步骤 5：创建属性操作对象  
[属性操作](DDBEC-legacy-concepts.md#legacy-attribute-actions)确定已加密并签名的项目属性、仅签名的属性以及未加密或签名的属性。  
在 Java 中，要指定属性操作，需要创建属性名称和`EncryptionFlags`值对。 HashMap   
例如，以下 Java 代码创建了一个`actions` HashMap 对`record`项目中的所有属性进行加密和签名，但分区键和排序密钥属性（已签名但未加密）以及未签名或加密的`test`属性除外。  

```
final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN);
final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN);
final Map<String, Set<EncryptionFlags>> actions = new HashMap<>();

for (final String attributeName : record.keySet()) {
  switch (attributeName) {
    case partitionKeyName: // fall through to the next case
    case sortKeyName:
      // Partition and sort keys must not be encrypted, but should be signed
      actions.put(attributeName, signOnly);
      break;
    case "test":
      // Neither encrypted nor signed
      break;
    default:
      // Encrypt and sign all other attributes
      actions.put(attributeName, encryptAndSign);
      break;
  }
}
```

步骤 6：加密并签名项目  
要加密并签名项目，请对 `encryptRecord` 的实例调用 `DynamoDBEncryptor` 方法。指定表项目 (`record`)、属性操作 (`actions`) 和加密上下文 (`encryptionContext`)。  

```
final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
```

步骤 7：将项目放入 DynamoDB 表中  
最后，将已加密且签名的项目放入 DynamoDB 表中。  

```
final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.defaultClient();
ddb.putItem(tableName, encrypted_record);
```

## 使用发电机 DBMapper
<a name="java-example-dynamodb-mapper"></a>

以下示例为您演示如何结合使用 DynamoDB Mapper 帮助程序类与 [Direct KMS 提供程序](direct-kms-provider.md)。Direct KMS 提供程序借助您指定的 AWS Key Management Service （AWS KMS）中的 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys) 生成并保护其加密材料。

您可以结合使用任何兼容的[加密材料提供程序](DDBEC-legacy-concepts.md#concept-material-provider) (CMP) 与 `DynamoDBMapper`，也可以结合使用 Direct KMS 提供程序与低级别 `DynamoDBEncryptor`。

**查看完整的代码示例**：[AwsKmsEncryptedObject.java](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedObject.java)

步骤 1：创建 Direct KMS 提供程序  
创建指定区域的 AWS KMS 客户端实例。然后，使用客户端实例借助您的首选 AWS KMS key创建 Direct KMS 提供程序的实例。  
此示例使用 Amazon 资源名称 (ARN) 来标识 AWS KMS key，但您可以使用[任何有效的密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id)标识符。  

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

第 2 步：创建 DynamoDB 加密器和 Dynamo DBMapper  
使用您在上一步中创建的 Direct KMS 提供程序创建 [DynamoDB Encryptor](java-using.md#attribute-encryptor) 的实例。您需要实例化低级别 DynamoDB Encryptor 才能使用 DynamoDB Mapper。  
接着，创建 DynamoDB 数据库的实例和映射器配置，然后使用它们创建 DynamoDB Mapper 的实例。  
当使用 `DynamoDBMapper` 添加或编辑已签名（或已加密并签名）项目时，将其配置为[使用保存行为](java-using.md#save-behavior)（如包含所有属性的 `PUT`），如以下示例所示。否则，您可能无法解密您的数据。

```
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp)
final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard().withRegion(region).build();

DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder().withSaveBehavior(SaveBehavior.PUT).build();
DynamoDBMapper mapper = new DynamoDBMapper(ddb, mapperConfig, new AttributeEncryptor(encryptor));
```

步骤 3：定义您的 DynamoDB 表  
接下来，定义您的 DynamoDB 表。使用注释指定[属性操作](java-using.md#attribute-actions-java)。此示例将创建一个 DynamoDB 表、`ExampleTable`，以及一个表示表项目的 `DataPoJo` 类。  
在此示例表中，将为主键属性签名，但不进行加密。这适用于使用 `@DynamoDBHashKey` 进行注释的 `partition_attribute` 以及使用 `@DynamoDBRangeKey` 进行注释的 `sort_attribute`。  
将为使用 `@DynamoDBAttribute` 进行注释的属性（如 `some numbers`）加密并签名。使用 `@DoNotEncrypt`（仅签名）或 DynamoDB 加密客户端定义的 `@DoNotTouch`（不进行加密或签名）加密注释的属性则例外。例如，由于 `leave me` 属性具有 `@DoNotTouch` 注释，因此不会为其加密或签名。  

```
@DynamoDBTable(tableName = "ExampleTable")
public static final class DataPoJo {
  private String partitionAttribute;
  private int sortAttribute;
  private String example;
  private long someNumbers;
  private byte[] someBinary;
  private String leaveMe;

  @DynamoDBHashKey(attributeName = "partition_attribute")
  public String getPartitionAttribute() {
    return partitionAttribute;
  }

  public void setPartitionAttribute(String partitionAttribute) {
    this.partitionAttribute = partitionAttribute;
  }

  @DynamoDBRangeKey(attributeName = "sort_attribute")
  public int getSortAttribute() {
    return sortAttribute;
  }

  public void setSortAttribute(int sortAttribute) {
    this.sortAttribute = sortAttribute;
  }

  @DynamoDBAttribute(attributeName = "example")
  public String getExample() {
    return example;
  }

  public void setExample(String example) {
    this.example = example;
  }

  @DynamoDBAttribute(attributeName = "some numbers")
  public long getSomeNumbers() {
    return someNumbers;
  }

  public void setSomeNumbers(long someNumbers) {
    this.someNumbers = someNumbers;
  }

  @DynamoDBAttribute(attributeName = "and some binary")
  public byte[] getSomeBinary() {
    return someBinary;
  }

  public void setSomeBinary(byte[] someBinary) {
    this.someBinary = someBinary;
  }

  @DynamoDBAttribute(attributeName = "leave me")
  @DoNotTouch
  public String getLeaveMe() {
    return leaveMe;
  }

  public void setLeaveMe(String leaveMe) {
    this.leaveMe = leaveMe;
  }

  @Override
  public String toString() {
    return "DataPoJo [partitionAttribute=" + partitionAttribute + ", sortAttribute="
        + sortAttribute + ", example=" + example + ", someNumbers=" + someNumbers
        + ", someBinary=" + Arrays.toString(someBinary) + ", leaveMe=" + leaveMe + "]";
  }
}
```

步骤 4：加密并保存表项目  
现在，当您创建一个表项目并使用 DynamoDB Mapper 保存它时，会在将此项目添加到表之前自动对其进行加密和签名。  
此示例定义一个名为 `record` 的表项目。在将此表项目保存到表中之前，将基于 `DataPoJo` 类中的注释为其属性加密和签名。在此示例中，将为 `PartitionAttribute`、`SortAttribute` 和 `LeaveMe` 之外的所有属性加密和签名。仅为 `PartitionAttribute` 和 `SortAttributes` 进行签名。不会为 `LeaveMe` 属性加密或签名。  
要为 `record` 项目加密并签名，然后将其添加到 `ExampleTable`，请调用 `DynamoDBMapper` 类的 `save` 方法。由于您的 DynamoDB Mapper 配置为使用 `PUT` 保存行为，因此项目将替换具有相同主键的任何项目，而不是更新这些项目。这将确保签名匹配，并且您可以在从表中获取项目时为其解密。  

```
DataPoJo record = new DataPoJo();
record.setPartitionAttribute("is this");
record.setSortAttribute(55);
record.setExample("data");
record.setSomeNumbers(99);
record.setSomeBinary(new byte[]{0x00, 0x01, 0x02});
record.setLeaveMe("alone");

mapper.save(record);
```

# 适用于 Python 的 DynamoDB 加密客户端
<a name="python"></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 加密客户端。您可以在上的[aws-dynamodb-encryption-python](https://github.com/aws/aws-dynamodb-encryption-python/)存储库中找到代码 GitHub，包括完整且经过测试的[示例代码](https://github.com/aws/aws-dynamodb-encryption-python/tree/master/examples)，以帮助您入门。

**注意**  
版本 1. *x*。 *x* 和 2。 *x*。 适用于 Python 的 DynamoDB 加密客户端的 *x* 已于 2022 [end-of-support 年](what-is-database-encryption-sdk.md#support) 7 月开始分阶段生效。请尽快升级到更新的版本。

**Topics**
+ [先决条件](#python-prerequisites)
+ [安装](#python-installation)
+ [使用适用于 Python 的 DynamoDB 加密客户端](python-using.md)
+ [Python 示例](python-examples.md)

## 先决条件
<a name="python-prerequisites"></a>

在安装适用于 Python 的 Amazon DynamoDB Encryption Client 之前，请确保满足以下先决条件。

**支持的 Python 版本**  
对于 Python 版本 3.3.0 及更高版本，亚马逊 DynamoDB 加密客户端需要 Python 3.8 或更高版本。要下载 Python，请参阅 [Python 下载](https://www.python.org/downloads/)。  
适用于 Python 的 Amazon DynamoDB Encryption Client 的早期版本支持 Python 2.7 和 Python 3.4 及更高版本，但我们建议您使用 DynamoDB 加密客户端的最新版本。

**适用于 Python 的 pip 安装工具**  
Python 3.6 及更高版本包括 **pip**，但您可能需要对其进行升级。有关升级或安装 pip 的更多信息，请参阅 **pip** 文档中的[安装](https://pip.pypa.io/en/latest/installation/)。

## 安装
<a name="python-installation"></a>

可以使用 **pip** 安装适用于 Python 的 Amazon DynamoDB Encryption Client，如以下示例中所示。

**安装最新版本**  

```
pip install dynamodb-encryption-sdk
```

有关使用 **pip** 安装和升级程序包的详细信息，请参阅[安装程序包](https://packaging.python.org/tutorials/installing-packages/)。

DynamoDB 加密客户端要求在所有平台上使用[加密库](https://cryptography.io/en/latest/)。所有 **pip** 版本在 Windows 上安装和构建**加密**库。**pip** 8.1 和更高版本在 Linux 上安装和构建**加密**库。如果使用早期版本的 **pip** 并且 Linux 环境没有构建**加密**库所需的工具，则需要安装这些工具。有关更多信息，请参阅[在 Linux 上构建加密](https://cryptography.io/en/latest/installation/#building-cryptography-on-linux)。

您可以从存储库中获取 DynamoDB 加密客户端的最新[aws-dynamodb-encryption-python](https://github.com/aws/aws-dynamodb-encryption-python/)开发版本。 GitHub

安装 DynamoDB 加密客户端后，先从在本指南中查找示例 Python 代码。

# 使用适用于 Python 的 DynamoDB 加密客户端
<a name="python-using"></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 加密客户端。除非您有不寻常的使用案例，否则我们建议您使用这些功能。

[有关使用 DynamoDB 加密客户端进行编程的详细信息，请参阅本指南中的 [Python](python-examples.md) 示例、存储库 GitHub中的 aws-dynamodb-encryption-python示例以及 DynamoDB 加密客户端的 [Python](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/) 文档。](https://github.com/aws/aws-dynamodb-encryption-python/tree/master/examples)

**Topics**
+ [客户端帮助程序类](#python-helpers)
+ [TableInfo 班级](#table-info)
+ [Python 中的属性操作](#python-attribute-actions)

## 客户端帮助程序类
<a name="python-helpers"></a>

适用于 Python 的 DynamoDB 加密客户端包括多个对 DynamoDB 的 Boto 3 类进行镜像的客户端帮助程序类。这些帮助程序类旨在更轻松地向您的现有 DynamoDB 应用程序添加加密和签名并且避免最常见问题，如下所示：
+ 通过向对象添加主密钥的覆盖操作，或者在您的[AttributeActions](#python-attribute-actions)`AttributeActions`对象明确要求客户端加密主密钥时抛出异常，防止您对项目中的主密钥进行加密。如果您的 `AttributeActions` 对象中的默认操作为 `DO_NOTHING`，则客户端帮助程序类会对主键使用该操作。否则，它们使用 `SIGN_ONLY`。
+ 创建[TableInfo 对象](#python-helpers)并根据对 Dynamo [DB 的调用填充 DynamoDB 加密](concepts.md#encryption-context)上下文。这有助于确保您的 DynamoDB 加密上下文准确且客户端可以标识主键。
+ 支持方法（如 `put_item` 和 `get_item`），这些方法在您在 DynamoDB 表中写入或读取时会以透明方式加密和解密表项目。仅不支持 `update_item` 方法。

您可以使用客户端帮助程序类而不是直接与较低级别的[项目加密程序](DDBEC-legacy-concepts.md#item-encryptor)交互。除非您需要在项目加密程序中设置高级选项，否则使用这些类。

客户端帮助程序类包括：
+ [EncryptedTable](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/table.html#module-dynamodb_encryption_sdk.encrypted.table)适用于使用 DynamoDB 中的[表](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table)资源一次处理一张表的应用程序。
+ [EncryptedResource](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/resource.html)适用于使用 DynamoDB 中的[服务资源](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#service-resource)类进行批处理的应用程序。
+ [EncryptedClient](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/client.html)适用于在 DynamoDB 中使用[较低级别客户端](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#client)的应用程序。

要使用客户端帮助程序类，调用者必须具有在目标表上调用 Dynam [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)oDB 操作的权限。

## TableInfo 班级
<a name="table-info"></a>

该[TableInfo](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/tools/structures.html#dynamodb_encryption_sdk.structures.TableInfo)类是一个代表一个 DynamoDB 表的辅助类，其中包含用于其主键和二级索引的字段。它有助于您获取有关表的准确的实时信息。

如果您使用的是[客户端帮助程序类](#python-helpers)，它会为您创建并使用 `TableInfo` 对象。否则，您可以明确创建一个。有关示例，请参阅[使用项目加密程序](python-examples.md#python-example-item-encryptor)。

当您在`TableInfo`对象上调用该`refresh_indexed_attributes`方法时，它会通过调用 DynamoDB [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)操作来填充该对象的属性值。查询表要比硬编码索引名称更加可靠。`TableInfo` 类还包括 `encryption_context_values` 属性，该属性提供了 [DynamoDB 加密上下文](concepts.md#encryption-context)所需的值。

要使用该`refresh_indexed_attributes`方法，调用者必须具有在目标表上调用 Dynam [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)oDB 操作的权限。

## Python 中的属性操作
<a name="python-attribute-actions"></a>

[属性操作](DDBEC-legacy-concepts.md#legacy-attribute-actions)告知项目加密程序将对项目的每个属性执行哪些操作。要在 Python 中指定属性操作，请创建具有默认操作和针对特定属性的任何例外的 `AttributeActions` 对象。有效值将在 `CryptoAction` 枚举类型中定义。

**重要**  
使用属性操作对表项进行加密后，在数据模型中添加或删除属性可能会导致签名验证错误，从而使您无法解密数据。有关详细说明，请参阅[更改数据模型](data-model.md)。

```
DO_NOTHING = 0
SIGN_ONLY = 1
ENCRYPT_AND_SIGN = 2
```

例如，此 `AttributeActions` 对象建立 `ENCRYPT_AND_SIGN` 作为所有属性的默认值，并且指定 `ISBN` 和 `PublicationYear` 属性的例外。

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

如果您使用的是[客户端帮助程序类](#python-helpers)，则无需指定主键属性的属性操作。该客户端帮助程序类阻止您加密主键。

如果您未使用客户端帮助程序类且默认操作为 `ENCRYPT_AND_SIGN`，则必须为主键指定操作。对主键建议的操作为 `SIGN_ONLY`。要轻松实现此操作，请使用 `set_index_keys` 方法，该方法对主键使用 SIGN\$1ONLY，或者使用 DO\$1NOTHING，这是默认操作。

**警告**  
请勿加密主键属性。它们必须保留为明文，以便 DynamoDB 查找项目而无需运行全表扫描。

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
)
actions.set_index_keys(*table_info.protected_index_keys())
```

# 适用于 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)
