使用适用于 DynamoDB 的 Java 客户端加密库 - AWS 数据库加密 SDK

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

使用适用于 DynamoDB 的 Java 客户端加密库

我们的客户端加密库已重命名为 AWS 数据库加密SDK。本开发人员指南仍提供有关 DynamoDB 加密客户端的信息。

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

有关使用适用于 DynamoDB 的 Java 客户端加密库进行编程的详细信息,请参阅 J ava 示例、-dynamodb 存储库中的 Java 示例。 aws-database-encryption-sdk GitHub

项目加密程序

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

DynamoDB 增强版客户端

您可以使用 DynamoDbEncryptionInterceptor 配置 DynamoDB 增强版客户端,以通过 DynamoDB PutItem 请求在客户端自动对项目进行加密和签名。使用 DynamoDB 增强型客户端,您可以使用带注释的数据类来定义属性操作。建议尽量使用 DynamoDB 增强型客户端。

DynamoDB 增强版客户端不支持可搜索的加密

注意

AWS 数据库加密SDK不支持对嵌套属性进行标注。

低级 DynamoDB API

您可以使用配置低级 DynamoDB,以便使用您的 API DynamoDB 请求DynamoDbEncryptionInterceptor在客户端自动加密和签署项目。PutItem

您必须使用低级 D API ynamoDB 才能使用可搜索的加密。

较低级别的 DynamoDbItemEncryptor

较低级别的 DynamoDbItemEncryptor 无需调用 DynamoDB 即可直接对您的表项目进行加密、签名或解密和验证。它不会发出 DynamoDB PutItemGetItem 请求。举例来说,您可以使用较低级别的 DynamoDbItemEncryptor 直接解密和验证已经检索到的 DynamoDB 项目。

较低级别的 DynamoDbItemEncryptor 不支持可搜索加密

DynamoD AWS B 数据库加密SDK中的属性操作

属性操作决定哪些属性值经过加密和签名,哪些仅经过签名,哪些经过签名并包含在加密上下文中,哪些会被忽略。

注意

要使用SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT加密操作,必须使用 3.3 或更高版本的 AWS 数据库加密SDK。在更新要包含的数据模型之前,先将新版本部署给所有读者SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT

如果您使用低级别 D API ynamoDB 或DynamoDbItemEncryptor较低级别,则必须手动定义属性操作。如果您使用 DynamoDB 增强型客户端,则可以手动定义属性操作,也可以使用带注释的数据类来生成一个 TableSchema。为了简化配置过程,建议使用带注释的数据类。使用带注释的数据类时,您只需要对对象建模一次。

注意

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

使用带注释的数据类通过 DynamoDB 增强版客户端和 DynamoDbEncryptionInterceptor 指定您的属性操作。Dynam SDK oDB AWS 数据库加密使用定义属性类型的标准 DynamoDB 属性标注来确定如何保护属性。默认情况下,除主键以外的所有属性均加密并签名,主键已签名但未加密。

注意

要使用SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT加密操作,必须使用 3.3 或更高版本的 AWS 数据库加密SDK。在更新要包含的数据模型之前,先将新版本部署给所有读者SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT

有关 aws-database-encryption-sdk DynamoDB 增强型客户端注释的更多指导,请参阅上 GitHub 的-dynamodb 存储库中的 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不支持对嵌套属性进行标注。

以下示例显示了用于定义ENCRYPT_AND_SIGNSIGN_ONLY、和DO_NOTHING属性操作的注释。有关显示用于定义的注释的示例SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT,请参阅 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);

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

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

分区和排序属性必须为SIGN_ONLYSIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT。如果将任何属性定义为SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT,则分区和排序属性也必须是SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT

注意

要使用SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT加密操作,必须使用 3.3 或更高版本的 AWS 数据库加密SDK。在更新要包含的数据模型之前,先将新版本部署给所有读者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);

DynamoD AWS B 数据库加密SDK中的加密配置

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

以下代码段使用 DynamoDB 增强版客户端、TableSchema 以及不同前缀定义的允许的未签名属性来定义 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 表后发生更改,则逻辑表名称可确保解密操作仍能识别该表。

允许的未签名属性

在您的属性操作中标记为 DO_NOTHING 的属性。

允许的未签名属性将告诉客户端哪些属性被排除在签名之外。客户端假设,所有的其他属性都包含在签名中。然后,在解密记录时,客户端会从您指定的允许的未签名属性中确定需要验证哪些属性以及需要忽略哪些属性。您将不能从允许的未签名属性中移除属性。

您可以通过创建一个列出所有 DO_NOTHING 属性的数组来显式定义允许的未签名属性。您还可以在命名 DO_NOTHING 属性时指定不同的前缀,并使用前缀告诉客户端哪些属性未签名。强烈建议指定一个不同的前缀,因为它可以简化未来添加新的 DO_NOTHING 属性的过程。有关更多信息,请参阅 更新您的数据模型

如果您没有为所有 DO_NOTHING 属性指定前缀,可以配置一个 allowedUnsignedAttributes 数组,该数组将显式列出客户端在解密时遇到这些属性时应该取消签名的所有属性。您只有在绝对必要时,才应显式定义允许的未签名属性。

搜索配置(可选)

SearchConfig 将定义信标版本

必须指定 SearchConfig 才能使用可搜索的加密签名信标

算法套件(可选)

algorithmSuiteId定义了 AWS 数据库加密SDK使用的算法套件。

除非您明确指定替代算法套件,否则 AWS 数据库加密将SDK使用默认算法套件。默认算法套件使用 AES-GCM 算法,包括密钥派生、数字签名密钥承诺。尽管默认算法套件可能适用于大多数应用程序,但您可以选择备用算法套件。例如,没有数字签名的算法套件可以满足某些信任模型的需求。有关 AWS 数据库加密SDK支持的算法套件的信息,请参见AWS 数据库加密中支持的算法套件 SDK

要选择不带ECDSA数字签名的 AES-GCM 算法套件,请在表加密配置中加入以下片段。

.algorithmSuiteId( DBEAlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384)

使用 AWS 数据库加密更新项目 SDK

UpdateItem对于已加密或签名的项目,数据库加密SDK不支持 ddb:。 AWS 要更新加密或签名的项目,必须使用 ddb: PutItem。如果将同一个主键指定为 PutItem 请求中现有的项目,则新项目将完全替代现有项目。更新项目后 CLOBBER,您还可以使用清除和替换保存时的所有属性。

解密签名集

在 AWS 数据库加密的 3.0.0 和 3.1.0 版本中SDK,如果将集合类型属性定义为SIGN_ONLY,则该集的值将按照提供的顺序进行规范化。DynamoDB 不保留集合的顺序。因此,包含该集合的项目的签名验证可能会失败。当集合的值的返回顺序与提供给 AWS 数据库加密的顺序不同时SDK,即使集合的属性包含相同的值,签名验证也会失败。

注意

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

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

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

如果您收到上述错误消息,并且认为要解密的项目包含使用版本 3.0.0 或 3.1.0 签名的集合,请查看-dy aws-database-encryption-sdk namodb-java 存储库的DecryptWithPermute目录,了解如何成功验证该集合 GitHub 的详细信息。