DynamoDB 中的可搜索加密 - AWS 数据库加密 SDK

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

DynamoDB 中的可搜索加密

要配置 Amazon DynamoDB 表以进行可搜索的加密,必须使用 AWS KMS 分层密钥环来生成、加密和解密用于保护项目的数据密钥。您还必须在表加密配置中包含 SearchConfig

注意

如果您使用适用于 DynamoDB 的 Java 客户端加密库,则必须使用适用于 DynamoDB 的 AWS 低级数据库加密 SDK API 来加密、签名、验证和解密您的表格项目。DynamoDB 增强版客户端和较低级别 DynamoDBItemEncryptor 不支持可搜索的加密。

通过使用信标配置二级索引

配置信标后,您必须先配置反映每个信标的二级索引,然后才能搜索加密的属性。

配置标准信标或复合信标时, AWS 数据库加密 SDK 会在信标名称中添加aws_dbe_b_前缀,以便服务器可以轻松识别信标。例如,如果您将复合信标命名为 compoundBeacon,则信标的完整名称实际上为 aws_dbe_b_compoundBeacon。如果您要配置包含标准信标或复合信标的二级索引,则必须在标识信标名称时包含 aws_dbe_b_ 前缀。

分区键和排序键

您将无法加密主键值。您的分区和排序密钥必须经过签名。您的主键值不能是标准或复合信标。

除非您指定任何SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT属性SIGN_ONLY,否则您的主键值必须是,分区和排序属性也必须是SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT

您的主键值可以是已签名的信标。如果您为每个主键值配置了不同的签名信标,则必须指定属性名称以将主键值标识为已签名信标名称。但是, AWS 数据库加密 SDK 不会为已签名的信标添加aws_dbe_b_前缀。即使您为主键值配置了不同的签名信标,您也只需要在配置二级索引时为主键值指定属性名称。

本地二级索引

本地二级索引的排序键可以是信标。

如果您为排序键指定信标,类型必须为 String。如果您为排序键指定标准信标或复合信标,则必须在指定信标名称时包含 aws_dbe_b_ 前缀。如果您指定签名信标,则请指定不包含任何前缀的信标名称。

全局二级索引

全局二级索引的分区键和排序键都可以是信标。

如果您为分区键或排序键指定信标,则类型必须为 String。如果您为排序键指定标准信标或复合信标,则必须在指定信标名称时包含 aws_dbe_b_ 前缀。如果您指定签名信标,则请指定不包含任何前缀的信标名称。

属性投影

投影是从表复制到二级索引的属性集。表的分区键和排序键始终投影到索引中;您可以投影其他属性以支持应用程序的查询要求。DynamoDB 为属性投影提供三种不同的选项:KEYS_ONLYINCLUDEALL

如果使用 INCLUDE 属性投影在信标上进行搜索,则您必须指定构造信标所用的所有属性的名称以及包含 aws_dbe_b_ 前缀的信标名称。例如,如果通过 field1field2field3 配置了复合信标 compoundBeacon,则必须在投影中指定 aws_dbe_b_compoundBeaconfield1field2field3

全局二级索引只能使用投影中显式指定的属性,但本地二级索引可以使用任何属性。

测试信标输出

如果您配置了复合信标或使用虚拟字段构造了信标,我们建议您在填充 DynamoDB 表之前验证这些信标是否产生了预期的输出。

AWS 数据库加密 SDK 提供的DynamoDbEncryptionTransforms服务可帮助您对虚拟场和复合信标输出进行故障排除。

以下代码段创建测试项目,使用 D ynamoDB 表加密配置定义DynamoDbEncryptionTransforms服务,并演示如何ResolveAttributes使用来验证虚拟字段是否产生预期的输出。

Java

查看完整的代码示例VirtualBeaconSearchableEncryptionExample.java

// Create test items final PutItemRequest itemWithHasTestResultPutRequest = PutItemRequest.builder() .tableName(ddbTableName) .item(itemWithHasTestResult) .build(); final PutItemResponse itemWithHasTestResultPutResponse = ddb.putItem(itemWithHasTestResultPutRequest); final PutItemRequest itemWithNoHasTestResultPutRequest = PutItemRequest.builder() .tableName(ddbTableName) .item(itemWithNoHasTestResult) .build(); final PutItemResponse itemWithNoHasTestResultPutResponse = ddb.putItem(itemWithNoHasTestResultPutRequest); // Define the DynamoDbEncryptionTransforms service final DynamoDbEncryptionTransforms trans = DynamoDbEncryptionTransforms.builder() .DynamoDbTablesEncryptionConfig(encryptionConfig).build(); // Verify configuration final ResolveAttributesInput resolveInput = ResolveAttributesInput.builder() .TableName(ddbTableName) .Item(itemWithHasTestResult) .Version(1) .build(); final ResolveAttributesOutput resolveOutput = trans.ResolveAttributes(resolveInput); // Verify that VirtualFields has the expected value Map<String, String> vf = new HashMap<>(); vf.put("stateAndHasTestResult", "CAt"); assert resolveOutput.VirtualFields().equals(vf);
C# / .NET

查看完整的代码示例VirtualBeaconSearchableEncryptionExample.cs

// Create item with hasTestResult=true var itemWithHasTestResult = new Dictionary<String, AttributeValue> { ["customer_id"] = new AttributeValue("ABC-123"), ["create_time"] = new AttributeValue { N = "1681495205" }, ["state"] = new AttributeValue("CA"), ["hasTestResult"] = new AttributeValue { BOOL = true } }; // Create item with hasTestResult=false var itemWithNoHasTestResult = new Dictionary<String, AttributeValue> { ["customer_id"] = new AttributeValue("DEF-456"), ["create_time"] = new AttributeValue { N = "1681495205" }, ["state"] = new AttributeValue("CA"), ["hasTestResult"] = new AttributeValue { BOOL = false } }; // Define the DynamoDbEncryptionTransforms service var trans = new DynamoDbEncryptionTransforms(encryptionConfig); // Verify configuration var resolveInput = new ResolveAttributesInput { TableName = ddbTableName, Item = itemWithHasTestResult, Version = 1 }; var resolveOutput = trans.ResolveAttributes(resolveInput); // Verify that VirtualFields has the expected value Debug.Assert(resolveOutput.VirtualFields.Count == 1); Debug.Assert(resolveOutput.VirtualFields["stateAndHasTestResult"] == "CAt");

以下代码段创建了一个测试项目,使用 D ynamoDB 表加密配置定义DynamoDbEncryptionTransforms服务,并演示了如何ResolveAttributes使用来验证复合信标是否产生了预期的输出。

Java

查看完整的代码示例CompoundBeaconSearchableEncryptionExample.java

// Create an item with both attributes used in the compound beacon. final HashMap<String, AttributeValue> item = new HashMap<>(); item.put("work_id", AttributeValue.builder().s("9ce39272-8068-4efd-a211-cd162ad65d4c").build()); item.put("inspection_date", AttributeValue.builder().s("2023-06-13").build()); item.put("inspector_id_last4", AttributeValue.builder().s("5678").build()); item.put("unit", AttributeValue.builder().s("011899988199").build()); // Define the DynamoDbEncryptionTransforms service final DynamoDbEncryptionTransforms trans = DynamoDbEncryptionTransforms.builder() .DynamoDbTablesEncryptionConfig(encryptionConfig).build(); // Verify configuration final ResolveAttributesInput resolveInput = ResolveAttributesInput.builder() .TableName(ddbTableName) .Item(item) .Version(1) .build(); final ResolveAttributesOutput resolveOutput = trans.ResolveAttributes(resolveInput); // Verify that CompoundBeacons has the expected value Map<String, String> cbs = new HashMap<>(); cbs.put("last4UnitCompound", "L-5678.U-011899988199"); assert resolveOutput.CompoundBeacons().equals(cbs); // Note : the compound beacon actually stored in the table is not "L-5678.U-011899988199" // but rather something like "L-abc.U-123", as both parts are EncryptedParts // and therefore the text is replaced by the associated beacon
C# / .NET

查看完整的代码示例CompoundBeaconSearchableEncryptionExample.cs

// Create an item with both attributes used in the compound beacon var item = new Dictionary<String, AttributeValue> { ["work_id"] = new AttributeValue("9ce39272-8068-4efd-a211-cd162ad65d4c"), ["inspection_date"] = new AttributeValue("2023-06-13"), ["inspector_id_last4"] = new AttributeValue("5678"), ["unit"] = new AttributeValue("011899988199") }; // Define the DynamoDbEncryptionTransforms service var trans = new DynamoDbEncryptionTransforms(encryptionConfig); // Verify configuration var resolveInput = new ResolveAttributesInput { TableName = ddbTableName, Item = item, Version = 1 }; var resolveOutput = trans.ResolveAttributes(resolveInput); // Verify that CompoundBeacons has the expected value Debug.Assert(resolveOutput.CompoundBeacons.Count == 1); Debug.Assert(resolveOutput.CompoundBeacons["last4UnitCompound"] == "L-5678.U-011899988199"); // Note : the compound beacon actually stored in the table is not "L-5678.U-011899988199" // but rather something like "L-abc.U-123", as both parts are EncryptedParts // and therefore the text is replaced by the associated beacon