

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

# 使用适用于 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**
+ [项目加密程序](#ddbec-item-encryptor)
+ [Java 中的属性操作](#attribute-actions-java)
+ [覆盖表名称](#override-table-name)

## 物品加密器：DynamodBenCryptor
<a name="ddbec-item-encryptor"></a>

[Java 中的 DynamoDB 加密客户端[只有一个项目](DDBEC-legacy-concepts.md#item-encryptor)加密器：较低级别的 DynamodBenCryptor](https://aws.github.io/aws-database-encryption-sdk-dynamodb/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/encryption/DynamoDBEncryptor.html) 

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

[属性操作](DDBEC-legacy-concepts.md#legacy-attribute-actions)确定加密并签名的属性值、仅签名的属性值以及忽略的属性值。

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

### DynamoDBEncryptor 的属性操作
<a name="attribute-action-default"></a>

要在您直接使用 [DynamoDBEncryptor](https://aws.github.io/aws-database-encryption-sdk-dynamodb/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/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-database-encryption-sdk-dynamodb/com/amazonaws/services/dynamodbv2/datamodeling/sdkv2/encryption/DynamoDBEncryptor.html#encryptRecord-java.util.Map-java.util.Map-com.amazonaws.services.dynamodbv2.datamodeling.sdkv2.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 加密上下文不匹配，则解密操作将失败。

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

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