

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

# 使用適用於 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) 目錄，以取得如何成功驗證集合的詳細資訊。