

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

# 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);
    }
}
```