

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

# 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)
