本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
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_ONLY
、INCLUDE
和 ALL
。
如果使用 INCLUDE 属性投影在信标上进行搜索,则您必须指定构造信标所用的所有属性的名称以及包含 aws_dbe_b_
前缀的信标名称。例如,如果通过 field1
、field2
和 field3
配置了复合信标 compoundBeacon
,则必须在投影中指定 aws_dbe_b_compoundBeacon
、field1
、field2
和 field3
。
全局二级索引只能使用投影中显式指定的属性,但本地二级索引可以使用任何属性。
测试信标输出
如果您配置了复合信标或使用虚拟字段构造了信标,我们建议您在填充 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");
- Rust
-
参见完整的代码示例:virtual _beacon_searchable_encryption.rs。
// Create item with hasTestResult=true
let item_with_has_test_result = HashMap::from([
(
"customer_id".to_string(),
AttributeValue::S("ABC-123".to_string()),
),
(
"create_time".to_string(),
AttributeValue::N("1681495205".to_string()),
),
("state".to_string(), AttributeValue::S("CA".to_string())),
("hasTestResult".to_string(), AttributeValue::Bool(true)),
]);
// Create item with hasTestResult=false
let item_with_no_has_test_result = HashMap::from([
(
"customer_id".to_string(),
AttributeValue::S("DEF-456".to_string()),
),
(
"create_time".to_string(),
AttributeValue::N("1681495205".to_string()),
),
("state".to_string(), AttributeValue::S("CA".to_string())),
("hasTestResult".to_string(), AttributeValue::Bool(false)),
]);
// Define the transform service
let trans = transform_client::Client::from_conf(encryption_config.clone())?;
// Verify the configuration
let resolve_output = trans
.resolve_attributes()
.table_name(ddb_table_name)
.item(item_with_has_test_result.clone())
.version(1)
.send()
.await?;
// Verify that VirtualFields has the expected value
let virtual_fields = resolve_output.virtual_fields.unwrap();
assert_eq!(virtual_fields.len(), 1);
assert_eq!(virtual_fields["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
- Rust
-
查看完整的代码示例:compound_beacon_searchable_encr y pt ion.rs
// Create an item with both attributes used in the compound beacon
let item = HashMap::from([
(
"work_id".to_string(),
AttributeValue::S("9ce39272-8068-4efd-a211-cd162ad65d4c".to_string()),
),
(
"inspection_date".to_string(),
AttributeValue::S("2023-06-13".to_string()),
),
(
"inspector_id_last4".to_string(),
AttributeValue::S("5678".to_string()),
),
(
"unit".to_string(),
AttributeValue::S("011899988199".to_string()),
),
]);
// Define the transforms service
let trans = transform_client::Client::from_conf(encryption_config.clone())?;
// Verify configuration
let resolve_output = trans
.resolve_attributes()
.table_name(ddb_table_name)
.item(item.clone())
.version(1)
.send()
.await?;
// Verify that CompoundBeacons has the expected value
Dlet compound_beacons = resolve_output.compound_beacons.unwrap();
assert_eq!(compound_beacons.len(), 1);
assert_eq!(
compound_beacons["last4UnitCompound"],
"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