

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

# AWS 适用于 DynamoDB 的数据库加密 SDK 可用编程语言
<a name="ddb-programming-languages"></a>

适用于 DynamoDB 的 AWS 数据库加密 SDK 适用于以下编程语言。特定于语言的库各不相同，但生成的实现是可互操作的。您可以使用一种语言实施进行加密，并使用另一种语言实施进行解密。互操作性可能受到语言约束的限制。如果是这样，这些约束将在有关语言实施的主题中进行描述。

**Topics**
+ [Java](ddb-java.md)
+ [.NET](ddb-net.md)
+ [Rust](ddb-rust.md)

# Java
<a name="ddb-java"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

本主题说明如何安装并使用适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x*。有关使用适用于 DynamoDB 的 AWS 数据库加密 SDK 进行编程的详细信息，请参阅上的-dynamodb 存储库[中的 Java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples) 示例。 aws-database-encryption-sdk GitHub

**注意**  
以下主题重点侧重于适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x*。  
我们的客户端加密库已[重命名为 AWS 数据库加密 SDK](DDBEC-rename.md)。 AWS 数据库加密 SDK 继续支持[旧版 DynamoDB](legacy-dynamodb-encryption-client.md) 加密客户端版本。

**Topics**
+ [先决条件](#ddb-java-prerequisites)
+ [安装](#ddb-java-installation)
+ [使用 Java 客户端](ddb-java-using.md)
+ [Java 示例](ddb-java-examples.md)
+ [将版本 3.x 添加到现有表](ddb-java-config-existing-table.md)
+ [迁移到版本 3.x](ddb-java-migrate.md)

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

在安装适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x* 之前，请确保满足以下先决条件。

**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)。

**AWS SDK for Java 2.x**  
适用于 DynamoDB 的 AWS 数据库加密 SDK 需要的 Dy [namoDB 增强型客户端模块](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)。 AWS SDK for Java 2.x可以安装整个开发工具包或仅安装此模块。  
有关更新版本的信息 适用于 Java 的 AWS SDK，请参阅[从 1.x 版迁移到 2.x 版。 适用于 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html)  
可通过 Apache Maven 获得。 适用于 Java 的 AWS SDK 你可以声明整个模块的依赖关系 适用于 Java 的 AWS SDK，也可以只声明`dynamodb-enhanced`模块的依赖关系。  

**适用于 Java 的 AWS SDK 使用 Apache Maven 安装**
+ 要[导入整个 适用于 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#build-the-entire-sdk-into-your-project)以作为依赖项，请在 `pom.xml` 文件中对其进行声明。
+ 要仅为 适用于 Java 的 AWS SDK中的 Amazon DynamoDB 模块创建依赖项，请按照[指定特定模块](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#modules-dependencies)的说明进行操作。将 `groupId` 设置为 `software.amazon.awssdk`，并将 `artifactID` 设置为 `dynamodb-enhanced`。
**注意**  
如果您使用 AWS KMS 密钥环或 AWS KMS 分层密钥环，则还需要为模块创建依赖关系。 AWS KMS 将 `groupId` 设置为 `software.amazon.awssdk`，并将 `artifactID` 设置为 `kms`。

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

您可以按以下方式安装适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x*。

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

```
<dependency>
  <groupId>software.amazon.cryptography</groupId>
  <artifactId>aws-database-encryption-sdk-dynamodb</artifactId>
  <version>version-number</version>
</dependency>
```

**使用 Gradle Kotlin**  
通过将以下内容添加到 Gradle 项目的*依赖项*部分，您可以使用 [Gradle](https://gradle.org/) 在适用于 Java 的 Amazon DynamoDB Encryption Client 上声明依赖项。  

```
implementation("software.amazon.cryptography:aws-database-encryption-sdk-dynamodb:version-number")
```

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

安装 SDK 后，请先查看本指南中的示例代码和上的 aws-database-encryption-sdk-dynamodb [存储库中的 Java 示例](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples)。 GitHub

# 使用适用于 DynamoDB 的 Java 客户端加密库
<a name="ddb-java-using"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

本主题介绍了适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x* 中的的一些函数和帮助程序类。

有关使用适用于 DynamoDB 的 Java 客户端加密库进行编程的详细信息，请参阅 [J](java-examples.md) ava 示例、-dynamodb 存储库[中的 Java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples) 示例。 aws-database-encryption-sdk GitHub

**Topics**
+ [项目加密程序](#ddb-item-encryptors)
+ [属性操作](#ddb-attribute-actions)
+ [加密配置](#ddb-config-encrypt)
+ [更新项目](#ddb-update-items)
+ [解密签名集](#ddb-java-signed-sets)

## 项目加密程序
<a name="ddb-item-encryptors"></a>

DynamoDB AWS 数据库加密 SDK 的核心是一个项目加密器。您可以使用适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x*，以通过以下方式对您的 DynamoDB 表项目进行加密、签名、验证和解密。

**DynamoDB 增强版客户端**  
您可以使用 `DynamoDbEncryptionInterceptor` 配置 [DynamoDB 增强版客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)，以通过 DynamoDB `PutItem` 请求在客户端自动对项目进行加密和签名。使用 DynamoDB 增强型客户端，您可以使用[带注释的数据类](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html#ddb-en-client-gs-tableschema-anno-bean)来定义属性操作。建议尽量使用 DynamoDB 增强型客户端。  
DynamoDB 增强版客户端不支持[可搜索的加密](searchable-encryption.md)。  
 AWS 数据库加密 SDK 不支持对[嵌套属性](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-adv-features-nested.html)进行标注。

**低级 DynamoDB API**  
您可以使用 `DynamoDbEncryptionInterceptor` 配置[低级 DynamoDB API](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html)，以通过 DynamoDB `PutItem` 请求在客户端自动对项目进行加密和签名。  
您必须通过使用低级 DynamoDB API 来使用[可搜索加密](searchable-encryption.md)。

**较低级别的 `DynamoDbItemEncryptor`**  
较低级别的 `DynamoDbItemEncryptor` 无需调用 DynamoDB 即可直接对您的表项目进行加密、签名或解密和验证。它不会发出 DynamoDB `PutItem` 或 `GetItem` 请求。举例来说，您可以使用较低级别的 `DynamoDbItemEncryptor` 直接解密和验证已经检索到的 DynamoDB 项目。  
较低级别的 `DynamoDbItemEncryptor` 不支持[可搜索加密](searchable-encryption.md)。

## 适用于 DynamoDB 的 AWS 数据库加密 SDK 中的属性操作
<a name="ddb-attribute-actions"></a>

[属性操作](concepts.md#crypt-actions)决定哪些属性值经过加密和签名，哪些仅经过签名，哪些经过签名并包含在加密上下文中，哪些会被忽略。

**注意**  
要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`加密操作，必须使用 AWS 数据库加密 SDK 的 3.3 或更高版本。在[更新要包含的数据模型之前，先将](ddb-update-data-model.md)新版本部署给所有读者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

如果您使用低级 DynamoDB API 或较低级别的 `DynamoDbItemEncryptor`，则必须手动定义属性操作。如果您使用 DynamoDB 增强型客户端，则可以手动定义属性操作，也可以使用带注释的数据类来[生成一个 `TableSchema`](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html)。为了简化配置过程，建议使用带注释的数据类。使用带注释的数据类时，您只需要对对象建模一次。

**注意**  
定义属性操作后，必须定义将哪些属性排除在签名之外。为了将来更方便添加新的未签名属性，建议您选择一个不同的前缀（例如“`:`”）来标识您的未签名属性。在定义 DynamoDB 架构和属性操作时，将此前缀包含在标记为 `DO_NOTHING` 的所有属性的属性名称中。

### 使用带注释的数据类
<a name="ddb-attribute-actions-annotated-data-class"></a>

使用[带注释的数据类](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html#ddb-en-client-gs-tableschema-anno-bean)通过 DynamoDB 增强版客户端和 `DynamoDbEncryptionInterceptor` 指定您的属性操作。适用于 DynamoDB 的 AWS 数据库加密 SDK 使用[标准的 DynamoDB 属性注释](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html)，该注释可定义属性类型以确定如何保护属性。默认情况下，除主键以外的所有属性均加密并签名，主键已签名但未加密。

**注意**  
要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`加密操作，必须使用 AWS 数据库加密 SDK 的 3.3 或更高版本。在[更新要包含的数据模型之前，先将](ddb-update-data-model.md)新版本部署给所有读者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

有关 aws-database-encryption-sdk DynamoDB 增强型客户端注释的更多指导，请参阅上 GitHub 的-dynamodb 存储库中的 [SimpleClass.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java)。

默认情况下，主键属性已签名但未加密（`SIGN_ONLY`），而所有其他属性均经过加密和签名（`ENCRYPT_AND_SIGN`）。如果将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。要指定例外情况，请使用在适用于 DynamoDB 的 Java 客户端加密库中定义的加密注释。例如，如果您只想对某个特定属性进行签名，请使用 `@DynamoDbEncryptionSignOnly` 注释。如果要对特定属性进行签名并将其包含在加密上下文中，请使用`@DynamoDbEncryptionSignAndIncludeInEncryptionContext`。如果对特定属性既不要签名也不要加密（`DO_NOTHING`），请使用 `@DynamoDbEncryptionDoNothing` 注释。

**注意**  
 AWS 数据库加密 SDK 不支持对[嵌套属性](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-adv-features-nested.html)进行标注。

以下示例显示了用于定义`ENCRYPT_AND_SIGN``SIGN_ONLY`、和`DO_NOTHING`属性操作的注释。有关显示用于定义的注释的示例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，请参阅 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass4.java)。

```
@DynamoDbBean
public class SimpleClass {

    private String partitionKey;
    private int sortKey;
    private String attribute1;
    private String attribute2;
    private String attribute3;

    @DynamoDbPartitionKey
    @DynamoDbAttribute(value = "partition_key")
    public String getPartitionKey() {
        return this.partitionKey;
    }

    public void setPartitionKey(String partitionKey) {
        this.partitionKey = partitionKey;
    }

    @DynamoDbSortKey
    @DynamoDbAttribute(value = "sort_key")
    public int getSortKey() {
        return this.sortKey;
    }

    public void setSortKey(int sortKey) {
        this.sortKey = sortKey;
    }

    public String getAttribute1() {
        return this.attribute1;
    }

    public void setAttribute1(String attribute1) {
        this.attribute1 = attribute1;
    }

    @DynamoDbEncryptionSignOnly
    public String getAttribute2() {
        return this.attribute2;
    }

    public void setAttribute2(String attribute2) {
        this.attribute2 = attribute2;
    }

    @DynamoDbEncryptionDoNothing
    public String getAttribute3() {
        return this.attribute3;
    }

    @DynamoDbAttribute(value = ":attribute3")
    public void setAttribute3(String attribute3) {
        this.attribute3 = attribute3;
    }
    
}
```

使用带注释的数据类创建 `TableSchema`，如下面的代码段所示。

```
final TableSchema<SimpleClass> tableSchema = TableSchema.fromBean(SimpleClass.class);
```

### 手动定义您的属性操作
<a name="ddb-attribute-actions-manual"></a>

要手动指定属性操作，请创建一个 `Map` 对象，在该对象中，名称/值对表示属性名称和指定的操作。

指定 `ENCRYPT_AND_SIGN` 以对属性进行加密和签名。指定 `SIGN_ONLY` 以对属性进行签名，但不进行加密。指定`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`对属性进行签名并将其包含在加密上下文中。如果不对属性进行签名，也将无法对其进行加密。指定 `DO_NOTHING` 以忽略某个属性。

分区和排序属性必须为`SIGN_ONLY`或`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

**注意**  
要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`加密操作，必须使用 AWS 数据库加密 SDK 的 3.3 或更高版本。在[更新要包含的数据模型之前，先将](ddb-update-data-model.md)新版本部署给所有读者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>();
// The partition attribute must be signed
attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT); 
// The sort attribute must be signed
attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT); 
attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY);
attributeActionsOnEncrypt.put("attribute3", CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT);
attributeActionsOnEncrypt.put(":attribute4", CryptoAction.DO_NOTHING);
```

## 适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置
<a name="ddb-config-encrypt"></a>

使用 AWS 数据库加密 SDK 时，必须为 DynamoDB 表显式定义加密配置。加密配置中所需的值取决于您是手动定义属性操作还是使用带注释的数据类来进行定义。

以下代码段使用 DynamoDB 增强版客户端、[https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html) 以及不同前缀定义的允许的未签名属性来定义 DynamoDB 表加密配置。

```
final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
tableConfigs.put(ddbTableName,
        DynamoDbEnhancedTableEncryptionConfig.builder()
            .logicalTableName(ddbTableName)
            .keyring(kmsKeyring)
            .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
            .schemaOnEncrypt(tableSchema)
            // Optional: only required if you use beacons
            .search(SearchConfig.builder() 
                    .writeVersion(1) // MUST be 1
                    .versions(beaconVersions)
                    .build())         
            .build());
```

**逻辑表名**  
适用于您的 DynamoDB 表的逻辑表名称。  
为简化 DynamoDB 还原操作，逻辑表名称以加密方式绑定到表中存储的所有数据。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。必须始终指定相同的逻辑表名。要成功解密，逻辑表名称必须与加密时所指定的名称相匹配。如果您的 DynamoDB 表名称在[从备份中恢复 DynamoDB 表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Restore.Tutorial.html)后发生更改，则逻辑表名称可确保解密操作仍能识别该表。

**允许的未签名属性**  
在您的属性操作中标记为 `DO_NOTHING` 的属性。  
允许的未签名属性将告诉客户端哪些属性被排除在签名之外。客户端假设，所有的其他属性都包含在签名中。然后，在解密记录时，客户端会从您指定的允许的未签名属性中确定需要验证哪些属性以及需要忽略哪些属性。您将不能从允许的未签名属性中移除属性。  
您可以通过创建一个列出所有 `DO_NOTHING` 属性的数组来显式定义允许的未签名属性。您还可以在命名 `DO_NOTHING` 属性时指定不同的前缀，并使用前缀告诉客户端哪些属性未签名。强烈建议指定一个不同的前缀，因为它可以简化未来添加新的 `DO_NOTHING` 属性的过程。有关更多信息，请参阅 [更新您的数据模型](ddb-update-data-model.md)。  
如果您没有为所有 `DO_NOTHING` 属性指定前缀，可以配置一个 `allowedUnsignedAttributes` 数组，该数组将显式列出客户端在解密时遇到这些属性时应该取消签名的所有属性。您只有在绝对必要时，才应显式定义允许的未签名属性。

**搜索配置（可选）**  
`SearchConfig` 将定义[信标版本](using-beacons.md#beacon-version)。  
必须指定 `SearchConfig` 才能使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)。

**算法套件（可选）**  
`algorithmSuiteId` 定义 AWS 数据库加密 SDK 使用哪种算法套件。  
除非您明确指定替代算法套件，否则 AWS 数据库加密 SDK 将使用[默认算法套件](supported-algorithms.md#recommended-algorithms)。默认算法套件将 AES-GCM 算法与密钥派生、[数字签名](concepts.md#digital-sigs)和[密钥承诺](concepts.md#key-commitment)结合使用。尽管默认算法套件可能适用于大多数应用程序，但您可以选择备用算法套件。例如，没有数字签名的算法套件可以满足某些信任模型的需求。有关 AWS 数据库加密 SDK 支持的算法套件的信息，请参阅[AWS 数据库加密 SDK 中支持的算法套件](supported-algorithms.md)。  
要选择[没有 ECDSA 数字签名的 AES-GCM 算法套件](supported-algorithms.md#other-algorithms)，请在表加密配置中加入以下片段。  

```
.algorithmSuiteId(
    DBEAlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384)
```

## 使用 AWS 数据库加密 SDK 更新项目
<a name="ddb-update-items"></a>

UpdateItem对于已加密或签名的项目，[数据库加密 SDK 不支持 ddb:](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)。 AWS 要更新加密或签名的项目，必须使用 [ddb: PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)。如果将同一个主键指定为 `PutItem` 请求中现有的项目，则新项目将完全替代现有项目。更新项目后，您还可以使用 [CLOBBER](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.SaveBehavior.html#CLOBBER) 在保存时清除和替换所有属性。

## 解密签名集
<a name="ddb-java-signed-sets"></a>

在 AWS 数据库加密 SDK 的 3.0.0 和 3.1.0 版本中，如果您[将集合类型](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.SetTypes)属性定义为`SIGN_ONLY`，则该集的值将按照提供的顺序进行规范化。DynamoDB 不保留集合的顺序。因此，包含该集合的项目的签名验证可能会失败。如果集合值的返回顺序与提供给 AWS 数据库加密 SDK 的顺序不同，即使集合的属性包含相同的值，签名验证也会失败。

**注意**  
 AWS 数据库加密 SDK 3.1.1 及更高版本对所有集合类型属性的值进行规范化，因此读取值的顺序与写入 DynamoDB 的顺序相同。

如果签名验证失败，则解密操作将失败并返回以下错误消息。


|  | 
| --- |
| software.amazon.cryptography.dbencryptionsdk.struc StructuredEncryptionException: 没有匹配的收件人标签。 | 

如果您收到上述错误消息，并且认为要解密的项目包含使用版本 3.0.0 或 3.1.0 签名的集合，请查看-dy aws-database-encryption-sdk namodb-java 存储库的[DecryptWithPermute](https://github.com/aws/aws-database-encryption-sdk-dynamodb-java/tree/v3.1.1/DecryptWithPermute)目录，了解如何成功验证该集合 GitHub 的详细信息。

# Java 示例
<a name="ddb-java-examples"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

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

以下示例演示了如何在未填充的全新 Amazon DynamoDB 表中配置适用于 DynamoDB 的 Java 客户端加密库。如果您想配置现有的 Amazon DynamoDB 表以进行客户端加密，请参阅 [将版本 3.x 添加到现有表](ddb-java-config-existing-table.md)。

**Topics**
+ [使用 DynamoDB 增强版客户端](#ddb-java-enhanced-client-example)
+ [使用低级 DynamoDB API](#ddb-java-lowlevel-API-example)
+ [使用较低的级别 DynamoDbItemEncryptor](#ddb-java-itemencryptor)

## 使用 DynamoDB 增强版客户端
<a name="ddb-java-enhanced-client-example"></a>

以下示例展示了如何作为 DynamoDB API 调用的一部分，结合使用 DynamoDB 增强型客户端和 `DynamoDbEncryptionInterceptor` 与 [AWS KMS 密钥环](use-kms-keyring.md)对 DynamoDB 表项目进行加密。

您可以在 DynamoDB 增强版客户端中使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中 AWS KMS 一个密钥环。

**注意**  
DynamoDB 增强版客户端不支持[可搜索的加密](searchable-encryption.md)。将 `DynamoDbEncryptionInterceptor` 与低级 DynamoDB API 一起使用，以便使用可搜索加密。

**查看完整的代码示例**：[EnhancedPutGetExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/EnhancedPutGetExample.java)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：根据带注释的数据类创建表架构**  
以下示例使用带注释的数据类创建 `TableSchema`。  
此示例假设带注释的数据类和属性操作是使用 [SimpleClass.java 定义的。](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java)有关为属性操作添加注释的更多指导，请参阅 [使用带注释的数据类](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。  
 AWS 数据库加密 SDK 不支持对[嵌套属性](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-adv-features-nested.html)进行标注。

```
final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步骤 4：创建加密配置**  
以下示例定义了一个 `tableConfigs` 映射，该映射表示 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  
要使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)，您还必须在加密配置中包括 [`SearchConfig`](ddb-java-using.md#ddb-search-config)。

```
final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
tableConfigs.put(ddbTableName,
    DynamoDbEnhancedTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .schemaOnEncrypt(tableSchema)
        .build());
```

**步骤 5：创建 `DynamoDbEncryptionInterceptor`**  
以下示例使用**步骤 4** 中的 `tableConfigs` 中创建一个新的 `DynamoDbEncryptionInterceptor`。  

```
final DynamoDbEncryptionInterceptor interceptor =
    DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
        CreateDynamoDbEncryptionInterceptorInput.builder()
            .tableEncryptionConfigs(tableConfigs)
            .build()
    );
```

**第 6 步：创建新的 AWS SDK DynamoDB 客户端**  
**以下示例使用步骤 5 中的创建了一个新 AWS 的 SDK DynamoDB 客户端`interceptor`。**  

```
final DynamoDbClient ddb = DynamoDbClient.builder()
        .overrideConfiguration(
                ClientOverrideConfiguration.builder()
                       .addExecutionInterceptor(interceptor)
                       .build())
        .build();
```

**步骤 7：创建 DynamoDB 增强版客户端并创建表**  
以下示例使用**步骤 6** 中创建的 AWS SDK DynamoDB 客户端创建 DynamoDB 增强型客户端，并使用带注释的数据类创建表。  

```
final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
        .dynamoDbClient(ddb)
        .build();
final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
```

**步骤 8：对表项目进行加密和签名**  
以下示例使用 DynamoDB 增强版客户端将项目放入 DynamoDB 表中。该项目在发送到 DynamoDB 之前将在客户端进行加密和签名。  

```
final SimpleClass item = new SimpleClass();
item.setPartitionKey("EnhancedPutGetExample");
item.setSortKey(0);
item.setAttribute1("encrypt and sign me!");
item.setAttribute2("sign me!");
item.setAttribute3("ignore me!");

table.putItem(item);
```

## 使用低级 DynamoDB API
<a name="ddb-java-lowlevel-API-example"></a>

以下示例演示如何使用带有 [AWS KMS 密钥环](use-kms-keyring.md)的低级 DynamoDB API，通过您的 DynamoDB `PutItem` 请求在客户端对项目自动进行加密和签名。

您可以使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中一个 AWS KMS 密钥环。

**查看完整的代码示例**：[BasicPutGetExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/BasicPutGetExample.java)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
         .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
         .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：配置属性操作**  
以下示例定义了一个 `attributeActionsOnEncrypt` 映射，该映射表示表项目的示例[属性操作](concepts.md#crypt-actions)。  
以下示例未将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>();
// The partition attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_ONLY); 
// The sort attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_ONLY); 
attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY);
attributeActionsOnEncrypt.put(":attribute3", CryptoAction.DO_NOTHING);
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步骤 4：定义 DynamoDB 表的加密配置**  
以下示例定义了一个 `tableConfigs` 映射，该映射表示此 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  
要使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)，您还必须在加密配置中包括 [`SearchConfig`](ddb-java-using.md#ddb-search-config)。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .attributeActionsOnEncrypt(attributeActionsOnEncrypt)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .build();
tableConfigs.put(ddbTableName, config);
```

**步骤 5：创建 `DynamoDbEncryptionInterceptor`**  
以下示例使用**步骤 4** 中的 `tableConfigs` 创建 `DynamoDbEncryptionInterceptor`。  

```
DynamoDbEncryptionInterceptor interceptor = DynamoDbEncryptionInterceptor.builder()
        .config(DynamoDbTablesEncryptionConfig.builder()
                .tableEncryptionConfigs(tableConfigs)
                .build())
        .build();
```

**第 6 步：创建新的 AWS SDK DynamoDB 客户端**  
**以下示例使用步骤 5 中的创建了一个新 AWS 的 SDK DynamoDB 客户端`interceptor`。**  

```
final DynamoDbClient ddb = DynamoDbClient.builder()
        .overrideConfiguration(
                ClientOverrideConfiguration.builder()
                       .addExecutionInterceptor(interceptor)
                       .build())
        .build();
```

**步骤 7：对 DynamoDB 表项目进行加密和签名**  
以下示例定义了一个 `item` 映射，该映射表示示例表项目并将该项目放入 DynamoDB 表中。该项目在发送到 DynamoDB 之前将在客户端进行加密和签名。  

```
final HashMap<String, AttributeValue> item = new HashMap<>();
item.put("partition_key", AttributeValue.builder().s("BasicPutGetExample").build());
item.put("sort_key", AttributeValue.builder().n("0").build());
item.put("attribute1", AttributeValue.builder().s("encrypt and sign me!").build());
item.put("attribute2", AttributeValue.builder().s("sign me!").build());
item.put(":attribute3", AttributeValue.builder().s("ignore me!").build());

final PutItemRequest putRequest = PutItemRequest.builder()
        .tableName(ddbTableName)
        .item(item)
        .build();

final PutItemResponse putResponse = ddb.putItem(putRequest);
```

## 使用较低的级别 DynamoDbItemEncryptor
<a name="ddb-java-itemencryptor"></a>

以下示例说明如何使用带有 [AWS KMS 密钥环](use-kms-keyring.md)的较低级别 `DynamoDbItemEncryptor` 来直接对表项目进行加密和签名。`DynamoDbItemEncryptor` 不会将项目放入 DynamoDB 表中。

您可以在 DynamoDB 增强版客户端中使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中 AWS KMS 一个密钥环。

**注意**  
较低级别的 `DynamoDbItemEncryptor` 不支持[可搜索加密](searchable-encryption.md)。将 `DynamoDbEncryptionInterceptor` 与低级 DynamoDB API 一起使用，以便使用可搜索加密。

**查看完整的代码示例**：[ItemEncryptDecryptExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/itemencryptor/ItemEncryptDecryptExample.java)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
         .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
         .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：配置属性操作**  
以下示例定义了一个 `attributeActionsOnEncrypt` 映射，该映射表示表项目的示例[属性操作](concepts.md#crypt-actions)。  
以下示例未将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>();
// The partition attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_ONLY); 
// The sort attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_ONLY); 
attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY);
attributeActionsOnEncrypt.put(":attribute3", CryptoAction.DO_NOTHING);
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步骤 4：定义 `DynamoDbItemEncryptor` 配置**  
以下示例定义 `DynamoDbItemEncryptor` 的配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  

```
final DynamoDbItemEncryptorConfig config = DynamoDbItemEncryptorConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .attributeActionsOnEncrypt(attributeActionsOnEncrypt)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .build();
```

**步骤 5：创建 `DynamoDbItemEncryptor`**  
以下示例使用**步骤 4** 中的 `config` 创建新的 `DynamoDbItemEncryptor`。  

```
final DynamoDbItemEncryptor itemEncryptor = DynamoDbItemEncryptor.builder()
        .DynamoDbItemEncryptorConfig(config)
        .build();
```

**步骤 6：直接对表项目进行加密和签名**  
以下示例使用 `DynamoDbItemEncryptor` 直接对项目进行加密和签名。`DynamoDbItemEncryptor` 不会将项目放入 DynamoDB 表中。  

```
final Map<String, AttributeValue> originalItem = new HashMap<>();
originalItem.put("partition_key", AttributeValue.builder().s("ItemEncryptDecryptExample").build());
originalItem.put("sort_key", AttributeValue.builder().n("0").build());
originalItem.put("attribute1", AttributeValue.builder().s("encrypt and sign me!").build());
originalItem.put("attribute2", AttributeValue.builder().s("sign me!").build());
originalItem.put(":attribute3", AttributeValue.builder().s("ignore me!").build());

final Map<String, AttributeValue> encryptedItem = itemEncryptor.EncryptItem(
        EncryptItemInput.builder()
                .plaintextItem(originalItem)
                .build()
).encryptedItem();
```

# 将现有 DynamoDB 表配置为使用适用于 DynamoDB AWS 的数据库加密 SDK
<a name="ddb-java-config-existing-table"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

使用适用于 DynamoDB 的 Java 客户端加密库的 3.*x* 版本，您可以配置现有的 Amazon DynamoDB 表以进行客户端加密。本主题提供有关添加版本 3.*x* 到已填充的现有 DynamoDB 表要采取的三个步骤的指导。

**先决条件**  
适用于 DynamoDB 的 Java 客户端加密库中的版本 3.*x* 需要 AWS SDK for Java 2.x 中提供的 [DynamoDB 增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)。如果您仍在使用 [Dynamo DBMapper](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html)，则必须迁移 AWS SDK for Java 2.x 到才能使用 DynamoDB 增强型客户端。

 按照[从 适用于 Java 的 AWS SDK的版本 1.x 迁移到 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html) 的说明进行操作。

然后，按照说明[开始使用 DynamoDB 增强型客户端 API](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started.html)。

在将表配置为使用适用于 DynamoDB 的 Java 客户端加密库之前，您需要[使用带注释的数据类](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html#ddb-en-client-gs-tableschema-anno-bean)生成 `TableSchema`，并且需要[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

## 步骤 1：准备读取和写入加密项目
<a name="ddb-java-add-step1"></a>

完成以下步骤，为 AWS 数据库加密 SDK 客户端做好读取和写入加密项目的准备。部署以下更改后，您的客户端将继续读取和写入明文项目。它不会对写入表中的任何新项目进行加密或签名，但却能够在加密项目显示后立即对其进行解密。这些更改使得客户端为开始[加密新项目](#ddb-java-add-step2)做好准备。在继续执行下一步操作之前，必须将以下更改部署到每一个读取器。

**1. 定义您的[属性操作](concepts.md#crypt-actions)**  
更新带注释的数据类以包含属性操作，这些操作定义哪些属性值将被加密和签名，哪些将仅被签名，哪些将被忽略。  
有关 DynamoDB 增强型客户端注释的更多指导，请参阅上 GitHub的 aws-database-encryption-sdk-dynamodb 存储库中的 [SimpleClass.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java)。  
默认情况下，主键属性已签名但未加密（`SIGN_ONLY`），而所有其他属性均经过加密和签名（`ENCRYPT_AND_SIGN`）。要指定例外情况，请使用在适用于 DynamoDB 的 Java 客户端加密库中定义的加密注释。例如，如果您只想对某个特定属性进行签名，请使用 `@DynamoDbEncryptionSignOnly` 注释。如果要对特定属性进行签名并将其包含在加密上下文中，请使用`@DynamoDbEncryptionSignAndIncludeInEncryptionContext`注释。如果对特定属性既不要签名也不要加密（`DO_NOTHING`），请使用 `@DynamoDbEncryptionDoNothing` 注释。  
如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。有关显示用于定义的注释的示例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，请参阅 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass4.java)。
有关注释的示例，请参阅 [使用带注释的数据类](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。

**2. 定义从签名中将可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端将假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**3. 创建[密钥环](keyrings.md)**  
以下示例创建一个 [AWS KMS 密钥环](use-kms-keyring.md)。 AWS KMS 密钥环使用对称加密或非对称 RSA AWS KMS keys 来生成、加密和解密数据密钥。  
该示例使用 `CreateMrkMultiKeyring` 创建带有对称加密 KMS 密钥的 AWS KMS 密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**4. 定义 DynamoDB 表的加密配置 **  
以下示例定义了一个 `tableConfigs` 映射，该映射表示此 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-java-using.md#logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  
必须指定 `FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT` 作为明文替代。此策略继续读取和写入明文项目，读取加密项目，并使客户端做好准备以写入加密项目。  

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .plaintextOverride(PlaintextOverride.FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

**5. 创建 `DynamoDbEncryptionInterceptor`**  
以下示例使用**步骤 3** 中的 `tableConfigs` 创建 `DynamoDbEncryptionInterceptor`。  

```
DynamoDbEncryptionInterceptor interceptor = DynamoDbEncryptionInterceptor.builder()
        .config(DynamoDbTablesEncryptionConfig.builder()
                .tableEncryptionConfigs(tableConfigs)                
                .build())
        .build();
```

## 步骤 2：写入已加密和签名项目
<a name="ddb-java-add-step2"></a>

更新 `DynamoDbEncryptionInterceptor` 配置中的明文策略，以允许客户端写入已加密和签名的项目。部署好以下更改后，客户端将根据您在**步骤 1** 中配置的属性操作对新项目进行加密和签名。客户将能够读取明文项目以及已加密和签名的项目。

在继续执行[步骤 3](#ddb-java-add-step3) 之前，您必须对表格中所有现有的明文项目进行加密和签名。您无法运行单一指标或查询来快速加密您的现有明文项目。使用对您的系统最有意义的过程。例如，您可以使用异步过程，以缓慢扫描表，然后使用您定义的属性操作和加密配置重写项目。要识别表中的纯文本项目，我们建议您扫描所有不包含 AWS 数据库加密 SDK 在项目加密`aws_dbe_head`和签名时添加的和`aws_dbe_foot`属性的项目。

以下示例更新了**步骤 1** 中的表加密配置。您必须使用 `FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT` 更新明文替代。该策略继续读取明文项目，但也会读取和写入加密项目。`DynamoDbEncryptionInterceptor`使用更新的内容创建一个新的`tableConfigs`。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .plaintextOverride(PlaintextOverride.FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

## 步骤 3：仅读取已加密和签名项目
<a name="ddb-java-add-step3"></a>

在对所有项目进行加密和签名后，请更新 `DynamoDbEncryptionInterceptor` 配置中的明文替代，以便仅允许客户端读取和写入已加密和签名的项目。部署好以下更改后，客户端将根据您在**步骤 1** 中配置的属性操作对新项目进行加密和签名。客户只能够读取已加密和签名的项目。

以下示例更新了**步骤 2** 中的表加密配置。您可以使用 `FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT` 更新明文替代，也可以从配置中移除明文策略。默认情况下，客户端仅读取和写入已加密和签名的项目。`DynamoDbEncryptionInterceptor`使用更新的内容创建一个新的`tableConfigs`。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        // Optional: you can also remove the plaintext policy from your configuration
        .plaintextOverride(PlaintextOverride.FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

# 迁移到适用于 DynamoDB 的 Java 客户端加密库的版本 3.x
<a name="ddb-java-migrate"></a>


****  

|  | 
| --- |
| 我们的客户端加密库已重命名为 AWS 数据库加密 SDK。本开发人员指南仍提供有关 [DynamoDB 加密客户端](legacy-dynamodb-encryption-client.md)的信息。 | 

适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x* 是对 2.*x* 代码库的重大改写。它包括许多更新，例如新的结构化数据格式、改进的多租户支持、无缝架构更改，以及可搜索的加密支持。本主题提供有关如何将代码迁移到版本 3.*x* 的指导。

## 从版本 1.x 迁移到 2.x
<a name="ddb-java-v1-to-v2"></a>

在迁移到版本 3.*x* 之前先迁移到版本 2.*x*。版本 2.*x* 已将最新提供程序的符号从 `MostRecentProvider` 更改为 `CachingMostRecentProvider`。如果您当前使用的是带有 `MostRecentProvider` 符号的适用于 DynamoDB 的 Java 客户端加密库的版本 1.*x*，必须将代码中的符号名称更新为 `CachingMostRecentProvider`。要了解更多信息，请参阅[最新提供程序的更新](most-recent-provider.md#mrp-versions)。

## 从版本 2.x 迁移到 3.x
<a name="ddb-java-v2-to-v3"></a>

以下步骤说明如何将您的代码从适用于 DynamoDB 的 Java 客户端加密库的版本 2.*x* 迁移到版本 3.*x*。

### 步骤 1：准备读取新格式的项目
<a name="ddb-java-migrate-step1"></a>

完成以下步骤，准备您的 AWS 数据库加密 SDK 客户端，以读取新格式的项目。部署以下更改后，您的客户端将继续以与版本 2.*x* 相同的行为方式运行。您的客户将继续读取和写入 2.*x* 格式中的项目，但是这些更改使客户端做好[读取新格式项目](#ddb-java-migrate-step2)的准备。

**将你的版本更新 适用于 Java 的 AWS SDK 到 2.x 版**  
适用于 DynamoDB 的 Java 客户端加密库的版本 3.*x* 需要 [DynamoDB 增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)。DynamoDB 增强版客户端取代了之前版本[中使用的 DBMapper](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html) Dynamo。要使用增强型客户端，您必须使用 AWS SDK for Java 2.x。  
按照[从 适用于 Java 的 AWS SDK的版本 1.x 迁移到 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html) 的说明进行操作。  
有关需要哪些 AWS SDK for Java 2.x 模块的更多信息，请参阅[先决条件](ddb-java.md#ddb-java-prerequisites)。

**配置您的客户端，以读取由旧版本加密的项目**  
以下过程概述了以下代码示例中所演示的步骤。  

1. 创建一个[密钥环](keyrings.md)。

   密钥环和[加密材料管理程序](concepts.md#crypt-materials-manager)将取代以前版本的适用于 DynamoDB 的 Java 客户端加密库中使用的加密材料提供程序。
**重要**  
您在创建密钥环时指定的包装密钥必须与版本 2.*x* 中用于加密材料提供程序的包装密钥相同。

1. 创建一个带注释的类的表架构。

   此步骤用于定义开始以新格式编写项目时将使用的属性操作。

   有关使用全新 DynamoDB 增强版客户端的指南，请参阅《适用于 Java 的 AWS SDK 开发人员指南》**中的[生成一个 `TableSchema`](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html)。

   以下示例假设您已使用新的属性操作注释从版本 2.*x* 中更新您的带注释类。有关为属性操作添加注释的更多指导，请参阅 [使用带注释的数据类](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。
**注意**  
如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。有关显示用于定义的注释的示例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，请参阅 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass4.java)。

1. 定义[从签名中可以排除哪些属性](ddb-java-using.md#allowed-unauth)。

1. 配置在 2.x 版本建模类中配置的属性操作的显式映射。

   此步骤定义用于以旧格式编写项目的属性操作。

1. 配置 `DynamoDBEncryptor` 您在适用于 DynamoDB 的 Java 客户端加密库的版本 2.*x* 中使用的 。

1. 配置遗留行为。

1. 创建 `DynamoDbEncryptionInterceptor`。

1. 创建一个新的 AWS SDK DynamoDB 客户端。

1. 创建 `DynamoDBEnhancedClient` 并使用您的建模类创建表。

   要了解 DynamoDB 增强版客户端的更多信息，请参阅[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep1 {

    public static void MigrationStep1(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Create a Keyring.
        //    This example creates an AWS KMS Keyring that specifies the 
        //    same kmsKeyId previously used in the version 2.x configuration.
        //    It uses the 'CreateMrkMultiKeyring' method to create the 
        //    keyring, so that the keyring can correctly handle both single
        //    region and Multi-Region KMS Keys.
        //    Note that this example uses the AWS SDK for Java v2 KMS client.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        // 2. Create a Table Schema over your annotated class.
        //    For guidance on using the new attribute actions 
        //    annotations, see SimpleClass.java in the 
        //    aws-database-encryption-sdk-dynamodb GitHub repository. 
        //    All primary key attributes must be signed but not encrypted 
        //    and by default all non-primary key attributes 
        //    are encrypted and signed (ENCRYPT_AND_SIGN).
        //    If you want a particular non-primary key attribute to be signed but
        //    not encrypted, use the 'DynamoDbEncryptionSignOnly' annotation.
        //    If you want a particular attribute to be neither signed nor encrypted
        //    (DO_NOTHING), use the 'DynamoDbEncryptionDoNothing' annotation.
        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        // 3. Define which attributes the client should expect to be excluded 
        //    from the signature when reading items.
        //    This value represents all unsigned attributes across the entire 
        //    dataset.
        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");

        // 4. Configure an explicit map of the attribute actions configured 
        //    in your version 2.x modeled class.
        final Map<String, CryptoAction> legacyActions = new HashMap<>();
        legacyActions.put("partition_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("sort_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
        legacyActions.put("attribute2", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute3", CryptoAction.DO_NOTHING);

        // 5. Configure the DynamoDBEncryptor that you used in version 2.x.
        final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient();
        final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId);
        final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp);

        // 6. Configure the legacy behavior.
        //    Input the DynamoDBEncryptor and attribute actions created in 
        //    the previous steps. For Legacy Policy, use 
        //    'FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy continues to read 
        //    and write items using the old format, but will be able to read
        //    items written in the new format as soon as they appear.
        final LegacyOverride legacyOverride = LegacyOverride
                .builder()
                .encryptor(oldEncryptor)
                .policy(LegacyPolicy.FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT)
                .attributeActionsOnEncrypt(legacyActions)
                .build();

        // 7. Create a DynamoDbEncryptionInterceptor with the above configuration.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .legacyOverride(legacyOverride)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 8. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 7.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 9. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb client 
        //    created in Step 8, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

### 步骤 2：用新格式编写项目
<a name="ddb-java-migrate-step2"></a>

将步骤 1 中的更改部署到所有读取器后，请完成以下步骤，将 AWS 数据库加密 SDK 客户端配置为以新格式写入项目。部署以下更改后，您的客户端将继续读取旧格式的项目，并且开始以新格式编写和读取项目。

以下过程概述了以下代码示例中所演示的步骤。

1. 继续配置密钥环、表架构、旧属性操作 `allowedUnsignedAttributes` 和 `DynamoDBEncryptor`，就像在[**步骤 1**](#ddb-java-migrate-step1) 中执行的操作一样。

1. 将遗留行为更新为仅使用新格式编写新项目。

1. 创建 `DynamoDbEncryptionInterceptor `

1. 创建一个新的 AWS SDK DynamoDB 客户端。

1. 创建 `DynamoDBEnhancedClient` 并使用您的建模类创建表。

   要了解 DynamoDB 增强版客户端的更多信息，请参阅[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep2 {

    public static void MigrationStep2(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Continue to configure your keyring, table schema, legacy 
        //    attribute actions, allowedUnsignedAttributes, and 
        //    DynamoDBEncryptor as you did in Step 1.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");

        final Map<String, CryptoAction> legacyActions = new HashMap<>();
        legacyActions.put("partition_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("sort_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
        legacyActions.put("attribute2", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute3", CryptoAction.DO_NOTHING);

        final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient();
        final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId);
        final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp);

        // 2. Update your legacy behavior to only write new items using the new
        //    format. 
        //    For Legacy Policy, use 'FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy
        //    continues to read items in both formats, but will only write items
        //    using the new format.
        final LegacyOverride legacyOverride = LegacyOverride
                .builder()
                .encryptor(oldEncryptor)
                .policy(LegacyPolicy.FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT)
                .attributeActionsOnEncrypt(legacyActions)
                .build();

        // 3. Create a DynamoDbEncryptionInterceptor with the above configuration.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .legacyOverride(legacyOverride)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 4. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 3.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 5. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb Client created
        //    in Step 4, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

部署步骤 2 的更改后，必须使用新格式重新加密表中的所有旧项目，然后才能继续执行[步骤 3](#ddb-java-migrate-step3)。您无法运行单一指标或查询来快速加密您的现有项目。使用对您的系统最有意义的过程。例如，您可以使用异步过程，以缓慢扫描表，然后使用您定义的新属性操作和加密配置重写项目。

### 步骤 3：只能以新格式读取和编写项目
<a name="ddb-java-migrate-step3"></a>

使用新格式重新加密表格中的所有项目后，您可以从配置中移除遗留行为。完成以下步骤以将客户端配置为仅以新格式读取和编写项目。

以下过程概述了以下代码示例中所演示的步骤。

1. 继续配置密钥环、表架构和 `allowedUnsignedAttributes`，就像在[**步骤 1**](#ddb-java-migrate-step1) 中执行的操作一样。从您的配置中移除旧属性操作和 `DynamoDBEncryptor`。

1. 创建 `DynamoDbEncryptionInterceptor`。

1. 创建一个新的 AWS SDK DynamoDB 客户端。

1. 创建 `DynamoDBEnhancedClient` 并使用您的建模类创建表。

   要了解 DynamoDB 增强版客户端的更多信息，请参阅[创建增强型客户端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep3 {

    public static void MigrationStep3(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Continue to configure your keyring, table schema,
        //    and allowedUnsignedAttributes as you did in Step 1.
        //    Do not include the configurations for the DynamoDBEncryptor or 
        //    the legacy attribute actions.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");


        // 3. Create a DynamoDbEncryptionInterceptor with the above configuration.
        //    Do not configure any legacy behavior.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 4. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 3.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 5. Create the DynamoDbEnhancedClient using the AWS SDK Client 
        //    created in Step 4, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

# .NET
<a name="ddb-net"></a>

本主题介绍如何安装和使用版本 3。 DynamoDB 的.NET 客户端加密库中的 *x*。有关使用适用于 DynamoDB 的 AWS 数据库加密 SDK 进行编程的详细信息，请参阅上-dynamodb 存储库[中的 aws-database-encryption-sdk .NET](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/) 示例。 GitHub

DynamoDB 的.NET 客户端加密库适用于使用 C\$1 和其他.NET 编程语言编写应用程序的开发人员。它在 Windows、macOS 和 Linux 上受支持。

适用于 DynamoDB 的 AWS 数据库加密 SDK 的所有[编程语言](ddb-programming-languages.md)实现均可互操作。但是，列表或地图数据类型 适用于 .NET 的 SDK 不支持空值。这意味着，如果您使用适用于 DynamoDB 的 Java 客户端加密库来编写包含列表或地图数据类型的空值的项目，则无法使用适用于 DynamoDB 的.NET 客户端加密库来解密和读取该项目。

**Topics**
+ [安装](#ddb-net-install)
+ [调试](#ddb-net-debugging)
+ [使用.NET 客户端](ddb-net-using.md)
+ [.NET 示](ddb-net-examples.md)
+ [将版本 3.x 添加到现有表](ddb-net-config-existing-table.md)

## 为 DynamoDB 安装.NET 客户端加密库
<a name="ddb-net-install"></a>

[DynamoDB 的.NET 客户端加密库以 AWS.cryptography 的形式提供。 DbEncryptionSDK。 DynamoDb](https://www.nuget.org/packages/AWS.Cryptography.DbEncryptionSDK.DynamoDb/)打包进去 NuGet。有关安装和构建库的详细信息，请参阅-dynamodb 存储库中的 [.NET README.md](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/DynamoDbEncryption/runtimes/net/README.md) 文件。 aws-database-encryption-sdk即使您没有 AWS Key Management Service 使用 () 密钥，DynamoDB 适用于 .NET 的 SDK 的.NET 客户端加密库也需要。AWS KMS随 适用于 .NET 的 SDK NuGet 软件包一起安装。

版本 3。 DynamoDB 的.NET 客户端加密库中的 *x* 支持.NET 6.0 和.NET Framework net48 及更高版本。

## 使用.NET 调试
<a name="ddb-net-debugging"></a>

DynamoDB 的.NET 客户端加密库不会生成任何日志。DynamoDB 的.NET 客户端加密库中的异常会生成异常消息，但不会生成堆栈跟踪。

为了帮助您进行调试，请务必在 适用于 .NET 的 SDK中启用日志记录功能。中的日志和错误消息 适用于 .NET 的 SDK 可以帮助您区分在 DynamoDB 的.NET 客户端加密库中出现的 适用于 .NET 的 SDK 错误和 DynamoDB 的.NET 客户端加密库中出现的错误。有关 适用于 .NET 的 SDK 日志记录的帮助，请参阅[AWSLogging](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-config-other.html#config-setting-awslogging)《*适用于 .NET 的 AWS SDK 开发人员指南》*。（要查看该主题，请展开 **Open to view .NET Framework content** 部分。）

# 使用适用于 DynamoDB 的.NET 客户端加密库
<a name="ddb-net-using"></a>

本主题解释了版本 3 中的一些函数和辅助类。 DynamoDB 的.NET 客户端加密库中的 *x*。

有关使用适用于 DynamoDB 的.NET 客户端加密库进行编程的详细信息，请参阅上的-dynamodb 存储库中的 [ aws-database-encryption-sdk.NET](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/) 示例。 GitHub

**Topics**
+ [项目加密程序](#ddb-net-item-encryptors)
+ [属性操作](#ddb-net-attribute-actions)
+ [加密配置](#ddb-net-config-encrypt)
+ [更新项目](#ddb-net-update-items)

## 项目加密程序
<a name="ddb-net-item-encryptors"></a>

DynamoDB AWS 数据库加密 SDK 的核心是一个项目加密器。你可以使用版本 3。 DynamoDB 的.NET 客户端加密库中的 *x*，用于通过以下方式对您的 DynamoDB 表项目进行加密、签名、验证和解密。

**适用于 DynamoDB 的低级 AWS 数据库加密 SDK API**  
您可以使用[表加密配置](#ddb-net-config-encrypt)来构建 DynamoDB 客户端，该客户端会自动使用您的 DynamoDB 请求在客户端对项目进行加密和签名。`PutItem`您可以直接使用此客户端，也可以构造[文档模型](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/dynamodb-intro.html#dynamodb-intro-apis-document)或[对象持久化模型](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/dynamodb-intro.html#dynamodb-intro-apis-object-persistence)。  
[您必须使用适用于 DynamoDB API 的低级 AWS 数据库加密 SDK 才能使用可搜索的加密。](searchable-encryption.md)

**较低级别的 `DynamoDbItemEncryptor`**  
较低级别的 `DynamoDbItemEncryptor` 无需调用 DynamoDB 即可直接对您的表项目进行加密、签名或解密和验证。它不会发出 DynamoDB `PutItem` 或 `GetItem` 请求。举例来说，您可以使用较低级别的 `DynamoDbItemEncryptor` 直接解密和验证已经检索到的 DynamoDB 项目。如果您使用较低级别`DynamoDbItemEncryptor`，我们建议您使用[低级编程模型，该模型](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/dynamodb-intro.html#dynamodb-intro-apis-low-level) 适用于 .NET 的 SDK 用于与 DynamoDB 通信。  
较低级别的 `DynamoDbItemEncryptor` 不支持[可搜索加密](searchable-encryption.md)。

## 适用于 DynamoDB 的 AWS 数据库加密 SDK 中的属性操作
<a name="ddb-net-attribute-actions"></a>

[属性操作](concepts.md#crypt-actions)决定哪些属性值经过加密和签名，哪些仅经过签名，哪些经过签名并包含在加密上下文中，哪些会被忽略。

要使用.NET 客户端指定属性操作，请使用对象模型手动定义属性操作。通过创建一个`Dictionary`对象来指定您的属性操作，其中名称-值对表示属性名称和指定操作。

指定 `ENCRYPT_AND_SIGN` 以对属性进行加密和签名。指定 `SIGN_ONLY` 以对属性进行签名，但不进行加密。指定`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`对属性进行签名并将其包含在加密上下文中。如果不对属性进行签名，也将无法对其进行加密。指定 `DO_NOTHING` 以忽略某个属性。

分区和排序属性必须为`SIGN_ONLY`或`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

**注意**  
定义属性操作后，必须定义将哪些属性排除在签名之外。为了将来更方便添加新的未签名属性，建议您选择一个不同的前缀（例如“`:`”）来标识您的未签名属性。在定义 DynamoDB 架构和属性操作时，将此前缀包含在标记为 `DO_NOTHING` 的所有属性的属性名称中。

以下对象模型演示了如何使用.NET 客户端指定`ENCRYPT_AND_SIGN``SIGN_ONLY``SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`、、和`DO_NOTHING`属性操作。此示例使用前缀 “`:`” 来标识`DO_NOTHING`属性。

**注意**  
要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`加密操作，必须使用 AWS 数据库加密 SDK 的 3.3 或更高版本。在[更新要包含的数据模型之前，先将](ddb-update-data-model.md)新版本部署给所有读者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT, // The partition attribute must be signed
    ["sort_key"] = CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT, // The sort attribute must be signed
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    ["attribute3"] = CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT,
    [":attribute4"] = CryptoAction.DO_NOTHING
};
```

## 适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置
<a name="ddb-net-config-encrypt"></a>

使用 AWS 数据库加密 SDK 时，必须为 DynamoDB 表显式定义加密配置。加密配置中所需的值取决于您是手动定义属性操作还是使用带注释的数据类来进行定义。

以下代码段使用适用于 DynamoDB API 的 AWS 低级数据库加密 SDK 定义了 DynamoDB 表加密配置，并允许使用不同前缀定义的未签名属性。

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    // Optional: SearchConfig only required if you use beacons
    Search = new SearchConfig
    {
        WriteVersion = 1, // MUST be 1
        Versions = beaconVersions
    }    
};
tableConfigs.Add(ddbTableName, config);
```

**逻辑表名**  
适用于您的 DynamoDB 表的逻辑表名称。  
为简化 DynamoDB 还原操作，逻辑表名称以加密方式绑定到表中存储的所有数据。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。必须始终指定相同的逻辑表名。要成功解密，逻辑表名称必须与加密时所指定的名称相匹配。如果您的 DynamoDB 表名称在[从备份中恢复 DynamoDB 表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Restore.Tutorial.html)后发生更改，则逻辑表名称可确保解密操作仍能识别该表。

**允许的未签名属性**  
在您的属性操作中标记为 `DO_NOTHING` 的属性。  
允许的未签名属性将告诉客户端哪些属性被排除在签名之外。客户端假设，所有的其他属性都包含在签名中。然后，在解密记录时，客户端会从您指定的允许的未签名属性中确定需要验证哪些属性以及需要忽略哪些属性。您将不能从允许的未签名属性中移除属性。  
您可以通过创建一个列出所有 `DO_NOTHING` 属性的数组来显式定义允许的未签名属性。您还可以在命名 `DO_NOTHING` 属性时指定不同的前缀，并使用前缀告诉客户端哪些属性未签名。强烈建议指定一个不同的前缀，因为它可以简化未来添加新的 `DO_NOTHING` 属性的过程。有关更多信息，请参阅 [更新您的数据模型](ddb-update-data-model.md)。  
如果您没有为所有 `DO_NOTHING` 属性指定前缀，可以配置一个 `allowedUnsignedAttributes` 数组，该数组将显式列出客户端在解密时遇到这些属性时应该取消签名的所有属性。您只有在绝对必要时，才应显式定义允许的未签名属性。

**搜索配置（可选）**  
`SearchConfig` 将定义[信标版本](using-beacons.md#beacon-version)。  
必须指定 `SearchConfig` 才能使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)。

**算法套件（可选）**  
`algorithmSuiteId` 定义 AWS 数据库加密 SDK 使用哪种算法套件。  
除非您明确指定替代算法套件，否则 AWS 数据库加密 SDK 将使用[默认算法套件](supported-algorithms.md#recommended-algorithms)。默认算法套件将 AES-GCM 算法与密钥派生、[数字签名](concepts.md#digital-sigs)和[密钥承诺](concepts.md#key-commitment)结合使用。尽管默认算法套件可能适用于大多数应用程序，但您可以选择备用算法套件。例如，没有数字签名的算法套件可以满足某些信任模型的需求。有关 AWS 数据库加密 SDK 支持的算法套件的信息，请参阅[AWS 数据库加密 SDK 中支持的算法套件](supported-algorithms.md)。  
要选择[没有 ECDSA 数字签名的 AES-GCM 算法套件](supported-algorithms.md#other-algorithms)，请在表加密配置中加入以下片段。  

```
AlgorithmSuiteId = DBEAlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384
```

## 使用 AWS 数据库加密 SDK 更新项目
<a name="ddb-net-update-items"></a>

UpdateItem对于包含加密或签名属性的项目，[数据库加密 SDK 不支持 ddb:](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)。 AWS 要更新加密或已签名的属性，必须使用 [ddb: PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)。如果将同一个主键指定为 `PutItem` 请求中现有的项目，则新项目将完全替代现有项目。更新项目后，您还可以使用 [CLOBBER](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.SaveBehavior.html#CLOBBER) 在保存时清除和替换所有属性。

# .NET 示
<a name="ddb-net-examples"></a>

以下示例向您展示如何使用适用于 DynamoDB 的.NET 客户端加密库来保护应用程序中的表项目。要查找更多示例（并贡献自己的示例），请参阅上的 aws-database-encryption-sdk-dy [namodb 存储库中的.NET 示例](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/net/src)。 GitHub

以下示例演示了如何在未填充的全新 Amazon DynamoDB 表中为 DynamoDB 配置.NET 客户端加密库。如果您想配置现有的 Amazon DynamoDB 表以进行客户端加密，请参阅 [将版本 3.x 添加到现有表](ddb-net-config-existing-table.md)。

**Topics**
+ [使用适用于 DynamoDB 的低级 AWS 数据库加密 SDK API](#ddb-net-lowlevel-API-example)
+ [使用较低的级别 `DynamoDbItemEncryptor`](#ddb-net-itemencryptor)

## 使用适用于 DynamoDB 的低级 AWS 数据库加密 SDK API
<a name="ddb-net-lowlevel-API-example"></a>

[以下示例说明如何使用适用于 DynamoDB 的低级 AWS 数据库加密 SDK API 和密钥环，通过AWS KMS 您的 DynamoDB 请求在客户端自动加密和签名项目。](use-kms-keyring.md) `PutItem`

您可以使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中一个 AWS KMS 密钥环。

**查看完整的代码示例**：[BasicPutGetExample.cs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/BasicPutGetExample.cs)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：配置属性操作**  
以下示例定义了一个`attributeActionsOnEncrypt`字典，该字典表示表格项目的示例[属性操作](concepts.md#crypt-actions)。  
以下示例未将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_ONLY, // The partition attribute must be SIGN_ONLY
    ["sort_key"] = CryptoAction.SIGN_ONLY, // The sort attribute must be SIGN_ONLY
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    [":attribute3"] = CryptoAction.DO_NOTHING
};
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-net-using.md#net-allowed-unauth)。  

```
const String unsignAttrPrefix = ":";
```

**步骤 4：定义 DynamoDB 表的加密配置**  
以下示例定义了一个 `tableConfigs` 映射，该映射表示此 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-net-using.md#net-logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-net-using.md#ddb-net-config-encrypt)。  
要使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)，您还必须在加密配置中包括 [`SearchConfig`](ddb-java-using.md#ddb-search-config)。

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix
};
tableConfigs.Add(ddbTableName, config);
```

**第 5 步：创建新的 AWS SDK DynamoDB 客户端**  
**以下示例使用步骤 4 中的创建了一个新 AWS 的 SDK DynamoDB 客户端`TableEncryptionConfigs`。**  

```
var ddb = new Client.DynamoDbClient(
    new DynamoDbTablesEncryptionConfig { TableEncryptionConfigs = tableConfigs });
```

**步骤 6：对 DynamoDB 表格项目进行加密和签名**  
以下示例定义了一个代表示例表项目的`item`字典，并将该项目放入 DynamoDB 表中。该项目在发送到 DynamoDB 之前将在客户端进行加密和签名。  

```
var item = new Dictionary<String, AttributeValue>
{
    ["partition_key"] = new AttributeValue("BasicPutGetExample"),
    ["sort_key"] = new AttributeValue { N = "0" },
    ["attribute1"] = new AttributeValue("encrypt and sign me!"),
    ["attribute2"] = new AttributeValue("sign me!"),
    [":attribute3"] = new AttributeValue("ignore me!")
};

PutItemRequest putRequest = new PutItemRequest
{
    TableName = ddbTableName,
    Item = item
};

PutItemResponse putResponse = await ddb.PutItemAsync(putRequest);
```

## 使用较低的级别 `DynamoDbItemEncryptor`
<a name="ddb-net-itemencryptor"></a>

以下示例说明如何使用带有 [AWS KMS 密钥环](use-kms-keyring.md)的较低级别 `DynamoDbItemEncryptor` 来直接对表项目进行加密和签名。`DynamoDbItemEncryptor` 不会将项目放入 DynamoDB 表中。

您可以在 DynamoDB 增强版客户端中使用任何支持的[密钥环](keyrings.md)，但我们建议尽可能使用其中 AWS KMS 一个密钥环。

**注意**  
较低级别的 `DynamoDbItemEncryptor` 不支持[可搜索加密](searchable-encryption.md)。使用适用于 DynamoDB 的低级 AWS 数据库加密 SDK API 来使用可搜索的加密。

**查看完整的代码示例**：[ItemEncryptDecryptExample.cs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/itemencryptor/ItemEncryptDecryptExample.cs)

**步骤 1：创建 AWS KMS 密钥环**  
以下示例使用`CreateAwsKmsMrkMultiKeyring`对称加密 KMS AWS KMS 密钥创建密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步骤 2：配置属性操作**  
以下示例定义了一个`attributeActionsOnEncrypt`字典，该字典表示表格项目的示例[属性操作](concepts.md#crypt-actions)。  
以下示例未将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<String, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_ONLY, // The partition attribute must be SIGN_ONLY
    ["sort_key"] = CryptoAction.SIGN_ONLY, // The sort attribute must be SIGN_ONLY
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    [":attribute3"] = CryptoAction.DO_NOTHING
};
```

**步骤 3：定义从签名中可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-net-using.md#net-allowed-unauth)。  

```
String unsignAttrPrefix = ":";
```

**步骤 4：定义 `DynamoDbItemEncryptor` 配置**  
以下示例定义 `DynamoDbItemEncryptor` 的配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-net-using.md#net-logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-net-using.md#ddb-net-config-encrypt)。  

```
var config = new DynamoDbItemEncryptorConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix
};
```

**步骤 5：创建 `DynamoDbItemEncryptor`**  
以下示例使用**步骤 4** 中的 `config` 创建新的 `DynamoDbItemEncryptor`。  

```
var itemEncryptor = new DynamoDbItemEncryptor(config);
```

**步骤 6：直接对表项目进行加密和签名**  
以下示例使用 `DynamoDbItemEncryptor` 直接对项目进行加密和签名。`DynamoDbItemEncryptor` 不会将项目放入 DynamoDB 表中。  

```
var originalItem = new Dictionary<String, AttributeValue>
{
    ["partition_key"] = new AttributeValue("ItemEncryptDecryptExample"),
    ["sort_key"] = new AttributeValue { N = "0" },
    ["attribute1"] = new AttributeValue("encrypt and sign me!"),
    ["attribute2"] = new AttributeValue("sign me!"),
    [":attribute3"] = new AttributeValue("ignore me!")
};

var encryptedItem = itemEncryptor.EncryptItem(
    new EncryptItemInput { PlaintextItem = originalItem }
).EncryptedItem;
```

# 将现有 DynamoDB 表配置为使用适用于 DynamoDB AWS 的数据库加密 SDK
<a name="ddb-net-config-existing-table"></a>

使用版本 3。 *x* 在 DynamoDB 的.NET 客户端加密库中，您可以将现有的 Amazon DynamoDB 表配置为用于客户端加密。本主题提供有关添加版本 3.*x* 到已填充的现有 DynamoDB 表要采取的三个步骤的指导。

## 步骤 1：准备读取和写入加密项目
<a name="ddb-net-add-step1"></a>

完成以下步骤，为 AWS 数据库加密 SDK 客户端做好读取和写入加密项目的准备。部署以下更改后，您的客户端将继续读取和写入明文项目。它不会对写入表中的任何新项目进行加密或签名，但却能够在加密项目显示后立即对其进行解密。这些更改使得客户端为开始[加密新项目](#ddb-net-add-step2)做好准备。在继续执行下一步操作之前，必须将以下更改部署到每一个读取器。

**1. 定义您的[属性操作](concepts.md#crypt-actions)**  
创建对象模型以定义哪些属性值将进行加密和签名，哪些仅进行签名，哪些将被忽略。  
默认情况下，主键属性已签名但未加密（`SIGN_ONLY`），而所有其他属性均经过加密和签名（`ENCRYPT_AND_SIGN`）。  
指定 `ENCRYPT_AND_SIGN` 以对属性进行加密和签名。指定 `SIGN_ONLY` 以对属性进行签名，但不进行加密。指定`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`要签名并归因并将其包含在加密上下文中。如果不对属性进行签名，也将无法对其进行加密。指定 `DO_NOTHING` 以忽略某个属性。有关更多信息，请参阅 [适用于 DynamoDB 的 AWS 数据库加密 SDK 中的属性操作](ddb-net-using.md#ddb-net-attribute-actions)。  
如果您指定了任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`属性，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_ONLY, // The partition attribute must be SIGN_ONLY
    ["sort_key"] = CryptoAction.SIGN_ONLY, // The sort attribute must be SIGN_ONLY
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    [":attribute3"] = CryptoAction.DO_NOTHING
};
```

**2. 定义从签名中将可以排除哪些属性**  
以下示例假设所有 `DO_NOTHING` 属性共享不同的前缀“`:`”，并使用该前缀定义允许的未签名属性。客户端将假设任何带有“`:`”前缀的属性名称都被排除在签名之外。有关更多信息，请参阅 [Allowed unsigned attributes](ddb-net-using.md#net-allowed-unauth)。  

```
const String unsignAttrPrefix = ":";
```

**3. 创建[密钥环](keyrings.md)**  
以下示例创建一个 [AWS KMS 密钥环](use-kms-keyring.md)。 AWS KMS 密钥环使用对称加密或非对称 RSA AWS KMS keys 来生成、加密和解密数据密钥。  
该示例使用 `CreateMrkMultiKeyring` 创建带有对称加密 KMS 密钥的 AWS KMS 密钥环。`CreateAwsKmsMrkMultiKeyring` 方法可确保密钥环能够正确处理单区域密钥和多区域密钥。  

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**4. 定义 DynamoDB 表的加密配置 **  
以下示例定义了一个 `tableConfigs` 映射，该映射表示此 DynamoDB 表的加密配置。  
此示例将 DynamoDB 表名称指定为[逻辑表名称](ddb-net-using.md#net-logical-table-name)。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。  
必须指定 `FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT` 作为明文替代。此策略继续读取和写入明文项目，读取加密项目，并使客户端做好准备以写入加密项目。  
有关表加密配置中包含的值的更多信息，请参阅[适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置](ddb-java-using.md#ddb-config-encrypt)。  

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    PlaintextOverride = FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT
};
tableConfigs.Add(ddbTableName, config);
```

**5. 创建新的 AWS SDK DynamoDB 客户端**  
**以下示例使用步骤 4 中的创建了一个新 AWS 的 SDK DynamoDB 客户端`TableEncryptionConfigs`。**  

```
var ddb = new Client.DynamoDbClient(
    new DynamoDbTablesEncryptionConfig { TableEncryptionConfigs = tableConfigs });
```

## 步骤 2：写入已加密和签名项目
<a name="ddb-net-add-step2"></a>

更新表加密配置中的明文策略，以允许客户端写入加密和签名的项目。部署好以下更改后，客户端将根据您在**步骤 1** 中配置的属性操作对新项目进行加密和签名。客户将能够读取明文项目以及已加密和签名的项目。

在继续执行[步骤 3](#ddb-net-add-step3) 之前，您必须对表格中所有现有的明文项目进行加密和签名。您无法运行单一指标或查询来快速加密您的现有明文项目。使用对您的系统最有意义的过程。例如，您可以使用异步过程，以缓慢扫描表，然后使用您定义的属性操作和加密配置重写项目。要识别表中的纯文本项目，我们建议您扫描所有不包含 AWS 数据库加密 SDK 在项目加密`aws_dbe_head`和签名时添加的和`aws_dbe_foot`属性的项目。

以下示例更新了**步骤 1** 中的表加密配置。您必须使用 `FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT` 更新明文替代。该策略继续读取明文项目，但也会读取和写入加密项目。使用更新后的 AWS DynamoDB 客户端创建一个新的 SDK DynamoDB 客户端。`TableEncryptionConfigs`

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    PlaintextOverride = FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT
};
tableConfigs.Add(ddbTableName, config);
```

## 步骤 3：仅读取已加密和签名项目
<a name="ddb-net-add-step3"></a>

对所有项目进行加密和签名后，请更新表加密配置中的明文替代，使其仅允许客户端读取和写入加密和签名的项目。部署好以下更改后，客户端将根据您在**步骤 1** 中配置的属性操作对新项目进行加密和签名。客户只能够读取已加密和签名的项目。

以下示例更新了**步骤 2** 中的表加密配置。您可以使用 `FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT` 更新明文替代，也可以从配置中移除明文策略。默认情况下，客户端仅读取和写入已加密和签名的项目。使用更新后的 AWS DynamoDB 客户端创建一个新的 SDK DynamoDB 客户端。`TableEncryptionConfigs`

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    // Optional: you can also remove the plaintext policy from your configuration
    PlaintextOverride = FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT
};
tableConfigs.Add(ddbTableName, config);
```

# Rust
<a name="ddb-rust"></a>

本主题介绍如何安装和使用版本 1。 适用于 DynamoDB 的 Rust 客户端加密库中的 *x*。有关使用适用于 DynamoDB 的 AWS 数据库加密 SDK 进行编程的详细信息，请参阅上的-dynamodb 存储库[中的 aws-database-encryption-sdk Rust](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/) 示例。 GitHub

适用于 DynamoDB 的 AWS 数据库加密 SDK 的所有编程语言实现均可互操作。

**Topics**
+ [先决条件](#ddb-rust-prerequisites)
+ [安装](#ddb-rust-install)
+ [使用 Rust 客户端](ddb-rust-using.md)

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

在安装适用于 DynamoDB 的 Rust 客户端加密库之前，请确保满足以下先决条件。

**安装 Rust 和 Cargo**  
使用 [r](https://rustup.rs/) ustup 安装当前稳定版本的 [Rust](https://www.rust-lang.org/)。  
有关下载和安装 rustup 的更多信息，请参阅《货运手册》中的[安装程序](https://doc.rust-lang.org/cargo/getting-started/installation.html)。

## 安装
<a name="ddb-rust-install"></a>

适用于 DynamoDB 的 Rust 客户端加密库在 Crates.io 上以箱子形式[aws-db-esdk](https://crates.io/crates/aws-db-esdk)提供。有关安装和构建库的详细信息，请参阅-dynamodb 存储库中的 [README.md](https://github.com/aws/aws-database-encryption-sdk-dynamodb/) 文件。 aws-database-encryption-sdk GitHub 

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

**安装最新版本**  
在您的项目目录中运行以下 Cargo 命令：  

```
cargo add aws-db-esdk
```
或者在你的 Cargo.toml 中添加以下一行：  

```
aws-db-esdk = "<version>"
```

# 使用 DynamoDB 的 Rust 客户端加密库
<a name="ddb-rust-using"></a>

本主题解释了版本 1 中的一些函数和辅助类。 适用于 DynamoDB 的 Rust 客户端加密库中的 *x*。

有关使用适用于 DynamoDB 的 Rust 客户端加密库进行编程的详细信息，请参阅上的-dynamodb 存储库[中的 aws-database-encryption-sdk Rust](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/) 示例。 GitHub

**Topics**
+ [项目加密程序](#ddb-rust-item-encryptors)
+ [属性操作](#ddb-rust-attribute-actions)
+ [加密配置](#ddb-rust-config-encrypt)
+ [更新项目](#ddb-rust-update-items)

## 项目加密程序
<a name="ddb-rust-item-encryptors"></a>

DynamoDB AWS 数据库加密 SDK 的核心是一个项目加密器。你可以使用版本 1。 DynamoDB 的 Rust 客户端加密库中的 *x*，用于通过以下方式对您的 DynamoDB 表项目进行加密、签名、验证和解密。

**适用于 DynamoDB 的低级 AWS 数据库加密 SDK API**  
您可以使用[表加密配置](#ddb-rust-config-encrypt)来构建 DynamoDB 客户端，该客户端会自动使用您的 DynamoDB 请求在客户端对项目进行加密和签名。`PutItem`  
[您必须使用适用于 DynamoDB API 的低级 AWS 数据库加密 SDK 才能使用可搜索的加密。](searchable-encryption.md)  
有关演示如何使用适用于 DynamoDB API 的低级 AWS 数据库加密 SDK 的示例，[请参阅](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/basic_get_put_example.rs)上的-dynamodb 存储库中的 basic\$1get\$1put\$1example.rs。 aws-database-encryption-sdk GitHub

**较低级别的 `DynamoDbItemEncryptor`**  
较低级别的 `DynamoDbItemEncryptor` 无需调用 DynamoDB 即可直接对您的表项目进行加密、签名或解密和验证。它不会发出 DynamoDB `PutItem` 或 `GetItem` 请求。举例来说，您可以使用较低级别的 `DynamoDbItemEncryptor` 直接解密和验证已经检索到的 DynamoDB 项目。  
较低级别的 `DynamoDbItemEncryptor` 不支持[可搜索加密](searchable-encryption.md)。  
有关演示如何使用较低级别`DynamoDbItemEncryptor`的示例，请参阅上的-dynamodb [存储库中的 item\$1encrypt\$1decryp](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/itemencryptor/item_encrypt_decrypt.rs) t.rs。 aws-database-encryption-sdk GitHub

## 适用于 DynamoDB 的 AWS 数据库加密 SDK 中的属性操作
<a name="ddb-rust-attribute-actions"></a>

[属性操作](concepts.md#crypt-actions)决定哪些属性值经过加密和签名，哪些仅经过签名，哪些经过签名并包含在加密上下文中，哪些会被忽略。

要使用 Rust 客户端指定属性操作，请使用对象模型手动定义属性操作。通过创建一个`HashMap`对象来指定您的属性操作，其中名称-值对表示属性名称和指定操作。

指定 `ENCRYPT_AND_SIGN` 以对属性进行加密和签名。指定 `SIGN_ONLY` 以对属性进行签名，但不进行加密。指定`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`对属性进行签名并将其包含在加密上下文中。如果不对属性进行签名，也将无法对其进行加密。指定 `DO_NOTHING` 以忽略某个属性。

分区和排序属性必须为`SIGN_ONLY`或`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果将任何属性定义为`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，则分区和排序属性也必须是`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

**注意**  
定义属性操作后，必须定义将哪些属性排除在签名之外。为了将来更方便添加新的未签名属性，建议您选择一个不同的前缀（例如“`:`”）来标识您的未签名属性。在定义 DynamoDB 架构和属性操作时，将此前缀包含在标记为 `DO_NOTHING` 的所有属性的属性名称中。

以下对象模型演示了如何使用 Rust 客户端指定`ENCRYPT_AND_SIGN``SIGN_ONLY``SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`、、和`DO_NOTHING`属性操作。此示例使用前缀 “`:`” 来标识`DO_NOTHING`属性。

```
let attribute_actions_on_encrypt = HashMap::from([
    ("partition_key".to_string(), CryptoAction::SignOnly),
    ("sort_key".to_string(), CryptoAction::SignOnly),
    ("attribute1".to_string(), CryptoAction::EncryptAndSign),
    ("attribute2".to_string(), CryptoAction::SignOnly),
    (":attribute3".to_string(), CryptoAction::DoNothing),
]);
```

## 适用于 DynamoDB 的 AWS 数据库加密 SDK 中的加密配置
<a name="ddb-rust-config-encrypt"></a>

使用 AWS 数据库加密 SDK 时，必须为 DynamoDB 表显式定义加密配置。加密配置中所需的值取决于您是手动定义属性操作还是使用带注释的数据类来进行定义。

以下代码段使用适用于 DynamoDB API 的 AWS 低级数据库加密 SDK 定义了 DynamoDB 表加密配置，并允许使用由不同前缀定义的未签名属性。

```
let table_config = DynamoDbTableEncryptionConfig::builder()
    .logical_table_name(ddb_table_name)
    .partition_key_name("partition_key")
    .sort_key_name("sort_key")
    .attribute_actions_on_encrypt(attribute_actions_on_encrypt)
    .keyring(kms_keyring)
    .allowed_unsigned_attribute_prefix(UNSIGNED_ATTR_PREFIX)
    // Specifying an algorithm suite is optional
    .algorithm_suite_id(
        DbeAlgorithmSuiteId::AlgAes256GcmHkdfSha512CommitKeyEcdsaP384SymsigHmacSha384,
    )
    .build()?;

let table_configs = DynamoDbTablesEncryptionConfig::builder()
    .table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
    .build()?;
```

**逻辑表名**  
适用于您的 DynamoDB 表的逻辑表名称。  
为简化 DynamoDB 还原操作，逻辑表名称以加密方式绑定到表中存储的所有数据。强烈建议您在首次定义加密配置时将 DynamoDB 表名指定为逻辑表名。必须始终指定相同的逻辑表名。要成功解密，逻辑表名称必须与加密时所指定的名称相匹配。如果您的 DynamoDB 表名称在[从备份中恢复 DynamoDB 表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Restore.Tutorial.html)后发生更改，则逻辑表名称可确保解密操作仍能识别该表。

**允许的未签名属性**  
在您的属性操作中标记为 `DO_NOTHING` 的属性。  
允许的未签名属性将告诉客户端哪些属性被排除在签名之外。客户端假设，所有的其他属性都包含在签名中。然后，在解密记录时，客户端会从您指定的允许的未签名属性中确定需要验证哪些属性以及需要忽略哪些属性。您将不能从允许的未签名属性中移除属性。  
您可以通过创建一个列出所有 `DO_NOTHING` 属性的数组来显式定义允许的未签名属性。您还可以在命名 `DO_NOTHING` 属性时指定不同的前缀，并使用前缀告诉客户端哪些属性未签名。强烈建议指定一个不同的前缀，因为它可以简化未来添加新的 `DO_NOTHING` 属性的过程。有关更多信息，请参阅 [更新您的数据模型](ddb-update-data-model.md)。  
如果您没有为所有 `DO_NOTHING` 属性指定前缀，可以配置一个 `allowedUnsignedAttributes` 数组，该数组将显式列出客户端在解密时遇到这些属性时应该取消签名的所有属性。您只有在绝对必要时，才应显式定义允许的未签名属性。

**搜索配置（可选）**  
`SearchConfig` 将定义[信标版本](using-beacons.md#beacon-version)。  
必须指定 `SearchConfig` 才能使用[可搜索的加密](searchable-encryption.md)或[签名信标](configure.md#signed-beacons)。

**算法套件（可选）**  
`algorithmSuiteId` 定义 AWS 数据库加密 SDK 使用哪种算法套件。  
除非您明确指定替代算法套件，否则 AWS 数据库加密 SDK 将使用[默认算法套件](supported-algorithms.md#recommended-algorithms)。默认算法套件将 AES-GCM 算法与密钥派生、[数字签名](concepts.md#digital-sigs)和[密钥承诺](concepts.md#key-commitment)结合使用。尽管默认算法套件可能适用于大多数应用程序，但您可以选择备用算法套件。例如，没有数字签名的算法套件可以满足某些信任模型的需求。有关 AWS 数据库加密 SDK 支持的算法套件的信息，请参阅[AWS 数据库加密 SDK 中支持的算法套件](supported-algorithms.md)。  
要选择[没有 ECDSA 数字签名的 AES-GCM 算法套件](supported-algorithms.md#other-algorithms)，请在表加密配置中加入以下片段。  

```
.algorithm_suite_id(
    DbeAlgorithmSuiteId::AlgAes256GcmHkdfSha512CommitKeyEcdsaP384SymsigHmacSha384,
)
```

## 使用 AWS 数据库加密 SDK 更新项目
<a name="ddb-rust-update-items"></a>

UpdateItem对于包含加密或签名属性的项目，[数据库加密 SDK 不支持 ddb:](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)。 AWS 要更新加密或已签名的属性，必须使用 [ddb: PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)。如果将同一个主键指定为 `PutItem` 请求中现有的项目，则新项目将完全替代现有项目。