本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
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