

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# AWS 適用於 DynamoDB 的資料庫加密 SDK
<a name="dynamodb-encryption-client"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

適用於 DynamoDB 的 AWS Database Encryption SDK 是一種軟體程式庫，可讓您在 [Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/) 設計中包含用戶端加密。適用於 DynamoDB 的 AWS Database Encryption SDK 提供屬性層級加密，可讓您指定要加密的項目，以及要包含在簽章中的項目，以確保資料的真實性。加密傳輸中和靜態的敏感資料有助於確保任何第三方都無法使用您的純文字資料，包括 AWS。

**注意**  
 AWS Database Encryption SDK 不支援 PartiQL。

在 DynamoDB 中，[資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.TablesItemsAttributes)是項目的集合。每個*項目*都是*屬性*的集合。每個屬性都有名稱和數值。適用於 DynamoDB 的 AWS Database Encryption SDK 會加密屬性的值。接著，它會透過屬性計算簽章。您可以指定要加密的屬性值，以及在[密碼編譯動作](concepts.md#crypt-actions)的簽章中包含哪些屬性值。

本章中的主題提供 DynamoDB AWS 資料庫加密 SDK 的概觀，包括加密的欄位、用戶端安裝和組態的指引，以及協助您開始使用的 Java 範例。

**Topics**
+ [用戶端加密和伺服器端加密](client-server-side.md)
+ [哪些欄位已加密並簽署？](DDB-encrypted-and-signed.md)
+ [DynamoDB 中的可搜尋加密](ddb-searchable-encryption.md)
+ [更新資料模型](ddb-update-data-model.md)
+ [AWS 適用於 DynamoDB 的資料庫加密 SDK 可用的程式設計語言](ddb-programming-languages.md)
+ [舊版 DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)

# 用戶端加密和伺服器端加密
<a name="client-server-side"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

適用於 DynamoDB 的 AWS Database Encryption SDK *支援用戶端加密*，您可以在其中加密資料表資料，然後再將其傳送至資料庫。不過，DynamoDB 提供伺服器端*靜態加密*功能，可在資料表保留到磁碟時將其透明加密，並在您存取資料表時解密。

您所應選擇的工具，取決於資料的敏感度以及應用程式的安全性需求。您可以同時使用 DynamoDB AWS 資料庫加密 SDK 和靜態加密。當您將加密和簽章的項目傳送至 DynamoDB 時，DynamoDB 不會將項目識別為受保護。它只會偵測具有二進位屬性值的一般資料表項目。

**伺服器端靜態加密**

DynamoDB 支援[靜態加密](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html)，這是一種*伺服器端加密*功能，DynamoDB 會在資料表保留到磁碟時為您透明加密資料表，並在您存取資料表資料時解密資料表。

當您使用 AWS SDK 與 DynamoDB 互動時，您的資料預設會透過 HTTPS 連線在傳輸中加密、在 DynamoDB 端點解密，然後在存放在 DynamoDB 之前重新加密。
+ **預設加密。**DynamoDB 會在寫入所有資料表時，以透明方式加密和解密資料表。沒有啟用或停用靜態加密的選項。
+ **DynamoDB 會建立和管理密碼編譯金鑰。 **每個資料表的唯一金鑰受到 的保護[AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)，這些 永遠不會讓 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) 處於未加密狀態。根據預設，DynamoDB [AWS 擁有的金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-owned-cmk) 在 DynamoDB 服務帳戶中使用 ，但您可以選擇帳戶中的 [AWS 受管金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk)或[客戶受管金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk)來保護部分或全部資料表。
+ **所有資料表資料都會在磁碟上加密。 **將加密的資料表儲存至磁碟時，DynamoDB 會加密所有資料表資料，包括[主索引](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey)鍵和本機和全域[次要索引](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.SecondaryIndexes)。如果您的資料表有排序索引鍵，則某些標示範圍界限的排序索引鍵將會以純文字的格式存放在資料表中繼資料中。
+ **與資料表相關的物件也會加密。**靜態加密可在 [DynamoDB 串流](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html)、[全域資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GlobalTables.html)和[備份](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/BackupRestore.html)寫入耐用媒體時加以保護。
+ **您的項目會在您存取時解密。 **當您存取資料表時，DynamoDB 會解密包含目標項目的資料表部分，並將純文字項目傳回給您。

**AWS 適用於 DynamoDB 的資料庫加密 SDK**

無論是在傳輸中、靜態時，還是從來源儲存至 DynamoDB 時，用戶端加密都可為資料提供端對端的保護。您的純文字資料絕不會公開給任何第三方，包括 AWS。您可以使用適用於 DynamoDB 的 AWS 資料庫加密 SDK 搭配新的 DynamoDB 資料表，也可以將現有的 Amazon DynamoDB 資料表遷移至適用於 DynamoDB 的 AWS 資料庫加密 SDK 的最新版本。
+ **傳輸中和靜態的資料都受到保護。**它永遠不會向任何第三方公開，包括 AWS。
+ **您可以簽署您的資料表項目。**您可以指示 DynamoDB 的 AWS Database Encryption SDK 計算資料表項目的全部或部分簽章，包括主索引鍵屬性。此簽章可讓您偵測對整體項目的未授權變更，包括新增或刪除屬性，或是交換屬性值。
+ 您可以透過[選取 keyring ](keyrings.md)來**判斷如何保護資料**。您的 keyring 會決定保護資料金鑰的包裝金鑰，最終決定您的資料。使用對您的任務而言最安全的包裝金鑰。
+ **適用於 DynamoDB 的 AWS Database Encryption SDK 不會加密整個資料表。**您可以選擇在項目中加密的屬性。適用於 DynamoDB 的 AWS Database Encryption SDK 不會加密整個項目。它不會加密屬性名稱，或是主索引鍵 (分割區索引鍵和排序索引鍵) 屬性的名稱或值。

**AWS Encryption SDK**

如果您要加密存放在 DynamoDB 中的資料，建議您使用適用於 DynamoDB 的 AWS 資料庫加密 SDK。

[AWS Encryption SDK](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/) 是用戶端加密程式庫，可協助您進行一般資料的加密和解密。雖然它可保護任何類型的資料，但在設計上並不是用來處理結構化資料 (例如資料庫記錄)。與適用於 DynamoDB 的 AWS 資料庫加密 SDK 不同， AWS Encryption SDK 無法提供項目層級完整性檢查，而且沒有辨識屬性或防止主要金鑰加密的邏輯。

如果您使用 AWS Encryption SDK 來加密資料表的任何元素，請記住，它與適用於 DynamoDB 的 AWS Database Encryption SDK 不相容。您無法用一個程式庫加密，但用另一個程式庫解密。

# 哪些欄位已加密並簽署？
<a name="DDB-encrypted-and-signed"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

適用於 DynamoDB 的 AWS Database Encryption SDK 是專為 Amazon DynamoDB 應用程式設計的用戶端加密程式庫。Amazon DynamoDB 將資料存放在[資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.TablesItemsAttributes)中，這是項目的集合。每個*項目*都是*屬性*的集合。每個屬性都有名稱和數值。適用於 DynamoDB 的 AWS Database Encryption SDK 會加密屬性的值。接著，它會透過屬性計算簽章。您可以指定哪些屬性值要加密，以及哪些屬性值要包含在簽章中。

加密可保護屬性值的機密性。簽署可提供所有已簽署屬性的完整性及其彼此的關係，並可提供驗證。它可讓您偵測對整體項目的未授權變更 (包括新增或刪除屬性)，或是替換已加密的值。

在加密的項目中，某些資料會保留為純文字，包括資料表名稱、所有屬性名稱、您未加密的屬性值、主索引鍵 （分割區索引鍵和排序索引鍵） 屬性的名稱和值，以及屬性類型。請勿在這些欄位中存放敏感性資訊。

如需 DynamoDB AWS 資料庫加密開發套件運作方式的詳細資訊，請參閱 [AWS 資料庫加密 SDK 的運作方式](how-it-works.md)。

**注意**  
DynamoDB AWS 資料庫加密 SDK 主題中提及*的所有屬性動作*都是指[密碼編譯動作](concepts.md#crypt-actions)。

**Topics**
+ [加密屬性值](#encrypt-attribute-values)
+ [簽署項目](#sign-the-item)

## 加密屬性值
<a name="encrypt-attribute-values"></a>

適用於 DynamoDB 的 AWS Database Encryption SDK 會加密您指定屬性的值 （而非屬性名稱或類型）。若要決定加密的是哪些屬性值，請使用[屬性動作](concepts.md#crypt-actions)。

例如，這個項目包括 `example` 和 `test` 屬性。

```
'example': 'data',
'test': 'test-value',
...
```

如果您將 `example` 屬性加密，但不加密 `test` 屬性，結果如下所示。已加密的 `example` 屬性值是二進位資料，而不是字串。

```
'example': Binary(b"'b\x933\x9a+s\xf1\xd6a\xc5\xd5\x1aZ\xed\xd6\xce\xe9X\xf0T\xcb\x9fY\x9f\xf3\xc9C\x83\r\xbb\\"),
'test': 'test-value'
...
```

每個項目的主要索引鍵屬性 - 分割區索引鍵和排序索引鍵 - 必須保持純文字，因為 DynamoDB 會使用它們在資料表中尋找項目。這些屬性應加以簽署，但不要加密。

適用於 DynamoDB 的 AWS Database Encryption SDK 會為您識別主要金鑰屬性，並確保其值已簽章，但未加密。而且，如果您找出您的主要索引鍵，然後試著將它加密，則用戶端會擲出例外狀況。

用戶端會將[材料描述](concepts.md#material-description)存放在新增至項目的新屬性 (`aws_dbe_head`) 中。資料描述說明項目的加密和簽署方式。用戶端會使用此資訊來驗證並解密項目。存放材料描述的欄位不會加密。

## 簽署項目
<a name="sign-the-item"></a>

加密指定的屬性值後，適用於 DynamoDB 的 AWS Database Encryption SDK 會計算雜湊型訊息驗證碼 (HMACs) 和[數位簽章](concepts.md#digital-sigs)，而不是材料描述、[加密內容](concepts.md#encryption-context)和[屬性動作](concepts.md#crypt-actions)`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`中標記為 `ENCRYPT_AND_SIGN`、 `SIGN_ONLY`或 的每個欄位的正式化。ECDSA 簽章預設為啟用，但非必要。用戶端會將 HMACs 和簽章存放在新增至項目的新屬性 (`aws_dbe_foot`) 中。

# DynamoDB 中的可搜尋加密
<a name="ddb-searchable-encryption"></a>

若要設定 Amazon DynamoDB 資料表進行可搜尋加密，您必須使用[AWS KMS 階層式 keyring](use-hierarchical-keyring.md) 來產生、加密和解密用於保護項目的資料金鑰。您還必須在資料表加密組態[`SearchConfig`](ddb-net-using.md#ddb-net-search-config)中包含 。

**注意**  
如果您使用適用於 DynamoDB 的 Java 用戶端加密程式庫，則必須使用適用於 DynamoDB API 的低階 AWS 資料庫加密開發套件來加密、簽署、驗證和解密資料表項目。DynamoDB 增強型用戶端和較低層級`DynamoDBItemEncryptor`不支援可搜尋加密。

**Topics**
+ [使用信標設定次要索引](#ddb-beacon-indexes)
+ [測試信標輸出](#ddb-beacon-testing)

## 使用信標設定次要索引
<a name="ddb-beacon-indexes"></a>

[設定信標](configure-beacons.md)之後，您必須先設定反映每個信標的次要索引，才能搜尋加密的屬性。

當您設定標準或複合信標時， AWS 資料庫加密 SDK 會將`aws_dbe_b_`字首新增至信標名稱，以便伺服器輕鬆識別信標。例如，如果您命名複合信標 `compoundBeacon`，則完整信標名稱實際上是 `aws_dbe_b_compoundBeacon`。如果您想要設定包含標準或複合信標的[次要索引](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html)，您必須在識別信標名稱時包含 `aws_dbe_b_`字首。

**分割區和排序索引鍵**  
您無法加密主索引鍵值。必須簽署您的分割區和排序索引鍵。您的主索引鍵值不能是標準或複合信標。  
您的主索引鍵值必須是 `SIGN_ONLY`，除非您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，否則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。  
您的主索引鍵值可以是已簽章的信標。如果您為每個主索引鍵值設定了不同的簽章信標，則必須指定屬性名稱，將主索引鍵值識別為簽章信標名稱。不過， AWS 資料庫加密 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`和 設定複合信標 `compoundBeacon``field3`，您必須在投影`field3`中指定 `field2`、、 `aws_dbe_b_compoundBeacon` `field1`和 。  
全域次要索引只能使用投影中明確指定的屬性，但本機次要索引可以使用任何屬性。

## 測試信標輸出
<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](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)。

```
// 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)

```
// 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
```

------

# 更新資料模型
<a name="ddb-update-data-model"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

當您設定 DynamoDB 的 AWS 資料庫加密 SDK 時，您會提供[屬性動作](concepts.md#crypt-actions)。加密時， AWS 資料庫加密 SDK 會使用屬性動作來識別要加密和簽署的屬性、要簽署的屬性 （但不加密），以及要忽略的屬性。您也可以定義[允許的未簽章屬性](ddb-java-using.md#allowed-unauth)，以明確告知用戶端哪些屬性已從簽章中排除。在解密時， AWS 資料庫加密 SDK 會使用您定義的允許未簽章屬性，來識別簽章中未包含哪些屬性。屬性動作不會儲存在加密的項目中，資料庫 AWS 加密 SDK 不會自動更新您的屬性動作。

請仔細選擇屬性動作。如有疑問，請使用**加密並簽署**。使用 AWS 資料庫加密 SDK 保護您的項目之後，您無法將現有的 `ENCRYPT_AND_SIGN`、 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性變更為 `DO_NOTHING`。不過，您可以安全地進行下列變更。
+ [新增 `ENCRYPT_AND_SIGN`、 `SIGN_ONLY`和 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性](#ddb-add-auth-attribute)
+ [移除現有的屬性](#ddb-remove-attribute)
+ [將現有`ENCRYPT_AND_SIGN`屬性變更為 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`](#ddb-encrypt-to-sign)
+ [將現有 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性變更為 `ENCRYPT_AND_SIGN`](#ddb-sign-to-encrypt)
+ [新增`DO_NOTHING`屬性](#ddb-add-unauth-attribute)
+ [將現有`SIGN_ONLY`屬性變更為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`](#ddb-signOnly-to-signInclude)
+ [將現有`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性變更為 `SIGN_ONLY`](#ddb-signInclude-to-signOnly)

**可搜尋加密的考量事項**  
在更新資料模型之前，請仔細考慮您的更新如何影響您從屬性建構的任何[信標](beacons.md)。使用信標撰寫新記錄之後，您就無法更新信標的組態。您無法更新與您用來建構信標的屬性相關聯的屬性動作。如果您移除現有的屬性及其相關聯的信標，您將無法使用該信標查詢現有的記錄。您可以為新增至記錄的新欄位建立新的信標，但無法更新現有的信標以包含新欄位。

**`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性的考量事項**  
根據預設，分割區和排序索引鍵是加密內容中包含的唯一屬性。您可以考慮定義其他欄位，`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`以便[AWS KMS 階層式 keyring](use-hierarchical-keyring.md) 的分支金鑰 ID 供應商可以識別從加密內容解密所需的分支金鑰。如需詳細資訊，請參閱[分支金鑰 ID 供應商](use-hierarchical-keyring.md#branch-key-id-supplier)。如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

**注意**  
若要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`密碼編譯動作，您必須使用 3.3 版或更新版本的 AWS 資料庫加密 SDK。將[您的資料模型更新](#ddb-update-data-model)為包含 之前，將新版本部署至所有讀者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

## 新增 `ENCRYPT_AND_SIGN`、 `SIGN_ONLY`和 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性
<a name="ddb-add-auth-attribute"></a>

若要新增 `ENCRYPT_AND_SIGN`、 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性，請在屬性動作中定義新的屬性。

您無法移除現有的`DO_NOTHING`屬性，並將其新增為 `ENCRYPT_AND_SIGN`、 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性。

**使用標註的資料類別**  
如果您使用 定義屬性動作`TableSchema`，請將新屬性新增至註釋的資料類別。如果您未指定新屬性的屬性動作註釋，用戶端預設會加密並簽署新屬性 （除非屬性是主索引鍵的一部分）。如果您只想要簽署新的屬性，則必須使用 `@DynamoDBEncryptionSignOnly`或 `@DynamoDBEncryptionSignAndIncludeInEncryptionContext`註釋新增新的屬性。

**使用物件模型**  
如果您手動定義屬性動作，請將新屬性新增至物件模型中的屬性動作`SIGN_ONLY`，並指定 `ENCRYPT_AND_SIGN`、 或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`作為屬性動作。

## 移除現有的屬性
<a name="ddb-remove-attribute"></a>

如果您決定不再需要 屬性，您可以停止將資料寫入該屬性，也可以正式將其從屬性動作中移除。當您停止將新資料寫入屬性時，屬性仍會顯示在屬性動作中。如果您未來需要再次開始使用 屬性，這會很有幫助。從您的屬性動作正式移除 屬性並不會從資料集移除它。您的資料集仍會包含包含該屬性的項目。

若要正式移除現有的 `ENCRYPT_AND_SIGN`、`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`、 `SIGN_ONLY`或 `DO_NOTHING` 屬性，請更新您的屬性動作。

如果您移除`DO_NOTHING`屬性，則不得將該屬性從[允許的未簽章屬性](ddb-java-using.md#allowed-unauth)中移除。即使您不再將新值寫入該屬性，用戶端仍需要知道該屬性未簽署，才能讀取包含該屬性的現有項目。

**使用標註的資料類別**  
如果您使用 定義屬性動作`TableSchema`，請從註釋的資料類別中移除 屬性。

**使用物件模型**  
如果您手動定義屬性動作，請從物件模型中的屬性動作中移除屬性。

## 將現有`ENCRYPT_AND_SIGN`屬性變更為 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`
<a name="ddb-encrypt-to-sign"></a>

若要將現有`ENCRYPT_AND_SIGN`屬性變更為 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，您必須更新您的屬性動作。部署更新之後，用戶端將能夠驗證和解密寫入 屬性的現有值，但只會簽署寫入 屬性的新值。

**注意**  
在將現有`ENCRYPT_AND_SIGN`屬性變更為 `SIGN_ONLY`或 之前，請仔細考慮您的安全需求`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。任何可存放敏感資料的屬性都應該加密。

**使用標註的資料類別**  
如果您使用 定義屬性動作`TableSchema`，請更新現有的屬性，以在註釋的資料類別中包含 `@DynamoDBEncryptionSignOnly`或 `@DynamoDBEncryptionSignAndIncludeInEncryptionContext`註釋。

**使用物件模型**  
如果您手動定義屬性動作，請將與現有屬性相關聯的屬性動作從 更新`ENCRYPT_AND_SIGN`為物件模型`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`中的 `SIGN_ONLY`或 。

## 將現有 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性變更為 `ENCRYPT_AND_SIGN`
<a name="ddb-sign-to-encrypt"></a>

若要將現有 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性變更為 `ENCRYPT_AND_SIGN`，您必須更新您的屬性動作。部署更新之後，用戶端將能夠驗證寫入 屬性的現有值，並將加密和簽署寫入 屬性的新值。

**使用標註的資料類別**  
如果您使用 定義屬性動作`TableSchema`，請從現有屬性中移除 `@DynamoDBEncryptionSignOnly`或 `@DynamoDBEncryptionSignAndIncludeInEncryptionContext`註釋。

**使用物件模型**  
如果您手動定義屬性動作，請在物件模型`ENCRYPT_AND_SIGN`中將與屬性相關聯的屬性動作從 `SIGN_ONLY`或 更新`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`為 。

## 新增`DO_NOTHING`屬性
<a name="ddb-add-unauth-attribute"></a>

若要降低新增`DO_NOTHING`屬性時的錯誤風險，建議您在命名`DO_NOTHING`屬性時指定不同的字首，然後使用該字首定義[允許的未簽署屬性](ddb-java-using.md#allowed-unauth)。

您無法從註釋的資料類別中移除現有的 `ENCRYPT_AND_SIGN``SIGN_ONLY`、 或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 屬性，然後將 屬性新增為`DO_NOTHING`屬性。您只能新增全新的`DO_NOTHING`屬性。

您新增`DO_NOTHING`屬性所採取的步驟，取決於您在清單中明確定義允許的未簽章屬性，還是使用字首。

**使用允許的未簽署屬性字首**  
如果您使用 定義屬性動作`TableSchema`，請使用 `@DynamoDBEncryptionDoNothing`註釋將新`DO_NOTHING`屬性新增至註釋的資料類別。如果您手動定義屬性動作，請更新您的屬性動作以包含新的屬性。請務必使用 屬性動作明確設定新`DO_NOTHING`屬性。您必須在新屬性的名稱中包含相同的不同字首。

**使用允許的未簽署屬性清單**

1. 將新`DO_NOTHING`屬性新增至允許的未簽章屬性清單，並部署更新的清單。

1. 從**步驟 1** 部署變更。

   在變更傳播到需要讀取此資料的所有主機之前，您無法繼續進行**步驟 3**。

1. 將新的`DO_NOTHING`屬性新增至您的屬性動作。

   1. 如果您使用 定義屬性動作`TableSchema`，請使用 `@DynamoDBEncryptionDoNothing`註釋將新`DO_NOTHING`屬性新增至註釋的資料類別。

   1. 如果您手動定義屬性動作，請更新您的屬性動作以包含新的屬性。請務必使用 屬性動作明確設定新`DO_NOTHING`屬性。

1. 從**步驟 3** 部署變更。

## 將現有`SIGN_ONLY`屬性變更為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`
<a name="ddb-signOnly-to-signInclude"></a>

若要將現有`SIGN_ONLY`屬性變更為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，您必須更新您的屬性動作。部署更新之後，用戶端將能夠驗證寫入 屬性的現有值，並將繼續簽署寫入 屬性的新值。寫入 屬性的新值將包含在[加密內容](concepts.md#encryption-context)中。

如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

**使用標註的資料類別**  
如果您使用 定義屬性動作`TableSchema`，請將與屬性相關聯的屬性動作從 更新`@DynamoDBEncryptionSignOnly`為 `@DynamoDBEncryptionSignAndIncludeInEncryptionContext`。

**使用物件模型**  
如果您手動定義屬性動作，請在物件模型`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`中將與屬性相關聯的屬性動作從 更新`SIGN_ONLY`為 。

## 將現有`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性變更為 `SIGN_ONLY`
<a name="ddb-signInclude-to-signOnly"></a>

若要將現有`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性變更為 `SIGN_ONLY`，您必須更新您的屬性動作。部署更新之後，用戶端將能夠驗證寫入 屬性的現有值，並將繼續簽署寫入 屬性的新值。寫入 屬性的新值不會包含在[加密內容](concepts.md#encryption-context)中。

在將現有`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性變更為 之前`SIGN_ONLY`，請仔細考慮您的更新如何影響[分支金鑰 ID 供應商](use-hierarchical-keyring.md#branch-key-id-supplier)的功能。

**使用標註的資料類別**  
如果您使用 定義屬性動作`TableSchema`，請將與屬性相關聯的屬性動作從 更新`@DynamoDBEncryptionSignAndIncludeInEncryptionContext`為 `@DynamoDBEncryptionSignOnly`。

**使用物件模型**  
如果您手動定義屬性動作，請在物件模型`SIGN_ONLY`中將與屬性相關聯的屬性動作從 更新`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`為 。

# AWS 適用於 DynamoDB 的資料庫加密 SDK 可用的程式設計語言
<a name="ddb-programming-languages"></a>

適用於 DynamoDB 的 AWS Database Encryption SDK 適用於下列程式設計語言。語言專屬的程式庫有所不同，但是產生的實作都是可互通的。您可以使用一種語言實作加密，並使用另一種語言進行解密。互通性可能受到語言限制。如果是這樣，這些限制會在語言實作的主題中加以說明。

**Topics**
+ [Java](ddb-java.md)
+ [.NET](ddb-net.md)
+ [Rust](ddb-rust.md)

# Java
<a name="ddb-java"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

本主題說明如何安裝和使用適用於 DynamoDB 的 Java 用戶端加密程式庫 3.*x* 版。如需使用適用於 DynamoDB 的 AWS 資料庫加密開發套件進行程式設計的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [Java 範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples)。

**注意**  
下列主題著重於 DynamoDB 的 Java 用戶端加密程式庫 3.*x* 版。  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。 AWS Database Encryption SDK 繼續支援[舊版 DynamoDB Encryption Client 版本](legacy-dynamodb-encryption-client.md)。

**Topics**
+ [先決條件](#ddb-java-prerequisites)
+ [安裝](#ddb-java-installation)
+ [使用 Java 用戶端](ddb-java-using.md)
+ [Java 範例](ddb-java-examples.md)
+ [將 3.x 版新增至現有資料表](ddb-java-config-existing-table.md)
+ [遷移至 3.x 版](ddb-java-migrate.md)

## 先決條件
<a name="ddb-java-prerequisites"></a>

在為 DynamoDB 安裝 Java 用戶端加密程式庫的 3.*x* 版之前，請確定您有下列先決條件。

**Java 開發環境**  
您會需要 Java 8 或更新版本。在 Oracle 網站上，移至 [Java SE 下載](https://www.oracle.com/java/technologies/downloads/)，然後下載並安裝 Java SE 開發套件 (JDK)。  
如果您使用 Oracle JDK，您還必須下載並安裝 [Java Cryptography Extension (JCE) Unlimited Strength 管轄權政策檔案](http://www.oracle.com/java/technologies/javase-jce8-downloads.html)。

**AWS SDK for Java 2.x**  
適用於 DynamoDB 的 AWS 資料庫加密 SDK 需要 的 [DynamoDB 增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)模組 AWS SDK for Java 2.x。您可以安裝整個 SDK 或只安裝這個模組。  
如需更新 版本的相關資訊 適用於 Java 的 AWS SDK，請參閱[從 1.x 版遷移至 2.x 版 適用於 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html)。  
可透過 Apache Maven 適用於 Java 的 AWS SDK 取得。您可以宣告整個 適用於 Java 的 AWS SDK或僅`dynamodb-enhanced`模組的相依性。  

**適用於 Java 的 AWS SDK 使用 Apache Maven 安裝**
+ 若要[匯入整個 適用於 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#build-the-entire-sdk-into-your-project) 作為相依性，請在 `pom.xml` 檔案中宣告它。
+ 若要僅針對 中的 Amazon DynamoDB 模組建立相依性 適用於 Java 的 AWS SDK，請遵循[指定特定模組](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#modules-dependencies)的指示。將 `groupId` 設定為 `software.amazon.awssdk`，將 `artifactID`設定為 `dynamodb-enhanced`。
**注意**  
如果您使用 AWS KMS keyring AWS KMS 或階層 keyring，您也需要為 AWS KMS 模組建立相依性。將 `groupId` 設定為 `software.amazon.awssdk`，將 `artifactID`設定為 `kms`。

## 安裝
<a name="ddb-java-installation"></a>

您可以使用下列方式安裝適用於 DynamoDB 的 Java 用戶端加密程式庫 3.*x* 版。

**使用 Apache Maven**  
Amazon DynamoDB Encryption Client for Java 可透過 [Apache Maven](https://maven.apache.org/) 使用下列相依性定義。  

```
<dependency>
  <groupId>software.amazon.cryptography</groupId>
  <artifactId>aws-database-encryption-sdk-dynamodb</artifactId>
  <version>version-number</version>
</dependency>
```

**使用 Gradle Kotlin**  
您可以使用 [Gradle](https://gradle.org/) 在適用於 Java 的 Amazon DynamoDB 加密用戶端上宣告相依性，方法是將以下內容新增至 Gradle 專案的*相依性*區段。  

```
implementation("software.amazon.cryptography:aws-database-encryption-sdk-dynamodb:version-number")
```

**手動**  
若要安裝 DynamoDB 的 Java 用戶端加密程式庫，請複製或下載 [aws-database-encryption-sdk-dynamodb](https://github.com/aws/aws-database-encryption-sdk-dynamodb/) GitHub 儲存庫。

安裝軟體開發套件後，請先查看本指南中的範例程式碼，以及 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [Java 範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples)。

# 使用適用於 DynamoDB 的 Java 用戶端加密程式庫
<a name="ddb-java-using"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

本主題說明 DynamoDB Java 用戶端加密程式庫 3.*x* 版中的一些函數和協助程式類別。

如需使用適用於 DynamoDB 的 Java 用戶端加密程式庫進行程式設計的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [Java](java-examples.md) [範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples)。

**Topics**
+ [項目加密程式](#ddb-item-encryptors)
+ [屬性動作](#ddb-attribute-actions)
+ [加密組態](#ddb-config-encrypt)
+ [更新項目](#ddb-update-items)
+ [解密已簽章的集合](#ddb-java-signed-sets)

## 項目加密程式
<a name="ddb-item-encryptors"></a>

DynamoDB AWS 資料庫加密開發套件的核心是項目加密程式。您可以使用適用於 DynamoDB 的 Java 用戶端加密程式庫 3.*x* 版，以下列方式加密、簽署、驗證和解密 DynamoDB 資料表項目。

**DynamoDB 增強型用戶端**  
您可以使用 設定 [DynamoDB 增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)`DynamoDbEncryptionInterceptor`，以使用 DynamoDB `PutItem`請求自動加密和簽署用戶端的項目。使用 DynamoDB 增強型用戶端，您可以使用[註釋的資料類別](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html#ddb-en-client-gs-tableschema-anno-bean)定義屬性動作。我們建議您盡可能使用 DynamoDB 增強型用戶端。  
DynamoDB 增強型用戶端不支援[可搜尋加密](searchable-encryption.md)。  
 AWS Database Encryption SDK 不支援[巢狀屬性](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-adv-features-nested.html)上的註釋。

**低階 DynamoDB API**  
您可以使用 [設定低階 DynamoDB API](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html)`DynamoDbEncryptionInterceptor`，以使用 DynamoDB `PutItem`請求在用戶端自動加密和簽署項目。  
您必須使用低階 DynamoDB API 來使用[可搜尋加密](searchable-encryption.md)。

**較低層級 `DynamoDbItemEncryptor`**  
較低層級會`DynamoDbItemEncryptor`直接加密和簽署或解密，並驗證您的資料表項目，而無需呼叫 DynamoDB。它不會發出 DynamoDB `PutItem`或 `GetItem` 請求。例如，您可以使用較低層級`DynamoDbItemEncryptor`直接解密和驗證您已擷取的 DynamoDB 項目。  
較低層級`DynamoDbItemEncryptor`不支援[可搜尋的加密](searchable-encryption.md)。

## DynamoDB AWS 資料庫加密 SDK 中的屬性動作
<a name="ddb-attribute-actions"></a>

[屬性動作](concepts.md#crypt-actions)會決定哪些屬性值會加密和簽署，哪些屬性值只會簽署、哪些屬性值會簽署並包含在加密內容中，以及哪些屬性值會被忽略。

**注意**  
若要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`密碼編譯動作，您必須使用 3.3 版或更新版本的 AWS 資料庫加密 SDK。將[您的資料模型更新](ddb-update-data-model.md)為包含 之前，將新版本部署至所有讀者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

如果您使用低階 DynamoDB API 或低階 `DynamoDbItemEncryptor`，您必須手動定義屬性動作。如果您使用 DynamoDB 增強型用戶端，您可以手動定義屬性動作，也可以使用註釋的資料類別來[產生 `TableSchema`](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html)。為了簡化組態程序，我們建議您使用標註的資料類別。當您使用標註的資料類別時，只需要建立物件模型一次。

**注意**  
定義屬性動作之後，您必須定義要從簽章中排除哪些屬性。為了在未來更容易新增未簽章的屬性，我們建議您選擇不同的字首 （例如 "`:`") 來識別未簽章的屬性。在標示`DO_NOTHING`為定義 DynamoDB 結構描述和屬性動作的所有屬性的屬性名稱中包含此字首。

### 使用標註的資料類別
<a name="ddb-attribute-actions-annotated-data-class"></a>

使用[標註的資料類別](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html#ddb-en-client-gs-tableschema-anno-bean)，透過 DynamoDB 增強型用戶端 和 指定屬性動作`DynamoDbEncryptionInterceptor`。適用於 DynamoDB 的 AWS Database Encryption SDK 使用[標準 DynamoDB 屬性註釋](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html)來定義屬性類型，以判斷如何保護屬性。除了主要索引鍵 (簽署但不加密) 以外，所有屬性都預設會進行加密和簽署。

**注意**  
若要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`密碼編譯動作，您必須使用 3.3 版或更新版本的 AWS 資料庫加密 SDK。將[您的資料模型更新](ddb-update-data-model.md)為包含 之前，將新版本部署至所有讀者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

如需 DynamoDB 增強型用戶端註釋的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [SimpleClass.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java)。 DynamoDB 

根據預設，主索引鍵屬性會經過簽署但未加密 (`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 Database Encryption SDK 不支援[巢狀屬性](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-adv-features-nested.html)上的註釋。

下列範例顯示用於定義 `ENCRYPT_AND_SIGN`、 `SIGN_ONLY`和 `DO_NOTHING`屬性動作的註釋。如需顯示用於定義 之註釋的範例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，請參閱 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/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);
```

### 手動定義屬性動作
<a name="ddb-attribute-actions-manual"></a>

若要手動指定屬性動作，請建立名稱值對代表屬性名稱和指定動作的`Map`物件。

指定 `ENCRYPT_AND_SIGN` 來加密和簽署 屬性。指定 `SIGN_ONLY`簽署但不加密 屬性。指定 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`以簽署 屬性，並將其包含在加密內容中。如果沒有也簽署屬性，則無法加密該屬性。指定 `DO_NOTHING` 忽略 屬性。

分割區和排序屬性必須是 `SIGN_ONLY`或 `SIGN_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。將[您的資料模型更新](ddb-update-data-model.md)為包含 之前，將新版本部署至所有讀者`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);
```

## DynamoDB AWS 資料庫加密 SDK 中的加密組態
<a name="ddb-config-encrypt"></a>

使用 AWS 資料庫加密 SDK 時，您必須明確定義 DynamoDB 資料表的加密組態。加密組態中所需的值取決於您是手動或使用註釋的資料類別來定義屬性動作。

下列程式碼片段使用 DynamoDB 增強型用戶端 [https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html)和由不同字首定義的允許未簽署屬性來定義 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 資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Restore.Tutorial.html)之後變更，邏輯資料表名稱可確保解密操作仍可辨識資料表。

**允許的未簽署屬性**  
在您的屬性動作`DO_NOTHING`中標記的屬性。  
允許的未簽章屬性會告知用戶端，哪些屬性會從簽章中排除。用戶端假設所有其他屬性都包含在簽章中。然後，在解密記錄時，用戶端會決定需要驗證哪些屬性，以及從您指定的允許未簽署屬性中忽略哪些屬性。您無法從允許的未簽署屬性中移除屬性。  
您可以建立列出所有屬性的陣列，明確定義允許的未簽章`DO_NOTHING`屬性。您也可以在命名`DO_NOTHING`屬性時指定不同的字首，並使用字首告訴用戶端哪些屬性未簽署。我們強烈建議指定不同的字首，因為它可簡化未來新增`DO_NOTHING`屬性的程序。如需詳細資訊，請參閱[更新資料模型](ddb-update-data-model.md)。  
如果您未為所有`DO_NOTHING`屬性指定字首，您可以設定`allowedUnsignedAttributes`陣列，明確列出用戶端在解密時遇到這些屬性時應取消簽署的所有屬性。只有在絕對必要時，才應該明確定義允許的未簽署屬性。

**搜尋組態 （選用）**  
`SearchConfig` 定義[信標版本](using-beacons.md#beacon-version)。  
`SearchConfig` 必須指定 才能使用[可搜尋加密](searchable-encryption.md)或[簽章的信標](configure.md#signed-beacons)。

**演算法套件 （選用）**  
`algorithmSuiteId` 定義 AWS 資料庫加密 SDK 使用的演算法套件。  
除非您明確指定替代演算法套件，否則 AWS 資料庫加密 SDK 會使用[預設演算法套件](supported-algorithms.md#recommended-algorithms)。預設演算法套件使用 AES-GCM 演算法搭配金鑰衍生、[數位簽章](concepts.md#digital-sigs)和[金鑰承諾](concepts.md#key-commitment)。雖然預設演算法套件可能適用於大多數應用程式，但您可以選擇替代演算法套件。例如，某些信任模型將由沒有數位簽章的演算法套件滿足。如需有關 AWS 資料庫加密 SDK 支援的演算法套件的資訊，請參閱 [AWS 資料庫加密 SDK 中支援的演算法套件](supported-algorithms.md)。  
若要選取[不含 ECDSA 數位簽章的 AES-GCM 演算法套件](supported-algorithms.md#other-algorithms)，請在資料表加密組態中包含下列程式碼片段。  

```
.algorithmSuiteId(
    DBEAlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384)
```

## 使用 AWS 資料庫加密 SDK 更新項目
<a name="ddb-update-items"></a>

 AWS Database Encryption SDK 不支援已加密或簽署之項目的 [ddb：UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)。若要更新加密或簽署的項目，您必須使用 [ddb：PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)。當您在`PutItem`請求中指定與現有項目相同的主索引鍵時，新項目會完全取代現有項目。您也可以在更新項目後，使用 [CLOBBER](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.SaveBehavior.html#CLOBBER) 在儲存時清除和取代所有屬性。

## 解密已簽章的集合
<a name="ddb-java-signed-sets"></a>

在 AWS 資料庫加密 SDK 的 3.0.0 和 3.1.0 版中，如果您將[集合類型](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes.SetTypes)屬性定義為 `SIGN_ONLY`，則集合的值會依提供的順序進行標準化。DynamoDB 不會保留集合的順序。因此，包含集合的項目的簽章驗證可能會失敗。簽章驗證會在以與提供給 AWS 資料庫加密 SDK 的不同順序傳回集合的值時失敗，即使集合屬性包含相同的值。

**注意**  
 AWS 資料庫加密 SDK 的 3.1.1 版和更新版本會將所有集合類型屬性的值標準化，以便以寫入 DynamoDB 的相同順序讀取這些值。

如果簽章驗證失敗，解密操作會失敗，並傳回下列錯誤訊息。


|  | 
| --- |
| software.amazon.cryptography.dbencryptionsdk.structuredencryption.model.StructuredEncryptionException：沒有相符的收件人標籤。 | 

如果您收到上述錯誤訊息，並認為您嘗試解密的項目包含使用 3.0.0 或 3.1.0 版簽署的集合，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb-java 儲存庫的 [DecryptWithPermute](https://github.com/aws/aws-database-encryption-sdk-dynamodb-java/tree/v3.1.1/DecryptWithPermute) 目錄，以取得如何成功驗證集合的詳細資訊。

# Java 範例
<a name="ddb-java-examples"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

下列範例示範如何使用適用於 DynamoDB 的 Java 用戶端加密程式庫來保護應用程式中的資料表項目。您可以在 GitHub 的 aws-database-encryption-sdk-dynamodb 儲存庫的 [Java 範例中](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples)找到更多範例 （並自行提供）。

下列範例示範如何在未填入的新 Amazon DynamoDB 資料表中設定 DynamoDB 的 Java 用戶端加密程式庫。如果您想要設定現有的 Amazon DynamoDB 資料表進行用戶端加密，請參閱 [將 3.x 版新增至現有資料表](ddb-java-config-existing-table.md)。

**Topics**
+ [使用 DynamoDB 增強型用戶端](#ddb-java-enhanced-client-example)
+ [使用低階 DynamoDB API](#ddb-java-lowlevel-API-example)
+ [使用較低層級的 DynamoDbItemEncryptor](#ddb-java-itemencryptor)

## 使用 DynamoDB 增強型用戶端
<a name="ddb-java-enhanced-client-example"></a>

下列範例示範如何使用 DynamoDB 增強型用戶端和 `DynamoDbEncryptionInterceptor`搭配 [AWS KMS keyring](use-kms-keyring.md) 來加密 DynamoDB 資料表項目，做為 DynamoDB API 呼叫的一部分。

您可以搭配 DynamoDB 增強型用戶端使用任何支援的 [keyring](keyrings.md)，但我們建議您盡可能使用其中一個 AWS KMS keyring。

**注意**  
DynamoDB 增強型用戶端不支援[可搜尋加密](searchable-encryption.md)。使用 `DynamoDbEncryptionInterceptor`搭配低階 DynamoDB API，以使用可搜尋的加密。

**請參閱完整的程式碼範例**：[EnhancedPutGetExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/EnhancedPutGetExample.java)

**步驟 1：建立 AWS KMS keyring**  
下列範例使用 `CreateAwsKmsMrkMultiKeyring`建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法可確保 keyring 可正確處理單一區域和多區域金鑰。  

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步驟 2：從註釋的資料類別建立資料表結構描述**  
下列範例使用註釋的資料類別來建立 `TableSchema`。  
此範例假設已使用 [SimpleClass.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java) 定義註釋的資料類別和屬性動作。如需註釋屬性動作的更多指引，請參閱 [使用標註的資料類別](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。  
 AWS Database Encryption SDK 不支援[巢狀屬性](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-adv-features-nested.html)上的註釋。

```
final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);
```

**步驟 3：定義從簽章中排除哪些屬性**  
下列範例假設所有`DO_NOTHING`屬性共用不同的字首「`:`」，並使用字首定義允許的未簽章屬性。用戶端假設任何具有「`:`」字首的屬性名稱都會從簽章中排除。如需詳細資訊，請參閱[Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步驟 4：建立加密組態**  
下列範例定義代表 DynamoDB 資料表加密組態的`tableConfigs`映射。  
此範例指定 DynamoDB 資料表名稱做為[邏輯資料表名稱](ddb-java-using.md#logical-table-name)。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。如需詳細資訊，請參閱[DynamoDB AWS 資料庫加密 SDK 中的加密組態](ddb-java-using.md#ddb-config-encrypt)。  
若要使用[可搜尋加密](searchable-encryption.md)或[已簽章的信標](configure.md#signed-beacons)，您還必須在加密組態[`SearchConfig`](ddb-java-using.md#ddb-search-config)中包含 。

```
final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
tableConfigs.put(ddbTableName,
    DynamoDbEnhancedTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .schemaOnEncrypt(tableSchema)
        .build());
```

**步驟 5：建立 `DynamoDbEncryptionInterceptor`**  
下列範例會使用**步驟 4 **`DynamoDbEncryptionInterceptor``tableConfigs`中的 建立新的 。  

```
final DynamoDbEncryptionInterceptor interceptor =
    DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
        CreateDynamoDbEncryptionInterceptorInput.builder()
            .tableEncryptionConfigs(tableConfigs)
            .build()
    );
```

**步驟 6：建立新的 AWS SDK DynamoDB 用戶端**  
下列範例使用步驟 5 `interceptor`中的 建立新的 AWS SDK DynamoDB 用戶端。 ****  

```
final DynamoDbClient ddb = DynamoDbClient.builder()
        .overrideConfiguration(
                ClientOverrideConfiguration.builder()
                       .addExecutionInterceptor(interceptor)
                       .build())
        .build();
```

**步驟 7：建立 DynamoDB 增強型用戶端並建立資料表**  
下列範例使用**步驟 6** 中建立的 AWS SDK DynamoDB 用戶端建立 DynamoDB 增強型用戶端，並使用註釋的資料類別建立資料表。  

```
final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
        .dynamoDbClient(ddb)
        .build();
final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
```

**步驟 8：加密和簽署資料表項目**  
下列範例會使用 DynamoDB 增強型用戶端將項目放入 DynamoDB 資料表。項目在傳送至 DynamoDB 之前，會先加密並簽署用戶端。  

```
final SimpleClass item = new SimpleClass();
item.setPartitionKey("EnhancedPutGetExample");
item.setSortKey(0);
item.setAttribute1("encrypt and sign me!");
item.setAttribute2("sign me!");
item.setAttribute3("ignore me!");

table.putItem(item);
```

## 使用低階 DynamoDB API
<a name="ddb-java-lowlevel-API-example"></a>

下列範例示範如何使用低階 DynamoDB API 搭配 [AWS KMS keyring](use-kms-keyring.md)，以自動加密和簽署具有 DynamoDB `PutItem`請求的用戶端項目。

您可以使用任何支援的 [keyring](keyrings.md)，但我們建議您盡可能使用其中一個 AWS KMS keyring。

**請參閱完整的程式碼範例**：[BasicPutGetExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/BasicPutGetExample.java)

**步驟 1：建立 AWS KMS keyring**  
下列範例使用 `CreateAwsKmsMrkMultiKeyring`建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法可確保 keyring 可正確處理單一區域和多區域金鑰。  

```
final MaterialProviders matProv = MaterialProviders.builder()
         .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
         .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步驟 2：設定屬性動作**  
下列範例定義代表資料表項目範例[屬性動作](concepts.md#crypt-actions)的`attributeActionsOnEncrypt`映射。  
下列範例不會將任何屬性定義為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>();
// The partition attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_ONLY); 
// The sort attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_ONLY); 
attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY);
attributeActionsOnEncrypt.put(":attribute3", CryptoAction.DO_NOTHING);
```

**步驟 3：定義從簽章中排除哪些屬性**  
下列範例假設所有`DO_NOTHING`屬性共用不同的字首「`:`」，並使用字首定義允許的未簽章屬性。用戶端假設任何具有「`:`」字首的屬性名稱都會從簽章中排除。如需詳細資訊，請參閱[Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步驟 4：定義 DynamoDB 資料表加密組態**  
下列範例會定義代表此 DynamoDB 資料表加密組態的`tableConfigs`映射。  
此範例會將 DynamoDB 資料表名稱指定為[邏輯資料表名稱](ddb-java-using.md#logical-table-name)。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。如需詳細資訊，請參閱[DynamoDB AWS 資料庫加密 SDK 中的加密組態](ddb-java-using.md#ddb-config-encrypt)。  
若要使用[可搜尋加密](searchable-encryption.md)或[已簽章的信標](configure.md#signed-beacons)，您還必須在加密組態[`SearchConfig`](ddb-java-using.md#ddb-search-config)中包含 。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .attributeActionsOnEncrypt(attributeActionsOnEncrypt)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .build();
tableConfigs.put(ddbTableName, config);
```

**步驟 5：建立 `DynamoDbEncryptionInterceptor`**  
下列範例`DynamoDbEncryptionInterceptor`使用步驟 4 `tableConfigs`中的 建立 。 ****  

```
DynamoDbEncryptionInterceptor interceptor = DynamoDbEncryptionInterceptor.builder()
        .config(DynamoDbTablesEncryptionConfig.builder()
                .tableEncryptionConfigs(tableConfigs)
                .build())
        .build();
```

**步驟 6：建立新的 AWS SDK DynamoDB 用戶端**  
下列範例使用步驟 5 `interceptor`中的 建立新的 AWS SDK DynamoDB 用戶端。 ****  

```
final DynamoDbClient ddb = DynamoDbClient.builder()
        .overrideConfiguration(
                ClientOverrideConfiguration.builder()
                       .addExecutionInterceptor(interceptor)
                       .build())
        .build();
```

**步驟 7：加密並簽署 DynamoDB 資料表項目**  
下列範例定義代表範例資料表項目的`item`映射，並將該項目放在 DynamoDB 資料表中。項目會在傳送至 DynamoDB 之前加密並簽署用戶端。  

```
final HashMap<String, AttributeValue> item = new HashMap<>();
item.put("partition_key", AttributeValue.builder().s("BasicPutGetExample").build());
item.put("sort_key", AttributeValue.builder().n("0").build());
item.put("attribute1", AttributeValue.builder().s("encrypt and sign me!").build());
item.put("attribute2", AttributeValue.builder().s("sign me!").build());
item.put(":attribute3", AttributeValue.builder().s("ignore me!").build());

final PutItemRequest putRequest = PutItemRequest.builder()
        .tableName(ddbTableName)
        .item(item)
        .build();

final PutItemResponse putResponse = ddb.putItem(putRequest);
```

## 使用較低層級的 DynamoDbItemEncryptor
<a name="ddb-java-itemencryptor"></a>

下列範例示範如何使用較低層級`DynamoDbItemEncryptor`的 [AWS KMS keyring](use-kms-keyring.md) 來直接加密和簽署資料表項目。`DynamoDbItemEncryptor` 不會將項目放在 DynamoDB 資料表中。

您可以搭配 DynamoDB 增強型用戶端使用任何支援的 [keyring](keyrings.md)，但我們建議您盡可能使用其中一個 AWS KMS keyring。

**注意**  
較低層級`DynamoDbItemEncryptor`不支援[可搜尋的加密](searchable-encryption.md)。使用 `DynamoDbEncryptionInterceptor`搭配低階 DynamoDB API，以使用可搜尋的加密。

**請參閱完整的程式碼範例**：I [ItemEncryptDecryptExample.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/itemencryptor/ItemEncryptDecryptExample.java)

**步驟 1：建立 AWS KMS keyring**  
下列範例使用 `CreateAwsKmsMrkMultiKeyring`建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法可確保 keyring 可正確處理單一區域和多區域金鑰。  

```
final MaterialProviders matProv = MaterialProviders.builder()
         .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
         .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步驟 2：設定屬性動作**  
下列範例定義代表資料表項目範例[屬性動作](concepts.md#crypt-actions)的`attributeActionsOnEncrypt`映射。  
下列範例不會將任何屬性定義為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
final Map<String, CryptoAction> attributeActionsOnEncrypt = new HashMap<>();
// The partition attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("partition_key", CryptoAction.SIGN_ONLY); 
// The sort attribute must be SIGN_ONLY
attributeActionsOnEncrypt.put("sort_key", CryptoAction.SIGN_ONLY); 
attributeActionsOnEncrypt.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
attributeActionsOnEncrypt.put("attribute2", CryptoAction.SIGN_ONLY);
attributeActionsOnEncrypt.put(":attribute3", CryptoAction.DO_NOTHING);
```

**步驟 3：定義從簽章中排除哪些屬性**  
下列範例假設所有`DO_NOTHING`屬性共用不同的字首「`:`」，並使用字首定義允許的未簽章屬性。用戶端假設任何具有「`:`」字首的屬性名稱都會從簽章中排除。如需詳細資訊，請參閱[Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**步驟 4：定義`DynamoDbItemEncryptor`組態**  
下列範例定義 的組態`DynamoDbItemEncryptor`。  
此範例會將 DynamoDB 資料表名稱指定為[邏輯資料表名稱](ddb-java-using.md#logical-table-name)。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。如需詳細資訊，請參閱[DynamoDB AWS 資料庫加密 SDK 中的加密組態](ddb-java-using.md#ddb-config-encrypt)。  

```
final DynamoDbItemEncryptorConfig config = DynamoDbItemEncryptorConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .attributeActionsOnEncrypt(attributeActionsOnEncrypt)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .build();
```

**步驟 5：建立 `DynamoDbItemEncryptor`**  
下列範例`DynamoDbItemEncryptor`使用**步驟 4 **`config`中的 建立新的 。  

```
final DynamoDbItemEncryptor itemEncryptor = DynamoDbItemEncryptor.builder()
        .DynamoDbItemEncryptorConfig(config)
        .build();
```

**步驟 6：直接加密和簽署資料表項目**  
下列範例使用 直接加密和簽署項目`DynamoDbItemEncryptor`。`DynamoDbItemEncryptor` 不會將項目放在 DynamoDB 資料表中。  

```
final Map<String, AttributeValue> originalItem = new HashMap<>();
originalItem.put("partition_key", AttributeValue.builder().s("ItemEncryptDecryptExample").build());
originalItem.put("sort_key", AttributeValue.builder().n("0").build());
originalItem.put("attribute1", AttributeValue.builder().s("encrypt and sign me!").build());
originalItem.put("attribute2", AttributeValue.builder().s("sign me!").build());
originalItem.put(":attribute3", AttributeValue.builder().s("ignore me!").build());

final Map<String, AttributeValue> encryptedItem = itemEncryptor.EncryptItem(
        EncryptItemInput.builder()
                .plaintextItem(originalItem)
                .build()
).encryptedItem();
```

# 設定現有的 DynamoDB 資料表以使用適用於 DynamoDB 的 AWS 資料庫加密 SDK
<a name="ddb-java-config-existing-table"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

使用適用於 DynamoDB 的 Java 用戶端加密程式庫 3.*x* 版，您可以將現有的 Amazon DynamoDB 資料表設定為用戶端加密。本主題提供將 3.*x* 版新增至現有填入的 DynamoDB 資料表之三個步驟的指引。

**先決條件**  
適用於 DynamoDB 的 Java 用戶端加密程式庫版本 3.*x* 需要 提供的 [DynamoDB 增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html) AWS SDK for Java 2.x 。如果您仍然使用 [DynamoDBMapper](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html)，您必須遷移至 AWS SDK for Java 2.x ，才能使用 DynamoDB 增強型用戶端。

 遵循[從 1.x 版遷移至 2.x 版 適用於 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html)的指示。

然後，遵循[使用 DynamoDB 增強型用戶端 API 開始使用](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started.html)的指示。

將資料表設定為使用 DynamoDB 的 Java 用戶端加密程式庫之前，您需要`TableSchema`[使用註釋的資料類別產生 ，](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html#ddb-en-client-gs-tableschema-anno-bean)並[建立增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

## 步驟 1：準備讀取和寫入加密的項目
<a name="ddb-java-add-step1"></a>

請完成下列步驟，以準備您的 AWS Database Encryption SDK 用戶端讀取和寫入加密的項目。部署下列變更後，用戶端將繼續讀取和寫入純文字項目。它不會加密或簽署寫入資料表的任何新項目，但一旦加密項目出現，它就能夠立即解密。這些變更可讓用戶端開始[加密新項目](#ddb-java-add-step2)。您必須先將下列變更部署到每個讀取器，才能繼續下一個步驟。

**1. 定義[您的屬性動作](concepts.md#crypt-actions)**  
更新您的註釋資料類別，以包含屬性動作，這些動作會定義哪些屬性值將加密和簽署、哪些屬性值只會簽署，以及哪些屬性值會被忽略。  
如需 DynamoDB 增強型用戶端註釋的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [SimpleClass.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass.java)。 DynamoDB   
根據預設，主要金鑰屬性會經過簽署但未加密 (`SIGN_ONLY`)，而所有其他屬性則會經過加密和簽署 (`ENCRYPT_AND_SIGN`)。若要指定例外狀況，請使用 DynamoDB 的 Java 用戶端加密程式庫中定義的加密註釋。例如，如果您希望特定屬性只簽署 ，請使用 `@DynamoDbEncryptionSignOnly`註釋。如果您想要在加密內容中簽署並包含特定屬性，請使用 `@DynamoDbEncryptionSignAndIncludeInEncryptionContext`註釋。如果您想要不簽署或加密特定屬性 (`DO_NOTHING`)，請使用 `@DynamoDbEncryptionDoNothing`註釋。  
如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如需顯示用於定義 之註釋的範例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，請參閱 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass4.java)。
如需註釋範例，請參閱 [使用標註的資料類別](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。

**2. 定義將從簽章中排除哪些屬性**  
下列範例假設所有`DO_NOTHING`屬性共用不同的字首「`:`」，並使用字首定義允許的未簽章屬性。用戶端將假設具有「`:`」字首的任何屬性名稱已從簽章中排除。如需詳細資訊，請參閱[Allowed unsigned attributes](ddb-java-using.md#allowed-unauth)。  

```
final String unsignedAttrPrefix = ":";
```

**3. 建立 [keyring](keyrings.md)**  
下列範例會建立 [AWS KMS keyring](use-kms-keyring.md)。 AWS KMS keyring 使用對稱加密或非對稱 RSA AWS KMS keys 來產生、加密和解密資料金鑰。  
此範例使用 `CreateMrkMultiKeyring`建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法可確保 keyring 可正確處理單一區域和多區域金鑰。  

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyId)
        .build();
final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**4. 定義 DynamoDB 資料表加密組態 **  
下列範例會定義代表此 DynamoDB 資料表加密組態的`tableConfigs`映射。  
此範例指定 DynamoDB 資料表名稱做為[邏輯資料表名稱](ddb-java-using.md#logical-table-name)。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。如需詳細資訊，請參閱[DynamoDB AWS 資料庫加密 SDK 中的加密組態](ddb-java-using.md#ddb-config-encrypt)。  
您必須指定 `FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT`做為純文字覆寫。此政策會繼續讀取和寫入純文字項目、讀取加密項目，以及準備用戶端寫入加密項目。  

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .plaintextOverride(PlaintextOverride.FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

**5. 建立 `DynamoDbEncryptionInterceptor`**  
下列範例`DynamoDbEncryptionInterceptor`使用步驟 3 `tableConfigs`中的 建立 。 ****  

```
DynamoDbEncryptionInterceptor interceptor = DynamoDbEncryptionInterceptor.builder()
        .config(DynamoDbTablesEncryptionConfig.builder()
                .tableEncryptionConfigs(tableConfigs)                
                .build())
        .build();
```

## 步驟 2：寫入加密和簽章的項目
<a name="ddb-java-add-step2"></a>

在您的`DynamoDbEncryptionInterceptor`組態中更新純文字政策，以允許用戶端寫入加密和簽署的項目。部署下列變更之後，用戶端會根據您在**步驟 1 **中設定的屬性動作來加密和簽署新項目。用戶端將能夠讀取純文字項目，以及加密和簽署的項目。

繼續進行[步驟 3](#ddb-java-add-step3) 之前，您必須加密並簽署資料表中的所有現有純文字項目。您可以執行沒有單一指標或查詢來快速加密現有的純文字項目。使用對您的系統最有意義的程序。例如，您可以使用慢速掃描資料表的非同步程序，並使用您定義的屬性動作和加密組態重寫項目。若要識別資料表中的純文字項目，建議您掃描所有不包含 AWS Database Encryption SDK 在加密`aws_dbe_head`和簽署項目時新增至項目的 和 `aws_dbe_foot` 屬性的項目。

下列範例會從**步驟 1 **更新資料表加密組態。您必須使用 更新純文字覆寫`FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT`。此政策會繼續讀取純文字項目，但也會讀取和寫入加密的項目。`DynamoDbEncryptionInterceptor` 使用更新的 建立新的 `tableConfigs`。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        .plaintextOverride(PlaintextOverride.FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

## 步驟 3：僅讀取加密和已簽章的項目
<a name="ddb-java-add-step3"></a>

在您加密並簽署所有項目之後，請更新`DynamoDbEncryptionInterceptor`組態中的純文字覆寫，只允許用戶端讀取和寫入加密和簽署的項目。部署下列變更之後，用戶端會根據您在**步驟 1 **中設定的屬性動作來加密和簽署新項目。用戶端只能讀取加密和簽署的項目。

下列範例會從**步驟 2 **更新資料表加密組態。您可以使用 更新純文字覆寫，`FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT`或從組態中移除純文字政策。根據預設，用戶端只會讀取和寫入加密和簽署的項目。`DynamoDbEncryptionInterceptor` 使用更新的 建立新的 `tableConfigs`。

```
final Map<String, DynamoDbTableEncryptionConfig> tableConfigs = new HashMap<>();
final DynamoDbTableEncryptionConfig config = DynamoDbTableEncryptionConfig.builder()
        .logicalTableName(ddbTableName)
        .partitionKeyName("partition_key")
        .sortKeyName("sort_key")
        .schemaOnEncrypt(tableSchema)
        .keyring(kmsKeyring)
        .allowedUnsignedAttributePrefix(unsignedAttrPrefix)
        // Optional: you can also remove the plaintext policy from your configuration
        .plaintextOverride(PlaintextOverride.FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT)
        .build();
tableConfigs.put(ddbTableName, config);
```

# 遷移至 DynamoDB Java 用戶端加密程式庫的 3.x 版
<a name="ddb-java-migrate"></a>


****  

|  | 
| --- |
| 我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。此開發人員指南仍提供有關 [DynamoDB 加密用戶端](legacy-dynamodb-encryption-client.md)的資訊。 | 

適用於 DynamoDB 的 Java 用戶端加密程式庫 3.*x* 版是 2.*x* 程式碼基礎的主要重寫。它包含許多更新，例如新的結構化資料格式、改善的多租戶支援、無縫結構描述變更，以及可搜尋的加密支援。本主題提供如何將程式碼遷移至 3.*x* 版的指引。

## 從 1.x 版遷移至 2.x 版
<a name="ddb-java-v1-to-v2"></a>

遷移至 2.*x* 版，然後再遷移至 3.*x* 版。2.*x* 版將最近提供者的符號從 變更為 `MostRecentProvider` `CachingMostRecentProvider`。如果您目前使用適用於 DynamoDB 的 Java 用戶端加密程式庫 1.*x* 版搭配 `MostRecentProvider`符號，則必須將程式碼中的符號名稱更新為 `CachingMostRecentProvider`。如需詳細資訊，請參閱[最近供應商的更新](most-recent-provider.md#mrp-versions)。

## 從 2.x 版遷移至 3.x
<a name="ddb-java-v2-to-v3"></a>

下列程序說明如何將程式碼從 2.*x* 版遷移至 DynamoDB Java 用戶端加密程式庫的 3.*x* 版。

### 步驟 1. 準備讀取新格式的項目
<a name="ddb-java-migrate-step1"></a>

請完成下列步驟，以準備您的 AWS Database Encryption SDK 用戶端以讀取新格式的項目。部署下列變更之後，您的用戶端會繼續以與 2.*x* 版相同的方式運作。您的用戶端將繼續讀取和寫入 2.*x* 版格式的項目，但這些變更可讓用戶端準備好[讀取新格式的項目](#ddb-java-migrate-step2)。

**將 更新 適用於 Java 的 AWS SDK 至 2.x 版**  
DynamoDB 的 Java 用戶端加密程式庫版本 3.*x* 需要 [DynamoDB 增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/dynamodb-enhanced-client.html)。DynamoDB 增強型用戶端會取代先前版本中使用的 [DynamoDBMapper](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html)。若要使用增強型用戶端，您必須使用 AWS SDK for Java 2.x。  
遵循[從 1.x 版遷移至 2.x 版 適用於 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html)的指示。  
如需需要哪些 AWS SDK for Java 2.x 模組的詳細資訊，請參閱 [先決條件](ddb-java.md#ddb-java-prerequisites)。

**將用戶端設定為讀取舊版加密的項目**  
下列程序提供以下程式碼範例中示範的步驟概觀。  

1. 建立 [keyring](keyrings.md)。

   Keyring 和[密碼編譯資料管理員](concepts.md#crypt-materials-manager)會取代 DynamoDB 舊版 Java 用戶端加密程式庫中使用的密碼編譯資料提供者。
**重要**  
您在建立 keyring 時指定的包裝金鑰，必須與您在 2.*x* 版中與密碼編譯資料提供者搭配使用的包裝金鑰相同。

1. 在註釋的類別上建立資料表結構描述。

   此步驟定義了當您開始以新格式寫入項目時將使用的屬性動作。

   如需使用新 DynamoDB 增強型用戶端的指引，請參閱《 *適用於 Java 的 AWS SDK 開發人員指南*》中的[產生 `TableSchema`](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-gs-tableschema.html)。

   下列範例假設您使用新的屬性動作註釋，從 2.*x* 版更新您的註釋類別。如需註釋屬性動作的更多指引，請參閱 [使用標註的資料類別](ddb-java-using.md#ddb-attribute-actions-annotated-data-class)。
**注意**  
如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如需顯示用於定義 之註釋的範例`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，請參閱 [SimpleClass4.java](https://github.com/aws/aws-database-encryption-sdk-dynamodb//blob/main/Examples/runtimes/java/DynamoDbEncryption/src/main/java/software/amazon/cryptography/examples/enhanced/SimpleClass4.java)。

1. 定義[要從簽章中排除哪些屬性](ddb-java-using.md#allowed-unauth)。

1. 設定 2.x 版模型化類別中所設定屬性動作的明確映射。

   此步驟定義用於以舊格式寫入項目的屬性動作。

1. 設定`DynamoDBEncryptor`您在 DynamoDB 的 Java 用戶端加密程式庫 2.*x* 版中使用的 。

1. 設定舊版行為。

1. 建立 `DynamoDbEncryptionInterceptor`。

1. 建立新的 AWS SDK DynamoDB 用戶端。

1. 建立 `DynamoDBEnhancedClient`並使用模型化類別建立資料表。

   如需 DynamoDB 增強型用戶端的詳細資訊，請參閱[建立增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep1 {

    public static void MigrationStep1(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Create a Keyring.
        //    This example creates an AWS KMS Keyring that specifies the 
        //    same kmsKeyId previously used in the version 2.x configuration.
        //    It uses the 'CreateMrkMultiKeyring' method to create the 
        //    keyring, so that the keyring can correctly handle both single
        //    region and Multi-Region KMS Keys.
        //    Note that this example uses the AWS SDK for Java v2 KMS client.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        // 2. Create a Table Schema over your annotated class.
        //    For guidance on using the new attribute actions 
        //    annotations, see SimpleClass.java in the 
        //    aws-database-encryption-sdk-dynamodb GitHub repository. 
        //    All primary key attributes must be signed but not encrypted 
        //    and by default all non-primary key attributes 
        //    are encrypted and signed (ENCRYPT_AND_SIGN).
        //    If you want a particular non-primary key attribute to be signed but
        //    not encrypted, use the 'DynamoDbEncryptionSignOnly' annotation.
        //    If you want a particular attribute to be neither signed nor encrypted
        //    (DO_NOTHING), use the 'DynamoDbEncryptionDoNothing' annotation.
        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        // 3. Define which attributes the client should expect to be excluded 
        //    from the signature when reading items.
        //    This value represents all unsigned attributes across the entire 
        //    dataset.
        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");

        // 4. Configure an explicit map of the attribute actions configured 
        //    in your version 2.x modeled class.
        final Map<String, CryptoAction> legacyActions = new HashMap<>();
        legacyActions.put("partition_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("sort_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
        legacyActions.put("attribute2", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute3", CryptoAction.DO_NOTHING);

        // 5. Configure the DynamoDBEncryptor that you used in version 2.x.
        final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient();
        final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId);
        final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp);

        // 6. Configure the legacy behavior.
        //    Input the DynamoDBEncryptor and attribute actions created in 
        //    the previous steps. For Legacy Policy, use 
        //    'FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy continues to read 
        //    and write items using the old format, but will be able to read
        //    items written in the new format as soon as they appear.
        final LegacyOverride legacyOverride = LegacyOverride
                .builder()
                .encryptor(oldEncryptor)
                .policy(LegacyPolicy.FORCE_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT)
                .attributeActionsOnEncrypt(legacyActions)
                .build();

        // 7. Create a DynamoDbEncryptionInterceptor with the above configuration.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .legacyOverride(legacyOverride)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 8. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 7.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 9. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb client 
        //    created in Step 8, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

### 步驟 2. 以新格式寫入項目
<a name="ddb-java-migrate-step2"></a>

將步驟 1 的變更部署到所有讀取器之後，請完成下列步驟，以設定 AWS 資料庫加密 SDK 用戶端以新格式寫入項目。部署下列變更後，用戶端會繼續讀取舊格式的項目，並開始寫入和讀取新格式的項目。

下列程序提供以下程式碼範例中示範的步驟概觀。

1. 繼續設定 keyring、資料表結構描述、舊版屬性動作、 和 `allowedUnsignedAttributes`，`DynamoDBEncryptor`如您在[**步驟 1 **](#ddb-java-migrate-step1)中所執行。

1. 更新您的舊版行為，只使用新格式撰寫新項目。

1. 建立 `DynamoDbEncryptionInterceptor `

1. 建立新的 AWS SDK DynamoDB 用戶端。

1. 建立 `DynamoDBEnhancedClient`並使用模型化類別建立資料表。

   如需 DynamoDB 增強型用戶端的詳細資訊，請參閱[建立增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep2 {

    public static void MigrationStep2(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Continue to configure your keyring, table schema, legacy 
        //    attribute actions, allowedUnsignedAttributes, and 
        //    DynamoDBEncryptor as you did in Step 1.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");

        final Map<String, CryptoAction> legacyActions = new HashMap<>();
        legacyActions.put("partition_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("sort_key", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute1", CryptoAction.ENCRYPT_AND_SIGN);
        legacyActions.put("attribute2", CryptoAction.SIGN_ONLY);
        legacyActions.put("attribute3", CryptoAction.DO_NOTHING);

        final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient();
        final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kmsClient, kmsKeyId);
        final DynamoDBEncryptor oldEncryptor = DynamoDBEncryptor.getInstance(cmp);

        // 2. Update your legacy behavior to only write new items using the new
        //    format. 
        //    For Legacy Policy, use 'FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT'. This policy
        //    continues to read items in both formats, but will only write items
        //    using the new format.
        final LegacyOverride legacyOverride = LegacyOverride
                .builder()
                .encryptor(oldEncryptor)
                .policy(LegacyPolicy.FORBID_LEGACY_ENCRYPT_ALLOW_LEGACY_DECRYPT)
                .attributeActionsOnEncrypt(legacyActions)
                .build();

        // 3. Create a DynamoDbEncryptionInterceptor with the above configuration.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .legacyOverride(legacyOverride)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 4. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 3.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 5. Create the DynamoDbEnhancedClient using the AWS SDK DynamoDb Client created
        //    in Step 4, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

部署步驟 2 變更後，您必須使用新格式重新加密資料表中的所有舊項目，才能繼續進行[步驟 3](#ddb-java-migrate-step3)。沒有您可以執行的單一指標或查詢，以快速加密現有的項目。使用對您的系統最有意義的程序。例如，您可以使用慢速掃描資料表的非同步程序，並使用您定義的新屬性動作和加密組態重寫項目。

### 步驟 3。僅讀取和寫入新格式的項目
<a name="ddb-java-migrate-step3"></a>

使用新格式重新加密資料表中的所有項目之後，您可以從組態中移除舊版行為。完成下列步驟，將用戶端設定為僅讀取和寫入新格式的項目。

下列程序提供以下程式碼範例中示範的步驟概觀。

1. 繼續設定 keyring、資料表結構描述，`allowedUnsignedAttributes`如您在[**步驟 1 **](#ddb-java-migrate-step1)中所執行。`DynamoDBEncryptor` 從組態中移除舊版屬性動作 和 。

1. 建立 `DynamoDbEncryptionInterceptor`。

1. 建立新的 AWS SDK DynamoDB 用戶端。

1. 建立 `DynamoDBEnhancedClient`並使用模型化類別建立資料表。

   如需 DynamoDB 增強型用戶端的詳細資訊，請參閱[建立增強型用戶端](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/ddb-en-client-getting-started-dynamodbTable.html#ddb-en-client-getting-started-dynamodbTable-eclient)。

```
public class MigrationExampleStep3 {

    public static void MigrationStep3(String kmsKeyId, String ddbTableName, int sortReadValue) {
        // 1. Continue to configure your keyring, table schema,
        //    and allowedUnsignedAttributes as you did in Step 1.
        //    Do not include the configurations for the DynamoDBEncryptor or 
        //    the legacy attribute actions.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMrkMultiKeyringInput keyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
                .generator(kmsKeyId)
                .build();
        final IKeyring kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);

        final TableSchema<SimpleClass> schemaOnEncrypt = TableSchema.fromBean(SimpleClass.class);

        final List<String> allowedUnsignedAttributes = Arrays.asList("attribute3");


        // 3. Create a DynamoDbEncryptionInterceptor with the above configuration.
        //    Do not configure any legacy behavior.
        final Map<String, DynamoDbEnhancedTableEncryptionConfig> tableConfigs = new HashMap<>();
        tableConfigs.put(ddbTableName,
                DynamoDbEnhancedTableEncryptionConfig.builder()
                        .logicalTableName(ddbTableName)
                        .keyring(kmsKeyring)
                        .allowedUnsignedAttributes(allowedUnsignedAttributes)
                        .schemaOnEncrypt(tableSchema)
                        .build());
        final DynamoDbEncryptionInterceptor interceptor =
                DynamoDbEnhancedClientEncryption.CreateDynamoDbEncryptionInterceptor(
                        CreateDynamoDbEncryptionInterceptorInput.builder()
                                .tableEncryptionConfigs(tableConfigs)
                                .build()
                );

        // 4. Create a new AWS SDK DynamoDb client using the 
        //    interceptor from Step 3.
        final DynamoDbClient ddb = DynamoDbClient.builder()
                .overrideConfiguration(
                        ClientOverrideConfiguration.builder()
                                .addExecutionInterceptor(interceptor)
                                .build())
                .build();

        // 5. Create the DynamoDbEnhancedClient using the AWS SDK Client 
        //    created in Step 4, and create a table with your modeled class.
        final DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();
        final DynamoDbTable<SimpleClass> table = enhancedClient.table(ddbTableName, tableSchema);
    }
}
```

# .NET
<a name="ddb-net"></a>

本主題說明如何安裝和使用適用於 DynamoDB 的 .NET 用戶端加密程式庫的 3.*x* 版。如需使用 DynamoDB AWS 資料庫加密開發套件進行程式設計的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 .[NET 範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/)。

DynamoDB 的 .NET 用戶端加密程式庫適用於以 C\$1 和其他 .NET 程式設計語言撰寫應用程式的開發人員。Windows、macOS 和 Linux 都提供支援。

適用於 DynamoDB 的 AWS Database Encryption SDK 的所有[程式設計語言](ddb-programming-languages.md)實作皆可互通。不過， 適用於 .NET 的 SDK 不支援清單或映射資料類型的空白值。這表示如果您使用適用於 DynamoDB 的 Java 用戶端加密程式庫來撰寫包含清單或映射資料類型空白值的項目，則無法使用適用於 DynamoDB 的 .NET 用戶端加密程式庫解密和讀取該項目。

**Topics**
+ [安裝](#ddb-net-install)
+ [除錯](#ddb-net-debugging)
+ [使用 .NET 用戶端](ddb-net-using.md)
+ [.NET 範例](ddb-net-examples.md)
+ [將 3.x 版新增至現有資料表](ddb-net-config-existing-table.md)

## 安裝適用於 DynamoDB 的 .NET 用戶端加密程式庫
<a name="ddb-net-install"></a>

DynamoDB 的 .NET 用戶端加密程式庫可作為 NuGet 中的 [AWS.Cryptography.DbEncryptionSDK.DynamoDb](https://www.nuget.org/packages/AWS.Cryptography.DbEncryptionSDK.DynamoDb/) 套件。如需安裝和建置程式庫的詳細資訊，請參閱 aws-database-encryption-sdk-dynamodb 儲存庫中的 [.NET README.md](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/DynamoDbEncryption/runtimes/net/README.md) 檔案。 適用於 .NET 的 SDK 即使您未使用 AWS Key Management Service (AWS KMS) 金鑰，適用於 DynamoDB 的 .NET 用戶端加密程式庫也需要 。與 NuGet 適用於 .NET 的 SDK 套件一起安裝。

DynamoDB 的 .NET 用戶端加密程式庫版本 3.*x* 支援 .NET 6.0 和 .NET Framework net48 及更新版本。

## 使用 .NET 進行偵錯
<a name="ddb-net-debugging"></a>

DynamoDB 的 .NET 用戶端加密程式庫不會產生任何日誌。DynamoDB 的 .NET 用戶端加密程式庫中的例外狀況會產生例外狀況訊息，但不會產生堆疊追蹤。

為了協助您偵錯，請務必在 中啟用記錄 適用於 .NET 的 SDK。的日誌和錯誤訊息 適用於 .NET 的 SDK 可協助您區分 中產生的錯誤 適用於 .NET 的 SDK 與 DynamoDB 的 .NET 用戶端加密程式庫中的錯誤。如需 適用於 .NET 的 SDK 記錄的說明，請參閱《 *適用於 .NET 的 AWS SDK 開發人員指南*》中的 [AWSLogging](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-config-other.html#config-setting-awslogging)。（若要查看主題，請展開**開啟以檢視 .NET Framework 內容**區段。)

# 使用適用於 DynamoDB 的 .NET 用戶端加密程式庫
<a name="ddb-net-using"></a>

本主題說明 DynamoDB 的 .NET 用戶端加密程式庫 3.*x* 版中的一些函數和協助程式類別。

如需使用適用於 DynamoDB 的 .NET 用戶端加密程式庫進行程式設計的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 .[NET 範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/)。

**Topics**
+ [項目加密程式](#ddb-net-item-encryptors)
+ [屬性動作](#ddb-net-attribute-actions)
+ [加密組態](#ddb-net-config-encrypt)
+ [更新項目](#ddb-net-update-items)

## 項目加密程式
<a name="ddb-net-item-encryptors"></a>

DynamoDB AWS 資料庫加密開發套件的核心是項目加密程式。您可以使用適用於 DynamoDB 的 .NET 用戶端加密程式庫 3.*x* 版，以下列方式加密、簽署、驗證和解密 DynamoDB 資料表項目。

**適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK**  
您可以使用[資料表加密組態](#ddb-net-config-encrypt)來建構 DynamoDB 用戶端，以使用 DynamoDB `PutItem`請求自動加密和簽署用戶端的項目。您可以直接使用此用戶端，也可以建構[文件模型](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/dynamodb-intro.html#dynamodb-intro-apis-document)或[物件持久性模型](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/dynamodb-intro.html#dynamodb-intro-apis-object-persistence)。  
您必須使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK，才能使用[可搜尋的加密](searchable-encryption.md)。

**較低層級 `DynamoDbItemEncryptor`**  
較低層級會`DynamoDbItemEncryptor`直接加密和簽署或解密，並驗證您的資料表項目，而無需呼叫 DynamoDB。它不會發出 DynamoDB `PutItem`或 `GetItem` 請求。例如，您可以使用較低層級`DynamoDbItemEncryptor`直接解密和驗證您已擷取的 DynamoDB 項目。如果您使用較低層級的 `DynamoDbItemEncryptor`，我們建議您使用 適用於 .NET 的 SDK 提供的[低階程式設計模型](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/dynamodb-intro.html#dynamodb-intro-apis-low-level)來與 DynamoDB 通訊。  
較低層級`DynamoDbItemEncryptor`不支援[可搜尋的加密](searchable-encryption.md)。

## DynamoDB AWS 資料庫加密 SDK 中的屬性動作
<a name="ddb-net-attribute-actions"></a>

[屬性動作](concepts.md#crypt-actions)會決定哪些屬性值經過加密和簽署、哪些屬性值只經過簽署、哪些屬性值經過簽署並包含在加密內容中，以及哪些屬性值會被忽略。

若要使用 .NET 用戶端指定屬性動作，請使用 物件模型手動定義屬性動作。透過建立名稱/值對代表屬性名稱和指定動作的`Dictionary`物件來指定屬性動作。

指定 `ENCRYPT_AND_SIGN` 來加密和簽署 屬性。指定 `SIGN_ONLY`簽署但不加密 屬性。指定 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`以簽署 屬性，並將其包含在加密內容中。如果沒有同時簽署屬性，則無法加密該屬性。指定 `DO_NOTHING` 以忽略 屬性。

分割區和排序屬性必須是 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您將任何屬性定義為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

**注意**  
定義屬性動作之後，您必須定義要從簽章中排除哪些屬性。為了在未來更容易新增未簽章的屬性，我們建議您選擇不同的字首 （例如 "`:`") 來識別未簽章的屬性。將此字首包含在標示`DO_NOTHING`為定義 DynamoDB 結構描述和屬性動作的所有屬性的屬性名稱中。

下列物件模型示範如何使用 `ENCRYPT_AND_SIGN`.NET `SIGN_ONLY`用戶端指定 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`、、 和 `DO_NOTHING` 屬性動作。此範例使用字首「`:`」來識別`DO_NOTHING`屬性。

**注意**  
若要使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`密碼編譯動作，您必須使用 3.3 版或更新版本的 AWS 資料庫加密 SDK。將[您的資料模型更新](ddb-update-data-model.md)為包含 之前，將新版本部署至所有讀者`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT, // The partition attribute must be signed
    ["sort_key"] = CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT, // The sort attribute must be signed
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    ["attribute3"] = CryptoAction.SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT,
    [":attribute4"] = CryptoAction.DO_NOTHING
};
```

## DynamoDB AWS 資料庫加密 SDK 中的加密組態
<a name="ddb-net-config-encrypt"></a>

使用 AWS 資料庫加密 SDK 時，您必須明確定義 DynamoDB 資料表的加密組態。加密組態中所需的值取決於您是手動還是使用註釋的資料類別來定義屬性動作。

下列程式碼片段使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK 來定義 DynamoDB 資料表加密組態，並允許由不同字首定義的未簽章屬性。

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    // Optional: SearchConfig only required if you use beacons
    Search = new SearchConfig
    {
        WriteVersion = 1, // MUST be 1
        Versions = beaconVersions
    }    
};
tableConfigs.Add(ddbTableName, config);
```

**邏輯資料表名稱**  
DynamoDB 資料表的邏輯資料表名稱。  
邏輯資料表名稱以密碼編譯方式繫結至資料表中存放的所有資料，以簡化 DynamoDB 還原操作。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。您必須一律指定相同的邏輯資料表名稱。若要成功解密，邏輯資料表名稱必須符合加密時指定的名稱。如果您的 DynamoDB 資料表名稱在[從備份還原 DynamoDB 資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Restore.Tutorial.html)之後變更，邏輯資料表名稱可確保解密操作仍可辨識資料表。

**允許的未簽署屬性**  
在您的屬性動作`DO_NOTHING`中標記的屬性。  
允許的未簽章屬性會告知用戶端，哪些屬性會從簽章中排除。用戶端假設所有其他屬性都包含在簽章中。然後，在解密記錄時，用戶端會決定需要驗證哪些屬性，以及從您指定的允許未簽署屬性中忽略哪些屬性。您無法從允許的未簽署屬性中移除屬性。  
您可以建立列出所有屬性的陣列，明確定義允許的未簽章`DO_NOTHING`屬性。您也可以在命名`DO_NOTHING`屬性時指定不同的字首，並使用字首告訴用戶端哪些屬性未簽署。我們強烈建議指定不同的字首，因為它可簡化未來新增`DO_NOTHING`屬性的程序。如需詳細資訊，請參閱[更新資料模型](ddb-update-data-model.md)。  
如果您未為所有`DO_NOTHING`屬性指定字首，您可以設定`allowedUnsignedAttributes`陣列，明確列出用戶端在解密時遇到這些屬性時應取消簽署的所有屬性。只有在絕對必要時，才應該明確定義允許的未簽署屬性。

**搜尋組態 （選用）**  
`SearchConfig` 定義[信標版本](using-beacons.md#beacon-version)。  
`SearchConfig` 必須指定 才能使用[可搜尋加密](searchable-encryption.md)或[簽章的信標](configure.md#signed-beacons)。

**演算法套件 （選用）**  
`algorithmSuiteId` 定義 AWS 資料庫加密 SDK 使用的演算法套件。  
除非您明確指定替代演算法套件，否則 AWS 資料庫加密 SDK 會使用[預設演算法套件](supported-algorithms.md#recommended-algorithms)。預設演算法套件使用 AES-GCM 演算法搭配金鑰衍生、[數位簽章](concepts.md#digital-sigs)和[金鑰承諾](concepts.md#key-commitment)。雖然預設演算法套件可能適用於大多數應用程式，但您可以選擇替代演算法套件。例如，某些信任模型將由沒有數位簽章的演算法套件滿足。如需有關 AWS 資料庫加密 SDK 支援的演算法套件的資訊，請參閱 [AWS 資料庫加密 SDK 中支援的演算法套件](supported-algorithms.md)。  
若要選取[不含 ECDSA 數位簽章的 AES-GCM 演算法套件](supported-algorithms.md#other-algorithms)，請在資料表加密組態中包含下列程式碼片段。  

```
AlgorithmSuiteId = DBEAlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384
```

## 使用 AWS 資料庫加密 SDK 更新項目
<a name="ddb-net-update-items"></a>

 AWS 資料庫加密 SDK 不支援包含加密或簽章屬性的項目 [ddb：UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)。若要更新加密或簽章的屬性，您必須使用 [ddb：PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)。當您在`PutItem`請求中指定與現有項目相同的主索引鍵時，新項目會完全取代現有項目。您也可以在更新項目後，使用 [CLOBBER](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.SaveBehavior.html#CLOBBER) 在儲存時清除和取代所有屬性。

# .NET 範例
<a name="ddb-net-examples"></a>

下列範例示範如何使用適用於 DynamoDB 的 .NET 用戶端加密程式庫來保護應用程式中的資料表項目。若要尋找更多範例 （並自行提供），請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 .[NET 範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb//tree/main/Examples/runtimes/net/src)。

下列範例示範如何在未填入的新 Amazon DynamoDB 資料表中設定 DynamoDB 的 .NET 用戶端加密程式庫。如果您想要設定現有的 Amazon DynamoDB 資料表進行用戶端加密，請參閱 [將 3.x 版新增至現有資料表](ddb-net-config-existing-table.md)。

**Topics**
+ [使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK](#ddb-net-lowlevel-API-example)
+ [使用較低層級 `DynamoDbItemEncryptor`](#ddb-net-itemencryptor)

## 使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK
<a name="ddb-net-lowlevel-API-example"></a>

下列範例示範如何使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK 搭配 [AWS KMS keyring](use-kms-keyring.md)，以自動加密和簽署 DynamoDB `PutItem`請求的用戶端項目。

您可以使用任何支援的 [keyring](keyrings.md)，但我們建議您盡可能使用其中一個 AWS KMS keyring。

**請參閱完整的程式碼範例**：[BasicPutGetExample.cs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/BasicPutGetExample.cs)

**步驟 1：建立 AWS KMS keyring**  
下列範例使用 `CreateAwsKmsMrkMultiKeyring`建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法可確保 keyring 可正確處理單一區域和多區域金鑰。  

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步驟 2：設定屬性動作**  
下列範例定義 `attributeActionsOnEncrypt` 字典，代表資料表項目的範例[屬性動作](concepts.md#crypt-actions)。  
下列範例不會將任何屬性定義為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_ONLY, // The partition attribute must be SIGN_ONLY
    ["sort_key"] = CryptoAction.SIGN_ONLY, // The sort attribute must be SIGN_ONLY
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    [":attribute3"] = CryptoAction.DO_NOTHING
};
```

**步驟 3：定義從簽章中排除哪些屬性**  
下列範例假設所有`DO_NOTHING`屬性共用不同的字首「`:`」，並使用字首來定義允許的未簽署屬性。用戶端假設任何具有「`:`」字首的屬性名稱都會從簽章中排除。如需詳細資訊，請參閱[Allowed unsigned attributes](ddb-net-using.md#net-allowed-unauth)。  

```
const String unsignAttrPrefix = ":";
```

**步驟 4：定義 DynamoDB 資料表加密組態**  
下列範例定義代表此 DynamoDB 資料表加密組態的`tableConfigs`映射。  
此範例會將 DynamoDB 資料表名稱指定為[邏輯資料表名稱](ddb-net-using.md#net-logical-table-name)。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。如需詳細資訊，請參閱[DynamoDB AWS 資料庫加密 SDK 中的加密組態](ddb-net-using.md#ddb-net-config-encrypt)。  
若要使用[可搜尋加密](searchable-encryption.md)或[已簽章的信標](configure.md#signed-beacons)，您還必須在加密組態[`SearchConfig`](ddb-java-using.md#ddb-search-config)中包含 。

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix
};
tableConfigs.Add(ddbTableName, config);
```

**步驟 5：建立新的 AWS SDK DynamoDB 用戶端**  
下列範例使用步驟 4 `TableEncryptionConfigs`中的 建立新的 AWS SDK DynamoDB 用戶端。 ****  

```
var ddb = new Client.DynamoDbClient(
    new DynamoDbTablesEncryptionConfig { TableEncryptionConfigs = tableConfigs });
```

**步驟 6：加密並簽署 DynamoDB 資料表項目**  
下列範例定義一個`item`字典，代表範例資料表項目，並將該項目放在 DynamoDB 資料表中。項目在傳送至 DynamoDB 之前，會先加密並簽署用戶端。  

```
var item = new Dictionary<String, AttributeValue>
{
    ["partition_key"] = new AttributeValue("BasicPutGetExample"),
    ["sort_key"] = new AttributeValue { N = "0" },
    ["attribute1"] = new AttributeValue("encrypt and sign me!"),
    ["attribute2"] = new AttributeValue("sign me!"),
    [":attribute3"] = new AttributeValue("ignore me!")
};

PutItemRequest putRequest = new PutItemRequest
{
    TableName = ddbTableName,
    Item = item
};

PutItemResponse putResponse = await ddb.PutItemAsync(putRequest);
```

## 使用較低層級 `DynamoDbItemEncryptor`
<a name="ddb-net-itemencryptor"></a>

下列範例示範如何使用較低層級 `DynamoDbItemEncryptor`搭配 [AWS KMS keyring](use-kms-keyring.md) 來直接加密和簽署資料表項目。`DynamoDbItemEncryptor` 不會將項目放在 DynamoDB 資料表中。

您可以搭配 DynamoDB 增強型用戶端使用任何支援的 [keyring](keyrings.md)，但我們建議您盡可能使用其中一個 AWS KMS keyring。

**注意**  
較低層級`DynamoDbItemEncryptor`不支援[可搜尋的加密](searchable-encryption.md)。使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK 來使用可搜尋的加密。

**請參閱完整的程式碼範例**： [ItemEncryptDecryptExample.cs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/tree/main/Examples/runtimes/net/src/itemencryptor/ItemEncryptDecryptExample.cs)

**步驟 1：建立 AWS KMS keyring**  
下列範例使用 `CreateAwsKmsMrkMultiKeyring`建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法可確保 keyring 可正確處理單一區域和多區域金鑰。  

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**步驟 2：設定屬性動作**  
下列範例定義 `attributeActionsOnEncrypt` 字典，代表資料表項目的範例[屬性動作](concepts.md#crypt-actions)。  
下列範例不會將任何屬性定義為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<String, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_ONLY, // The partition attribute must be SIGN_ONLY
    ["sort_key"] = CryptoAction.SIGN_ONLY, // The sort attribute must be SIGN_ONLY
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    [":attribute3"] = CryptoAction.DO_NOTHING
};
```

**步驟 3：定義從簽章中排除哪些屬性**  
下列範例假設所有`DO_NOTHING`屬性共用不同的字首「`:`」，並使用字首來定義允許的未簽署屬性。用戶端假設任何具有「`:`」字首的屬性名稱都會從簽章中排除。如需詳細資訊，請參閱[Allowed unsigned attributes](ddb-net-using.md#net-allowed-unauth)。  

```
String unsignAttrPrefix = ":";
```

**步驟 4：定義`DynamoDbItemEncryptor`組態**  
下列範例定義 的組態`DynamoDbItemEncryptor`。  
此範例指定 DynamoDB 資料表名稱做為[邏輯資料表名稱](ddb-net-using.md#net-logical-table-name)。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。如需詳細資訊，請參閱[DynamoDB AWS 資料庫加密 SDK 中的加密組態](ddb-net-using.md#ddb-net-config-encrypt)。  

```
var config = new DynamoDbItemEncryptorConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix
};
```

**步驟 5：建立 `DynamoDbItemEncryptor`**  
下列範例`DynamoDbItemEncryptor`使用**步驟 4 **`config`中的 建立新的 。  

```
var itemEncryptor = new DynamoDbItemEncryptor(config);
```

**步驟 6：直接加密和簽署資料表項目**  
下列範例使用 直接加密和簽署項目`DynamoDbItemEncryptor`。`DynamoDbItemEncryptor` 不會將項目放在 DynamoDB 資料表中。  

```
var originalItem = new Dictionary<String, AttributeValue>
{
    ["partition_key"] = new AttributeValue("ItemEncryptDecryptExample"),
    ["sort_key"] = new AttributeValue { N = "0" },
    ["attribute1"] = new AttributeValue("encrypt and sign me!"),
    ["attribute2"] = new AttributeValue("sign me!"),
    [":attribute3"] = new AttributeValue("ignore me!")
};

var encryptedItem = itemEncryptor.EncryptItem(
    new EncryptItemInput { PlaintextItem = originalItem }
).EncryptedItem;
```

# 設定現有的 DynamoDB 資料表以使用適用於 DynamoDB 的 AWS 資料庫加密 SDK
<a name="ddb-net-config-existing-table"></a>

使用適用於 DynamoDB 的 .NET 用戶端加密程式庫的 3.*x* 版，您可以將現有的 Amazon DynamoDB 資料表設定為用戶端加密。本主題提供將 3.*x* 版新增至現有填入的 DynamoDB 資料表的三個步驟指引。

## 步驟 1：準備讀取和寫入加密的項目
<a name="ddb-net-add-step1"></a>

請完成下列步驟，以準備您的 AWS Database Encryption SDK 用戶端讀取和寫入加密的項目。部署下列變更後，用戶端將繼續讀取和寫入純文字項目。它不會加密或簽署寫入資料表的任何新項目，但一旦加密項目出現，它就能夠立即解密。這些變更可讓用戶端開始[加密新項目](#ddb-net-add-step2)。您必須先將下列變更部署到每個讀取器，才能繼續下一個步驟。

**1. 定義您的[屬性動作](concepts.md#crypt-actions)**  
建立物件模型以定義要加密和簽署哪些屬性值、僅簽署哪些屬性值，以及將忽略哪些屬性值。  
根據預設，主要金鑰屬性會經過簽署但未加密 (`SIGN_ONLY`)，而所有其他屬性則會經過加密和簽署 (`ENCRYPT_AND_SIGN`)。  
指定 `ENCRYPT_AND_SIGN` 來加密和簽署 屬性。指定 `SIGN_ONLY`簽署但不加密 屬性。指定 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT` 以簽署和屬性，並將其包含在加密內容中。如果沒有同時簽署屬性，則無法加密該屬性。指定 `DO_NOTHING` 以忽略 屬性。如需詳細資訊，請參閱[DynamoDB AWS 資料庫加密 SDK 中的屬性動作](ddb-net-using.md#ddb-net-attribute-actions)。  
如果您指定任何`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`屬性，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

```
var attributeActionsOnEncrypt = new Dictionary<string, CryptoAction>
{
    ["partition_key"] = CryptoAction.SIGN_ONLY, // The partition attribute must be SIGN_ONLY
    ["sort_key"] = CryptoAction.SIGN_ONLY, // The sort attribute must be SIGN_ONLY
    ["attribute1"] = CryptoAction.ENCRYPT_AND_SIGN,
    ["attribute2"] = CryptoAction.SIGN_ONLY,
    [":attribute3"] = CryptoAction.DO_NOTHING
};
```

**2. 定義將從簽章中排除哪些屬性**  
下列範例假設所有`DO_NOTHING`屬性共用不同的字首「`:`」，並使用字首定義允許的未簽章屬性。用戶端將假設具有「`:`」字首的任何屬性名稱已從簽章中排除。如需詳細資訊，請參閱[Allowed unsigned attributes](ddb-net-using.md#net-allowed-unauth)。  

```
const String unsignAttrPrefix = ":";
```

**3. 建立 [keyring](keyrings.md)**  
下列範例會建立 [AWS KMS keyring](use-kms-keyring.md)。 AWS KMS keyring 使用對稱加密或非對稱 RSA AWS KMS keys 來產生、加密和解密資料金鑰。  
此範例使用 `CreateMrkMultiKeyring`建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法可確保 keyring 可正確處理單一區域和多區域金鑰。  

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsMrkMultiKeyringInput { Generator = kmsKeyId };
var kmsKeyring = matProv.CreateAwsKmsMrkMultiKeyring(keyringInput);
```

**4. 定義 DynamoDB 資料表加密組態 **  
下列範例會定義代表此 DynamoDB 資料表加密組態的`tableConfigs`映射。  
此範例指定 DynamoDB 資料表名稱做為[邏輯資料表名稱](ddb-net-using.md#net-logical-table-name)。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。  
您必須指定 `FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT`做為純文字覆寫。此政策會繼續讀取和寫入純文字項目、讀取加密項目，以及準備用戶端寫入加密項目。  
如需資料表加密組態中包含之值的詳細資訊，請參閱 [DynamoDB AWS 資料庫加密 SDK 中的加密組態](ddb-java-using.md#ddb-config-encrypt)。  

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    PlaintextOverride = FORCE_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT
};
tableConfigs.Add(ddbTableName, config);
```

**5. 建立新的 AWS SDK DynamoDB 用戶端**  
他遵循範例使用步驟 4 `TableEncryptionConfigs`中的 建立新的 AWS SDK DynamoDB 用戶端。 ****  

```
var ddb = new Client.DynamoDbClient(
    new DynamoDbTablesEncryptionConfig { TableEncryptionConfigs = tableConfigs });
```

## 步驟 2：寫入加密和簽章的項目
<a name="ddb-net-add-step2"></a>

更新資料表加密組態中的純文字政策，以允許用戶端寫入加密和簽署的項目。部署下列變更之後，用戶端會根據您在**步驟 1 **中設定的屬性動作來加密和簽署新項目。用戶端將能夠讀取純文字項目，以及加密和簽署的項目。

在繼續[步驟 3](#ddb-net-add-step3) 之前，您必須加密和簽署資料表中的所有現有純文字項目。您可以執行沒有單一指標或查詢來快速加密現有的純文字項目。使用對您的系統最有意義的程序。例如，您可以使用慢速掃描資料表的非同步程序，並使用您定義的屬性動作和加密組態重寫項目。若要識別資料表中的純文字項目，建議您掃描所有不包含 AWS Database Encryption SDK 在加密`aws_dbe_head`和簽署項目時新增至項目的 和 `aws_dbe_foot` 屬性的項目。

下列範例會從**步驟 1 **更新資料表加密組態。您必須使用 更新純文字覆寫`FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT`。此政策會繼續讀取純文字項目，但也會讀取和寫入加密的項目。使用更新的 建立新的 AWS SDK DynamoDB 用戶端`TableEncryptionConfigs`。

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    PlaintextOverride = FORBID_WRITE_PLAINTEXT_ALLOW_READ_PLAINTEXT
};
tableConfigs.Add(ddbTableName, config);
```

## 步驟 3：僅讀取加密和已簽章的項目
<a name="ddb-net-add-step3"></a>

在您加密並簽署所有項目之後，請更新資料表加密組態中的純文字覆寫，以僅允許用戶端讀取和寫入加密和簽署的項目。部署下列變更之後，用戶端會根據您在**步驟 1 **中設定的屬性動作來加密和簽署新項目。用戶端只能讀取加密和簽署的項目。

下列範例會從**步驟 2 **更新資料表加密組態。您可以使用 更新純文字覆寫，`FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT`或從組態中移除純文字政策。根據預設，用戶端只會讀取和寫入加密和簽署的項目。使用更新的 建立新的 AWS SDK DynamoDB 用戶端`TableEncryptionConfigs`。

```
Dictionary<String, DynamoDbTableEncryptionConfig> tableConfigs =
    new Dictionary<String, DynamoDbTableEncryptionConfig>();
DynamoDbTableEncryptionConfig config = new DynamoDbTableEncryptionConfig
{
    LogicalTableName = ddbTableName,
    PartitionKeyName = "partition_key",
    SortKeyName = "sort_key",
    AttributeActionsOnEncrypt = attributeActionsOnEncrypt,
    Keyring = kmsKeyring,
    AllowedUnsignedAttributePrefix = unsignAttrPrefix,
    // Optional: you can also remove the plaintext policy from your configuration
    PlaintextOverride = FORBID_WRITE_PLAINTEXT_FORBID_READ_PLAINTEXT
};
tableConfigs.Add(ddbTableName, config);
```

# Rust
<a name="ddb-rust"></a>

本主題說明如何安裝和使用適用於 DynamoDB 的 Rust 用戶端加密程式庫的 1.*x* 版。如需使用 DynamoDB AWS 資料庫加密開發套件進行程式設計的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [Rust 範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/)。

適用於 DynamoDB 的 AWS Database Encryption SDK 的所有程式設計語言實作皆可互通。

**Topics**
+ [先決條件](#ddb-rust-prerequisites)
+ [安裝](#ddb-rust-install)
+ [使用 Rust 用戶端](ddb-rust-using.md)

## 先決條件
<a name="ddb-rust-prerequisites"></a>

在為 DynamoDB 安裝 Rust 用戶端加密程式庫之前，請確定您有下列先決條件。

**安裝 Rust 和 Cargo**  
使用 [rustup](https://rustup.rs/) 安裝目前穩定的 [Rust](https://www.rust-lang.org/) 版本。  
如需下載和安裝中斷的詳細資訊，請參閱 Cargo Book 中的[安裝程序](https://doc.rust-lang.org/cargo/getting-started/installation.html)。

## 安裝
<a name="ddb-rust-install"></a>

適用於 DynamoDB 的 Rust 用戶端加密程式庫在 Crates.io：// 上以 [aws-db-esdk](https://crates.io/crates/aws-db-esdk) 木箱的形式提供。如需安裝和建置程式庫的詳細資訊，請參閱 aws-database-encryption-sdk-dynamodb[aws-database-encryption-sdk-dynamodb GitHub 儲存庫中的 README.md](https://github.com/aws/aws-database-encryption-sdk-dynamodb/) 檔案。 GitHub 

**手動**  
若要安裝 DynamoDB 的 Rust 用戶端加密程式庫，請複製或下載 [aws-database-encryption-sdk-dynamodb](https://github.com/aws/aws-database-encryption-sdk-dynamodb/) GitHub 儲存庫。

**若要安裝最新版本**  
在專案目錄中執行下列 Cargo 命令：  

```
cargo add aws-db-esdk
```
或將以下行新增至 Cargo.toml：  

```
aws-db-esdk = "<version>"
```

# 使用適用於 DynamoDB 的 Rust 用戶端加密程式庫
<a name="ddb-rust-using"></a>

本主題說明 DynamoDB 的 Rust 用戶端加密程式庫 1.*x* 版中的一些函數和協助程式類別。

如需使用適用於 DynamoDB 的 Rust 用戶端加密程式庫進行程式設計的詳細資訊，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [Rust 範例](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/)。

**Topics**
+ [項目加密程式](#ddb-rust-item-encryptors)
+ [屬性動作](#ddb-rust-attribute-actions)
+ [加密組態](#ddb-rust-config-encrypt)
+ [更新項目](#ddb-rust-update-items)

## 項目加密程式
<a name="ddb-rust-item-encryptors"></a>

DynamoDB AWS 資料庫加密開發套件的核心是項目加密程式。您可以使用適用於 DynamoDB 的 Rust 用戶端加密程式庫 1.*x* 版，以下列方式加密、簽署、驗證和解密 DynamoDB 資料表項目。

**適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK**  
您可以使用[資料表加密組態](#ddb-rust-config-encrypt)來建構 DynamoDB 用戶端，該用戶端會使用 DynamoDB `PutItem`請求自動加密和簽署用戶端的項目。  
您必須使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK，才能使用[可搜尋的加密](searchable-encryption.md)。  
如需示範如何使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK 的範例，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [basic\$1get\$1put\$1example.rs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/basic_get_put_example.rs)。

**較低層級 `DynamoDbItemEncryptor`**  
較低層級會`DynamoDbItemEncryptor`直接加密和簽署或解密，並驗證您的資料表項目，而無需呼叫 DynamoDB。它不會發出 DynamoDB `PutItem`或 `GetItem` 請求。例如，您可以使用較低層級`DynamoDbItemEncryptor`直接解密和驗證您已擷取的 DynamoDB 項目。  
較低層級`DynamoDbItemEncryptor`不支援[可搜尋的加密](searchable-encryption.md)。  
如需示範如何使用較低層級 的範例`DynamoDbItemEncryptor`，請參閱 GitHub 上 aws-database-encryption-sdk-dynamodb 儲存庫中的 [item\$1encrypt\$1decrypt.rs](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/releases/rust/db_esdk/examples/itemencryptor/item_encrypt_decrypt.rs)。

## DynamoDB AWS 資料庫加密 SDK 中的屬性動作
<a name="ddb-rust-attribute-actions"></a>

[屬性動作](concepts.md#crypt-actions)會決定要加密和簽署哪些屬性值、僅簽署哪些屬性值、在加密內容中簽署和包含哪些屬性值，以及忽略哪些屬性值。

若要使用 Rust 用戶端指定屬性動作，請使用 物件模型手動定義屬性動作。建立`HashMap`物件，其中名稱/值對代表屬性名稱和指定的動作，以指定您的屬性動作。

指定 `ENCRYPT_AND_SIGN` 來加密和簽署 屬性。指定 `SIGN_ONLY`簽署但不加密 屬性。指定 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`以簽署 屬性，並將其包含在加密內容中。如果沒有同時簽署屬性，則無法加密該屬性。指定 `DO_NOTHING` 以忽略 屬性。

分割區和排序屬性必須是 `SIGN_ONLY`或 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。如果您將任何屬性定義為 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`，則分割區和排序屬性也必須是 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`。

**注意**  
定義屬性動作之後，您必須定義要從簽章中排除哪些屬性。為了在未來更容易新增未簽章的屬性，我們建議您選擇不同的字首 （例如 "`:`") 來識別未簽章的屬性。將此字首包含在標示`DO_NOTHING`為定義 DynamoDB 結構描述和屬性動作的所有屬性的屬性名稱中。

下列物件模型示範如何使用 Rust `ENCRYPT_AND_SIGN` `SIGN_ONLY`用戶端指定 `SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`、、 和 `DO_NOTHING` 屬性動作。此範例使用字首「`:`」來識別`DO_NOTHING`屬性。

```
let attribute_actions_on_encrypt = HashMap::from([
    ("partition_key".to_string(), CryptoAction::SignOnly),
    ("sort_key".to_string(), CryptoAction::SignOnly),
    ("attribute1".to_string(), CryptoAction::EncryptAndSign),
    ("attribute2".to_string(), CryptoAction::SignOnly),
    (":attribute3".to_string(), CryptoAction::DoNothing),
]);
```

## DynamoDB AWS 資料庫加密 SDK 中的加密組態
<a name="ddb-rust-config-encrypt"></a>

使用 AWS 資料庫加密 SDK 時，您必須明確定義 DynamoDB 資料表的加密組態。加密組態中所需的值取決於您是手動還是使用註釋的資料類別來定義屬性動作。

下列程式碼片段使用適用於 DynamoDB API 的低階 AWS 資料庫加密 SDK 來定義 DynamoDB 資料表加密組態，並允許由不同字首定義的未簽章屬性。

```
let table_config = DynamoDbTableEncryptionConfig::builder()
    .logical_table_name(ddb_table_name)
    .partition_key_name("partition_key")
    .sort_key_name("sort_key")
    .attribute_actions_on_encrypt(attribute_actions_on_encrypt)
    .keyring(kms_keyring)
    .allowed_unsigned_attribute_prefix(UNSIGNED_ATTR_PREFIX)
    // Specifying an algorithm suite is optional
    .algorithm_suite_id(
        DbeAlgorithmSuiteId::AlgAes256GcmHkdfSha512CommitKeyEcdsaP384SymsigHmacSha384,
    )
    .build()?;

let table_configs = DynamoDbTablesEncryptionConfig::builder()
    .table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
    .build()?;
```

**邏輯資料表名稱**  
DynamoDB 資料表的邏輯資料表名稱。  
邏輯資料表名稱以密碼編譯方式繫結至資料表中存放的所有資料，以簡化 DynamoDB 還原操作。當您第一次定義加密組態時，強烈建議指定您的 DynamoDB 資料表名稱做為邏輯資料表名稱。您必須一律指定相同的邏輯資料表名稱。若要成功解密，邏輯資料表名稱必須符合加密時指定的名稱。如果您的 DynamoDB 資料表名稱在[從備份還原 DynamoDB 資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Restore.Tutorial.html)之後變更，邏輯資料表名稱可確保解密操作仍可辨識資料表。

**允許的未簽署屬性**  
在您的屬性動作`DO_NOTHING`中標記的屬性。  
允許的未簽章屬性會告知用戶端，哪些屬性會從簽章中排除。用戶端假設所有其他屬性都包含在簽章中。然後，在解密記錄時，用戶端會決定需要驗證哪些屬性，以及從您指定的允許未簽署屬性中忽略哪些屬性。您無法從允許的未簽署屬性中移除屬性。  
您可以建立列出所有屬性的陣列，明確定義允許的未簽章`DO_NOTHING`屬性。您也可以在命名`DO_NOTHING`屬性時指定不同的字首，並使用字首告訴用戶端哪些屬性未簽署。我們強烈建議指定不同的字首，因為它可簡化未來新增`DO_NOTHING`屬性的程序。如需詳細資訊，請參閱[更新資料模型](ddb-update-data-model.md)。  
如果您未為所有`DO_NOTHING`屬性指定字首，您可以設定`allowedUnsignedAttributes`陣列，明確列出用戶端在解密時遇到這些屬性時應取消簽署的所有屬性。只有在絕對必要時，才應該明確定義允許的未簽署屬性。

**搜尋組態 （選用）**  
`SearchConfig` 定義[信標版本](using-beacons.md#beacon-version)。  
`SearchConfig` 必須指定 才能使用[可搜尋的加密](searchable-encryption.md)或[簽章的信標](configure.md#signed-beacons)。

**演算法套件 （選用）**  
`algorithmSuiteId` 定義 AWS 資料庫加密 SDK 使用的演算法套件。  
除非您明確指定替代演算法套件，否則 AWS 資料庫加密 SDK 會使用[預設演算法套件](supported-algorithms.md#recommended-algorithms)。預設演算法套件使用 AES-GCM 演算法搭配金鑰衍生、[數位簽章](concepts.md#digital-sigs)和[金鑰承諾](concepts.md#key-commitment)。雖然預設演算法套件可能適用於大多數應用程式，但您可以選擇替代演算法套件。例如，某些信任模型將由沒有數位簽章的演算法套件滿足。如需有關 AWS 資料庫加密 SDK 支援的演算法套件的資訊，請參閱 [AWS 資料庫加密 SDK 中支援的演算法套件](supported-algorithms.md)。  
若要選取[不含 ECDSA 數位簽章的 AES-GCM 演算法套件](supported-algorithms.md#other-algorithms)，請在資料表加密組態中包含下列程式碼片段。  

```
.algorithm_suite_id(
    DbeAlgorithmSuiteId::AlgAes256GcmHkdfSha512CommitKeyEcdsaP384SymsigHmacSha384,
)
```

## 使用 AWS 資料庫加密 SDK 更新項目
<a name="ddb-rust-update-items"></a>

 AWS 資料庫加密 SDK 不支援包含加密或簽章屬性的項目 [ddb：UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)。若要更新加密或簽章的屬性，您必須使用 [ddb：PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)。當您在`PutItem`請求中指定與現有項目相同的主索引鍵時，新項目會完全取代現有項目。

# 舊版 DynamoDB 加密用戶端
<a name="legacy-dynamodb-encryption-client"></a>

2023 年 6 月 9 日，我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。 AWS Database Encryption SDK 繼續支援舊版 DynamoDB Encryption Client 版本。如需使用重新命名變更之用戶端加密程式庫不同部分的詳細資訊，請參閱 [Amazon DynamoDB 加密用戶端重新命名](DDBEC-rename.md)。

若要遷移至最新版本的 DynamoDB Java 用戶端加密程式庫，請參閱 [遷移至 3.x 版](ddb-java-migrate.md)。

**Topics**
+ [AWS DynamoDB 版本的資料庫加密 SDK 支援](#legacy-support)
+ [DynamoDB 加密用戶端的運作方式](DDBEC-legacy-how-it-works.md)
+ [Amazon DynamoDB 加密用戶端概念](DDBEC-legacy-concepts.md)
+ [密碼編譯資料提供者](crypto-materials-providers.md)
+ [Amazon DynamoDB Encryption Client 可用的程式設計語言](programming-languages.md)
+ [變更您的資料模型](data-model.md)
+ [故障診斷 DynamoDB Encryption Client 應用程式的問題](troubleshooting.md)

## AWS DynamoDB 版本的資料庫加密 SDK 支援
<a name="legacy-support"></a>

舊版章節中的主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。

下表列出支援 Amazon DynamoDB 中用戶端加密的語言和版本。


| 程式設計語言 | 版本 | SDK 主要版本生命週期階段 | 
| --- | --- | --- | 
|  Java  |  1.*x* 版  |  終止[End-of-Support階段](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)，自 2022 年 7 月起生效  | 
|  Java  |  2.*x* 版  |  [一般可用性](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle) (GA)  | 
|  Java  |  3.*x* 版  |  [一般可用性](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle) (GA)  | 
|  Python  |  1.*x* 版  |  終止[End-of-Support階段](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)，自 2022 年 7 月起生效  | 
|  Python  |  2.*x* 版  |  終止[End-of-Support階段](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)，自 2022 年 7 月起生效  | 
|  Python  |  3.*x* 版  |  [一般可用性](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle) (GA)  | 

# DynamoDB 加密用戶端的運作方式
<a name="DDBEC-legacy-how-it-works"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

DynamoDB 加密用戶端專為保護您存放在 DynamoDB 中的資料而設計。程式庫包括您可以擴展或以原狀使用的安全實作。再者，大多數元素是由摘要元素表示，所以您可建立和使用相容的自訂元件。

**加密並簽署資料表項目**

DynamoDB Encryption Client 的核心是一個*項目加密程式*，可加密、簽署、驗證和解密資料表項目。它會接受資料表項目相關資訊，以及要加密並簽署項目的相關指示。其將從您選取及設定的[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider)取得加密資料，以及該項資料使用方式的指示。

下圖顯示此程序的高階檢視。

![\[在 DynamoDB 加密用戶端中加密和簽署項目\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/arch-encrypt.png)


若要加密和簽署資料表項目，DynamoDB 加密用戶端需要：
+ **資料表的相關資訊。 **它會從您提供的 [DynamoDB 加密內容](concepts.md#encryption-context)取得資料表的相關資訊。有些協助程式會從 DynamoDB 取得必要資訊，並為您建立 DynamoDB 加密內容。
**注意**  
*DynamoDB 加密用戶端*中的 DynamoDB 加密內容與 AWS Key Management Service (AWS KMS) 和 中的*加密內容*無關 AWS Encryption SDK。
+ **哪些屬性要加密並簽署。**其將從您提供的[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)取得這項資訊。
+ **加密資料，包括加密金鑰和簽署金鑰。**其將從您選取及設定的[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP) 取得這些資料。
+ **加密並簽署項目的指示**。CMP 會將可供使用加密資料 (包括加密和簽署演算法) 的指示新增至[實際資料描述](DDBEC-legacy-concepts.md#legacy-material-description)。

[項目加密程式](DDBEC-legacy-concepts.md#item-encryptor)會使用上述所有元素來加密並簽署項目。項目加密程式也會將兩個屬性新增至此項目：包含加密和簽署指示 (實際資料描述) 的[資料描述屬性](DDBEC-legacy-concepts.md#legacy-material-description)，以及包含簽章的屬性。您可直接與項目加密程式互動，或使用為您與項目加密程式互動的協助程式功能來實作安全的預設行為。

結果是包含已加密並簽署之資料的 DynamoDB 項目。

**驗證並解密資料表項目**

如下圖所示，這些元件也會一起運作來驗證並解密項目。

![\[驗證和解密 DynamoDB 加密用戶端中的項目\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/arch-decrypt.png)


為了驗證和解密項目，DynamoDB 加密用戶端需要相同的元件、具有相同組態的元件，或專為解密項目而設計的元件，如下所示：
+ [DynamoDB 加密內容](concepts.md#encryption-context)中**資料表的相關資訊**。
+ **要驗證和解密哪些屬性。**其將從[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)取得這項資訊。
+ **解密資料，包括驗證和加密金鑰**，來自您選取和設定的[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP)。

  已加密的項目不包含用來進行加密的 CMP 相關記錄。您必須提供相同的 CMP、具有相同組態的 CMP，或設計用來解密項目的 CMP。
+ **如何加密並簽署項目的相關資訊**，包括加密和簽署演算法。用戶端會從項目中的[資料描述屬性](DDBEC-legacy-concepts.md#legacy-material-description)取得這些資訊。

[項目加密程式](DDBEC-legacy-concepts.md#item-encryptor)會使用上述所有元素來驗證並解密項目。此外，它不會移除資料描述和簽章屬性。結果是純文字 DynamoDB 項目。

# Amazon DynamoDB 加密用戶端概念
<a name="DDBEC-legacy-concepts"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

本主題說明 Amazon DynamoDB 加密用戶端中使用的概念和術語。

若要了解 DynamoDB 加密用戶端的元件如何互動，請參閱 [DynamoDB 加密用戶端的運作方式](DDBEC-legacy-how-it-works.md)。

**Topics**
+ [密碼編譯資料提供者 (CMP)](#concept-material-provider)
+ [項目加密程式](#item-encryptor)
+ [屬性動作](#legacy-attribute-actions)
+ [資料描述](#legacy-material-description)
+ [DynamoDB 加密內容](#legacy-encryption-context)
+ [提供者存放區](#provider-store)

## 密碼編譯資料提供者 (CMP)
<a name="concept-material-provider"></a>

實作 DynamoDB 加密用戶端時，您的第一個任務之一是[選取密碼編譯資料提供者](crypto-materials-providers.md) (CMP) （也稱為*加密資料提供者*)。您的選擇會決定其餘的大部分實作。

*密碼編譯資料提供者* (CMP) 會收集、整合及傳回[項目加密程式](#item-encryptor)用來加密並簽署資料表項目的密碼編譯資料。CMP 會決定要使用的加密演算法，以及如何產生及保護加密和簽署金鑰。

CMP 會與項目加密程式互動。項目加密程式會請求 CMP 提供加密和解密資料，而 CMP 會將這些資料傳回給項目加密程式。然後，項目加密程式會使用密碼編譯資料將項目加密並簽署，或驗證並解密。

您會在設定用戶端時指定 CMP。您可以建立相容的自訂 CMP，或使用程式庫的其中一個 CMP。大多數 CMP 都適用於多種程式設計語言。

## 項目加密程式
<a name="item-encryptor"></a>

*項目加密程式*是執行 DynamoDB 加密用戶端密碼編譯操作的較低層級元件。其將請求[密碼編譯資料提供者](#concept-material-provider) (CMP) 提供密碼編譯資料，然後使用 CMP 傳回的資料將資料表項目加密並簽署，或驗證並解密。

您可以直接與項目加密程式互動，或使用您的程式庫所提供的協助程式。例如，適用於 Java 的 DynamoDB 加密用戶端包含可與 搭配使用的`AttributeEncryptor`協助程式類別`DynamoDBMapper`，而不是直接與`DynamoDBEncryptor`項目加密程式互動。Python 程式庫包括 `EncryptedTable`、`EncryptedClient` 和 `EncryptedResource` 協助程式類別，這些類別會替您與項目加密程式互動。

## 屬性動作
<a name="legacy-attribute-actions"></a>

*屬性動作*會告知項目加密程式要對項目的每個屬性執行什麼動作。

屬性動作值可以是下列其中一項：
+ **加密和簽署** – 加密屬性值。在項目簽章中包含屬性 (名稱和值)。
+ **僅限簽署** – 在項目簽章中包含 屬性。
+ **什麼都不做** – 請勿加密或簽署 屬性。

對於可以儲存敏感資料的任何屬性，請使用**加密並簽署**。針對主索引鍵屬性 (分割區索引鍵和排序索引鍵)，使用**僅簽署**。[資料描述屬性](#legacy-material-description)和簽章屬性不會進行簽署或加密。您不需要指定這些屬性的屬性動作。

請仔細選擇屬性動作。如有疑問，請使用**加密並簽署**。使用 DynamoDB 加密用戶端來保護資料表項目之後，您就無法在沒有簽章驗證錯誤風險的情況下變更屬性的動作。如需詳細資訊，請參閱[變更您的資料模型](data-model.md)。

**警告**  
請勿加密主索引鍵的屬性。它們必須保持純文字，以便 DynamoDB 可以在不執行完整資料表掃描的情況下找到項目。

如果 [DynamoDB 加密內容](concepts.md#encryption-context)識別您的主要金鑰屬性，當您嘗試加密它們時，用戶端會擲回錯誤。

您用來為每種程式設計語言指定屬性動作的技巧都不同。而且，該技巧可以專屬於您所使用的協助程式類別。

如需詳細資訊，請參閱程式設計語言的文件。
+ [Python](python-using.md#python-attribute-actions)
+ [Java](java-using.md#attribute-actions-java)

## 資料描述
<a name="legacy-material-description"></a>

已加密資料表項目的*資料描述*包含資料表項目加密和簽署方式的相關資訊 (例如加密演算法)。[密碼編譯資料提供者](#concept-material-provider) (CMP) 會在整合可供加密和簽署的密碼編譯資料時記錄資料描述。稍後，當它需要整合密碼編譯資料來驗證和解密項目時，它會使用資料描述作為其指南。

在 DynamoDB 加密用戶端中，材料描述是指三個相關元素：

**請求的資料描述**  
有些[密碼編譯資料提供者](#concept-material-provider) (CMP) 可讓您指定進階選項，例如加密演算法。若要指出您的選擇，請將名稱值對新增至請求中 [DynamoDB 加密內容](concepts.md#encryption-context)的資料描述屬性，以加密資料表項目。此元素又稱為*請求的資料描述*。請求的資料描述中的有效值由您所選的 CMP 定義。  
由於資料描述可能覆寫安全的預設值，除非您有充分理由要使用請求的資料描述，否則建議您將其省略。

**實際資料描述**  
[密碼編譯資料提供者](#concept-material-provider) (CMP) 傳回的資料描述又稱為*實際資料描述*。它會描述 CMP 在整合密碼編譯資料時所用的實際值。通常包含請求的資料描述及新增和變更 (如果有)。

**資料描述屬性**  
用戶端會在已加密項目的*資料描述屬性*中儲存實際資料描述。資料描述屬性名稱為 `amzn-ddb-map-desc`，而其值為實際資料描述。用戶端會使用資料描述屬性中的值來驗證並解密項目。

## DynamoDB 加密內容
<a name="legacy-encryption-context"></a>

*DynamoDB 加密內容*會將資料表和項目的相關資訊提供給[密碼編譯資料提供者](#concept-material-provider) (CMP)。在進階實作中，DynamoDB 加密內容可以包含[請求的資料描述](#legacy-material-description)。

當您加密資料表項目時，DynamoDB 加密內容會以密碼編譯方式繫結至加密的屬性值。當您解密時，如果 DynamoDB 加密內容與用來加密的 DynamoDB 加密內容不完全、區分大小寫相符，解密操作會失敗。如果您直接與[項目加密程式](#item-encryptor)互動，您必須在呼叫加密或解密方法時提供 DynamoDB 加密內容。大多數協助程式會為您建立 DynamoDB 加密內容。

**注意**  
*DynamoDB 加密用戶端*中的 DynamoDB 加密內容與 AWS Key Management Service (AWS KMS) 和 中的*加密內容*無關 AWS Encryption SDK。

DynamoDB 加密內容可包含下列欄位。所有欄位和值都是選用的。
+ 資料表名稱
+ 分割區索引鍵名稱
+ 排序索引鍵名稱
+ 屬性名稱值組
+ [請求的資料描述](#legacy-material-description)

## 提供者存放區
<a name="provider-store"></a>

*提供者存放區* 是一個可傳回[密碼編譯資料提供者](#concept-material-provider) (CMP) 的元件。提供者存放區可以建立 CMP，或從另一個來源 (例如另一個提供者存放區) 取得。提供者存放區會在持久性儲存體中儲存其建立的 CMP 版本，而存放的每個 CMP 都是依照請求者的資料名稱與版本號碼進行識別。

DynamoDB 加密用戶端中的[最近提供者](most-recent-provider.md)會從提供者存放區取得其 CMPs，但您可以使用提供者存放區將 CMPs 提供給任何元件。每個最近提供者都與一個提供者存放區相關聯，但提供者存放區可以將 CMP 提供給多部主機上的許多請求者。

提供者存放區會隨需建立新的 CMP 版本，並傳回新的和現有版本。它也會傳回特定資料名稱的最新版本號碼。這使請求者能夠得知提供者存放區何時有可請求的新版 CMP。

DynamoDB 加密用戶端包含[ MetaStore](most-recent-provider.md#about-metastore)，這是使用存放在 DynamoDB 中的金鑰建立包裝 CMPs 並使用內部 DynamoDB 加密用戶端加密的提供者存放區。

**進一步了解**：
+ 提供者存放區：[Java](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/providers/store/ProviderStore.html)、[Python](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/src/dynamodb_encryption_sdk/material_providers/store/__init__.py)
+ 中繼存放區：[Java](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/providers/store/MetaStore.html)、[Python](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/materials_providers/metastore.html#module-dynamodb_encryption_sdk.material_providers.store.meta)

# 密碼編譯資料提供者
<a name="crypto-materials-providers"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

使用 DynamoDB 加密用戶端時，您所做的最重要決策之一是選取[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP)。CMP 會整合密碼編譯資料，並將其傳回至項目加密程式。它也會決定加密和簽署金鑰的產生方式、要為每個項目產生新的金鑰資料還是重複使用這些資料，以及所使用的加密和簽署演算法等。

您可以從 DynamoDB Encryption Client 程式庫中提供的實作中選擇 CMP，或建置相容的自訂 CMP。您的 CMP 選擇也可能取決於您所使用的[程式設計語言](programming-languages.md)。

本主題說明最常見的 CMP，並提供相關建議以協助您選擇最適用於應用程式的 CMP。

**直接 KMS 資料提供者**  
Direct KMS 資料提供者會在 下保護您的資料表項目[AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)，這些項目絕不會讓 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) 處於未加密狀態。您的應用程式不會產生或管理任何密碼編譯資料。由於它使用 AWS KMS key 為每個項目產生唯一的加密和簽署金鑰，因此每次加密或解密項目時，此提供者 AWS KMS 都會呼叫 。  
如果您使用 AWS KMS ，而且每筆交易一個 AWS KMS 呼叫對您的應用程式來說是可行的，則此供應商是不錯的選擇。  
如需詳細資訊，請參閱[直接 KMS 資料提供者](direct-kms-provider.md)。

**包裝資料提供者 (包裝 CMP)**  
包裝資料提供者 （包裝 CMP) 可讓您在 DynamoDB 加密用戶端外部產生和管理包裝和簽署金鑰。  
包裝 CMP 會為每個項目產生唯一的加密金鑰。接著，它會使用您所提供的包裝 (或取消包裝) 和簽署金鑰。如此，您可決定包裝和簽署金鑰的產生方式，以及要讓每個項目各有唯一的金鑰還是重複使用這些金鑰。包裝 CMP 是[直接 KMS 提供者](direct-kms-provider.md)的安全替代方案，適用於不使用 AWS KMS 且可以安全管理密碼編譯資料的應用程式。  
如需詳細資訊，請參閱[包裝資料提供者](wrapped-provider.md)。

**最近提供者**  
*最近提供者*是一個[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP)，旨在與[提供者存放區](DDBEC-legacy-concepts.md#provider-store)搭配使用。它會從提供者存放區取得 CMP，並取得它從 CMP 傳回的密碼編譯資料。最近提供者通常會使用各個 CMP 因應多次密碼編譯資料請求，但您也可以使用提供者存放區的功能來控制資料重複使用的程度、決定輪換 CMP 的頻率，甚至在不變更最近提供者的情況下變更所使用的 CMP 類型。  
您可以將最近提供者與任何相容的提供者存放區搭配使用。DynamoDB 加密用戶端包含 MetaStore，這是傳回包裝 CMPs的提供者存放區。  
對於需要盡可能避免呼叫其密碼編譯來源的應用程式，以及可重複使用部分密碼編譯資料而不會違反安全性需求的應用程式，最近提供者將是理想的選擇。例如，它可讓您在 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)的 下保護您的密碼編譯資料，而不必 AWS KMS 在每次加密或解密項目時呼叫 。  
如需詳細資訊，請參閱[最近提供者](most-recent-provider.md)。

**靜態資料提供者**  
靜態資料提供者是針對測試、概念驗證示範和舊版相容性而設計的。它不會為每個項目產生任何唯一的密碼編譯資料。它會傳回您所提供的相同加密和簽署金鑰，並直接使用這些金鑰來加密、解密和簽署您的資料表項目。  
Java 程式庫中的[非對稱靜態提供者](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/providers/AsymmetricStaticProvider.html)不是靜態提供者。其僅提供[包裝 CMP](wrapped-provider.md) 的替代建構函數。此提供者可在生產環境中安全地使用，但只要情況允許，您即應直接使用包裝 CMP。

**Topics**
+ [直接 KMS 資料提供者](direct-kms-provider.md)
+ [包裝資料提供者](wrapped-provider.md)
+ [最近提供者](most-recent-provider.md)
+ [靜態資料提供者](static-provider.md)

# 直接 KMS 資料提供者
<a name="direct-kms-provider"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

*Direct KMS 資料提供者* (Direct KMS 提供者） 可在 下保護您的資料表項目[AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)，這些項目絕不會讓 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) 處於未加密狀態。此[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider)會為每個資料表項目傳回唯一的加密金鑰和簽署金鑰。若要這樣做，它會 AWS KMS 在每次加密或解密項目時呼叫 。

如果您以高頻率和大規模處理 DynamoDB 項目，可能會超過 AWS KMS [requests-per-second數限制](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html#requests-per-second)，導致處理延遲。如果您需要超過限制，請在 [AWS 支援 中心](https://console.aws.amazon.com/support/home)建立案例。您也可以考慮使用金鑰重複使用受限的密碼編譯資料提供者，例如[最近提供者](most-recent-provider.md)。

若要使用直接 KMS 提供者，發起人必須擁有 [AWS 帳戶](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)、至少一個 AWS KMS key和 許可，才能在 上呼叫 [GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 和 [Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 操作 AWS KMS key。 AWS KMS key 必須是對稱加密金鑰；DynamoDB 加密用戶端不支援非對稱加密。如果您使用的是 [DynamoDB 全域資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GlobalTables.html)，建議您指定[AWS KMS 多區域金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)。如需詳細資訊，請參閱[使用方式](#provider-kms-how-to-use)。

**注意**  
當您使用直接 KMS 提供者時，主要金鑰屬性的名稱和值會以純文字顯示在相關 AWS KMS 操作的[AWS KMS 加密內容](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)和 AWS CloudTrail 日誌中。不過，DynamoDB 加密用戶端永遠不會公開任何加密屬性值的純文字。

Direct KMS 提供者是 DynamoDB Encryption Client 支援的數個[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMPs) 之一。如需其他 CMP 的相關資訊，請參閱[密碼編譯資料提供者](crypto-materials-providers.md)。

**如需範例程式碼，請參閱：**
+ Java：[AwsKmsEncryptedItem](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedItem.java)
+ Python：[aws-kms-encrypted-table](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_table.py)，[aws-kms-encrypted-item](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_item.py)

**Topics**
+ [使用方式](#provider-kms-how-to-use)
+ [運作方式](#provider-kms-how-it-works)

## 使用方式
<a name="provider-kms-how-to-use"></a>

若要建立直接 KMS 提供者，請使用金鑰 ID 參數在您的帳戶中指定對稱加密 [KMS 金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)。金鑰 ID 參數的值可以是 的金鑰 ID、金鑰 ARN、別名名稱或別名 ARN AWS KMS key。如需金鑰識別符的詳細資訊，請參閱《 *AWS Key Management Service 開發人員指南*》中的[金鑰識別符](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id)。

Direct KMS 提供者需要對稱加密 KMS 金鑰。無法使用非對稱 KMS 金鑰。不過，您可以使用多區域 KMS 金鑰、具有匯入金鑰材料的 KMS 金鑰，或自訂金鑰存放區中的 KMS 金鑰。您必須擁有 KMS 金鑰的 [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 和 [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 許可。因此，您必須使用客戶受管金鑰，而非 AWS 受管或 AWS 擁有的 KMS 金鑰。

適用於 Python 的 DynamoDB 加密用戶端會在金鑰 ID 參數值中，決定要 AWS KMS 從 區域呼叫的區域，如果包含一個。否則，如果您在 AWS KMS 用戶端中指定一個 或您在 中設定的 區域，它會使用 區域 適用於 Python (Boto3) 的 AWS SDK。如需 Python 中區域選擇的資訊，請參閱《適用於 Python (Boto3) 的 AWS SDK API 參考》中的[組態](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html)。

如果您指定的用戶端包含區域，則適用於 Java 的 DynamoDB 加密用戶端會決定 AWS KMS 從用戶端中的 AWS KMS 區域呼叫的區域。否則，它會使用您在 中設定的 區域 適用於 Java 的 AWS SDK。如需 中區域選擇的相關資訊 適用於 Java 的 AWS SDK，請參閱《 適用於 Java 的 AWS SDK 開發人員指南》中的[AWS 區域 選擇](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-region-selection.html)。

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

```
// Replace the example key ARN and Region with valid values for your application
final String keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
final String region = 'us-west-2'
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
```

------
#### [ Python ]

下列範例使用金鑰 ARN 來指定 AWS KMS key。如果您的金鑰識別符不包含 AWS 區域，DynamoDB 加密用戶端會從設定的 Botocore 工作階段、如果有，或從 Boto 預設值取得區域。

```
# Replace the example key ID with a valid value
kms_key = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=kms_key)
```

------

如果您使用的是 [Amazon DynamoDB 全域資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GlobalTables.html)，建議您使用 AWS KMS 多區域金鑰加密資料。多區域金鑰 AWS KMS keys 不同 AWS 區域 ，可以互換使用，因為它們具有相同的金鑰 ID 和金鑰材料。如需詳細資訊，請參閱《 *AWS Key Management Service 開發人員指南*》中的[使用多區域金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)。

**注意**  
如果您使用的是全域資料表 [2017.11.29 版](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/globaltables.V1.html)，則必須設定屬性動作，才不會加密或簽署預留複寫欄位。如需詳細資訊，請參閱[舊版全域資料表的問題](troubleshooting.md#fix-global-tables)。

若要搭配 DynamoDB 加密用戶端使用多區域金鑰，請建立多區域金鑰並將其複寫至應用程式執行所在的區域。然後將直接 KMS 提供者設定為在 DynamoDB 加密用戶端呼叫的區域中使用多區域金鑰 AWS KMS。

下列範例會設定 DynamoDB 加密用戶端來加密美國東部 （維吉尼亞北部） (us-east-1) 區域中的資料，並使用多區域金鑰在美國西部 （奧勒岡） (us-west-2) 區域中解密資料。

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

在此範例中，DynamoDB 加密用戶端 AWS KMS 會從 AWS KMS 用戶端中的 區域取得要呼叫的 區域。此`keyArn`值可識別相同區域中的多區域金鑰。

```
// Encrypt in us-east-1

// Replace the example key ARN and Region with valid values for your application
final String usEastKey = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
final String region = 'us-east-1'
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, usEastKey);
```

```
// Decrypt in us-west-2

// Replace the example key ARN and Region with valid values for your application
final String usWestKey = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
final String region = 'us-west-2'
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, usWestKey);
```

------
#### [ Python ]

在此範例中，DynamoDB 加密用戶端 AWS KMS 會從金鑰 ARN 中的 區域取得要呼叫的 區域。

```
# Encrypt in us-east-1

# Replace the example key ID with a valid value
us_east_key = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=us_east_key)
```

```
# Decrypt in us-west-2

# Replace the example key ID with a valid value
us_west_key = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=us_west_key)
```

------

## 運作方式
<a name="provider-kms-how-it-works"></a>

Direct KMS 提供者會傳回受 AWS KMS key 您指定 保護的加密和簽署金鑰，如下圖所示。

![\[DynamoDB 加密用戶端中直接 KMS 提供者的輸入、處理和輸出\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/directKMS.png)

+ 若要產生加密資料，直接 KMS 提供者 AWS KMS 會要求 使用您指定的 AWS KMS key 為每個項目[產生唯一的資料金鑰](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html)。它會從[資料金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#data-keys)的純文字複本衍生項目的加密和簽署金鑰，然後傳回加密和簽署金鑰，以及在項目[資料描述屬性](DDBEC-legacy-concepts.md#legacy-material-description)中存放的加密資料金鑰。

  項目加密程式會在使用加密和簽署金鑰後，盡快將其從記憶體中移除。加密的項目中只會儲存用來衍生這些金鑰的資料金鑰加密複本。
+ 若要產生解密資料，直接 KMS 提供者 AWS KMS 會要求 解密加密的資料金鑰。隨後，它會從純文字資料金鑰衍生驗證和簽署金鑰，並將它們傳回至項目加密程式。

  項目加密程式會驗證該項目，如果驗證成功，則會將加密的值解密。接著，它會盡快從記憶體中移除這些金鑰。

### 取得加密資料
<a name="direct-kms-get-encryption-materials"></a>

本節將詳細說明直接 KMS 提供者在接收到來自[項目加密程式](DDBEC-legacy-concepts.md#item-encryptor)的加密資料請求時的輸入、輸出和處理情形。

**輸入** (從應用程式)
+ 的金鑰 ID AWS KMS key。

**輸入** (從項目加密程式)
+ [DynamoDB 加密內容](concepts.md#encryption-context)

**輸出** (到項目加密程式)
+ 加密金鑰 (純文字)
+ 簽署金鑰
+ 在[實際資料描述](DDBEC-legacy-concepts.md#legacy-material-description)中：這些值會儲存在用戶端新增至項目的資料描述屬性中。
  + amzn-ddb-env-key：由 加密的 Base64-encoded資料金鑰 AWS KMS key
  + amzn-ddb-env-alg：加密演算法，預設為 [AES/256](https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/archived-crypto-projects/aes-development)
  + amzn-ddb-sig-alg：簽署演算法，預設為 [HmacSHA256/256](https://en.wikipedia.org/wiki/HMAC)
  + amzn-ddb-wrap-alg：kms

**處理**

1. Direct KMS 提供者會傳送 AWS KMS 請求，以使用指定的 AWS KMS key 來[產生項目的唯一資料金鑰](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html)。此操作會傳回以 AWS KMS key加密的純文字金鑰和複本。這項資料又稱為*初始金鑰資料*。

   此要求包含 [AWS KMS 加密內容](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)中的下列純文字值。這些非機密值會以密碼編譯的方式繫結至加密的物件，而在解密時需要相同的加密細節。您可以使用這些值來識別 [AWS CloudTrail 日誌](https://docs.aws.amazon.com/kms/latest/developerguide/monitoring-overview.html) AWS KMS 中的 呼叫。
   + amzn-ddb-env-alg – 預設 AES/256 加密演算法
   + amzn-ddb-sig-alg – 簽署演算法，預設 HmacSHA256/256
   + （選用） aws-kms-table – *資料表名稱*
   + （選用） *分割區索引鍵名稱* – *分割區索引鍵值* （二進位值為 Base64-encoded)
   + （選用） *排序索引鍵名稱* – *排序索引鍵值* （二進位值為 Base64-encoded)

   Direct KMS 提供者會從項目的 DynamoDB AWS KMS 加密內容取得加密內容的值。 [DynamoDB ](concepts.md#encryption-context) 如果 DynamoDB 加密內容不包含值，例如資料表名稱，則會從 AWS KMS 加密內容中省略該名稱值對。

1. 直接 KMS 提供者會從資料金鑰衍生對稱加密金鑰和簽署金鑰。根據預設，其將使用[安全雜湊演算法 (SHA) 256](https://en.wikipedia.org/wiki/SHA-2) 和 [RFC5869 HMAC 式金鑰衍生函數](https://tools.ietf.org/html/rfc5869)，衍生 256 位元 AES 對稱加密金鑰和 256 位元 HMAC-SHA-256 簽署金鑰。

1. 直接 KMS 提供者會將輸出傳回至項目加密程式。

1. 項目加密程式會採用實際資料描述中指定的演算法，使用加密金鑰為指定的屬性加密，並使用簽署金鑰加以簽署。它會盡快從記憶體中移除這些純文字金鑰。

### 取得解密資料
<a name="direct-kms-get-decryption-materials"></a>

本節將詳細說明直接 KMS 提供者在接收到來自[項目加密程式](DDBEC-legacy-concepts.md#item-encryptor)的解密資料請求時的輸入、輸出和處理情形。

**輸入** (從應用程式)
+ 的金鑰 ID AWS KMS key。

  金鑰 ID 的值可以是 的金鑰 ID、金鑰 ARN、別名名稱或別名 ARN AWS KMS key。未包含在金鑰 ID 中的任何值，例如 區域，都必須在[AWS 具名設定檔](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html#cli-configure-files-using-profiles)中可用。金鑰 ARN 提供所有需要的值 AWS KMS 。

**輸入** (從項目加密程式)
+ [DynamoDB 加密內容](concepts.md#encryption-context)的副本，其中包含材料描述屬性的內容。

**輸出** (到項目加密程式)
+ 加密金鑰 (純文字)
+ 簽署金鑰

**處理**

1. Direct KMS 提供者會從加密項目中的資料描述屬性取得加密的資料金鑰。

1. 它會要求 AWS KMS 使用指定的 AWS KMS key 來[解密](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html)加密的資料金鑰。此操作會傳回純文字金鑰。

   此要求必須使用先前用來產生和加密資料金鑰的相同 [AWS KMS 加密內容](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)。
   + aws-kms-table – *資料表名稱*
   + *分割區索引鍵名稱* – *分割區索引鍵值* （二進位值為 Base64-encoded)
   + （選用） *排序索引鍵名稱* – *排序索引鍵值* （二進位值為 Base64-encoded)
   + amzn-ddb-env-alg – 預設 AES/256 加密演算法
   + amzn-ddb-sig-alg – 簽署演算法，預設 HmacSHA256/256

1. 直接 KMS 提供者會使用[安全雜湊演算法 (SHA) 256](https://en.wikipedia.org/wiki/SHA-2) 和 [RFC5869 HMAC 式金鑰衍生函數](https://tools.ietf.org/html/rfc5869)，從資料金鑰衍生 256 位元 AES 對稱加密金鑰和 256 位元 HMAC-SHA-256 簽署金鑰。

1. 直接 KMS 提供者會將輸出傳回至項目加密程式。

1. 項目加密程式會使用簽署金鑰來驗證項目。如果成功，則會使用對稱加密金鑰將加密的屬性值解密。這些操作會使用實際資料描述中指定的加密和簽署演算法。項目加密程式會盡快從記憶體中移除這些純文字金鑰。

# 包裝資料提供者
<a name="wrapped-provider"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

*包裝資料提供者* （包裝 CMP) 可讓您將來自任何來源的包裝和簽署金鑰與 DynamoDB 加密用戶端搭配使用。包裝 CMP 不依賴於任何 AWS 服務。不過，您必須在用戶端以外產生及管理包裝和簽署金鑰，包括提供正確的金鑰來驗證和解密項目。

包裝 CMP 會為每個項目產生唯一的項目加密金鑰。其將使用您所提供的包裝金鑰來包裝項目加密金鑰，並將包裝的項目加密金鑰儲存至項目的[資料描述屬性](DDBEC-legacy-concepts.md#legacy-material-description)。因為您提供包裝和簽署金鑰，所以由您決定包裝和簽署金鑰的產生方式，以及要讓每個項目各有唯一的金鑰還是重複使用。

對於可以管理密碼編譯資料的應用程式而言，包裝 CMP 是安全的實作與理想的選擇。

包裝 CMP 是 DynamoDB Encryption Client 支援的幾個[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMPs) 之一。如需其他 CMP 的相關資訊，請參閱[密碼編譯資料提供者](crypto-materials-providers.md)。

**如需範例程式碼，請參閱：**
+ Java：[AsymmetricEncryptedItem](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AsymmetricEncryptedItem.java)
+ Python：[wrapped-rsa-encrypted-table](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/wrapped_rsa_encrypted_table.py)，[wrapped-symmetric-encrypted-table](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/wrapped_symmetric_encrypted_table.py)

**Topics**
+ [使用方式](#wrapped-cmp-how-to-use)
+ [運作方式](#wrapped-cmp-how-it-works)

## 使用方式
<a name="wrapped-cmp-how-to-use"></a>

若要建立包裝 CMP，請指定包裝金鑰 (加密時需要)、取消包裝金鑰 (解密時需要) 以及簽署金鑰。您必須在加密和解密項目時提供金鑰。

包裝、取消包裝和簽署金鑰可以是對稱金鑰或非對稱金鑰對。

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

```
// This example uses asymmetric wrapping and signing key pairs
final KeyPair wrappingKeys = ...
final KeyPair signingKeys = ...

final WrappedMaterialsProvider cmp = 
    new WrappedMaterialsProvider(wrappingKeys.getPublic(),
                                 wrappingKeys.getPrivate(),
                                 signingKeys);
```

------
#### [ Python ]

```
# This example uses symmetric wrapping and signing keys
wrapping_key = ...
signing_key  = ...

wrapped_cmp = WrappedCryptographicMaterialsProvider(
    wrapping_key=wrapping_key,
    unwrapping_key=wrapping_key,
    signing_key=signing_key
)
```

------

## 運作方式
<a name="wrapped-cmp-how-it-works"></a>

包裝 CMP 會為每個項目產生新的項目加密金鑰。如下圖所示，它會使用您所提供的包裝、取消包裝和簽署金鑰。

![\[DynamoDB 加密用戶端中包裝材料提供者的輸入、處理和輸出\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/wrappedCMP.png)


### 取得加密資料
<a name="wrapped-cmp-get-encryption-materials"></a>

本節將詳細說明包裝資料提供者 (包裝 CMP) 在接收到加密資料請求時的輸入、輸出和處理情形。

**輸入** (從應用程式)
+ 包裝金鑰：[進階加密標準](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) (AES) 對稱金鑰，或 [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) 公有金鑰。如有任何已加密的屬性值，則為必要。否則為選用並予以忽略。
+ 取消包裝金鑰：選用並予以忽略。
+ 簽署金鑰

**輸入** (從項目加密程式)
+ [DynamoDB 加密內容](concepts.md#encryption-context)

**輸出** (到項目加密程式)：
+ 純文字項目加密金鑰
+ 簽署金鑰 (不變)
+ [實際資料描述](DDBEC-legacy-concepts.md#legacy-material-description)：這些值會儲存在用戶端新增至項目的[資料描述屬性](DDBEC-legacy-concepts.md#legacy-material-description)中。
  + `amzn-ddb-env-key`：Base64 編碼的包裝項目加密金鑰
  + `amzn-ddb-env-alg`：用來加密項目的加密演算法。預設為 AES-256-CBC。
  + `amzn-ddb-wrap-alg`：包裝 CMP 用來包裝項目加密金鑰的包裝演算法。如果包裝金鑰是 AES 金鑰，則會使用未填補的 `AES-Keywrap` (如 [RFC 3394](https://tools.ietf.org/html/rfc3394.html) 定義) 來包裝此金鑰。如果包裝金鑰是 RSA 金鑰，則會使用 RSA OAEP (MGF1 填補) 來加密此金鑰。

**處理**

當您加密項目時，您會傳入包裝金鑰和簽署金鑰。取消包裝金鑰為選用並予以忽略。

1. 包裝 CMP 會為資料表項目產生唯一的對稱項目加密金鑰。

1. 它會使用您指定的包裝金鑰來包裝項目加密金鑰。接著，它會盡快從記憶體中移除此金鑰。

1. 其將傳回純文字項目加密金鑰、您所提供的簽署金鑰，以及包含包裝項目加密金鑰和加密與包裝演算法的[實際資料描述](DDBEC-legacy-concepts.md#legacy-material-description)。

1. 項目加密程式會使用純文字加密金鑰來加密項目。它會使用您所提供的簽署金鑰來簽署金鑰。接著，它會盡快從記憶體中移除這些純文字金鑰。它會將實際資料描述中的欄位 (包括包裝加密金鑰 (`amzn-ddb-env-key`)) 複製到項目的資料描述屬性。

### 取得解密資料
<a name="wrapped-cmp-get-decryption-materials"></a>

本節將詳細說明包裝資料提供者 (包裝 CMP) 在接收到解密資料請求時的輸入、輸出和處理情形。

**輸入** (從應用程式)
+ 包裝金鑰：選用並予以忽略。
+ 取消包裝金鑰：相同的[進階加密標準](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) (AES) 對稱金鑰，或與加密使用的 [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) 公有金鑰對應的 RSA 私有金鑰。如有任何已加密的屬性值，則為必要。否則為選用並予以忽略。
+ 簽署金鑰

**輸入** (從項目加密程式)
+ [DynamoDB 加密內容](concepts.md#encryption-context)的副本，其中包含材料描述屬性的內容。

**輸出** (到項目加密程式)
+ 純文字項目加密金鑰
+ 簽署金鑰 (不變)

**處理**

當您解密項目時，您會傳入取消包裝金鑰和簽署金鑰。包裝金鑰為選用並予以忽略。

1. 包裝 CMP 會從項目的資料描述屬性取得包裝項目加密金鑰。

1. 它會使用取消包裝金鑰和演算法來取消包裝項目加密金鑰。

1. 它會將純文字項目加密金鑰、簽署金鑰以及加密和簽署演算法傳回給項目加密程式。

1. 項目加密程式會使用簽署金鑰來驗證項目。如果成功，則會使用項目加密金鑰來將項目解密。接著，它會盡快從記憶體中移除這些純文字金鑰。

# 最近提供者
<a name="most-recent-provider"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

*最近提供者*是一個[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP)，旨在與[提供者存放區](DDBEC-legacy-concepts.md#provider-store)搭配使用。它會從提供者存放區取得 CMP，並取得它從 CMP 傳回的密碼編譯資料。其通常會使用各個 CMP 因應多次密碼編譯資料請求。但您也可以使用提供者存放區的功能來控制資料的重複使用程度、決定 CMP 的輪換頻率，甚至在不變更「最近提供者」的情況下變更所使用的 CMP 類型。

**注意**  
與最近提供者的 `MostRecentProvider`符號相關聯的程式碼可能會在程序的生命週期內將密碼編譯資料存放在記憶體中。它可能會允許發起人使用他們不再獲授權使用的金鑰。  
`MostRecentProvider` 符號已在 DynamoDB 加密用戶端的較舊支援版本中棄用，並從 2.0.0 版中移除。它被 `CachingMostRecentProvider`符號取代。如需詳細資訊，請參閱[最近提供者的更新](#mrp-versions)。

對於需要盡可能避免呼叫提供者存放區與其密碼編譯來源的應用程式，以及可重複使用部分密碼編譯資料而不會違反安全性需求的應用程式，最近提供者將是理想的選擇。例如，它可讓您在 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)的 下保護您的密碼編譯資料，而不必 AWS KMS 在每次加密或解密項目時呼叫 。

您選擇的提供者存放區可決定最近提供者使用的 CMP 類型，以及其取得新 CMP 的頻率。您可以使用任何相容提供者存放區搭配最近提供者，包括您所設計的自訂提供者存放區。

DynamoDB 加密用戶端包含 *MetaStore*，可建立和傳回[包裝材料提供者 ](wrapped-provider.md)（包裝 CMPs)。MetaStore 會儲存其在內部 DynamoDB 資料表中產生的多個包裝 CMPs 版本，並透過 DynamoDB 加密用戶端的內部執行個體進行用戶端加密來保護它們。

您可以設定 MetaStore 使用任何類型的內部 CMP 來保護資料表中的資料，包括產生受 保護之密碼編譯資料的[直接 KMS 提供者](direct-kms-provider.md) AWS KMS key、使用您提供的包裝和簽署金鑰的包裝 CMP，或您設計的相容自訂 CMP。

**如需範例程式碼，請參閱：**
+ Java：[MostRecentEncryptedItem](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/MostRecentEncryptedItem.java)
+ Python：[most\$1recent\$1provider\$1encrypted\$1table](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/most_recent_provider_encrypted_table.py)

**Topics**
+ [使用方式](#mrp-how-to-use-it)
+ [運作方式](#mrp-how-it-works)
+ [最近提供者的更新](#mrp-versions)

## 使用方式
<a name="mrp-how-to-use-it"></a>

若要建立最近提供者，您必須建立及設定提供者存放區，然後建立可使用該提供者存放區的最近提供者。

下列範例示範如何建立最近使用 MetaStore 的提供者，並使用來自[直接 KMS 提供者](direct-kms-provider.md)的密碼編譯資料來保護其內部 DynamoDB 資料表中的版本。這些範例使用 [`CachingMostRecentProvider`](#mrp-versions)符號。

每個最近提供者都有一個在 MetaStore 資料表中識別其 CMPs 的名稱、[time-to-live](#most-recent-provider-ttl)(TTL) 設定，以及決定快取可以保留多少個項目的快取大小設定。這些範例將快取大小設定為 1000 個項目，TTL 為 60 秒。

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

```
// Set the name for MetaStore's internal table
final String keyTableName = 'metaStoreTable'

// Set the Region and AWS KMS key
final String region = 'us-west-2'
final String keyArn = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'

// Set the TTL and cache size
final long ttlInMillis = 60000;
final long cacheSize = 1000;

// Name that identifies the MetaStore's CMPs in the provider store
final String materialName = 'testMRP'

// Create an internal DynamoDB client for the MetaStore
final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard().withRegion(region).build();

// Create an internal Direct KMS Provider for the MetaStore
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider kmsProv = new DirectKmsMaterialProvider(kms, keyArn);

// Create an item encryptor for the MetaStore,
// including the Direct KMS Provider
final DynamoDBEncryptor keyEncryptor = DynamoDBEncryptor.getInstance(kmsProv);

// Create the MetaStore
final MetaStore metaStore = new MetaStore(ddb, keyTableName, keyEncryptor);

//Create the Most Recent Provider
final CachingMostRecentProvider cmp = new CachingMostRecentProvider(metaStore, materialName, ttlInMillis, cacheSize);
```

------
#### [ Python ]

```
# Designate an AWS KMS key
kms_key_id = 'arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'

# Set the name for MetaStore's internal table
meta_table_name = 'metaStoreTable'

# Name that identifies the MetaStore's CMPs in the provider store
material_name = 'testMRP'

# Create an internal DynamoDB table resource for the MetaStore
meta_table = boto3.resource('dynamodb').Table(meta_table_name)

# Create an internal Direct KMS Provider for the MetaStore
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=kms_key_id)
    
# Create the MetaStore with the Direct KMS Provider
meta_store = MetaStore(
    table=meta_table,
    materials_provider=kms_cmp
)

# Create a Most Recent Provider using the MetaStore
#    Sets the TTL (in seconds) and cache size (# entries)
most_recent_cmp = MostRecentProvider(
    provider_store=meta_store,
    material_name=material_name,
    version_ttl=60.0,
    cache_size=1000
)
```

------

## 運作方式
<a name="mrp-how-it-works"></a>

最近提供者會從提供者存放區取得 CMP。然後，它會使用 CMP 來產生密碼編譯資料並將其傳回給項目加密程式。

### 關於最近提供者
<a name="about-mrp"></a>

最近的提供者會從提供者[存放區](DDBEC-legacy-concepts.md#provider-store)取得[密碼編譯資料](DDBEC-legacy-concepts.md#concept-material-provider)提供者 (CMP)。然後，它會使用 CMP 來產生可傳回的密碼編譯資料。每個最近提供者都會與一個提供者存放區相關聯，但提供者存放區可以將 CMP 提供給多部主機上的多個提供者。

最近提供者可與任何提供者存放區中的任何相容 CMP 搭配使用。它會向 CMP 請求加密或解密資料，並將輸出傳回給項目加密程式。並不會執行任何密碼編譯操作。

若要向提供者存取區請求 CMP，最近提供者可提供其資料名稱以及想要使用的現有 CMP 版本。針對加密資料，最近提供者一律會請求最大 (「最近」) 版本。針對解密資料，其將請求用來建立加密資料的 CMP 版本 (如下圖所示)。

![\[最近提供者\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/most-recent-provider-1.png)


最近提供者會將提供者存放區傳回的 CMP 版本儲存於記憶體中的本機最久未使用 (LRU) 快取。此快取可讓最近提供者取得它所需的 CMP，而不需針對每個項目呼叫提供者存放區。您可以隨需清除此快取。

最近的提供者使用可設定的[time-to-live值](#most-recent-provider-ttl)，您可以根據應用程式的特性進行調整。

### 關於中繼存放區
<a name="about-metastore"></a>

您可以使用最近提供者搭配任何提供者存放區，包括相容的自訂提供者存放區。DynamoDB 加密用戶端包含 MetaStore，這是您可以設定和自訂的安全實作。

*中繼存放區*是一個[提供者存放區](DDBEC-legacy-concepts.md#provider-store)，可建立及傳回包裝 CMP 所需的包裝金鑰、取消包裝金鑰和簽署金鑰設定的[包裝 CMP](wrapped-provider.md)。MetaStore 是最近提供者的安全選項，因為包裝 CMPs一律為每個項目產生唯一的項目加密金鑰。只有可保護項目加密金鑰的包裝金鑰以及簽署金鑰能重複使用。

下圖說明中繼存放區元件以及其與最近提供者互動的方式。

![\[中繼存放區\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/most-recent-provider-2.png)


MetaStore 會產生包裝 CMPs，然後將它們 （以加密形式） 存放在內部 DynamoDB 資料表中。分割區索引鍵是最近提供者材料的名稱；排序索引鍵是其版本編號。資料表中的資料受到內部 DynamoDB 加密用戶端的保護，包括項目加密程式和內部[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP)。

您可在中繼存放區使用任何類型的內部 CMP，包括[直接 KMS 提供者](wrapped-provider.md)、具有您所提供密碼編譯資料的包裝 CMP，或相容的自訂 CMP。如果 MetaStore 中的內部 CMP 是直接 KMS 提供者，則可重複使用的包裝和簽署金鑰會受到 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)() [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys) 中的 保護AWS KMS。每次 MetaStore 將新的 CMP 版本新增至其內部資料表或從其內部資料表取得 CMP 版本 AWS KMS 時，都會呼叫 。

### 設定time-to-live值
<a name="most-recent-provider-ttl"></a>

您可以為您建立的每個最近提供者設定time-to-live(TTL) 值。一般而言，請使用適用於您應用程式的最低 TTL 值。

TTL 值的使用會在最近提供者的 `CachingMostRecentProvider`符號中變更。

**注意**  
最近提供者的`MostRecentProvider`符號已在 DynamoDB 加密用戶端的較舊支援版本中棄用，並從 2.0.0 版中移除。它被 `CachingMostRecentProvider`符號取代。我們建議您盡快更新程式碼。如需詳細資訊，請參閱[最近提供者的更新](#mrp-versions)。

**`CachingMostRecentProvider`**  
會以兩種不同的方式`CachingMostRecentProvider`使用 TTL 值。  
+ TTL 會決定最近提供者檢查提供者存放區是否有新版本的 CMP 的頻率。如果有新版本可用，最近提供者會取代其 CMP 並重新整理其密碼編譯資料。否則，它會繼續使用其目前的 CMP 和密碼編譯資料。
+ TTL 會決定快取中的 CMPs 可以使用多久。在使用快取的 CMP 進行加密之前，最近提供者會評估其在快取中的時間。如果 CMP 快取時間超過 TTL，則會從快取中移出 CMP，而最近提供者會從其提供者存放區取得最新版本的新 CMP。

**`MostRecentProvider`**  
在 中`MostRecentProvider`，TTL 會決定最近提供者檢查提供者存放區是否有新版本的 CMP 的頻率。如果有新版本可用，最近提供者會取代其 CMP 並重新整理其密碼編譯資料。否則，它會繼續使用其目前的 CMP 和密碼編譯資料。

TTL 不會判斷新 CMP 版本的建立頻率。您可以透過[輪換密碼編譯資料](#most-recent-provider-rotate)來建立新的 CMP 版本。

理想的 TTL 值會隨應用程式及其延遲和可用性目標而有所不同。較低的 TTL 可減少密碼編譯資料儲存在記憶體中的時間，進而改善您的安全性設定檔。此外，較低的 TTL 會更頻繁地重新整理重要資訊。例如，如果您的內部 CMP 是[直接 KMS 提供者](direct-kms-provider.md)，它會更頻繁地驗證發起人是否仍獲授權使用 AWS KMS key。

不過，如果 TTL 太短，對提供者存放區的頻繁呼叫可能會增加您的成本，並導致提供者存放區調節來自您應用程式和其他共用您服務帳戶的應用程式的請求。您也可能受益於將 TTL 與輪換密碼編譯材料的速率進行協調。

在測試期間， 會在不同的工作負載下變更 TTL 和快取大小，直到您找到適合您應用程式以及安全性和效能標準的組態為止。

### 輪換密碼編譯資料
<a name="most-recent-provider-rotate"></a>

當最近提供者需要加密資料時，一律會使用其已知的最新版本 CMP。其檢查較新版本的頻率，取決於您在設定最近提供者時所設定的[time-to-live](#most-recent-provider-ttl)(TTL) 值。

當 TTL 過期時，最近提供者會檢查提供者存放區是否有較新版本的 CMP。如果有的話，最近的提供者會取得它，並取代其快取中的 CMP。它會使用此 CMP 及其密碼編譯資料，直到發現提供者存放區有較新的版本為止。

若要告知提供者存放區為最近提供者建立新的 CMP 版本，請以最近提供者的資料名稱呼叫提供者存放區的「建立新提供者」操作。提供者存放區會建立新的 CMP，並且在其內部儲存體中使用較大版本號碼儲存已加密的複本。(它也會傳回 CMP，但您可予以捨棄。) 因此，當最近提供者下次查詢提供者存放區以取得其 CMPs 的最大版本編號時，就會取得新的較大版本編號，並在後續對存放區的請求中使用它來查看是否已建立新的 CMP 版本。

您可以根據時間、處理的項目或屬性數目，或是對您應用程式有意義的任何其他度量，為您的「建立新提供者」呼叫進行排程。

### 取得加密資料
<a name="most-recent-provider-encrypt"></a>

最近提供者會使用下列程序 (如下圖所示)，取得它傳回給項目加密程式的加密資料。輸出取決於提供者存放區所傳回的 CMP 類型。最近提供者可以使用任何相容的提供者存放區，包括 DynamoDB 加密用戶端中包含的 MetaStore。

![\[DynamoDB 加密用戶端中最近提供者的輸入、處理和輸出\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/most-recent-provider-provider-store.png)


當您使用 [`CachingMostRecentProvider`符號](#mrp-versions)建立最近提供者時，您可以指定提供者存放區、最近提供者的名稱，以及[time-to-live](#most-recent-provider-ttl)(TTL) 值。您也可以選擇性地指定快取大小，以決定快取中可存在的密碼編譯資料數目上限。

當項目加密程式向最近提供者詢問加密資料時，最近提供者會開始搜尋其快取中的 CMP 最新版本。
+ 如果它在其快取中找到最新版本的 CMP，且 CMP 未超過 TTL 值，則最近提供者會使用 CMP 來產生加密資料。接著，它會將加密資料傳回給項目加密程式。此作業不需要呼叫提供者存放區。
+ 如果最新版本的 CMP 不在其快取中，或位於快取中但已超過其 TTL 值，則最近提供者會向其提供者存放區請求 CMP。此請求包括最近提供者資料名稱及其所知的最大版本號碼。

  1. 提供者存放區會從其持久性儲存體傳回 CMP。如果提供者存放區是 MetaStore，則會使用最近提供者材料名稱做為分割區索引鍵，並將版本編號做為排序索引鍵，從其內部 DynamoDB 資料表取得加密的包裝 CMP。中繼存放區會使用其內部項目加密程式和內部 CMP，將包裝 CMP 解密。接著，它會將純文字 CMP 傳回給最近提供者。如果內部 CMP 是[直接 KMS 提供者](direct-kms-provider.md)，這個步驟就包括對 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/) (AWS KMS) 的呼叫。

  1. CMP 會將 `amzn-ddb-meta-id` 欄位新增至[實際資料描述](DDBEC-legacy-concepts.md#legacy-material-description)。其值為資料名稱與其內部資料表中的 CMP 版本。提供者存放區會將 CMP 傳回給最近提供者。

  1. 最近提供者會快取記憶體中的 CMP。

  1. 最近提供者會使用 CMP 來產生加密資料。接著，它會將加密資料傳回給項目加密程式。

### 取得解密資料
<a name="most-recent-provider-decrypt"></a>

當項目加密程式向最近提供者詢問解密資料時，最近提供者會使用下列程序來取得和傳回解密資料。

1. 最近提供者會向提供者存放區詢問用來加密項目的密碼編譯資料版本號碼。其將從項目的[資料描述屬性](DDBEC-legacy-concepts.md#legacy-material-description)傳入實際資料描述。

1. 提供者存放區會從實際資料描述中的 `amzn-ddb-meta-id` 欄位取得加密 CMP 版本號碼，並將它傳回給最近提供者。

1. 最近提供者會在其快取中搜尋用來加密和簽署項目的 CMP 版本。
+ 如果發現 CMP 的相符版本在其快取中，且 CMP 未超過[time-to-live(TTL) 值](#most-recent-provider-ttl)，則最近提供者會使用 CMP 產生解密資料。接著，它會將解密資料傳回給項目加密程式。此操作不需要呼叫提供者存放區或任何其他 CMP。
+ 如果 CMP 的相符版本不在快取中，或快取 AWS KMS key 超過其 TTL 值，則最近提供者會向其提供者存放區請求 CMP。其會在請求中傳送資料名稱與加密 CMP 版本號碼。

  1. 提供者存放區會使用最近提供者名稱作為分割區索引鍵並使用版本號碼作為排序索引鍵，在其持久性儲存體中搜尋 CMP。
     + 如果其持久性儲存體中沒有此名稱和版本號碼，則提供者存放區會擲出例外狀況。如果提供者存放區用來產生 CMP，則 CMP 應存放在其持久性儲存體中 (除非它遭到故意刪除)。
     + 如果提供者存放區的持久性儲存體中有具備相符名稱和版本號碼的 CMP，則提供者存放區會將指定的 CMP 傳回給最近提供者。

       如果提供者存放區是 MetaStore，則會從其 DynamoDB 資料表取得加密的 CMP。然後，它會先使用其內部 CMP 提供的密碼編譯資料、將已加密的 CMP 解密，再將 CMP 傳回給最近提供者。如果內部 CMP 是[直接 KMS 提供者](direct-kms-provider.md)，這個步驟就包括對 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/) (AWS KMS) 的呼叫。

  1. 最近提供者會快取記憶體中的 CMP。

  1. 最近提供者會使用 CMP 來產生解密資料。接著，它會將解密資料傳回給項目加密程式。

## 最近提供者的更新
<a name="mrp-versions"></a>

最近提供者的 符號從 變更為 `MostRecentProvider` `CachingMostRecentProvider`。

**注意**  
代表最近提供者的 `MostRecentProvider`符號已在適用於 Java 的 DynamoDB 加密用戶端 1.15 版和適用於 Python 的 DynamoDB 加密用戶端 1.3 版中棄用，並在兩種語言實作中從 DynamoDB 加密用戶端 2.0.0 版中移除。請改用 `CachingMostRecentProvider`。

`CachingMostRecentProvider` 實作下列變更：
+ 當記憶體中的時間超過設定的[time-to-live (TTL) 值](#most-recent-provider-ttl)時， 會`CachingMostRecentProvider`定期從記憶體中移除密碼編譯資料。

  `MostRecentProvider` 可能會在程序的生命週期內將密碼編譯資料存放在記憶體中。因此，最近提供者可能不知道授權變更。在呼叫者的許可被撤銷後，它可能會使用加密金鑰。

  如果您無法更新至此新版本，您可以定期呼叫快取上的 `clear()`方法，以取得類似的效果。此方法會手動排清快取內容，並要求最近提供者請求新的 CMP 和新的密碼編譯資料。
+ `CachingMostRecentProvider` 也包含快取大小設定，可讓您進一步控制快取。

若要更新 `CachingMostRecentProvider`，您必須變更程式碼中的符號名稱。在所有其他方面， `CachingMostRecentProvider` 與 完全向後相容`MostRecentProvider`。您不需要重新加密任何資料表項目。

不過， `CachingMostRecentProvider`會產生更多對基礎金鑰基礎設施的呼叫。它會在每個time-to-live(TTL) 間隔至少呼叫提供者存放區一次。具有許多作用中 CMPs的應用程式 （由於頻繁輪換） 或具有大型機群的應用程式最有可能對此變更敏感。

在發佈更新後的程式碼之前，請徹底進行測試，以確保更頻繁的呼叫不會損害您的應用程式，或導致供應商所依賴的服務限流，例如 AWS Key Management Service (AWS KMS) 或 Amazon DynamoDB。若要緩解任何效能問題，`CachingMostRecentProvider`請根據您觀察到的效能特性，調整 的快取大小和time-to-live。如需準則，請參閱[設定time-to-live值](#most-recent-provider-ttl)。

# 靜態資料提供者
<a name="static-provider"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

*靜態資料提供者* (Static CMP) 是非常簡單的[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP)，用於測試、proof-of-concept示範和舊版相容性。

若要使用靜態 CMP 加密資料表項目，請提供[進階加密標準](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) (AES) 對稱加密金鑰與簽署金鑰或金鑰對。您必須提供相同的金鑰，才能將已加密的項目解密。靜態 CMP 不會執行任何密碼編譯操作。它反而會以原狀傳遞您提供給項目加密程式的加密金鑰。項目加密程式會直接以加密金鑰加密項目。然後，直接使用簽署金鑰進行簽署。

因為靜態 CMP 不會產生任何獨特的密碼編譯資料，您處理的所有資料表項目都會使用相同加密金鑰進行加密並由相同的簽署金鑰進行簽署。當您使用相同的金鑰加密眾多項目的屬性值，或使用相同金鑰或金鑰對來簽署所有項目時，可能會超出金鑰的密碼編譯限制。

**注意**  
Java 程式庫中的[非對稱靜態提供者](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/providers/AsymmetricStaticProvider.html)不是靜態提供者。其僅提供[包裝 CMP](wrapped-provider.md) 的替代建構函數。此可在生產環境中安全地使用，但只要情況允許，您即應直接使用包裝 CMP。

靜態 CMP 是 DynamoDB Encryption Client 支援的數個[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMPs) 之一。如需其他 CMP 的相關資訊，請參閱[密碼編譯資料提供者](crypto-materials-providers.md)。

**如需範例程式碼，請參閱：**
+ Java：[SymmetricEncryptedItem](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/SymmetricEncryptedItem.java)

**Topics**
+ [使用方式](#static-cmp-how-to-use)
+ [運作方式](#static-cmp-how-it-works)

## 使用方式
<a name="static-cmp-how-to-use"></a>

若要建立靜態提供者，請提供加密金鑰或金鑰對和簽署金鑰或金鑰對。您必須提供金鑰資料才能加密和解密資料表項目。

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

```
// To encrypt
SecretKey cek = ...;        // Encryption key
SecretKey macKey =  ...;    // Signing key
EncryptionMaterialsProvider provider = new SymmetricStaticProvider(cek, macKey);

// To decrypt
SecretKey cek = ...;        // Encryption key
SecretKey macKey =  ...;    // Verification key
EncryptionMaterialsProvider provider = new SymmetricStaticProvider(cek, macKey);
```

------
#### [ Python ]

```
# You can provide encryption materials, decryption materials, or both
encrypt_keys = EncryptionMaterials(
    encryption_key = ...,
    signing_key = ...
)

decrypt_keys = DecryptionMaterials(
    decryption_key = ...,
    verification_key = ...
)

static_cmp = StaticCryptographicMaterialsProvider(
    encryption_materials=encrypt_keys
    decryption_materials=decrypt_keys
)
```

------

## 運作方式
<a name="static-cmp-how-it-works"></a>

靜態提供者會傳遞您提供給項目加密程式的加密和簽署金鑰，直接用來加密和簽署資料表項目。除非您針對每個項目提供不同的金鑰，否則每個項目都會使用相同金鑰。

![\[DynamoDB 加密用戶端中靜態資料提供者的輸入、處理和輸出\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/staticCMP.png)


### 取得加密資料
<a name="static-cmp-get-encryption-materials"></a>

本節將詳細說明靜態資料提供者 (靜態 CMP) 在接收到加密資料請求時的輸入、輸出和處理情形。

**輸入** (從應用程式)
+ 加密金鑰 – 這必須是對稱金鑰，例如[進階加密標準](https://tools.ietf.org/html/rfc3394.html) (AES) 金鑰。
+ 簽署金鑰 – 這可以是對稱金鑰或非對稱金鑰對。

**輸入** (從項目加密程式)
+ [DynamoDB 加密內容](concepts.md#encryption-context)

**輸出** (到項目加密程式)
+ 當作輸入傳遞的加密金鑰。
+ 當作輸入傳遞的簽署金鑰。
+ 實際資料描述：[請求的資料描述](DDBEC-legacy-concepts.md#legacy-material-description) (如果有) 會維持原狀。

### 取得解密資料
<a name="static-cmp-get-decryption-materials"></a>

本節將詳細說明靜態資料提供者 (靜態 CMP) 在接收到解密資料請求時的輸入、輸出和處理情形。

雖然它包括取得加密資料及取得解密資料的個別方法，但是行為相同。

**輸入** (從應用程式)
+ 加密金鑰 – 這必須是對稱金鑰，例如[進階加密標準](https://tools.ietf.org/html/rfc3394.html) (AES) 金鑰。
+ 簽署金鑰 – 這可以是對稱金鑰或非對稱金鑰對。

**輸入** (從項目加密程式)
+ [DynamoDB 加密內容](concepts.md#encryption-context) （未使用）

**輸出** (到項目加密程式)
+ 當作輸入傳遞的加密金鑰。
+ 當作輸入傳遞的簽署金鑰。

# Amazon DynamoDB Encryption Client 可用的程式設計語言
<a name="programming-languages"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的相關資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

Amazon DynamoDB 加密用戶端適用於下列程式設計語言。語言專屬的程式庫有所不同，但是產生的實作都是可互通的。例如，您可以使用 Java 用戶端來加密 (和簽署) 項目，以及使用 Python 用戶端將項目解密。

如需詳細資訊，請參閱相關主題。

**Topics**
+ [Java](java.md)
+ [Python](python.md)

# 適用於 Java 的 Amazon DynamoDB 加密用戶端
<a name="java"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

本主題說明如何安裝和使用適用於 Java 的 Amazon DynamoDB 加密用戶端。如需使用 DynamoDB 加密用戶端進行程式設計的詳細資訊，請參閱 [Java 範例](java-examples.md)、GitHub 上 aws-dynamodb-encryption-java 儲存庫中[的範例](https://github.com/aws/aws-dynamodb-encryption-java/tree/master/examples)，以及 DynamoDB 加密用戶端的 [Javadoc](https://aws.github.io/aws-dynamodb-encryption-java/)。

**注意**  
適用於 Java 的 DynamoDB 加密用戶端版本 1.*x*.*x* 自 2022 年 7 月起處於[end-of-support階段](what-is-database-encryption-sdk.md#support)。盡快升級至較新的版本。

**Topics**
+ [先決條件](#java-prerequisites)
+ [安裝](#java-installation)
+ [使用適用於 Java 的 DynamoDB 加密用戶端](java-using.md)
+ [Java 範例](java-examples.md)

## 先決條件
<a name="java-prerequisites"></a>

安裝適用於 Java 的 Amazon DynamoDB 加密用戶端之前，請確定您有下列先決條件。

**Java 開發環境**  
您會需要 Java 8 或更新版本。在 Oracle 網站上，移至 [Java SE 下載](https://www.oracle.com/java/technologies/downloads/)，然後下載並安裝 Java SE 開發套件 (JDK)。  
如果您使用 Oracle JDK，您還必須下載並安裝 [Java Cryptography Extension (JCE) Unlimited Strength 管轄權政策檔案](http://www.oracle.com/java/technologies/javase-jce8-downloads.html)。

**適用於 Java 的 AWS SDK**  
DynamoDB 加密用戶端需要 的 DynamoDB 模組， 適用於 Java 的 AWS SDK 即使您的應用程式未與 DynamoDB 互動。您可以安裝整個 SDK 或只安裝這個模組。如果您使用 Maven，請將 `aws-java-sdk-dynamodb` 新增到 `pom.xml` 檔案。  
如需安裝和設定 的詳細資訊 適用於 Java 的 AWS SDK，請參閱 [適用於 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/getting-started.html)。

## 安裝
<a name="java-installation"></a>

您可以透過下列方式安裝適用於 Java 的 Amazon DynamoDB 加密用戶端。

**手動**  
若要安裝適用於 Java 的 Amazon DynamoDB 加密用戶端，請複製或下載 [aws-dynamodb-encryption-java](https://github.com/aws/aws-dynamodb-encryption-java/) GitHub 儲存庫。

**使用 Apache Maven**  
Amazon DynamoDB Encryption Client for Java 可透過 [Apache Maven](https://maven.apache.org/) 使用下列相依性定義。  

```
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-dynamodb-encryption-java</artifactId>
  <version>version-number</version>
</dependency>
```

安裝軟體開發套件後，請先查看本指南中的範例程式碼，以及 GitHub 上的 [DynamoDB 加密用戶端 Javadoc](https://aws.github.io/aws-dynamodb-encryption-java/)。

# 使用適用於 Java 的 DynamoDB 加密用戶端
<a name="java-using"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

本主題說明在 Java 中可能無法在其他程式設計語言實作中找到的 DynamoDB 加密用戶端的一些功能。

如需使用 DynamoDB 加密用戶端進行程式設計的詳細資訊，請參閱 [Java 範例](java-examples.md)、GitHub `aws-dynamodb-encryption-java repository`上 中[的範例](https://github.com/aws/aws-dynamodb-encryption-java/tree/master/examples)，以及 DynamoDB 加密用戶端的 [Javadoc](https://aws.github.io/aws-dynamodb-encryption-java/)。



**Topics**
+ [項目加密程式](#attribute-encryptor)
+ [設定儲存行為](#save-behavior)
+ [Java 中的屬性動作](#attribute-actions-java)
+ [覆寫表格名稱](#override-table-name)

## 項目加密程式：AttributeEncryptor 和 DynamoDBEncryptor
<a name="attribute-encryptor"></a>

Java 中的 DynamoDB 加密用戶端有兩個[項目加密程式](DDBEC-legacy-concepts.md#item-encryptor)：較低層級的 [DynamoDBEncryptor](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html) 和 [AttributeEncryptor](#attribute-encryptor)。

`AttributeEncryptor` 是一種協助程式類別，可協助您在 DynamoDB 加密用戶端的 中使用 [DynamoDBMapper](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html) 適用於 Java 的 AWS SDK 與 。 `DynamoDB Encryptor` DynamoDB 當您搭配 `DynamoDBMapper` 使用 `AttributeEncryptor` 時，它會在您保存項目時，透明地加密和簽署您的項目。當您載入項目時，它也會透明地驗證和解密您的項目。

## 設定儲存行為
<a name="save-behavior"></a>

您可以使用 `AttributeEncryptor`和 `DynamoDBMapper` ，將資料表項目新增或取代為僅簽署或加密和簽署的屬性。對於這些任務，我們建議您將其設定為使用 `PUT` 儲存行為，如下列範例所示。否則，您將可能無法解密資料。

```
DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder().withSaveBehavior(SaveBehavior.PUT).build();
DynamoDBMapper mapper = new DynamoDBMapper(ddb, mapperConfig, new AttributeEncryptor(encryptor));
```

如果您使用預設儲存行為，只會更新在資料表項目中建模的屬性，則未建模的屬性不會包含在簽章中，也不會透過資料表寫入變更。因此，在稍後讀取所有屬性時，簽章將不會驗證，因為它不包含未建模的屬性。

您也可以使用 `CLOBBER` 儲存行為。這種行為與 `PUT` 儲存行為完全相同，差別在於它會停用樂觀鎖定並覆寫表格中的項目。

為了防止簽章錯誤，如果 `AttributeEncryptor` 與未設定為 `CLOBBER`或 的儲存行為`DynamoDBMapper`的 搭配使用，則 DynamoDB Encryption Client 會擲回執行期例外狀況`PUT`。

若要查看範例中使用的此程式碼，請參閱 [使用 DynamoDBMapper](java-examples.md#java-example-dynamodb-mapper)和 GitHub 中`aws-dynamodb-encryption-java`儲存庫中的 [AwsKmsEncryptedObject.java](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedObject.java) 範例。

## Java 中的屬性動作
<a name="attribute-actions-java"></a>

[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)決定哪些屬性值會加密並簽署，哪些屬性值只會簽署，以及哪些屬性值會予忽略。您用來指定屬性動作的方法取決於您使用的是 `DynamoDBMapper` 和 `AttributeEncryptor`，還是較低層層級的 [DynamoDBEncryptor](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html)。

**重要**  
使用屬性動作加密表格項目後，從資料模型新增或移除屬性可能會導致簽章驗證錯誤，讓您無法解密資料。如需更詳細的說明，請參閱[變更您的資料模型](data-model.md)。

### DynamoDBMapper 的屬性動作
<a name="attribute-action-java-mapper"></a>

當您使用 `DynamoDBMapper` 和 `AttributeEncryptor` 時，您可使用註釋來指定屬性動作。DynamoDB 加密用戶端使用[標準 DynamoDB 屬性註釋](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Annotations.html)來定義屬性類型，以判斷如何保護屬性。除了主要索引鍵 (簽署但不加密) 以外，所有屬性都預設會進行加密和簽署。

**注意**  
雖然您可以 (而且應該) 簽署屬性值，但請勿使用 [@DynamoDBVersionAttribute 註釋](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptimisticLocking.html)來加密屬性值。否則，使用其值的情況將會造成想不到的影響。

```
// Attributes are encrypted and signed
@DynamoDBAttribute(attributeName="Description")

// Partition keys are signed but not encrypted
@DynamoDBHashKey(attributeName="Title")

// Sort keys are signed but not encrypted
@DynamoDBRangeKey(attributeName="Author")
```

若要指定例外狀況，請使用 DynamoDB Encryption Client for Java 中定義的加密註釋。如果您在類別層級指定例外狀況，這些例外狀況就會成為類別的預設值。

```
// Sign only
@DoNotEncrypt

// Do nothing; not encrypted or signed
@DoNotTouch
```

例如，這些註釋會簽署但不會加密 `PublicationYear` 屬性，且不會加密或簽署 `ISBN` 屬性值。

```
// Sign only (override the default)
@DoNotEncrypt
@DynamoDBAttribute(attributeName="PublicationYear")

// Do nothing (override the default)
@DoNotTouch
@DynamoDBAttribute(attributeName="ISBN")
```

### DynamoDBEncryptor 的屬性動作
<a name="attribute-action-default"></a>

若要在您直接使用 [DynamoDBEncryptor](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html) 時指定屬性動作，請建立 `HashMap` 物件，其中的名稱值組代表屬性名稱和指定的動作。

屬性動作的有效值會定義於 `EncryptionFlags` 列舉類型中。您可以同時使用 `ENCRYPT` 與 `SIGN`、單獨使用 `SIGN`，或省略兩者。不過，如果您`ENCRYPT`單獨使用 ，DynamoDB Encryption Client 會擲回錯誤。您無法加密您未簽署的屬性。

```
ENCRYPT
SIGN
```

**警告**  
請勿加密主索引鍵的屬性。它們必須保持純文字，以便 DynamoDB 可以在不執行完整資料表掃描的情況下找到項目。

如果您在加密內容中指定主金鑰，然後在任一主金鑰屬性的屬性動作`ENCRYPT`中指定 ，則 DynamoDB 加密用戶端會擲回例外狀況。

例如，下列 Java 程式碼會建立 `actions` HashMap，該 HashMap 會加密並簽署 `record` 項目中的所有屬性。例外狀況是分割索引鍵和排序索引鍵屬性 (已簽署但未加密)，以及未簽署或加密的 `test` 屬性。

```
final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN);
final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN);
final Map<String, Set<EncryptionFlags>> actions = new HashMap<>();

for (final String attributeName : record.keySet()) {
  switch (attributeName) {
    case partitionKeyName: // no break; falls through to next case
    case sortKeyName:
      // Partition and sort keys must not be encrypted, but should be signed
      actions.put(attributeName, signOnly);
      break;
    case "test":
      // Don't encrypt or sign
      break;
    default:
      // Encrypt and sign everything else
      actions.put(attributeName, encryptAndSign);
      break;
  }
}
```

然後，當您呼叫 的 [encryptRecord](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html#encryptRecord-java.util.Map-java.util.Map-com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext-) 方法時`DynamoDBEncryptor`，請將映射指定為 `attributeFlags` 參數的值。例如，`encryptRecord` 的這項呼叫會使用 `actions` 映射。

```
// Encrypt the plaintext record
final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
```

## 覆寫表格名稱
<a name="override-table-name"></a>

在 DynamoDB 加密用戶端中，DynamoDB 資料表的名稱是傳遞給加密和解密方法的 [DynamoDB 加密內容](concepts.md#encryption-context)元素。當您加密或簽署資料表項目時，DynamoDB 加密內容會以密碼編譯方式繫結至加密文字，包括資料表名稱。如果傳遞至解密方法的 DynamoDB 加密內容與傳遞至加密方法的 DynamoDB 加密內容不相符，解密操作會失敗。

有時候，表格的名稱會發生變更，例如當您備份表格或執行[時間點復原時](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html)。當您解密或驗證這些項目的簽章時，您必須傳入用於加密和簽署項目的相同 DynamoDB 加密內容，包括原始資料表名稱。目前的表格名稱是不需要的。

當您使用 時`DynamoDBEncryptor`，您可以手動組合 DynamoDB 加密內容。不過，如果您使用的是 `DynamoDBMapper`， 會為您`AttributeEncryptor`建立 DynamoDB 加密內容，包括目前的資料表名稱。若要告訴 `AttributeEncryptor` 建立具有不同資料表名稱的加密內容，請使用 `EncryptionContextOverrideOperator`。

例如，下列程式碼會建立密碼編譯材料提供者 (CMP) 和 `DynamoDBEncryptor`。然後它會呼叫 `DynamoDBEncryptor` 的 `setEncryptionContextOverrideOperator` 方法。它使用覆寫一個表格名稱的 `overrideEncryptionContextTableName` 運算子。以這種方式設定時， `AttributeEncryptor`會建立包含 的 DynamoDB 加密內容`newTableName`，以取代 `oldTableName`。如需完整的範例，請參閱 [EncryptionContextOverridesWithDynamoDBMapper.java](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/EncryptionContextOverridesWithDynamoDBMapper.java)。

```
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);

encryptor.setEncryptionContextOverrideOperator(EncryptionContextOperators.overrideEncryptionContextTableName(
                oldTableName, newTableName));
```

當您呼叫 `DynamoDBMapper` (解密和驗證項目) 的載入方法時，您可以指定原始資料表名稱。

```
mapper.load(itemClass, DynamoDBMapperConfig.builder()
                .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement(oldTableName))
                .build());
```

您也可以使用 `overrideEncryptionContextTableNameUsingMap` 運算子，該運算子會覆寫多個表格名稱。

表格名稱覆寫運算子通常用於解密資料和驗證簽章。不過，您可以在加密和簽署時，使用它們將 DynamoDB 加密內容中的資料表名稱設定為不同的值。

如果您使用的是 `DynamoDBEncryptor`，請勿使用表格名稱覆寫運算子。請改為使用原始表格名稱建立加密內容，並將其提交至解密方法。

# 適用於 Java 的 DynamoDB 加密用戶端的範例程式碼
<a name="java-examples"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

下列範例示範如何使用適用於 Java 的 DynamoDB 加密用戶端來保護應用程式中的 DynamoDB 資料表項目。您可以在 GitHub 上 [aws-dynamodb-encryption-java](https://github.com/aws/aws-dynamodb-encryption-java/) 儲存庫[的範例](https://github.com/aws/aws-dynamodb-encryption-java/tree/master/examples)目錄中找到更多範例 （並自行提供）。

**Topics**
+ [使用 DynamoDBEncryptor](#java-example-ddb-encryptor)
+ [使用 DynamoDBMapper](#java-example-dynamodb-mapper)

## 使用 DynamoDBEncryptor
<a name="java-example-ddb-encryptor"></a>

這個範例說明如何使用較低層級的 [DynamoDBEncryptor](https://aws.github.io/aws-dynamodb-encryption-java/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.html) 搭配[直接 KMS 提供者](direct-kms-provider.md)。Direct KMS 提供者會在您指定的 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys) in AWS Key Management Service (AWS KMS) 下產生並保護其密碼編譯資料。

您可以使用任何相容的[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP) 搭配 `DynamoDBEncryptor`，而且可以使用直接 KMS 提供者搭配 `DynamoDBMapper` 與 [AttributeEncryptor](java-using.md#attribute-encryptor)。

**查看完整的程式碼範例**：[AwsKmsEncryptedItem.java](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedItem.java)

步驟 1：建立直接 KMS 提供者  
建立具有指定區域的 AWS KMS 用戶端執行個體。然後，使用用戶端執行個體，以您偏好的 建立直接 KMS 提供者的執行個體 AWS KMS key。  
此範例使用 Amazon Resource Name (ARN) 來識別 AWS KMS key，但您可以使用[任何有效的金鑰識別符](https://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html#find-cmk-id-arn)。  

```
final String keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";
final String region = "us-west-2";
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
```

步驟 2：建立項目  
這個範例會定義 `record` HashMap，其代表範例資料表項目。  

```
final String partitionKeyName = "partition_attribute";
final String sortKeyName = "sort_attribute";

final Map<String, AttributeValue> record = new HashMap<>();
record.put(partitionKeyName, new AttributeValue().withS("value1"));
record.put(sortKeyName, new AttributeValue().withN("55"));
record.put("example", new AttributeValue().withS("data"));
record.put("numbers", new AttributeValue().withN("99"));
record.put("binary", new AttributeValue().withB(ByteBuffer.wrap(new byte[]{0x00, 0x01, 0x02})));
record.put("test", new AttributeValue().withS("test-value"));
```

步驟 3：建立 DynamoDBEncryptor  
使用直接 KMS 提供者建立 `DynamoDBEncryptor` 的執行個體。  

```
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);
```

步驟 4：建立 DynamoDB 加密內容  
[DynamoDB 加密內容](concepts.md#encryption-context)包含資料表結構及其加密和簽署方式的相關資訊。如果您使用 `DynamoDBMapper`，`AttributeEncryptor` 會為您建立加密細節。  

```
final String tableName = "testTable";

final EncryptionContext encryptionContext = new EncryptionContext.Builder()
    .withTableName(tableName)
    .withHashKeyName(partitionKeyName)
    .withRangeKeyName(sortKeyName)
    .build();
```

步驟 5：建立屬性動作物件  
[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)決定項目的哪些屬性會加密並簽署，哪些屬性只會簽署，以及哪些屬性不會加密或簽署。  
在 Java 中，若要指定屬性動作，您可建立屬性名稱和 `EncryptionFlags` 值組的 HashMap。  
例如，下列 Java 程式碼會建立 `actions` HashMap，其可加密並簽署 `record` 項目中的所有屬性，但是分割區索引鍵與排序索引鍵屬性 (簽署但不加密) 以及 `test` 屬性 (不簽署或加密) 除外。  

```
final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN);
final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN);
final Map<String, Set<EncryptionFlags>> actions = new HashMap<>();

for (final String attributeName : record.keySet()) {
  switch (attributeName) {
    case partitionKeyName: // fall through to the next case
    case sortKeyName:
      // Partition and sort keys must not be encrypted, but should be signed
      actions.put(attributeName, signOnly);
      break;
    case "test":
      // Neither encrypted nor signed
      break;
    default:
      // Encrypt and sign all other attributes
      actions.put(attributeName, encryptAndSign);
      break;
  }
}
```

步驟 6：將項目加密並簽署  
若要加密並簽署資料表項目，請在 `encryptRecord` 的執行個體上呼叫 `DynamoDBEncryptor` 方法。指定資料表項目 (`record`)、屬性動作 (`actions`) 及加密細節 (`encryptionContext`)。  

```
final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
```

步驟 7：將項目放入 DynamoDB 資料表  
最後，將加密和簽署的項目放入 DynamoDB 資料表。  

```
final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.defaultClient();
ddb.putItem(tableName, encrypted_record);
```

## 使用 DynamoDBMapper
<a name="java-example-dynamodb-mapper"></a>

下列範例示範如何搭配 [Direct KMS 提供者](direct-kms-provider.md)使用 DynamoDB 映射器協助程式類別。Direct KMS 提供者會在您指定的 AWS Key Management Service (AWS KMS) [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)中的 下產生並保護其密碼編譯資料。

您可以使用任何相容的[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider) (CMP) 搭配 `DynamoDBMapper`，而且可以使用直接 KMS 提供者搭配較低層級的 `DynamoDBEncryptor`。

**查看完整的程式碼範例**：[AwsKmsEncryptedObject.java](https://github.com/aws/aws-dynamodb-encryption-java/blob/master/examples/src/main/java/com/amazonaws/examples/AwsKmsEncryptedObject.java)

步驟 1：建立直接 KMS 提供者  
建立具有指定區域的 AWS KMS 用戶端執行個體。然後，使用用戶端執行個體，以您偏好的 建立直接 KMS 提供者的執行個體 AWS KMS key。  
此範例使用 Amazon Resource Name (ARN) 來識別 AWS KMS key，但您可以使用[任何有效的金鑰識別符](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id)。  

```
final String keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";
final String region = "us-west-2";
      
final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build();
final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
```

步驟 2：建立 DynamoDB 加密程式和 DynamoDBMapper  
使用您在上一個步驟中建立的直接 KMS 提供者來建立 [DynamoDB 加密程式](java-using.md#attribute-encryptor)的執行個體。您需要執行個體化較低層級的 DynamoDB Encryptor，才能使用 DynamoDB Mapper。  
接著，建立 DynamoDB 資料庫的執行個體和映射器組態，並使用它們來建立 DynamoDB Mapper 的執行個體。  
使用 `DynamoDBMapper` 加入或編輯已簽署 (或已加密並簽署) 的項目時，請將其設定成[使用儲存行為](java-using.md#save-behavior) (例如 `PUT`) 納入所有屬性，如以下範例所示。否則，您將可能無法解密資料。

```
final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp)
final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard().withRegion(region).build();

DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder().withSaveBehavior(SaveBehavior.PUT).build();
DynamoDBMapper mapper = new DynamoDBMapper(ddb, mapperConfig, new AttributeEncryptor(encryptor));
```

步驟 3：定義您的 DynamoDB 資料表  
接著，定義您的 DynamoDB 資料表。請使用註釋指定[屬性動作](java-using.md#attribute-actions-java)。此範例會建立代表資料表項目的 DynamoDB 資料表`ExampleTable`、 和 `DataPoJo`類別。  
該範例資料表的主索引鍵屬性將經過簽署但未加密。這包括了標註 `@DynamoDBHashKey` 的 `partition_attribute`，以及標註 `@DynamoDBRangeKey` 的 `sort_attribute`。  
凡是標註 `@DynamoDBAttribute` 的屬性 (例如 `some numbers`) 都將進行加密並簽署。例外狀況是使用 DynamoDB Encryption Client 定義的 `@DoNotEncrypt`（僅簽署） 或 `@DoNotTouch`（不加密或簽署） 加密註釋的屬性。例如，`leave me` 屬性由於設有 `@DoNotTouch` 註釋，其將不會進行加密或簽署。  

```
@DynamoDBTable(tableName = "ExampleTable")
public static final class DataPoJo {
  private String partitionAttribute;
  private int sortAttribute;
  private String example;
  private long someNumbers;
  private byte[] someBinary;
  private String leaveMe;

  @DynamoDBHashKey(attributeName = "partition_attribute")
  public String getPartitionAttribute() {
    return partitionAttribute;
  }

  public void setPartitionAttribute(String partitionAttribute) {
    this.partitionAttribute = partitionAttribute;
  }

  @DynamoDBRangeKey(attributeName = "sort_attribute")
  public int getSortAttribute() {
    return sortAttribute;
  }

  public void setSortAttribute(int sortAttribute) {
    this.sortAttribute = sortAttribute;
  }

  @DynamoDBAttribute(attributeName = "example")
  public String getExample() {
    return example;
  }

  public void setExample(String example) {
    this.example = example;
  }

  @DynamoDBAttribute(attributeName = "some numbers")
  public long getSomeNumbers() {
    return someNumbers;
  }

  public void setSomeNumbers(long someNumbers) {
    this.someNumbers = someNumbers;
  }

  @DynamoDBAttribute(attributeName = "and some binary")
  public byte[] getSomeBinary() {
    return someBinary;
  }

  public void setSomeBinary(byte[] someBinary) {
    this.someBinary = someBinary;
  }

  @DynamoDBAttribute(attributeName = "leave me")
  @DoNotTouch
  public String getLeaveMe() {
    return leaveMe;
  }

  public void setLeaveMe(String leaveMe) {
    this.leaveMe = leaveMe;
  }

  @Override
  public String toString() {
    return "DataPoJo [partitionAttribute=" + partitionAttribute + ", sortAttribute="
        + sortAttribute + ", example=" + example + ", someNumbers=" + someNumbers
        + ", someBinary=" + Arrays.toString(someBinary) + ", leaveMe=" + leaveMe + "]";
  }
}
```

步驟 4：加密並儲存資料表項目  
現在，當您建立資料表項目並使用 DynamoDB Mapper 儲存該項目時，該項目會在新增至資料表之前自動加密和簽署。  
本範例定義的資料表項目名為 `record`。該項目儲存至資料表之前，其屬性將根據 `DataPoJo` 類別中的註釋進行加密與簽署。就本例而言，所有屬性除了 `PartitionAttribute`、`SortAttribute` 和 `LeaveMe` 以外都將加密並簽署。`PartitionAttribute` 和 `SortAttributes` 只會進行簽署，而 `LeaveMe` 屬性則完全未加密或簽署。  
若要加密並簽署 `record` 項目，然後將其加入至 `ExampleTable`，請呼叫 `DynamoDBMapper` 類別的 `save` 方法。由於您的 DynamoDB Mapper 已設定為使用`PUT`儲存行為，因此項目會使用相同的主索引鍵取代任何項目，而不是更新它。這可確保簽章相符，而且您從資料表取得該項目後便能將其解密。  

```
DataPoJo record = new DataPoJo();
record.setPartitionAttribute("is this");
record.setSortAttribute(55);
record.setExample("data");
record.setSomeNumbers(99);
record.setSomeBinary(new byte[]{0x00, 0x01, 0x02});
record.setLeaveMe("alone");

mapper.save(record);
```

# 適用於 Python 的 DynamoDB 加密用戶端
<a name="python"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

本主題說明如何安裝和使用適用於 Python 的 DynamoDB Encryption Client。您可以在 GitHub 上的 [aws-dynamodb-encryption-python](https://github.com/aws/aws-dynamodb-encryption-python/) 儲存庫中找到程式碼 (包括完整和已測試的[範本程式碼](https://github.com/aws/aws-dynamodb-encryption-python/tree/master/examples))，協助您開始使用。

**注意**  
適用於 Python 的 DynamoDB Encryption Client 版本 1.*x*.*x* 和 2.*x*.*x* 自 2022 年 7 月起處於[end-of-support階段](what-is-database-encryption-sdk.md#support)。盡快升級至較新的版本。

**Topics**
+ [先決條件](#python-prerequisites)
+ [安裝](#python-installation)
+ [使用適用於 Python 的 DynamoDB 加密用戶端](python-using.md)
+ [Python 範例](python-examples.md)

## 先決條件
<a name="python-prerequisites"></a>

安裝適用於 Python 的 Amazon DynamoDB 加密用戶端之前，請確定您有下列先決條件。

**支援的 Python 版本**  
Amazon DynamoDB Encryption Client for Python 3.3.0 版及更新版本需要 Python 3.8 或更新版本。若要下載 Python，請參閱 [Python 下載](https://www.python.org/downloads/)。  
舊版的 Amazon DynamoDB Encryption Client for Python 支援 Python 2.7 和 Python 3.4 及更新版本，但我們建議您使用最新版本的 DynamoDB Encryption Client。

**適用於 Python 的 pip 安裝工具**  
Python 3.6 和更新版本包含 **pip**，但您可能想要將其升級。如需升級或安裝 pip 的詳細資訊，請參閱 **pip** 文件中的[安裝](https://pip.pypa.io/en/latest/installation/)。

## 安裝
<a name="python-installation"></a>

使用 **pip** 安裝 Amazon DynamoDB Encryption Client for Python，如下列範例所示。

**若要安裝最新版本**  

```
pip install dynamodb-encryption-sdk
```

如需使用 **pip** 來安裝及升級套件的詳細資訊，請參閱[安裝套件](https://packaging.python.org/tutorials/installing-packages/)。

DynamoDB 加密用戶端在所有平台上都需要[密碼編譯程式庫](https://cryptography.io/en/latest/)。Windows 上所有版本的 **pip** 都將安裝並建置**密碼編譯**程式庫，而 Linux 上的 **pip** 8.1 和更新版本則會安裝並建置**密碼編譯**。如果您使用舊版 **pip**，而且您的 Linux 環境沒有建置**密碼編譯**程式庫所需的工具，您就需要加以安裝。如需詳細資訊，請參閱[在 Linux 上建置密碼編譯](https://cryptography.io/en/latest/installation/#building-cryptography-on-linux)。

您可以從 GitHub 上的 [aws-dynamodb-encryption-python](https://github.com/aws/aws-dynamodb-encryption-python/) 儲存庫取得最新的 DynamoDB Encryption Client 開發版本。

安裝 DynamoDB 加密用戶端後，請先查看本指南中的範例 Python 程式碼。

# 使用適用於 Python 的 DynamoDB 加密用戶端
<a name="python-using"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

本主題說明 DynamoDB Encryption Client for Python 的某些功能，這些功能在其他程式設計語言實作中可能找不到。這些功能旨在讓您更輕鬆地以最安全的方式使用 DynamoDB 加密用戶端。若非遇到罕見的使用案例，我們都建議您使用這些功能。

如需使用 DynamoDB 加密用戶端進行程式設計的詳細資訊，請參閱本指南中的 [Python 範例](python-examples.md)、GitHub 上 aws-dynamodb-encryption-python 儲存庫中[的範例](https://github.com/aws/aws-dynamodb-encryption-python/tree/master/examples)，以及 DynamoDB 加密用戶端的 [Python 文件](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/)。

**Topics**
+ [用戶端協助程式類別](#python-helpers)
+ [TableInfo 類別](#table-info)
+ [Python 中的屬性動作](#python-attribute-actions)

## 用戶端協助程式類別
<a name="python-helpers"></a>

DynamoDB Encryption Client for Python 包含數個用戶端協助程式類別，可鏡像 DynamoDB 的 Boto 3 類別。這些協助程式類別旨在讓您更輕鬆地將加密和簽署新增至現有的 DynamoDB 應用程式，並避免最常見的問題，如下所示：
+ 藉由將主索引鍵的覆寫動作新增至 [AttributeActions](#python-attribute-actions) 物件，或藉由在您的 `AttributeActions` 物件明確指示用戶端為主索引鍵加密時擲回例外狀況，以防止您將項目中的主索引鍵加密。如果 `AttributeActions` 物件中的預設動作為 `DO_NOTHING`，則用戶端協助程式類別會將該動作用於主索引鍵。否則會使用 `SIGN_ONLY`。
+ 建立 [TableInfo 物件](#python-helpers)，並根據對 [DynamoDB 的呼叫填入 DynamoDB 加密內容](concepts.md#encryption-context)。 DynamoDB 這有助於確保您的 DynamoDB 加密內容準確，且用戶端可以識別主金鑰。
+ 當您寫入 DynamoDB 資料表或從 DynamoDB 資料表讀取時`get_item`，支援透明加密和解密資料表項目的方法，例如 `put_item`和 。只有 `update_item` 方法不受支援。

您可以使用用戶端協助程式類別，而無須直接與較低層級的[項目加密程式](DDBEC-legacy-concepts.md#item-encryptor)互動。只有在需要於項目加密程式中設定進階選項時，才使用這些類別。

用戶端協助程式類別包括：
+ [EncryptedTable](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/table.html#module-dynamodb_encryption_sdk.encrypted.table) 適用於在 DynamoDB 中使用[資料表](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#table)資源的應用程式，一次處理一個資料表。
+ [EncryptedResource](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/resource.html) 適用於在 DynamoDB 中使用[服務資源](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#service-resource)類別進行批次處理的應用程式。
+ [EncryptedClient](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/client.html) 適用於在 DynamoDB [中使用較低層級用戶端](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#client)的應用程式。

若要使用用戶端協助程式類別，呼叫者必須具有在目標資料表上呼叫 DynamoDB [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) 操作的許可。

## TableInfo 類別
<a name="table-info"></a>

[TableInfo](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/tools/structures.html#dynamodb_encryption_sdk.structures.TableInfo) 類別是代表 DynamoDB 資料表的協助程式類別，包含其主索引鍵和次要索引的欄位。它可協助您取得正確而即時的資料表相關資訊。

如果您使用的是[用戶端協助程式類別](#python-helpers)，其將為您建立並使用 `TableInfo` 物件。否則，您可以明確建立一個物件。如需範例，請參閱 [使用項目加密程式](python-examples.md#python-example-item-encryptor)。

當您在`TableInfo`物件上呼叫 `refresh_indexed_attributes`方法時，它會呼叫 DynamoDB [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) 操作來填入物件的屬性值。查詢資料表會比進行索引名稱的硬編碼可靠得多。`TableInfo` 類別也包含 `encryption_context_values` 屬性，提供 [DynamoDB 加密內容](concepts.md#encryption-context)所需的值。

若要使用 `refresh_indexed_attributes`方法，發起人必須具有在目標資料表上呼叫 DynamoDB [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) 操作的許可。

## Python 中的屬性動作
<a name="python-attribute-actions"></a>

[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)會告知項目加密程式要對項目的每個屬性執行什麼動作。若要指定 Python 中的屬性動作，請建立具有預設動作和特定屬性之任何例外狀況的 `AttributeActions` 物件。有效值會在 `CryptoAction` 列舉類型中加以定義。

**重要**  
使用屬性動作加密表格項目後，從資料模型新增或移除屬性可能會導致簽章驗證錯誤，讓您無法解密資料。如需更詳細的說明，請參閱[變更您的資料模型](data-model.md)。

```
DO_NOTHING = 0
SIGN_ONLY = 1
ENCRYPT_AND_SIGN = 2
```

例如，此 `AttributeActions` 物件會建立 `ENCRYPT_AND_SIGN` 作為所有屬性的預設值，並指定 `ISBN` 和 `PublicationYear` 屬性的例外狀況。

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
    attribute_actions={
        'ISBN': CryptoAction.DO_NOTHING,
        'PublicationYear': CryptoAction.SIGN_ONLY
    }
)
```

若您使用的是[用戶端協助程式類別](#python-helpers)，您不需要指定主索引鍵屬性的屬性動作。用戶端協助程式類別可防止您將主索引鍵加密。

若未使用用戶端協助程式類別，且預設動作為 `ENCRYPT_AND_SIGN`，則必須指定主索引鍵的動作。建議的主索引鍵動作為 `SIGN_ONLY`。若要加以簡化，請使用會對主索引鍵使用 SIGN\$1ONLY 的 `set_index_keys` 方法，或是在預設動作為 DO\$1NOTHING 時使用此動作。

**警告**  
請勿加密主索引鍵的屬性。它們必須保持純文字，以便 DynamoDB 可以在不執行完整資料表掃描的情況下找到項目。

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
)
actions.set_index_keys(*table_info.protected_index_keys())
```

# 適用於 Python 的 DynamoDB 加密用戶端的範例程式碼
<a name="python-examples"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

下列範例示範如何使用適用於 Python 的 DynamoDB 加密用戶端來保護應用程式中的 DynamoDB 資料。您可以在 GitHub 上 [aws-dynamodb-encryption-python](https://github.com/aws/aws-dynamodb-encryption-python/) 儲存庫[的範例](https://github.com/aws/aws-dynamodb-encryption-python/tree/master/examples)目錄中找到更多範例 （並自行提供）。

**Topics**
+ [使用 EncryptedTable 用戶端協助程式類別](#python-example-table)
+ [使用項目加密程式](#python-example-item-encryptor)

## 使用 EncryptedTable 用戶端協助程式類別
<a name="python-example-table"></a>

下列範例示範如何使用 [Direct KMS Provider](direct-kms-provider.md) 搭配`EncryptedTable`[用戶端協助程式類別](python-using.md#python-helpers)。此範例使用與以下[使用項目加密程式](#python-example-item-encryptor)範例相同的[密碼編譯資料提供者](DDBEC-legacy-concepts.md#concept-material-provider)。不過，其將使用 `EncryptedTable` 類別，而不是直接與較低層級的[項目加密程式](DDBEC-legacy-concepts.md#item-encryptor)互動。

比較這些範例，您就可以看見用戶端協助程式類別為您所做的事情。這包括建立 [DynamoDB 加密內容](concepts.md#encryption-context)，並確保主金鑰屬性一律已簽署，但從未加密。若要建立加密內容並探索主金鑰，用戶端協助程式類別會呼叫 DynamoDB [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) 操作。若要執行此程式碼，您必須擁有呼叫此作業的權利。

**查看完整的程式碼範例**：[aws\$1kms\$1encrypted\$1table.py](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_table.py)

步驟 1：建立資料表  
首先，使用資料表名稱建立標準 DynamoDB 資料表的執行個體。  

```
table_name='test-table'
table = boto3.resource('dynamodb').Table(table_name)
```

步驟 2：建立密碼編譯資料提供者  
建立您所選[密碼編譯資料提供者](crypto-materials-providers.md) (CMP) 的執行個體。  
本範例使用[直接 KMS 提供者](direct-kms-provider.md)，但您可以使用任何相容的 CMP。若要建立直接 KMS 提供者，請指定 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)。此範例使用 的 Amazon Resource Name (ARN) AWS KMS key，但您可以使用任何有效的金鑰識別符。  

```
kms_key_id='arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=kms_key_id)
```

步驟 3：建立屬性動作物件  
[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)會告知項目加密程式要對項目的每個屬性執行什麼動作。這個範例中的 `AttributeActions` 物件會加密並簽署所有項目，但 `test` 屬性 (予以忽略) 除外。  
當您使用用戶端協助程式類別時，請勿指定主要索引鍵屬性的屬性動作。`EncryptedTable` 類別會簽署 (但絕不會加密) 主要索引鍵屬性。  

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
    attribute_actions={'test': CryptoAction.DO_NOTHING}
)
```

步驟 4：建立已加密的資料表  
使用標準資料表、直接 KMS 提供者和屬性動作，來建立已加密的資料表。這個步驟可完成設定。  

```
encrypted_table = EncryptedTable(
    table=table,
    materials_provider=kms_cmp,
    attribute_actions=actions
)
```

步驟 5：在資料表中放入純文字項目  
當您在 上呼叫 `put_item`方法時`encrypted_table`，您的資料表項目會以透明方式加密、簽署，並新增至您的 DynamoDB 資料表。  
首先，定義資料表項目。  

```
plaintext_item = {
    'partition_attribute': 'value1',
    'sort_attribute': 55
    'example': 'data',
    'numbers': 99,
    'binary': Binary(b'\x00\x01\x02'),
    'test': 'test-value'
}
```
然後，在資料表中放入該項目。  

```
encrypted_table.put_item(Item=plaintext_item)
```

若要以加密形式從 DynamoDB 資料表取得項目，請在 `table` 物件上呼叫 `get_item`方法。若要取得已解密的項目，請在 `get_item` 物件上呼叫 `encrypted_table` 方法。

## 使用項目加密程式
<a name="python-example-item-encryptor"></a>

此範例說明如何在加密資料表[項目時，直接與 DynamoDB 加密用戶端](DDBEC-legacy-concepts.md#item-encryptor)中的項目加密程式互動，而不是使用與您項目加密程式互動的[用戶端協助程式類別](python-using.md#python-helpers)。 DynamoDB 

當您使用此技術時，您可以手動建立 DynamoDB 加密內容和組態物件 (`CryptoConfig`)。此外，您會在一個呼叫中加密項目，並將它們放在 DynamoDB 資料表中的個別呼叫中。這可讓您自訂`put_item`呼叫，並使用 DynamoDB 加密用戶端來加密和簽署從未傳送至 DynamoDB 的結構化資料。

本範例使用[直接 KMS 提供者](direct-kms-provider.md)，但您可以使用任何相容的 CMP。

**查看完整的程式碼範例**：[aws\$1kms\$1encrypted\$1item.py](https://github.com/aws/aws-dynamodb-encryption-python/blob/master/examples/src/dynamodb_encryption_sdk_examples/aws_kms_encrypted_item.py)

步驟 1：建立資料表  
首先，使用資料表名稱建立標準 DynamoDB 資料表資源的執行個體。  

```
table_name='test-table'
table = boto3.resource('dynamodb').Table(table_name)
```

步驟 2：建立密碼編譯資料提供者  
建立您所選[密碼編譯資料提供者](crypto-materials-providers.md) (CMP) 的執行個體。  
本範例使用[直接 KMS 提供者](direct-kms-provider.md)，但您可以使用任何相容的 CMP。若要建立直接 KMS 提供者，請指定 [AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)。此範例使用 的 Amazon Resource Name (ARN) AWS KMS key，但您可以使用任何有效的金鑰識別符。  

```
kms_key_id='arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab'
kms_cmp = AwsKmsCryptographicMaterialsProvider(key_id=kms_key_id)
```

步驟 3：使用 TableInfo 協助程式類別  
若要從 DynamoDB 取得資料表的相關資訊，請建立 [TableInfo](python-using.md#python-helpers) 協助程式類別的執行個體。當您直接使用項目加密程式時，您需要建立 `TableInfo` 執行個體及呼叫其方法。[用戶端協助程式類別](python-using.md#python-helpers)會為您執行此作業。  
`refresh_indexed_attributes` 方法`TableInfo`使用 [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) DynamoDB 操作來取得資料表的即時準確資訊。這包括其主要索引鍵及其本機和全域輔助索引。呼叫端必須具備呼叫 `DescribeTable` 的許可。  

```
table_info = TableInfo(name=table_name)
table_info.refresh_indexed_attributes(table.meta.client)
```

步驟 4：建立 DynamoDB 加密內容  
[DynamoDB 加密內容](concepts.md#encryption-context)包含資料表結構及其加密和簽署方式的相關資訊。此範例會明確建立 DynamoDB 加密內容，因為它會與項目加密程式互動。[用戶端協助程式類別](python-using.md#python-helpers)會為您建立 DynamoDB 加密內容。  
若要取得分割區索引鍵和排序索引鍵，您可以使用 [TableInfo](python-using.md#python-helpers) 協助程式類別的屬性。  

```
index_key = {
    'partition_attribute': 'value1',
    'sort_attribute': 55
}

encryption_context = EncryptionContext(
    table_name=table_name,
    partition_key_name=table_info.primary_index.partition,
    sort_key_name=table_info.primary_index.sort,
    attributes=dict_to_ddb(index_key)
)
```

步驟 5：建立屬性動作物件  
[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)會告知項目加密程式要對項目的每個屬性執行什麼動作。這個範例中的 `AttributeActions` 物件會加密並簽署所有項目，但主要索引鍵屬性 (簽署但不加密) 和 `test` 屬性 (予以忽略) 除外。  
當您直接與項目加密程式互動且預設動作為 `ENCRYPT_AND_SIGN` 時，您必須為主要索引鍵指定替代動作。您可以使用 `set_index_keys` 方法，該方法針對主要索引鍵使用 `SIGN_ONLY`，或使用 `DO_NOTHING` (如果這是預設動作)。  
若要指定主索引鍵，此範例會使用 [TableInfo](python-using.md#python-helpers) 物件中的索引鍵，這會由對 DynamoDB 的呼叫填入。這項技巧比硬編碼主要索引鍵名稱還要安全。  

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
    attribute_actions={'test': CryptoAction.DO_NOTHING}
)
actions.set_index_keys(*table_info.protected_index_keys())
```

步驟 6：建立項目的組態  
若要設定 DynamoDB 加密用戶端，請使用您剛在資料表項目的 [CryptoConfig](https://aws-dynamodb-encryption-python.readthedocs.io/en/latest/lib/encrypted/config.html) 組態中建立的物件。用戶端協助程式類別會為您建立 CryptoConfig。  

```
crypto_config = CryptoConfig(
    materials_provider=kms_cmp,
    encryption_context=encryption_context,
    attribute_actions=actions
)
```

步驟 7：將項目加密  
此步驟會加密並簽署項目，但不會將其放入 DynamoDB 資料表中。  
當您使用用戶端協助程式類別時，您的項目會以透明方式加密和簽署，然後在您呼叫協助程式類別的 `put_item`方法時新增至 DynamoDB 資料表。當您直接使用項目加密程式時，加密和放置動作都是獨立的。  
首先，建立純文字項目。  

```
plaintext_item = {
    'partition_attribute': 'value1',
    'sort_key': 55,
    'example': 'data',
    'numbers': 99,
    'binary': Binary(b'\x00\x01\x02'),
    'test': 'test-value'
}
```
然後，將它加密並簽署。`encrypt_python_item` 方法需要 `CryptoConfig` 組態物件。  

```
encrypted_item = encrypt_python_item(plaintext_item, crypto_config)
```

步驟 8：在資料表中放入此項目  
此步驟會將加密和簽章的項目放入 DynamoDB 資料表。  

```
table.put_item(Item=encrypted_item)
```

若要檢視已加密的項目，請在原始 `get_item` 物件 (而非 `table` 物件) 上呼叫 `encrypted_table` 方法。不需進行驗證或解密，即可從 DynamoDB 資料表取得項目。

```
encrypted_item = table.get_item(Key=partition_key)['Item']
```

下圖顯示一部分已加密並簽署資料表項目的範例。

已加密的屬性值為二進位資料。主要索引鍵屬性 (`partition_attribute` 和 `sort_attribute`) 及 `test` 屬性的名稱和值都保持純文字形式。輸出也會顯示包含簽章 (`*amzn-ddb-map-sig*`) 的屬性和[資料描述屬性](DDBEC-legacy-concepts.md#legacy-material-description) (`*amzn-ddb-map-desc*`)。

![\[已加密並簽署的項目摘錄\]](http://docs.aws.amazon.com/zh_tw/database-encryption-sdk/latest/devguide/images/encrypted-item-closeup.png)


# 變更您的資料模型
<a name="data-model"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

每次加密或解密項目時，您需要提供[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)，以告知 DynamoDB 加密用戶端要加密和簽署哪些屬性、要簽署哪些屬性 （但不要加密），以及要忽略哪些屬性。屬性動作不會儲存在加密的項目中，DynamoDB Encryption Client 不會自動更新您的屬性動作。

**重要**  
DynamoDB 加密用戶端不支援加密現有、未加密的 DynamoDB 資料表資料。

每當您變更資料模型時，也就是，當您新增或移除資料表項目中的屬性時，就可能發生錯誤。如果您指定的屬性動作並未考量項目中的所有屬性，此項目便無法如您預期的方式進行加密和簽署。更重要的是，如果您在加密項目時提供的屬性動作與您在解密項目時提供的屬性動作不同，則簽章驗證可能會失敗。

例如，如果用來加密項目的屬性動作告知要簽署 `test` 屬性，則項目中的簽章會包含 `test` 屬性。但是如果用來解密項目的屬性動作並未考量 `test` 屬性，則驗證會因為用戶端嘗試驗證不包含 `test` 屬性的簽章而失敗。

當多個應用程式讀取和寫入相同的 DynamoDB 項目時，這是一個特別的問題，因為 DynamoDB 加密用戶端必須計算所有應用程式中項目的相同簽章。對於任何分散式應用程式來說，這也是一個問題，因為屬性動作的變更必須傳播到所有主機。即使您的 DynamoDB 資料表是由一個主機在一個程序中存取，如果專案變得更複雜，建立最佳實務程序將有助於防止錯誤。

若要避免使您無法讀取資料表項目的簽章驗證錯誤，請使用下列指導。
+ [新增屬性](#add-attribute) — 如果新屬性變更您的屬性動作，請在項目中包含新屬性之前，先完全部署屬性動作變更。
+ [移除屬性](#remove-attribute) — 如果您停止在項目中使用屬性，請勿變更屬性動作。
+ 變更動作 — 在您使用屬性動作組態來加密資料表項目之後，您無法安全地變更現有屬性的預設動作或動作，而無需重新加密資料表中的每個項目。

簽章驗證錯誤可能非常難以解決，因此最好的方法是避免這些錯誤的發生。

**Topics**
+ [新增屬性](#add-attribute)
+ [移除屬性](#remove-attribute)

## 新增屬性
<a name="add-attribute"></a>

當您將新屬性新增至資料表項目時，您可能需要變更屬性動作。若要避免簽章驗證錯誤，我們建議您在兩階段的程序中實作此變更。在啟動第二個階段之前，請確認第一個階段已完成。

1. 在所有讀取或寫入資料表的應用程式中變更屬性動作。部署這些變更，並確認更新已傳播到所有目的地主機。

1. 將值寫入資料表項目中的新屬性。

這個兩階段的方法可確保所有應用程式和主機都具有相同的屬性動作，並在遇到新屬性之前計算相同的簽章。即使屬性的動作是*不執行任何動作* (不加密或簽署)，這個方法仍很重要，因為某些加密器的預設值是加密和簽署。

下列範例顯示此程序中第一個階段的程式碼。這些範例會新增項目屬性 `link`，此屬性會存放另一個資料表項目的連結。此連結必須維持純文字的形式，因此此範例會為其指派僅簽署動作。完全部署此變更，然後確認所有應用程式和主機都有新的屬性動作之後，您就可以開始在資料表項目中使用該 `link` 屬性。

------
#### [ Java DynamoDB Mapper ]

使用 `DynamoDB Mapper` 和 `AttributeEncryptor` 時，主要索引鍵 (簽署但不加密) 以外，所有屬性都預設會進行加密和簽署。若要指定僅簽署動作，請使用 `@DoNotEncrypt` 註釋。

此範例會針對新 `link` 屬性使用 `@DoNotEncrypt` 註釋。

```
@DynamoDBTable(tableName = "ExampleTable")
public static final class DataPoJo {
  private String partitionAttribute;
  private int sortAttribute;
  private String link;

  @DynamoDBHashKey(attributeName = "partition_attribute")
  public String getPartitionAttribute() {
    return partitionAttribute;
  }
    
  public void setPartitionAttribute(String partitionAttribute) {
    this.partitionAttribute = partitionAttribute;
  }

  @DynamoDBRangeKey(attributeName = "sort_attribute")
  public int getSortAttribute() {
    return sortAttribute;
  }

  public void setSortAttribute(int sortAttribute) {
    this.sortAttribute = sortAttribute;
  }

  @DynamoDBAttribute(attributeName = "link")
  @DoNotEncrypt
  public String getLink() {
    return link;
  }

  public void setLink(String link) {
    this.link = link;
  }

  @Override
  public String toString() {
    return "DataPoJo [partitionAttribute=" + partitionAttribute + ",
        sortAttribute=" + sortAttribute + ",
        link=" + link + "]";
  }
}
```

------
#### [ Java DynamoDB encryptor ]

 在較低層級的 DynamoDB 加密程式中，您必須為每個屬性設定動作。此範例使用 switch 陳述式，其中預設值為 `encryptAndSign`，而且會針對分割索引鍵、排序索引鍵和新 `link` 屬性指定例外狀況。在此範例中，如果在使用連結屬性程式碼之前未將其完全部署，則某些應用程式會加密並簽署此連結屬性，但其他應用程式則僅簽署此連結屬性。

```
for (final String attributeName : record.keySet()) {
    switch (attributeName) {
        case partitionKeyName:
            // fall through to the next case
        case sortKeyName:
            // partition and sort keys must be signed, but not encrypted
            actions.put(attributeName, signOnly);
            break;
        case "link":
            // only signed
            actions.put(attributeName, signOnly);
            break;
        default:
            // Encrypt and sign all other attributes
            actions.put(attributeName, encryptAndSign);
            break;
    }
}
```

------
#### [ Python ]

在適用於 Python 的 DynamoDB 加密用戶端中，您可以為所有屬性指定預設動作，然後指定例外狀況。

若您使用的是 Python [用戶端協助程式類別](python-using.md#python-helpers)，您不需要指定主索引鍵屬性的屬性動作。用戶端協助程式類別可防止您將主索引鍵加密。但是，如果您不使用用戶端協助程式類別，則必須在您的分割區索引鍵和排序索引鍵上設定 SIGN\$1ONLY 動作。如果您不小心加密了分割區或排序索引鍵，您將無法在沒有進行完整資料表掃描的情況下復原資料。

此範例會指定新 `link` 屬性 (取得 `SIGN_ONLY` 動作) 的例外狀況。

```
actions = AttributeActions(
    default_action=CryptoAction.ENCRYPT_AND_SIGN,
    attribute_actions={
      'example': CryptoAction.DO_NOTHING,  
      'link': CryptoAction.SIGN_ONLY
    }
)
```

------

## 移除屬性
<a name="remove-attribute"></a>

如果您在已使用 DynamoDB Encryption Client 加密的項目中不再需要 屬性，您可以停止使用 屬性。但是，請勿刪除或變更該屬性的動作。如果您這樣做，然後遇到具有該屬性的項目，則針對該項目計算的簽章將不符合原始簽章，且簽章驗證將會失敗。

雖然您可能想要從程式碼中移除屬性的所有追蹤，但請新增註解，指出該項目已不再使用，而不是將其刪除。即使您執行完整資料表掃描以刪除該屬性的所有執行個體，具有該屬性的加密項目可能會被快取或在組態中的某處處理中。

# 故障診斷 DynamoDB Encryption Client 應用程式的問題
<a name="troubleshooting"></a>

**注意**  
我們的用戶端加密程式庫已[重新命名為 AWS 資料庫加密 SDK](DDBEC-rename.md)。下列主題提供有關適用於 Java 的 DynamoDB 加密用戶端 1.*x*-2.*x* 版和適用於 Python 的 DynamoDB 加密用戶端 1.*x*-3.*x* 版的資訊。如需詳細資訊，請參閱[AWS 資料庫加密 SDK for DynamoDB 版本支援](legacy-dynamodb-encryption-client.md#legacy-support)。

本節說明使用 DynamoDB 加密用戶端時可能遇到的問題，並提供解決這些問題的建議。

若要提供 DynamoDB 加密用戶端的意見回饋，請在 [aws-dynamodb-encryption-java](https://github.com/aws/aws-dynamodb-encryption-java/) 或 [aws-dynamodb-encryption-python](https://github.com/aws/aws-dynamodb-encryption-python/) GitHub 儲存庫中提出問題。

若要提供有關此文件的意見回饋，請使用任何頁面上的意見回饋連結。

**Topics**
+ [存取遭拒](#kms-permissions)
+ [簽章驗證失敗](#change-data-model)
+ [舊版全域資料表的問題](#fix-global-tables)
+ [最近提供者的效能不佳](#mrp-ttl-delay)

## 存取遭拒
<a name="kms-permissions"></a>

**問題**：您的應用程式遭拒，無法存取其所需的資源。

**建議**：了解必要的許可，並將這些許可新增至您的應用程式執行所在的安全性細節。

**詳細資訊**

若要執行使用 DynamoDB 加密用戶端程式庫的應用程式，發起人必須具有使用其元件的許可。否則他們會遭拒，無法存取所需的元素。
+ DynamoDB 加密用戶端不需要 Amazon Web Services (AWS) 帳戶或依賴任何 AWS 服務。不過，如果您的應用程式使用 AWS，您需要 [AWS 帳戶](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)和[具有帳戶使用許可的使用者](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started_create-admin-group.html)。
+ DynamoDB 加密用戶端不需要 Amazon DynamoDB。不過，如果使用 用戶端的應用程式建立 DynamoDB 資料表、將項目放入資料表或從資料表取得項目，呼叫者必須具有在您的 中使用所需 DynamoDB 操作的許可 AWS 帳戶。如需詳細資訊，請參閱《*Amazon DynamoDB 開發人員指南*》中的[存取控制主題](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/access-control-overview.html)。
+ 如果您的應用程式在 DynamoDB Encryption Client for Python 中使用[用戶端協助程式類別](python-using.md#python-helpers)，呼叫者必須具有呼叫 DynamoDB [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) 操作的許可。
+ DynamoDB 加密用戶端不需要 AWS Key Management Service (AWS KMS)。不過，如果您的應用程式使用[直接 KMS 資料提供者](direct-kms-provider.md)，或它使用[最近提供者](most-recent-provider.md)搭配使用 的提供者存放區 AWS KMS，呼叫者必須具有使用 AWS KMS [GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 和 [Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 操作的許可。

## 簽章驗證失敗
<a name="change-data-model"></a>

**問題**：項目因為簽章驗證失敗而無法解密。此項目也無法如您所願進行加密和簽署。

**建議**：確保您提供的屬性動作會考量項目中的所有屬性。將項目解密時，請務必提供與用來解密項目之動作相符的屬性動作。

**詳細資訊**

您提供的[屬性動作](DDBEC-legacy-concepts.md#legacy-attribute-actions)會告知 DynamoDB 加密用戶端要加密和簽署的屬性、要簽署的屬性 （但不加密），以及要忽略的屬性。

如果您指定的屬性動作並未考量項目中的所有屬性，此項目便無法如您預期的方式進行加密和簽署。如果您在加密項目時提供的屬性動作與您在解密項目時提供的屬性動作不同，則簽章驗證可能會失敗。這是一個特殊問題，出現於新屬性動作尚未傳播到所有主機的分散式應用程式中。

簽章驗證錯誤很難解決。如需協助防範其發生，請在變更資料模型時採取額外的預防措施。如需詳細資訊，請參閱[變更您的資料模型](data-model.md)。

## 舊版全域資料表的問題
<a name="fix-global-tables"></a>

**問題**：舊版 Amazon DynamoDB 全域資料表中的項目無法解密，因為簽章驗證失敗。

**建議**：設定屬性動作，讓保留的複寫欄位不會加密或簽署。

**詳細資訊**

您可以使用 DynamoDB 加密用戶端搭配 [DynamoDB 全域資料表](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GlobalTables.html)。我們建議您使用具有[多區域 KMS 金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)的全域資料表，並將 KMS 金鑰複寫到複寫全域資料表的所有 AWS 區域 。

從全域資料表 [2019.11.21 版](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/globaltables.V2.html)開始，您可以將全域資料表與 DynamoDB 加密用戶端搭配使用，而不需要任何特殊組態。不過，如果您使用全域資料表 [2017.11.29 版](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/globaltables.V1.html)，您必須確保保留的複寫欄位未加密或簽署。

如果您使用的是全域資料表 2017.11.29 版，則必須在 `DO_NOTHING` [Java](java-using.md#attribute-actions-java) 或 [Python](python-using.md#python-attribute-actions) `@DoNotTouch`中將下列屬性的屬性動作設定為 。
+ `aws:rep:deleting`
+ `aws:rep:updatetime`
+ `aws:rep:updateregion`

如果您使用任何其他版本的全域資料表，則不需要任何動作。

## 最近提供者的效能不佳
<a name="mrp-ttl-delay"></a>

**問題**：您的應用程式回應較差，特別是在更新至較新版本的 DynamoDB 加密用戶端之後。

**建議**：調整time-to-live值和快取大小。

**詳細資訊**

最新提供者旨在透過允許有限的密碼編譯資料重複使用，改善使用 DynamoDB 加密用戶端的應用程式效能。當您為應用程式設定最新提供者時，您必須平衡改善的效能與快取和重複使用引起的安全問題。

在較新版本的 DynamoDB 加密用戶端中，time-to-live(TTL) 值會決定可使用快取密碼編譯材料提供者 CMPs) 的時間長度。TTL 也會判斷最近提供者檢查 CMP 新版本的頻率。

如果您的 TTL 太長，您的應用程式可能會違反您的業務規則或安全標準。如果您的 TTL 太短，經常呼叫提供者存放區可能會導致提供者存放區調節來自您應用程式和其他共用您服務帳戶的應用程式的請求。若要解決此問題，請將 TTL 和快取大小調整為符合您延遲和可用性目標，並符合安全標準的值。如需詳細資訊，請參閱[設定time-to-live值](most-recent-provider.md#most-recent-provider-ttl)。