

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

# 適用於 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)
