

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# DynamoDB의 검색 가능한 암호화
<a name="ddb-searchable-encryption"></a>

검색 가능한 암호화를 위해 Amazon DynamoDB 테이블을 구성하려면 [AWS KMS 계층 키링](use-hierarchical-keyring.md)을 사용하여 항목을 보호하는 데 사용되는 데이터 키를 생성, 암호화 및 복호화해야 합니다. 또한 테이블 암호화 구성에 [`SearchConfig`](ddb-net-using.md#ddb-net-search-config)를 포함해야 합니다.

**참고**  
DynamoDB용 Java 클라이언트 측 암호화 라이브러리를 사용하는 경우 DynamoDB API용 하위 수준 AWS Database Encryption SDK를 사용하여 테이블 항목을 암호화, 서명, 확인 및 해독해야 합니다. DynamoDB Enhanced Client와 하위 수준 `DynamoDBItemEncryptor`은 검색 가능한 암호화를 지원하지 않습니다.

**Topics**
+ [비컨을 사용한 보조 인덱스 구성](#ddb-beacon-indexes)
+ [비컨 출력 테스트](#ddb-beacon-testing)

## 비컨을 사용한 보조 인덱스 구성
<a name="ddb-beacon-indexes"></a>

[비컨를 구성한](configure-beacons.md) 후 암호화된 속성을 검색하려면 먼저 각 비컨을 반영하는 보조 인덱스를 구성해야 합니다.

표준 또는 복합 비컨을 구성하면 AWS Database Encryption SDK가 비컨 이름에 `aws_dbe_b_` 접두사를 추가하여 서버가 비컨을 쉽게 식별할 수 있도록 합니다. 예를 들어 복합 비컨 `compoundBeacon`의 이름을 지정하면 실제로는 전체 비컨 이름이 `aws_dbe_b_compoundBeacon`가 됩니다. 표준 또는 복합 비컨을 포함하는 [보조 인덱스](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html)를 구성하려면 비컨 이름을 식별할 때 `aws_dbe_b_` 접두사를 포함해야 합니다.

**파티션 키와 정렬 키**  
프라이머리 키 값은 암호화할 수 없습니다. 파티션 및 정렬 키에 서명해야 합니다. 프라이머리 키 값은 표준 또는 복합 비컨이 될 수 없습니다.  
`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 속성을 지정`SIGN_ONLY`하지 않는 한 기본 키 값은 이어야 하며, 파티션 및 정렬 속성도 여야 합니다`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`.  
프라이머리 키 값은 서명된 비컨일 수 있습니다. 각 프라이머리 키 값에 대해 고유한 서명된 비컨을 구성한 경우 프라이머리 키 값을 서명된 비컨 이름으로 식별하는 속성 이름을 지정해야 합니다. 그러나 AWS Database Encryption SDK는 서명된 비컨에 `aws_dbe_b_` 접두사를 추가하지 않습니다. 프라이머리 키 값에 대해 고유한 서명된 비컨를 구성한 경우에도 보조 인덱스를 구성할 때 프라이머리 키 값의 속성 이름만 지정하면 됩니다.

**로컬 보조 인덱스**  
[로컬 보조 인덱스](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html)의 정렬 키는 비컨일 수 있습니다.  
정렬 키에 비컨를 지정하는 경우 유형은 문자열이어야 합니다. 정렬 키에 표준 또는 복합 비컨를 지정하는 경우 비컨 이름을 지정할 때 `aws_dbe_b_` 접두사를 포함해야 합니다. 서명된 비컨를 지정하는 경우 접두사 없이 비컨 이름을 지정합니다.

**글로벌 보조 인덱스**  
[글로벌 보조 인덱스](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html)의 파티션 키와 정렬 키는 모두 비컨일 수 있습니다.  
파티션이나 정렬 키에 비컨을 지정하는 경우 유형은 문자열이어야 합니다. 정렬 키에 표준 또는 복합 비컨를 지정하는 경우 비컨 이름을 지정할 때 `aws_dbe_b_` 접두사를 포함해야 합니다. 서명된 비컨를 지정하는 경우 접두사 없이 비컨 이름을 지정합니다.

**속성 프로젝션**  
[프로젝션](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Projections)은 테이블에서 보조 인덱스로 복사되는 속성 집합입니다. 테이블의 파티션 키와 정렬 키는 항상 인덱스로 프로젝션되지만, 다른 속성을 프로젝션하여 애플리케이션의 쿼리 요건을 지원하는 것도 가능합니다. DynamoDB는 속성 프로젝션을 위한 세 가지 옵션(`KEYS_ONLY`, `INCLUDE`, 및 `ALL`)을 제공합니다.  
INCLUDE 속성 프로젝션을 사용하여 비컨을 검색하는 경우 비컨을 구성하는 모든 속성의 이름과 `aws_dbe_b_` 접두사를 포함한 비컨 이름을 지정해야 합니다. 예를 들어 `field1`, `field2`, 및 `field3`에서 복합 비콘 `compoundBeacon`을 구성한 경우 프로젝션에서 `aws_dbe_b_compoundBeacon`, `field1`, `field2`, 및 `field3`를 지정해야 합니다.  
글로벌 보조 인덱스는 프로젝션에 명시적으로 지정된 속성만 사용할 수 있지만 로컬 보조 인덱스는 모든 속성을 사용할 수 있습니다.

## 비컨 출력 테스트
<a name="ddb-beacon-testing"></a>

[복합 비컨을 구성](configure-beacons.md#config-compound-beacons)하거나 [가상 필드를](configure-beacons.md#create-virtual-field) 사용하여 비컨을 구성한 경우 DynamoDB 테이블을 채우기 전에 이러한 비컨이 예상 출력을 생성하는지 확인하는 것이 좋습니다.

 AWS Database Encryption SDK는 가상 필드 및 복합 비컨 출력 문제를 해결하는 데 도움이 되는 `DynamoDbEncryptionTransforms` 서비스를 제공합니다.

### 가상 필드 테스트
<a name="ddb-beacon-testing-virtual-field"></a>

다음 코드 조각은 테스트 항목을 생성하고, [DynamoDB 테이블 암호화 구성](ddb-java-using.md#ddb-config-encrypt)으로 `DynamoDbEncryptionTransforms` 서비스를 정의하고,를 사용하여 가상 필드가 예상 출력을 생성하는지 `ResolveAttributes` 확인하는 방법을 보여줍니다.

------
#### [ Java ]

**전체 코드 샘플**: [VirtualBeaconSearchableEncryptionExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/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\$1 / .NET ]

**전체 코드 샘플: VirtualBeaconSearchableEncryptionExample.cs를 참조**하세요. [VirtualBeaconSearchableEncryptionExample.cs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/searchableencryption/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\$1beacon\$1searchable\$1encryption.rs를 참조**하세요. [https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/searchableencryption/virtual_beacon_searchable_encryption.rs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/searchableencryption/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");
```

------

### 복합 비컨 테스트
<a name="ddb-beacon-testing-compound-beacon"></a>

다음 코드 조각은 테스트 항목을 생성하고, [DynamoDB 테이블 암호화 구성](ddb-java-using.md#ddb-config-encrypt)으로 `DynamoDbEncryptionTransforms` 서비스를 정의하고,를 `ResolveAttributes` 사용하여 복합 비컨이 예상 출력을 생성하는지 확인하는 방법을 보여줍니다.

------
#### [ Java ]

**전체 코드 샘플**: [CompoundBeaconSearchableEncryptionExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/searchableencryption/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\$1 / .NET ]

**전체 코드 샘플**: [CompoundBeaconSearchableEncryptionExample.cs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/searchableencryption/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\$1beacon\$1searchable\$1encryption.rs를 참조하세요**. [https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/searchableencryption/compound_beacon_searchable_encryption.rs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/searchableencryption/compound_beacon_searchable_encryption.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 
let 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
```

------