

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

# Keyring
<a name="keyrings"></a>


****  

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

 AWS Database Encryption SDK 使用 *keyring *來執行[信封加密](concepts.md#envelope-encryption)。Keyring 會產生、加密及解密資料金鑰。Keyring 會決定保護每個加密記錄的唯一資料金鑰的來源，以及加密該資料金鑰的[包裝金鑰](concepts.md#wrapping-key)。您可以在加密時指定 keyring，並在解密時指定相同或不同的 keyring。

您可以個別使用每個 keyring 或是結合 keyring 成為[多重 keyring](use-multi-keyring.md)。雖然多數 keyring 可以產生、加密及解密資料金鑰，您可能想要建立僅執行一個特定操作的 keyring，例如只會產生資料金鑰的 keyring，並將該 keyring 與其他 keyring 結合使用。

我們建議您使用 keyring 來保護您的包裝金鑰，並在安全界限內執行密碼編譯操作，例如 AWS KMS keyring，其使用 AWS KMS keys 永遠不會讓 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) 處於未加密狀態。您也可以編寫 keyring，該 keyring 使用存放在硬體安全模組 (HSMs) 中的包裝金鑰，或受其他主金鑰服務保護。

您的 keyring 會決定保護資料金鑰的包裝金鑰，最終決定您的資料。使用對您的任務而言最安全的包裝金鑰。盡可能使用受硬體安全模組 (HSM) 或金鑰管理基礎設施保護的包裝金鑰，例如 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) 中的 KMS 金鑰或 中的加密金鑰[AWS CloudHSM](https://docs.aws.amazon.com/cloudhsm/latest/userguide/)。

 AWS Database Encryption SDK 提供數個 keyring 和 keyring 組態，您可以建立自己的自訂 keyring。您也可以建立[包含相同或不同類型之一或多個 keyring 的多 keyring](use-multi-keyring.md)。

**Topics**
+ [keyring 如何運作](#using-keyrings)
+ [AWS KMS keyring](use-kms-keyring.md)
+ [AWS KMS 階層式 keyring](use-hierarchical-keyring.md)
+ [AWS KMS ECDH keyring](use-kms-ecdh-keyring.md)
+ [原始 AES keyring](use-raw-aes-keyring.md)
+ [原始 RSA keyring](use-raw-rsa-keyring.md)
+ [原始 ECDH keyring](use-raw-ecdh-keyring.md)
+ [多重 keyring](use-multi-keyring.md)

## keyring 如何運作
<a name="using-keyrings"></a>


****  

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

當您在資料庫中加密和簽署欄位時， AWS 資料庫加密 SDK 會向 keyring 要求加密資料。keyring 會傳回純文字資料金鑰、由 keyring 中每個包裝金鑰加密的資料金鑰複本，以及與資料金鑰相關聯的 MAC 金鑰。 AWS Database Encryption SDK 使用純文字金鑰來加密資料，然後盡快從記憶體中移除純文字資料金鑰。然後， AWS 資料庫加密 SDK 新增[了資料描述](concepts.md#material-description)，其中包含加密的資料金鑰和其他資訊，例如加密和簽署指示。 AWS 資料庫加密 SDK 使用 MAC 金鑰來計算雜湊型訊息驗證碼 (HMACs)，而非材料描述的標準化，以及標示為 `ENCRYPT_AND_SIGN`或 的所有欄位`SIGN_ONLY`。

當您解密資料時，您可以使用與用來加密資料相同的 keyring，或不同的 keyring。若要解密資料，解密 keyring 必須能夠存取加密 keyring 中的至少一個包裝金鑰。

 AWS 資料庫加密 SDK 會將加密的資料金鑰從材料描述傳遞至 keyring，並要求 keyring 解密其中任何一個金鑰。keyring 使用其包裝金鑰來解密其中一個加密的資料金鑰，並傳回純文字資料金鑰。 AWS Database Encryption SDK 使用純文字資料金鑰來解密資料。如果 keyring 中沒有任何包裝金鑰可以解密任何加密的資料金鑰，則解密操作會失敗。

您可以使用單一 keyring，也可以將相同類型或不同類型的 keyring 結合成[多重 keyring](use-multi-keyring.md)。當您加密資料時，多重 keyring 會傳回由構成多重 keyring 的所有 keyring 中所有包裝金鑰加密的資料金鑰複本，以及與資料金鑰相關聯的 MAC 金鑰。您可以使用 keyring 搭配多 keyring 中的任何一個包裝金鑰來解密資料。

# AWS KMS keyring
<a name="use-kms-keyring"></a>


****  

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

 AWS KMS keyring 使用對稱加密或非對稱 RSA [AWS KMS keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#master_keys)來產生、加密和解密資料金鑰。 AWS Key Management Service (AWS KMS) 會保護您的 KMS 金鑰，並在 FIPS 邊界內執行密碼編譯操作。我們建議您盡可能使用 AWS KMS keyring 或具有類似安全屬性的 keyring。

您也可以在 AWS KMS keyring 中使用對稱多區域 KMS 金鑰。如需使用多區域的詳細資訊和範例 AWS KMS keys，請參閱 [使用多區域 AWS KMS keys](#config-mrks)。如需多區域金鑰的相關資訊，請參閱《 *AWS Key Management Service 開發人員指南*》中的[使用多區域金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)。

AWS KMS keyring 可以包含兩種類型的包裝金鑰：
+ **產生器金鑰**：產生純文字資料金鑰並將其加密。加密資料的 keyring 必須有一個產生器金鑰。
+ **其他金鑰**：加密產生器金鑰產生的純文字資料金鑰。 AWS KMS keyrings 可以有零個或多個其他金鑰。

您必須擁有產生器金鑰才能加密記錄。當 AWS KMS keyring 只有一個 AWS KMS 金鑰時，該金鑰會用來產生和加密資料金鑰。

與所有 keyring 一樣， AWS KMS keyring 可以獨立使用，也可以與相同或不同類型的其他 keyring [多重 keyring](use-multi-keyring.md)搭配使用。

**Topics**
+ [AWS KMS keyring 的必要許可](#kms-keyring-permissions)
+ [在 AWS KMS keyring AWS KMS keys 中識別](#kms-keyring-id)
+ [建立 AWS KMS keyring](#kms-keyring-create)
+ [使用多區域 AWS KMS keys](#config-mrks)
+ [使用 AWS KMS 探索 keyring](#kms-keyring-discovery)
+ [使用 AWS KMS 區域探索 keyring](#kms-keyring-regional)

## AWS KMS keyring 的必要許可
<a name="kms-keyring-permissions"></a>

 AWS 資料庫加密 SDK 不需要 ， AWS 帳戶 也不依賴任何 AWS 服務。不過，若要使用 AWS KMS keyring，您需要 keyring AWS KMS keys 中 的 AWS 帳戶 和下列最低許可。
+ 若要使用 AWS KMS keyring 加密，您需要產生器金鑰上的 [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 許可。您需要 AWS KMS keyring 中所有其他金鑰的 [kms:Encrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html) 許可。
+ 若要使用 AWS KMS keyring 解密，您需要 AWS KMS keyring 中至少一個金鑰的 [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 許可。
+ 若要使用由 AWS KMS keyring 組成的多 keyring 加密，您需要產生器 keyring 中產生器金鑰的 [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 許可。您需要所有其他 AWS KMS keyring 中所有其他金鑰的 [kms:Encrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html) 許可。
+ 若要使用非對稱 RSA AWS KMS keyring 加密，您不需要 [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) 或 [kms:Encrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html)，因為您必須在建立 keyring 時指定要用於加密的公有金鑰材料。使用此 keyring 加密時不會進行任何 AWS KMS 呼叫。若要使用非對稱 RSA AWS KMS keyring 解密，您需要 [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 許可。

如需 許可的詳細資訊 AWS KMS keys，請參閱《 *AWS Key Management Service 開發人員指南*》中的[身分驗證和存取控制](https://docs.aws.amazon.com/kms/latest/developerguide/control-access.html)。

## 在 AWS KMS keyring AWS KMS keys 中識別
<a name="kms-keyring-id"></a>

 AWS KMS keyring 可以包含一或多個 AWS KMS keys。若要在 AWS KMS keyring AWS KMS key 中指定 ，請使用支援的 AWS KMS 金鑰識別符。您可以用來識別 keyring AWS KMS key 中 的金鑰識別符會因 操作和語言實作而有所不同。如需 金鑰識別符的詳細資訊 AWS KMS key，請參閱《 *AWS Key Management Service 開發人員指南*》中的[金鑰識別符](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id)。

最佳實務是使用最適用於您任務的特定金鑰識別符。
+ 若要使用 AWS KMS keyring 加密，您可以使用[金鑰 ID](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-id)、[金鑰 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN)、[別名名稱](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-alias-name)或[別名 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-alias-ARN) 來加密資料。
**注意**  
如果您在加密 keyring 中指定 KMS 金鑰的別名名稱或別名 ARN，加密操作會將目前與別名相關聯的金鑰 ARN 儲存在加密資料金鑰的中繼資料中。它不會儲存別名。別名的變更不會影響用來解密加密資料金鑰的 KMS 金鑰。
+ 若要使用 AWS KMS keyring 解密，您必須使用金鑰 ARN 來識別 AWS KMS keys。如需詳細資訊，請參閱[選取包裝金鑰](configure.md#config-keys)。
+ 在用於加密和解密的 keyring 中，您必須使用金鑰 ARN 來識別 AWS KMS keys。

解密時， AWS 資料庫加密 SDK 會在 AWS KMS keyring 中搜尋 AWS KMS key 可解密其中一個加密資料金鑰的 。具體而言， AWS 資料庫加密 SDK 會對材料描述中的每個加密資料金鑰使用下列模式。
+  AWS Database Encryption SDK 會從材料描述的中繼資料取得 AWS KMS key 加密資料金鑰的 金鑰 ARN。
+  AWS Database Encryption SDK 會搜尋 AWS KMS key 具有相符金鑰 ARN 的 解密 keyring。
+ 如果在 keyring 中找到 AWS KMS key 具有相符金鑰 ARN 的 ， AWS 資料庫加密 SDK AWS KMS 會要求 使用 KMS 金鑰來解密加密的資料金鑰。
+ 否則會跳到下一個加密的資料金鑰 (如果有)。

## 建立 AWS KMS keyring
<a name="kms-keyring-create"></a>

您可以使用相同 AWS KMS key 或不同 AWS 帳戶 和 AWS KMS keys 中的單一或多個 來設定每個 AWS KMS keyring AWS 區域。 AWS KMS key 必須是對稱加密金鑰 (`SYMMETRIC_DEFAULT`) 或非對稱 RSA KMS 金鑰。您也可以使用對稱加密[多區域 KMS 金鑰](#config-mrks)。您可以在多 AWS KMS keyring 中使用一或多個 keyring。 [多重 keyring](use-multi-keyring.md)

您可以建立加密和解密資料的 AWS KMS keyring，也可以建立專門用於加密或解密的 AWS KMS keyring。當您建立 AWS KMS keyring 來加密資料時，必須指定*產生器金鑰*，這是用來產生純文字資料金鑰並將其加密 AWS KMS key 的 。資料金鑰在數學上與 KMS 金鑰無關。然後，如果您選擇，您可以指定其他 AWS KMS keys 來加密相同的純文字資料金鑰。若要解密受此 keyring 保護的加密欄位，您使用的解密 keyring 必須包含至少一個在 keyring 中 AWS KMS keys 定義的 ，或否 AWS KMS keys。（沒有 的 AWS KMS keyring AWS KMS keys 稱為[AWS KMS 探索 keyring](#kms-keyring-discovery)。)

加密 keyring 或 multi-keyring 中的所有包裝金鑰都必須能夠加密資料金鑰。如果任何包裝金鑰無法加密，加密方法會失敗。因此，發起人必須擁有 keyring 中所有金鑰[的必要許可](#kms-keyring-permissions)。如果您使用探索 keyring 單獨加密資料或在多 keyring 中加密資料，加密操作會失敗。

下列範例使用 `CreateAwsKmsMrkMultiKeyring`方法建立具有對稱加密 KMS 金鑰的 AWS KMS keyring。`CreateAwsKmsMrkMultiKeyring` 方法會自動建立 AWS KMS 用戶端，並確保 keyring 可正確處理單一區域和多區域金鑰。這些範例使用[金鑰 ARNs](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) 來識別 KMS 金鑰。如需詳細資訊，請參閱[在 AWS KMS keyring AWS KMS keys 中識別](#kms-keyring-id)

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

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

------
#### [ C\$1 / .NET ]

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var createAwsKmsMrkMultiKeyringInput = new CreateAwsKmsMrkMultiKeyringInput
{
    Generator = kmsKeyArn
};
var awsKmsMrkMultiKeyring = matProv.CreateAwsKmsMrkMultiKeyring(createAwsKmsMrkMultiKeyringInput);
```

------
#### [ Rust ]

```
let provider_config = MaterialProvidersConfig::builder().build()?;
let mat_prov = client::Client::from_conf(provider_config)?;
let kms_keyring = mat_prov
    .create_aws_kms_mrk_multi_keyring()
    .generator(kms_key_id)
    .send()
    .await?;
```

------

下列範例使用 `CreateAwsKmsRsaKeyring`方法建立具有非對稱 RSA KMS 金鑰的 AWS KMS keyring。若要建立非對稱 RSA AWS KMS keyring，請提供下列值。
+ `kmsClient`：建立新的 AWS KMS 用戶端
+ `kmsKeyID`：識別非對稱 RSA KMS 金鑰的金鑰 ARN
+ `publicKey`：UTF-8 編碼 PEM 檔案的 ByteBuffer，代表您傳遞給 之金鑰的公有金鑰 `kmsKeyID`
+ `encryptionAlgorithm`：加密演算法必須為 `RSAES_OAEP_SHA_256`或 `RSAES_OAEP_SHA_1`

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

```
 final MaterialProviders matProv = MaterialProviders.builder()
    .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
    .build();
final CreateAwsKmsRsaKeyringInput createAwsKmsRsaKeyringInput =
    CreateAwsKmsRsaKeyringInput.builder()
        .kmsClient(KmsClient.create())
        .kmsKeyId(rsaKMSKeyArn)
        .publicKey(publicKey)
        .encryptionAlgorithm(EncryptionAlgorithmSpec.RSAES_OAEP_SHA_256)
        .build();
IKeyring awsKmsRsaKeyring = matProv.CreateAwsKmsRsaKeyring(createAwsKmsRsaKeyringInput);
```

------
#### [ C\$1 / .NET ]

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var createAwsKmsRsaKeyringInput = new CreateAwsKmsRsaKeyringInput
{
    KmsClient = new AmazonKeyManagementServiceClient(),
    KmsKeyId = rsaKMSKeyArn,
    PublicKey = publicKey,
    EncryptionAlgorithm = EncryptionAlgorithmSpec.RSAES_OAEP_SHA_256
};
IKeyring awsKmsRsaKeyring = matProv.CreateAwsKmsRsaKeyring(createAwsKmsRsaKeyringInput);
```

------
#### [ Rust ]

```
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;
let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
let kms_rsa_keyring = mpl
    .create_aws_kms_rsa_keyring()
    .kms_key_id(rsa_kms_key_arn)
    .public_key(public_key)
    .encryption_algorithm(aws_sdk_kms::types::EncryptionAlgorithmSpec::RsaesOaepSha256)
    .kms_client(aws_sdk_kms::Client::new(&sdk_config))
    .send()
    .await?;
```

------

## 使用多區域 AWS KMS keys
<a name="config-mrks"></a>

您可以使用多區域 AWS KMS keys 做為 AWS 資料庫加密 SDK 中的包裝金鑰。如果您使用多區域金鑰進行加密 AWS 區域，則可以使用不同 中的相關多區域金鑰進行解密 AWS 區域。

多區域 KMS 金鑰是一組不同 AWS KMS keys 中的 AWS 區域 ，具有相同的金鑰材料和金鑰 ID。您可以使用這些*相關*金鑰，就像它們在不同區域中是相同的金鑰一樣。多區域金鑰支援常見的災難復原和備份案例，這些案例需要在一個區域中加密，並在不同區域中解密，而無需進行跨區域呼叫 AWS KMS。如需多區域金鑰的相關資訊，請參閱《 *AWS Key Management Service 開發人員指南*》中的[使用多區域金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)。

為了支援多區域金鑰， AWS 資料庫加密 SDK AWS KMS multi-Region-aware keyring。`CreateAwsKmsMrkMultiKeyring` 方法同時支援單一區域和多區域金鑰。
+ 對於單一區域金鑰，multi-Region-aware符號的行為類似於單一區域 AWS KMS keyring。它只會嘗試使用加密資料的單一區域金鑰來解密加密文字。為了簡化您的 AWS KMS keyring 體驗，我們建議您在每次使用對稱加密 KMS 金鑰時使用 `CreateAwsKmsMrkMultiKeyring`方法。
+ 對於多區域金鑰，multi-Region-aware符號會嘗試使用與加密資料相同的多區域金鑰，或在您指定的區域中使用相關的多區域金鑰來解密加密文字。

在採用多個 KMS 金鑰的multi-Region-aware keyring 中，您可以指定多個單一區域金鑰和多區域金鑰。不過，您只能從一組相關的多區域金鑰中指定一個金鑰。如果您使用相同的金鑰 ID 指定多個金鑰識別符，則建構函式呼叫會失敗。

下列範例使用多區域 KMS 金鑰建立 AWS KMS keyring。範例會將多區域金鑰指定為產生器金鑰，並將單一區域金鑰指定為子金鑰。

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

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsMrkMultiKeyringInput createAwsKmsMrkMultiKeyringInput =
    CreateAwsKmsMrkMultiKeyringInput.builder()
            .generator(multiRegionKeyArn)
            .kmsKeyIds(Collections.singletonList(kmsKeyArn))
            .build();
IKeyring awsKmsMrkMultiKeyring = matProv.CreateAwsKmsMrkMultiKeyring(createAwsKmsMrkMultiKeyringInput);
```

------
#### [ C\$1 / .NET ]

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var createAwsKmsMrkMultiKeyringInput = new CreateAwsKmsMrkMultiKeyringInput
{
    Generator = multiRegionKeyArn,
    KmsKeyIds = new List<String> { kmsKeyArn }
};
var awsKmsMrkMultiKeyring = matProv.CreateAwsKmsMrkMultiKeyring(createAwsKmsMrkMultiKeyringInput);
```

------
#### [ Rust ]

```
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

let aws_kms_mrk_multi_keyring = mpl
    .create_aws_kms_mrk_multi_keyring()
    .generator(multiRegion_key_arn)
    .kms_key_ids(vec![key_arn.to_string()])
    .send()
    .await?;
```

------

當您使用多區域 AWS KMS keyring 時，您可以在嚴格模式下解密加密文字或探索模式。若要以嚴格模式解密加密文字，請在您要解密加密文字的區域中，使用相關多區域金鑰的金鑰 ARN 執行個體化多區域multi-Region-aware符號。如果您在不同的區域中指定相關多區域金鑰的金鑰 ARN （例如，記錄加密的區域），multi-Region-aware符號會為此進行跨區域呼叫 AWS KMS key。

在嚴格模式下解密時，multi-Region-aware符號需要金鑰 ARN。它只接受來自每組相關多區域金鑰的一個金鑰 ARN。

您也可以使用 AWS KMS 多區域金鑰在*探索模式中*解密。在探索模式中解密時，您不會指定任何 AWS KMS keys。（如需單一區域 AWS KMS 探索 keyring 的資訊，請參閱 [使用 AWS KMS 探索 keyring](#kms-keyring-discovery)。)

如果您使用多區域金鑰加密，探索模式中的multi-Region-aware符號會嘗試使用本機區域中相關的多區域金鑰來解密。如果不存在，呼叫會失敗。在探索模式中， AWS 資料庫加密 SDK 不會嘗試對用於加密的多區域金鑰進行跨區域呼叫。

## 使用 AWS KMS 探索 keyring
<a name="kms-keyring-discovery"></a>

解密時，最佳實務是指定 AWS 資料庫加密 SDK 可以使用的包裝金鑰。若要遵循此最佳實務，請使用 AWS KMS 解密 keyring，將 AWS KMS 包裝金鑰限制為您指定的金鑰。不過，您也可以建立*AWS KMS 探索 keyring*，也就是不指定任何包裝金鑰的 AWS KMS keyring。

 AWS Database Encryption SDK 為 AWS KMS 多區域金鑰提供標準 AWS KMS 探索 keyring 和探索 keyring。如需搭配 AWS 資料庫加密 SDK 使用多區域金鑰的詳細資訊，請參閱 [使用多區域 AWS KMS keys](#config-mrks)。

由於未指定任何包裝金鑰，探索 keyring 無法加密資料。如果您使用探索 keyring 單獨加密資料或在多 keyring 中加密資料，加密操作會失敗。

解密時，探索 keyring 可讓 AWS 資料庫加密 SDK 透過使用該加密 AWS KMS key 的 AWS KMS 來要求解密任何加密的資料金鑰，無論誰擁有或有權存取該金鑰 AWS KMS key。呼叫只有在發起人具有 的`kms:Decrypt`許可時才會成功 AWS KMS key。

**重要**  
如果您在解密多 keyring 中包含 AWS KMS 探索 keyring，則探索 keyring 會覆寫多 keyring 中其他 keyring 指定的所有 KMS 金鑰限制。 [多重 keyring](use-multi-keyring.md)多 keyring 的行為類似於其限制最低的 keyring。如果您單獨使用探索 keyring 或在多 keyring 中加密資料，加密操作會失敗

 AWS 資料庫加密 SDK 為方便起見提供了 AWS KMS 探索 keyring。不過，基於下列原因，建議您在可能時使用較具限制的 keyring。
+ **真實性** – 探索 AWS KMS keyring 可以使用用於加密材料描述中資料金鑰的任何 AWS KMS key ，只要發起人具有使用該金鑰 AWS KMS key 解密的許可。這可能不是發起 AWS KMS key 人打算使用的 。例如，其中一個加密的資料金鑰可能已在較不安全的情況下加密 AWS KMS key ，任何人都可以使用。
+ **延遲和效能** – 探索 AWS KMS keyring 可能比其他 keyring 明顯較慢，因為 AWS Database Encryption SDK 會嘗試解密所有加密的資料金鑰，包括 AWS KMS keys 在其他 AWS 帳戶 和 區域中加密的資料金鑰，而且 AWS KMS keys 發起人無權使用 進行解密。

如果您使用探索 keyring，我們建議您使用[*探索篩選條件*](configure.md#config-discovery)來限制 KMS 金鑰，這些金鑰可用於指定 AWS 帳戶 和 [分割區](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)中的金鑰。如需尋找帳戶 ID 和分割區的說明，請參閱《》中的[識別 AWS 帳戶 符](https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html)和 [ARN 格式](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-syntax)*AWS 一般參考*。

下列程式碼範例會使用 AWS KMS 探索篩選條件來執行個體化探索 keyring，以限制 AWS 資料庫加密 SDK 可用於`aws`分割區和`111122223333`範例帳戶中的 KMS 金鑰。

使用此程式碼之前，請將範例 AWS 帳戶 和分割區值取代為 AWS 帳戶 和分割區的有效值。如果您的 KMS 金鑰位於中國區域，請使用`aws-cn`分割區值。如果您的 KMS 金鑰位於 中 AWS GovCloud (US) Regions，請使用`aws-us-gov`分割區值。對於所有其他 AWS 區域，請使用`aws`分割區值。

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

```
// Create discovery filter
DiscoveryFilter discoveryFilter = DiscoveryFilter.builder()
        .partition("aws")
        .accountIds(111122223333)
        .build();
// Create the discovery keyring
CreateAwsKmsMrkDiscoveryMultiKeyringInput createAwsKmsMrkDiscoveryMultiKeyringInput = CreateAwsKmsMrkDiscoveryMultiKeyringInput.builder()
        .discoveryFilter(discoveryFilter)
        .build();
IKeyring decryptKeyring = matProv.CreateAwsKmsMrkDiscoveryMultiKeyring(createAwsKmsMrkDiscoveryMultiKeyringInput);
```

------
#### [ C\$1 / .NET ]

```
// Create discovery filter
var discoveryFilter = new DiscoveryFilter
{
    Partition = "aws",
    AccountIds = 111122223333
};
// Create the discovery keyring
var createAwsKmsMrkDiscoveryMultiKeyringInput = new CreateAwsKmsMrkDiscoveryMultiKeyringInput
{
    DiscoveryFilter = discoveryFilter
};
var decryptKeyring = matProv.CreateAwsKmsMrkDiscoveryMultiKeyring(createAwsKmsMrkDiscoveryMultiKeyringInput);
```

------
#### [ Rust ]

```
// Create discovery filter
let discovery_filter = DiscoveryFilter::builder()
    .partition("aws")
    .account_ids(111122223333)
    .build()?;

// Create the discovery keyring
let decrypt_keyring = mpl
    .create_aws_kms_mrk_discovery_multi_keyring()
    .discovery_filter(discovery_filter)
    .send()
    .await?;
```

------

## 使用 AWS KMS 區域探索 keyring
<a name="kms-keyring-regional"></a>

*AWS KMS 區域探索 keyring* 是不指定 KMS 金鑰 ARNs keyring。相反地，它允許 AWS 資料庫加密 SDK 僅使用 KMS 金鑰來解密 AWS 區域。

使用 AWS KMS 區域探索 keyring 解密時， AWS 資料庫加密 SDK 會解密在指定 AWS KMS key 中的 下加密的任何加密資料金鑰 AWS 區域。若要成功，發起人在加密資料金鑰 AWS 區域 的指定 AWS KMS keys 中，必須擁有至少一個 的`kms:Decrypt`許可。

如同其他探索 keyring，區域探索 keyring 不會影響加密。它只有在解密加密的欄位時才有效。如果您在用於加密和解密的多 keyring 中使用區域探索 keyring，則只有在解密時才有效。如果您使用多區域探索 keyring 單獨加密資料或在多 keyring 中加密資料，加密操作會失敗。

**重要**  
如果您在解密多 keyring 中包含 AWS KMS 區域探索 keyring，區域探索 keyring 會覆寫多 keyring 中其他 keyring 指定的所有 KMS 金鑰限制。 [多重 keyring](use-multi-keyring.md)多 keyring 的行為類似於其限制最低的 keyring。 AWS KMS 探索 keyring 本身或多 keyring 使用時，不會影響加密。

 AWS Database Encryption SDK 中的區域探索 keyring 嘗試僅使用指定區域中的 KMS 金鑰進行解密。當您使用探索 keyring 時，您可以在 AWS KMS 用戶端上設定 區域。這些 AWS 資料庫加密 SDK 實作不會依區域篩選 KMS 金鑰，但 AWS KMS 會失敗指定區域外 KMS 金鑰的解密請求。

如果您使用探索 keyring，我們建議您使用*探索篩選條件*，將解密所用的 KMS 金鑰限制為指定 AWS 帳戶 和 分割區中的金鑰。

例如，下列程式碼會使用探索篩選條件建立 AWS KMS 區域探索 keyring。此 keyring 將 AWS 資料庫加密 SDK 限制為美國西部 （奧勒岡） 區域 (us-west-2) 帳戶 111122223333 中的 KMS 金鑰。

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

```
// Create the discovery filter
DiscoveryFilter discoveryFilter = DiscoveryFilter.builder()
        .partition("aws")
        .accountIds(111122223333)
        .build();
// Create the discovery keyring
CreateAwsKmsMrkDiscoveryMultiKeyringInput createAwsKmsMrkDiscoveryMultiKeyringInput = CreateAwsKmsMrkDiscoveryMultiKeyringInput.builder()
        .discoveryFilter(discoveryFilter)
        .regions("us-west-2")
        .build();
IKeyring decryptKeyring = matProv.CreateAwsKmsMrkDiscoveryMultiKeyring(createAwsKmsMrkDiscoveryMultiKeyringInput);
```

------
#### [ C\$1 / .NET ]

```
// Create discovery filter
var discoveryFilter = new DiscoveryFilter
{
    Partition = "aws",
    AccountIds = 111122223333
};
// Create the discovery keyring
var createAwsKmsMrkDiscoveryMultiKeyringInput = new CreateAwsKmsMrkDiscoveryMultiKeyringInput
{
    DiscoveryFilter = discoveryFilter,
    Regions = us-west-2
};
var decryptKeyring = matProv.CreateAwsKmsMrkDiscoveryMultiKeyring(createAwsKmsMrkDiscoveryMultiKeyringInput);
```

------
#### [ Rust ]

```
// Create discovery filter
let discovery_filter = DiscoveryFilter::builder()
    .partition("aws")
    .account_ids(111122223333)
    .build()?;

// Create the discovery keyring
let decrypt_keyring = mpl
    .create_aws_kms_mrk_discovery_multi_keyring()
    .discovery_filter(discovery_filter)
    .regions(us-west-2)
    .send()
    .await?;
```

------

# AWS KMS 階層式 keyring
<a name="use-hierarchical-keyring"></a>


****  

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

**注意**  
自 2023 年 7 月 24 日起，不支援在開發人員預覽版期間建立的分支金鑰。建立新的分支金鑰，以繼續使用您在開發人員預覽期間建立的金鑰存放區。

使用 AWS KMS 階層式 keyring，您可以在對稱加密 KMS 金鑰下保護密碼編譯資料，而無需 AWS KMS 在每次加密或解密記錄時呼叫 。對於需要將對 的呼叫降至最低的應用程式 AWS KMS，以及可以重複使用某些密碼編譯資料而不違反其安全要求的應用程式，這是理想的選擇。

階層式 keyring 是一種密碼編譯資料快取解決方案，使用保留在 Amazon DynamoDB 資料表中的 AWS KMS 受保護*分支金鑰*，然後本機快取用於加密和解密操作的分支金鑰資料，以減少 AWS KMS 呼叫次數。DynamoDB 資料表做為管理和保護分支金鑰的金鑰存放區。它會存放作用中的分支金鑰和所有舊版的分支金鑰。*作用中*分支金鑰是最新的分支金鑰版本。階層式 keyring 會為每個加密請求使用唯一的資料加密金鑰，並使用衍生自作用中分支金鑰的唯一包裝金鑰來加密每個資料加密金鑰。階層式 keyring 取決於作用中分支索引鍵與其衍生包裝索引鍵之間建立的階層。

階層式 keyring 通常使用每個分支金鑰版本來滿足多個請求。但是，您可以控制重複使用作用中分支金鑰的程度，並判斷作用中分支金鑰的輪換頻率。分支金鑰的作用中版本會保持作用中狀態，直到您[將其輪換](rotate-branch-key.md)為止。舊版的作用中分支金鑰不會用於執行加密操作，但仍然可以查詢並用於解密操作。

當您執行個體化階層 keyring 時，它會建立本機快取。您可以指定[快取限制](#cache-limit)，定義分支金鑰資料在本機快取中存放的時間上限，然後再過期並從快取移出。階層式 keyring 會 AWS KMS 呼叫一次 來解密分支金鑰，並在 操作中第一次指定 `branch-key-id` 時組合分支金鑰材料。然後，分支金鑰資料會存放在本機快取中，並重複使用於指定 的所有加密和解密操作，`branch-key-id`直到快取限制過期為止。在本機快取中存放分支金鑰材料可減少 AWS KMS 呼叫。例如，請考慮 15 分鐘的快取限制。如果您在該快取限制內執行 10，000 個加密操作，[傳統 AWS KMS keyring](use-kms-keyring.md) 將需要進行 10，000 次 AWS KMS 呼叫，以滿足 10，000 個加密操作。如果您有一個作用中的 `branch-key-id`，則階層式 keyring 只需要呼叫一次 AWS KMS ，以滿足 10，000 個加密操作。

本機快取會將加密資料與解密資料分開。加密資料是從作用中分支金鑰組合而成，並重複使用於所有加密操作，直到快取限制過期為止。解密資料是從加密欄位中繼資料中識別的分支金鑰 ID 和版本組合而成，並且會重複使用於與分支金鑰 ID 和版本相關的所有解密操作，直到快取限制到期為止。本機快取一次可以存放相同分支金鑰的多個版本。當本機快取設定為使用 時[branch key ID supplier](#branch-key-id-supplier)，它也可以一次存放來自多個作用中分支金鑰的分支金鑰資料。

**注意**  
 AWS 資料庫加密 SDK 中提到的所有*階層式 keyring* 都是指 AWS KMS 階層式 keyring。

**Topics**
+ [運作方式](#how-hierarchical-keyring-works)
+ [先決條件](#hierarchical-keyring-prereqs)
+ [所需的許可](#hierarchical-keyring-permissions)
+ [選擇快取](#hierarchical-keyring-caches)
+ [建立階層 keyring](#initialize-hierarchical-keyring)
+ [使用階層式 keyring 進行可搜尋的加密](#searchable-encryption-hierarchical-keyrings)

## 運作方式
<a name="how-hierarchical-keyring-works"></a>

下列逐步解說說明階層式 keyring 如何組合加密和解密資料，以及 keyring 為加密和解密操作所做的不同呼叫。如需包裝金鑰衍生和純文字資料金鑰加密程序的技術詳細資訊，請參閱[AWS KMS 階層式 keyring 技術詳細資訊](reference.md#hierarchical-keyring-details)。

**加密和簽署**  
下列逐步解說說明階層式 keyring 如何組合加密資料並衍生唯一的包裝金鑰。

1. 加密方法會向階層式 keyring 詢問加密資料。keyring 會產生純文字資料金鑰，然後檢查本機快取中是否有有效的分支金鑰材料來產生包裝金鑰。如果有有效的分支金鑰材料， keyring 會繼續進行**步驟 4**。

1. 如果沒有有效的分支金鑰材料，階層式 keyring 會查詢作用中分支金鑰的金鑰存放區。

   1. 金鑰存放區會呼叫 AWS KMS 來解密作用中分支金鑰，並傳回純文字作用中分支金鑰。識別作用中分支金鑰的資料會序列化，以在解密呼叫中提供其他已驗證的資料 (AAD) AWS KMS。

   1. 金鑰存放區會傳回純文字分支金鑰和識別它的資料，例如分支金鑰版本。

1. 階層式 keyring 會組合分支金鑰材料 （純文字分支金鑰和分支金鑰版本），並將它們的副本存放在本機快取中。

1. 階層式 keyring 會從純文字分支金鑰和 16 位元組隨機 salt 衍生唯一的包裝金鑰。它使用衍生的包裝金鑰來加密純文字資料金鑰的副本。

加密方法使用加密資料來加密和簽署記錄。如需如何在 AWS 資料庫加密 SDK 中加密和簽署記錄的詳細資訊，請參閱[加密和簽署](how-it-works.md#encrypt-and-sign)。

**解密和驗證**  
下列逐步解說說明階層式 keyring 如何組合解密資料和解密加密的資料金鑰。

1. 解密方法會從加密記錄的資料描述欄位中識別加密的資料金鑰，並將其傳遞至階層式 keyring。

1. 階層式 keyring 會將識別加密資料金鑰的資料還原序列化，包括分支金鑰版本、16 位元組 salt，以及描述資料金鑰如何加密的其他資訊。

   如需詳細資訊，請參閱[AWS KMS 階層式 keyring 技術詳細資訊](reference.md#hierarchical-keyring-details)。

1. 階層式 keyring 會檢查本機快取中是否有與**步驟 2 **中識別的分支金鑰版本相符的有效分支金鑰材料。如果有有效的分支金鑰材料， keyring 會繼續進行**步驟 6**。

1. 如果沒有有效的分支金鑰資料，階層式 keyring 會查詢符合**步驟 2 **中所識別分支金鑰版本的分支金鑰存放區。

   1. 金鑰存放區會呼叫 AWS KMS 來解密分支金鑰，並傳回純文字作用中分支金鑰。識別作用中分支金鑰的資料會序列化，以在解密呼叫中提供其他已驗證的資料 (AAD) AWS KMS。

   1. 金鑰存放區會傳回純文字分支金鑰和識別它的資料，例如分支金鑰版本。

1. 階層式 keyring 會組合分支金鑰材料 （純文字分支金鑰和分支金鑰版本），並將它們的副本存放在本機快取中。

1. 階層式 keyring 使用**步驟 2** 中識別的組合分支金鑰材料和 16 位元組的 salt 來重現加密資料金鑰的唯一包裝金鑰。

1. 階層式 keyring 使用重現的包裝金鑰來解密資料金鑰，並傳回純文字資料金鑰。

解密方法使用解密資料和純文字資料金鑰來解密和驗證記錄。如需如何在 AWS 資料庫加密 SDK 中解密和驗證記錄的詳細資訊，請參閱[解密和驗證](how-it-works.md#decrypt-and-verify)。

## 先決條件
<a name="hierarchical-keyring-prereqs"></a>

在建立和使用階層 keyring 之前，請確定符合下列先決條件。
+ 您或您的金鑰存放區管理員[已建立金鑰存放](create-keystore.md)區，並[建立至少一個作用中的分支金鑰](create-branch-keys.md)。
+ 您已[設定金鑰存放區動作](keystore-actions.md#config-keystore-actions)。
**注意**  
如何設定金鑰存放區動作，決定您可以執行哪些操作，以及階層式 keyring 可以使用哪些 KMS 金鑰。如需詳細資訊，請參閱 [金鑰存放區動作](keystore-actions.md)。
+ 您擁有存取和使用金鑰存放區和分支金鑰所需的 AWS KMS 許可。如需詳細資訊，請參閱[所需的許可](#hierarchical-keyring-permissions)。
+ 您已檢閱支援的快取類型，並設定最符合您需求的快取類型。如需詳細資訊，請參閱[選擇快取](#hierarchical-keyring-caches)

## 所需的許可
<a name="hierarchical-keyring-permissions"></a>

 AWS 資料庫加密 SDK 不需要 ， AWS 帳戶 也不依賴任何 AWS 服務。不過，若要使用階層式 keyring，您需要 AWS 帳戶 和 AWS KMS key（金鑰存放區） 中對稱加密的下列最低許可。
+ 若要使用階層式 keyring 加密和解密資料，您需要 [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html)。
+ 若要[建立](create-branch-keys.md)和[輪換](rotate-branch-key.md)分支金鑰，您需要 [kms:GenerateDataKeyWithoutPlaintext](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKeyWithoutPlaintext.html) 和 [kms:ReEncrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_ReEncrypt.html)。

如需控制對分支金鑰和金鑰存放區之存取的詳細資訊，請參閱 [實作最低權限的許可](keystore-least-privilege.md)。

## 選擇快取
<a name="hierarchical-keyring-caches"></a>

階層式 keyring 透過本機快取用於加密和解密操作的分支金鑰資料 AWS KMS ，減少對 進行的呼叫數量。在[建立階層 keyring](#initialize-hierarchical-keyring) 之前，您需要決定要使用的快取類型。您可以使用預設快取或自訂快取，以符合您的需求。

階層式 keyring 支援下列快取類型：
+ [預設快取](#cache-default)
+ [MultiThreaded快取](#cache-multithreaded)
+ [StormTracking 快取](#cache-stormtracking)
+ [共用快取](#cache-shared)

### 預設快取
<a name="cache-default"></a>

對於大多數使用者，預設快取滿足其執行緒需求。預設快取旨在支援大量多執行緒環境。當分支金鑰材料項目過期時，預設快取 AWS KMS 會提前 10 秒通知一個執行緒分支金鑰材料項目即將過期，以防止多個執行緒呼叫。這可確保只有一個執行緒將請求傳送至 AWS KMS 以重新整理快取。

預設和 StormTracking 快取支援相同的執行緒模型，但您只需要指定使用預設快取的進入容量。如需更精細的快取自訂，請使用 [StormTracking 快取](#cache-stormtracking)。

除非您想要自訂可在本機快取中存放的分支金鑰材料項目數目，否則在建立階層式 keyring 時不需要指定快取類型。如果您未指定快取類型，階層式 keyring 會使用預設快取類型，並將進入容量設定為 1000。

若要自訂預設快取，請指定下列值：
+ **項目容量**： 限制可在本機快取中存放的分支金鑰材料項目數量。

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

```
.cache(CacheType.builder()
        .Default(DefaultCache.builder()
        .entryCapacity(100)
        .build())
```

------
#### [ C\$1 / .NET ]

```
CacheType defaultCache = new CacheType
{
    Default = new DefaultCache{EntryCapacity = 100}
};
```

------
#### [ Rust ]

```
let cache: CacheType = CacheType::Default(
    DefaultCache::builder()
        .entry_capacity(100)
        .build()?,
);
```

------

### MultiThreaded快取
<a name="cache-multithreaded"></a>

MultiThreaded快取可在多執行緒環境中安全使用，但它不提供將 AWS KMS 或 Amazon DynamoDB 呼叫降至最低的任何功能。因此，當分支金鑰材料項目過期時，所有執行緒都會同時收到通知。這可能會導致多個 AWS KMS 呼叫重新整理快取。

若要使用MultiThreaded快取，請指定下列值：
+ **項目容量**： 限制可在本機快取中存放的分支金鑰材料項目數量。
+ **項目剔除尾端大小**：定義達到進入容量時要剔除的項目數量。

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

```
.cache(CacheType.builder()
        .MultiThreaded(MultiThreadedCache.builder()
        .entryCapacity(100)
        .entryPruningTailSize(1)                                        
        .build())
```

------
#### [ C\$1 / .NET ]

```
CacheType multithreadedCache = new CacheType
{
    MultiThreaded = new MultiThreadedCache
    {
        EntryCapacity = 100,
        EntryPruningTailSize = 1
    }
};
```

------
#### [ Rust ]

```
CacheType::MultiThreaded(
            MultiThreadedCache::builder()
                    .entry_capacity(100)
                    .entry_pruning_tail_size(1)
                    .build()?)
```

------

### StormTracking 快取
<a name="cache-stormtracking"></a>

StormTracking 快取旨在支援大量多執行緒環境。當分支金鑰材料項目過期時， StormTracking 快取 AWS KMS 會提前通知一個執行緒分支金鑰材料項目即將過期，以防止多個執行緒呼叫。這可確保只有一個執行緒將請求傳送至 AWS KMS 以重新整理快取。



若要使用 StormTracking 快取，請指定下列值：
+ **項目容量**： 限制可在本機快取中存放的分支金鑰材料項目數量。

  預設值：1000 個項目
+ **項目剔除尾部大小**： 定義一次要剔除的分支金鑰材料項目數目。

  預設值：1 個項目
+ **寬限期**：定義過期前嘗試重新整理分支金鑰材料的秒數。

  預設值：10 秒
+ **Grace 間隔**：定義嘗試重新整理分支金鑰資料之間的秒數。

  預設值：1 秒
+ **Fan out**：定義可同時嘗試重新整理分支金鑰材料的次數。

  預設值：20 次嘗試
+ **飛行中存留時間 (TTL)**：定義直到嘗試重新整理分支金鑰資料逾時的秒數。每當快取傳回以`NoSuchEntry`回應 時`GetCacheEntry`，該分支金鑰會被視為正在*傳輸中*，直到使用`PutCache`項目寫入相同的金鑰為止。

  預設值：10 秒
+ **休眠**：定義`fanOut`超過 時執行緒應休眠的秒數。

  預設值：20 毫秒

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

```
.cache(CacheType.builder()
        .StormTracking(StormTrackingCache.builder()
        .entryCapacity(100)
        .entryPruningTailSize(1)
        .gracePeriod(10)
        .graceInterval(1)
        .fanOut(20) 
        .inFlightTTL(10)
        .sleepMilli(20)                                        
        .build())
```

------
#### [ C\$1 / .NET ]

```
CacheType stormTrackingCache = new CacheType
{
    StormTracking = new StormTrackingCache
    {
        EntryCapacity = 100,
        EntryPruningTailSize = 1,
        FanOut = 20,
        GraceInterval = 1,
        GracePeriod = 10,
        InFlightTTL = 10,
        SleepMilli = 20
    }
};
```

------
#### [ Rust ]

```
CacheType::StormTracking(
                StormTrackingCache::builder()
                    .entry_capacity(100)
                    .entry_pruning_tail_size(1)
                    .grace_period(10)
                    .grace_interval(1)
                    .fan_out(20)
                    .in_flight_ttl(10)
                    .sleep_milli(20)
                    .build()?)
```

------

### 共用快取
<a name="cache-shared"></a>

根據預設，階層式 keyring 會在您每次執行個體化 keyring 時建立新的本機快取。不過，共用快取可讓您跨多個階層 keyring 共用快取，以協助節省記憶體。共用快取不會為每個您執行個體化的階層式 keyring 建立新的密碼編譯資料快取，而是只會在記憶體中儲存一個快取，供參考該快取的所有階層式 keyring 使用。共用快取可避免在 keyring 之間重複密碼編譯資料，有助於最佳化記憶體使用量。相反地，階層式 keyring 可以存取相同的基礎快取，從而減少整體記憶體使用量。

建立共用快取時，您仍然會定義快取類型。您可以指定 [預設快取](#cache-default)、 [MultiThreaded快取](#cache-multithreaded)或 [StormTracking 快取](#cache-stormtracking)做為快取類型，或取代任何相容的自訂快取。



**分區**  
多個階層式 keyring 可以使用單一共用快取。當您使用共用快取建立階層 keyring 時，您可以定義選用的**分割區 ID**。分割區 ID 會區分要寫入快取的階層式 keyring。如果兩個階層 keyring 參考相同的分割區 ID、 [logical key store name](create-keystore.md#logical-key-store-name)和分支金鑰 ID，則兩個 keyring 將在快取中共用相同的快取項目。如果您使用相同的共用快取建立兩個階層 keyring，但分割區 IDs 不同，則每個 keyring 只會從共用快取內自己的指定分割區存取快取項目。分割區在共用快取中充當邏輯分割區，允許每個階層 keyring 在自己的指定分割區上獨立運作，而不會干擾存放在另一個分割區中的資料。

如果您想要重複使用或共用分割區中的快取項目，您必須定義自己的分割區 ID。當您將分割區 ID 傳遞至階層式 keyring 時，keyring 可以重複使用共用快取中已存在的快取項目，而不必再次擷取並重新授權分支金鑰資料。如果您未指定分割區 ID，則每次執行個體化階層式 keyring 時，都會自動將唯一的分割區 ID 指派給 keyring。

下列程序示範如何使用[預設快取類型](#cache-default)建立共用快取，並將其傳遞至階層式 keyring。

1. 使用物料提供者程式庫 `CryptographicMaterialsCache`(MPL) 建立 (CMC)。 [https://github.com/aws/aws-cryptographic-material-providers-library](https://github.com/aws/aws-cryptographic-material-providers-library)

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

   ```
   // Instantiate the MPL
   final MaterialProviders matProv =
       MaterialProviders.builder()
           .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
           .build();
   
   // Create a CacheType object for the Default cache
   final CacheType cache =
       CacheType.builder() 
           .Default(DefaultCache.builder().entryCapacity(100).build())
           .build();
   
   // Create a CMC using the default cache
   final CreateCryptographicMaterialsCacheInput cryptographicMaterialsCacheInput =
       CreateCryptographicMaterialsCacheInput.builder()
           .cache(cache)
           .build();
   
   final ICryptographicMaterialsCache sharedCryptographicMaterialsCache =
       matProv.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
   ```

------
#### [ C\$1 / .NET ]

   ```
   // Instantiate the MPL
   var materialProviders = new MaterialProviders(new MaterialProvidersConfig());
    
   // Create a CacheType object for the Default cache
   var cache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} };
    
   // Create a CMC using the default cache
   var cryptographicMaterialsCacheInput = new CreateCryptographicMaterialsCacheInput {Cache = cache};
    
   var sharedCryptographicMaterialsCache = materialProviders.CreateCryptographicMaterialsCache(cryptographicMaterialsCacheInput);
   ```

------
#### [ Rust ]

   ```
   // Instantiate the MPL
   let mpl_config = MaterialProvidersConfig::builder().build()?;
   let mpl = mpl_client::Client::from_conf(mpl_config)?;
   
   // Create a CacheType object for the default cache
   let cache: CacheType = CacheType::Default(
       DefaultCache::builder()
           .entry_capacity(100)
           .build()?,
   );
   
   // Create a CMC using the default cache
   let shared_cryptographic_materials_cache: CryptographicMaterialsCacheRef = mpl.
       create_cryptographic_materials_cache()
       .cache(cache)
       .send()
       .await?;
   ```

------

1. 建立共用快取的`CacheType`物件。

   `sharedCryptographicMaterialsCache` 將您在**步驟 1 **中建立的 傳遞至新`CacheType`物件。

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

   ```
   // Create a CacheType object for the sharedCryptographicMaterialsCache
   final CacheType sharedCache =
       CacheType.builder()
           .Shared(sharedCryptographicMaterialsCache)
           .build();
   ```

------
#### [ C\$1 / .NET ]

   ```
   // Create a CacheType object for the sharedCryptographicMaterialsCache
   var sharedCache = new CacheType { Shared = sharedCryptographicMaterialsCache };
   ```

------
#### [ Rust ]

   ```
   // Create a CacheType object for the shared_cryptographic_materials_cache
   let shared_cache: CacheType = CacheType::Shared(shared_cryptographic_materials_cache);
   ```

------

1. 將`sharedCache`物件從**步驟 2** 傳遞至階層 keyring。

   當您使用共用快取建立階層式 keyring 時，您可以選擇性地定義 ，`partitionID`以在多個階層式 keyring 之間共用快取項目。如果您未指定分割區 ID，階層式 keyring 會自動為 keyring 指派唯一的分割區 ID。
**注意**  
如果您建立兩個或多個參考相同分割區 ID、 和分支金鑰 ID 的 keyring[logical key store name](create-keystore.md#logical-key-store-name)，您的階層 keyring 將在共用快取中共用相同的快取項目。如果您不希望多個 keyring 共用相同的快取項目，則必須為每個階層 keyring 使用唯一的分割區 ID。

   下列範例會使用 建立階層式 keyring[branch key ID supplier](#branch-key-id-supplier)，快取[限制](#cache-limit)為 600 秒。如需下列階層式 keyring 組態中定義之值的詳細資訊，請參閱 [建立階層 keyring](#initialize-hierarchical-keyring)。

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

   ```
   // Create the Hierarchical keyring
   final CreateAwsKmsHierarchicalKeyringInput keyringInput =
       CreateAwsKmsHierarchicalKeyringInput.builder()
           .keyStore(keystore)
           .branchKeyIdSupplier(branchKeyIdSupplier)
           .ttlSeconds(600)
           .cache(sharedCache)
           .partitionID(partitionID)
           .build();        
   final IKeyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
   ```

------
#### [ C\$1 / .NET ]

   ```
   // Create the Hierarchical keyring        
   var createKeyringInput = new CreateAwsKmsHierarchicalKeyringInput
   {
      KeyStore = keystore,
      BranchKeyIdSupplier = branchKeyIdSupplier,
      Cache = sharedCache,
      TtlSeconds = 600,
      PartitionId = partitionID
   };
   var keyring = materialProviders.CreateAwsKmsHierarchicalKeyring(createKeyringInput);
   ```

------
#### [ Rust ]

   ```
   // Create the Hierarchical keyring
   let keyring1 = mpl
       .create_aws_kms_hierarchical_keyring()
       .key_store(key_store1)
       .branch_key_id(branch_key_id.clone())
       // CryptographicMaterialsCacheRef is an Rc (Reference Counted), so if you clone it to
       // pass it to different Hierarchical Keyrings, it will still point to the same
       // underlying cache, and increment the reference count accordingly.
       .cache(shared_cache.clone())
       .ttl_seconds(600)
       .partition_id(partition_id.clone())
       .send()
       .await?;
   ```

------

## 建立階層 keyring
<a name="initialize-hierarchical-keyring"></a>

若要建立階層 keyring，您必須提供下列值：
+ **金鑰存放區名稱**

  您或金鑰存放區管理員建立做為金鑰存放區的 DynamoDB 資料表名稱。
+ 

  **快取限制存留時間 (TTL)**

  分支金鑰材料項目在本機快取過期前可以使用的秒數。快取限制 TTL 決定用戶端呼叫 AWS KMS 以授權使用分支金鑰的頻率。該值必須大於零。快取限制 TTL 過期後，永遠不會提供項目，並且會從本機快取移出。
+ **分支金鑰識別符**

  您可以靜態設定 `branch-key-id`，以識別金鑰存放區中的單一作用中分支金鑰，或提供分支金鑰 ID 供應商。

  

  *分支金鑰 ID 供應商*會使用存放在加密內容中的欄位，來判斷解密記錄所需的分支金鑰。根據預設，加密內容中只會包含分割區和排序金鑰。不過，您可以使用`SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT`[密碼編譯動作](concepts.md#crypt-actions)，在加密內容中包含其他欄位。

  對於每個租用戶都有自己的分支金鑰的多租用戶資料庫，我們強烈建議使用分支金鑰 ID 供應商。您可以使用分支金鑰 ID 供應商為分支金鑰 IDs 建立易記的名稱，以便輕鬆識別特定租用戶的正確分支金鑰 ID。例如，易記名稱可讓您將分支金鑰稱為 ，`tenant1`而不是 `b3f61619-4d35-48ad-a275-050f87e15122`。

  對於解密操作，您可以靜態設定單一階層 keyring 將解密限制為單一租用戶，也可以使用分支金鑰 ID 供應商來識別負責解密記錄的租用戶。
+ **（選用） 快取**

  如果您想要自訂快取類型或可在本機快取中存放的分支金鑰材料項目數量，請在初始化 keyring 時指定快取類型和項目容量。

  階層式 keyring 支援下列快取類型：預設、MultiThreaded、StormTracking和共用。如需示範如何定義每個快取類型的詳細資訊和範例，請參閱 [選擇快取](#hierarchical-keyring-caches)。

  如果您未指定快取，階層式 keyring 會自動使用預設快取類型，並將進入容量設定為 1000。
+ **（選用） 分割區 ID**

  如果您指定 [共用快取](#cache-shared)，您可以選擇定義分割區 ID。分割區 ID 會區分要寫入快取的階層式 keyring。如果您想要重複使用或共用分割區中的快取項目，您必須定義自己的分割區 ID。您可以為分割區 ID 指定任何字串。如果您未指定分割區 ID，則會在建立時自動將唯一的分割區 ID 指派給 keyring。

  如需詳細資訊，請參閱[Partitions](#shared-cache-partitions)。
**注意**  
如果您建立兩個或多個參考相同分割區 ID、 和分支金鑰 ID 的 keyring[logical key store name](create-keystore.md#logical-key-store-name)，您的階層 keyring 將在共用快取中共用相同的快取項目。如果您不希望多個 keyring 共用相同的快取項目，則必須為每個階層 keyring 使用唯一的分割區 ID。
+ **（選用） 授予權杖的清單**

  如果您使用[授權](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)控制對階層式 keyring 中 KMS 金鑰的存取，您必須在初始化 keyring 時提供所有必要的授予權杖。

### 使用靜態分支金鑰 ID 建立階層 keyring
<a name="static-branch-key-id-config"></a>

下列範例示範如何建立具有靜態分支金鑰 ID、 [預設快取](#cache-default)和快取限制 TTL 600 秒的階層式 keyring。

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

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder()
        .keyStore(branchKeyStoreName)
        .branchKeyId(branch-key-id)
        .ttlSeconds(600)
        .build();
final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
```

------
#### [ C\$1 / .NET ]

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsHierarchicalKeyringInput
{
   KeyStore = keystore,
   BranchKeyIdSupplier = branchKeyIdSupplier,
   TtlSeconds = 600
};
var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
```

------
#### [ Rust ]

```
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

let hierarchical_keyring = mpl
    .create_aws_kms_hierarchical_keyring()
    .branch_key_id(branch_key_id)
    .key_store(branch_key_store_name)
    .ttl_seconds(600)
    .send()
    .await?;
```

------

### 使用分支金鑰 ID 供應商建立階層 keyring
<a name="branch-key-id-supplier-config"></a>

下列程序示範如何使用分支金鑰 ID 供應商建立階層 keyring。

1. 建立分支金鑰 ID 供應商

   下列範例會為**步驟 1 **中建立的兩個分支金鑰建立易記名稱，並使用 DynamoDB 用戶端的 AWS Database Encryption SDK 呼叫 來`CreateDynamoDbEncryptionBranchKeyIdSupplier`建立分支金鑰 ID 供應商。

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

   ```
   // Create friendly names for each branch-key-id 
   class ExampleBranchKeyIdSupplier implements IDynamoDbKeyBranchKeyIdSupplier {
       private static String branchKeyIdForTenant1;
       private static String branchKeyIdForTenant2;
   
       public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) {
           this.branchKeyIdForTenant1 = tenant1Id;
           this.branchKeyIdForTenant2 = tenant2Id;
       }
   // Create the branch key ID supplier    
   final DynamoDbEncryption ddbEnc = DynamoDbEncryption.builder()
           .DynamoDbEncryptionConfig(DynamoDbEncryptionConfig.builder().build())
           .build();
   final BranchKeyIdSupplier branchKeyIdSupplier = ddbEnc.CreateDynamoDbEncryptionBranchKeyIdSupplier(
       CreateDynamoDbEncryptionBranchKeyIdSupplierInput.builder()
               .ddbKeyBranchKeyIdSupplier(new ExampleBranchKeyIdSupplier(branch-key-ID-tenant1, branch-key-ID-tenant2))
               .build()).branchKeyIdSupplier();
   ```

------
#### [ C\$1 / .NET ]

   ```
   // Create friendly names for each branch-key-id
    class ExampleBranchKeyIdSupplier : DynamoDbKeyBranchKeyIdSupplierBase {
       private String _branchKeyIdForTenant1;
       private String _branchKeyIdForTenant2;
   
       public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) {
           this._branchKeyIdForTenant1 = tenant1Id;
           this._branchKeyIdForTenant2 = tenant2Id;
       }    
   // Create the branch key ID supplier
   var ddbEnc = new DynamoDbEncryption(new DynamoDbEncryptionConfig());
   var branchKeyIdSupplier = ddbEnc.CreateDynamoDbEncryptionBranchKeyIdSupplier(
       new CreateDynamoDbEncryptionBranchKeyIdSupplierInput
       {
           DdbKeyBranchKeyIdSupplier = new ExampleBranchKeyIdSupplier(branch-key-ID-tenant1, branch-key-ID-tenant2)
       }).BranchKeyIdSupplier;
   ```

------
#### [ Rust ]

   ```
   // Create friendly names for each branch_key_id
   pub struct ExampleBranchKeyIdSupplier {
       branch_key_id_for_tenant1: String,
       branch_key_id_for_tenant2: String,
   }
   
   impl ExampleBranchKeyIdSupplier {
       pub fn new(tenant1_id: &str, tenant2_id: &str) -> Self {
           Self {
               branch_key_id_for_tenant1: tenant1_id.to_string(),
               branch_key_id_for_tenant2: tenant2_id.to_string(),
           }
       }
   }
   
   // Create the branch key ID supplier                                        
   let dbesdk_config = DynamoDbEncryptionConfig::builder().build()?;
   let dbesdk = dbesdk_client::Client::from_conf(dbesdk_config)?;
   let supplier = ExampleBranchKeyIdSupplier::new(tenant1_branch_key_id, tenant2_branch_key_id);
   
   let branch_key_id_supplier = dbesdk
       .create_dynamo_db_encryption_branch_key_id_supplier()
       .ddb_key_branch_key_id_supplier(supplier)
       .send()
       .await?
       .branch_key_id_supplier
       .unwrap();
   ```

------

1. 建立階層 keyring

   下列範例會使用**步驟 1 **中建立的分支金鑰 ID 供應商初始化階層 keyring，快取限制 TLL 為 600 秒，快取大小上限為 1000。

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

   ```
   final MaterialProviders matProv = MaterialProviders.builder()
           .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
           .build();
   final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder()
           .keyStore(keystore)
           .branchKeyIdSupplier(branchKeyIdSupplier)
           .ttlSeconds(600)
           .cache(CacheType.builder() //OPTIONAL
                   .Default(DefaultCache.builder()
                   .entryCapacity(100)
                   .build())
           .build())
           .build();
   final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
   ```

------
#### [ C\$1 / .NET ]

   ```
   var matProv = new MaterialProviders(new MaterialProvidersConfig());
   var keyringInput = new CreateAwsKmsHierarchicalKeyringInput
   {
      KeyStore = keystore,
      BranchKeyIdSupplier = branchKeyIdSupplier,
      TtlSeconds = 600, 
      Cache = new CacheType
      {
           Default = new DefaultCache { EntryCapacity = 100 }
      }
   };
   var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
   ```

------
#### [ Rust ]

   ```
   let mpl_config = MaterialProvidersConfig::builder().build()?;
   let mpl = mpl_client::Client::from_conf(mpl_config)?;
   
   let hierarchical_keyring = mpl
       .create_aws_kms_hierarchical_keyring()
       .branch_key_id_supplier(branch_key_id_supplier)
       .key_store(key_store)
       .ttl_seconds(600)
       .send()
       .await?;
   ```

------

## 使用階層式 keyring 進行可搜尋的加密
<a name="searchable-encryption-hierarchical-keyrings"></a>

[可搜尋加密](searchable-encryption.md)可讓您在不解密整個資料庫的情況下搜尋加密的記錄。這可透過使用[信標](beacons.md)為加密欄位的純文字值編製索引來完成。若要實作可搜尋加密，您必須使用階層式 keyring。

金鑰存放區`CreateKey`操作會產生分支金鑰和*信標金鑰*。分支金鑰用於記錄加密和解密操作。信標金鑰用於產生信標。

分支金鑰和信標金鑰受到 AWS KMS key 您在建立金鑰存放區服務時指定的相同保護。`CreateKey` 操作呼叫 AWS KMS 以產生分支金鑰後，它會再次呼叫 [kms:GenerateDataKeyWithoutPlaintext](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKeyWithoutPlaintext.html)，以使用以下請求產生信標金鑰。

```
{
   "EncryptionContext": { 
      "branch-key-id" : "branch-key-id",
      "type" : type,
      "create-time" : "timestamp",
      "tablename" : "the logical table name for your key store",
      "kms-arn" : the KMS key ARN,
      "hierarchy-version" : 1
   },
   "KeyId": "the KMS key ARN",
   "NumberOfBytes": "32"
}
```

產生這兩個金鑰後， `CreateKey`操作會呼叫 [ddb：TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html) 來寫入兩個新項目，以將分支金鑰和信標金鑰保留在您的分支金鑰存放區中。

當您[設定標準信標](configure-beacons.md#config-standard-beacons)時， AWS 資料庫加密 SDK 會查詢信標金鑰的金鑰存放區。然後，它會使用 HMAC extract-and-expand金鑰衍生函數 ([HKDF](https://en.wikipedia.org/wiki/HKDF)) 來結合信標金鑰與[標準信標](beacons.md#standard-beacon-overview)的名稱，為指定的信標建立 HMAC 金鑰。

與分支金鑰不同，金鑰存放區`branch-key-id`中每個 只有一個信標金鑰版本。信標金鑰永遠不會輪換。

### 定義您的信標金鑰來源
<a name="beacon-key-source"></a>

當您定義標準和複合信標的信標[版本](using-beacons.md#beacon-version)時，您必須識別信標金鑰，並定義信標金鑰資料的快取存留時間 (TTL)。信標金鑰資料會存放在與分支金鑰不同的本機快取中。下列程式碼片段示範如何`keySource`為單一租戶資料庫定義 。透過`branch-key-id`與其相關聯的 來識別您的信標金鑰。

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

```
keySource(BeaconKeySource.builder()
        .single(SingleKeyStore.builder()
                .keyId(branch-key-id)
                .cacheTTL(6000)
                .build())
        .build())
```

------
#### [ C\$1 / .NET ]

```
KeySource = new BeaconKeySource
{
    Single = new SingleKeyStore
    {
       KeyId = branch-key-id,
       CacheTTL = 6000
    }
}
```

------
#### [ Rust ]

```
 .key_source(BeaconKeySource::Single(
    SingleKeyStore::builder()
        // `keyId` references a beacon key.
        // For every branch key we create in the keystore,
        // we also create a beacon key.
        // This beacon key is not the same as the branch key,
        // but is created with the same ID as the branch key.
        .key_id(branch_key_id)
        .cache_ttl(6000)
        .build()?,
))
```

------

**在多租戶資料庫中定義信標來源**  
如果您有多租戶資料庫，您必須在設定 時指定下列值`keySource`。  
+ 

  **keyFieldName**

  定義存放與用於為指定租用戶產生信標之信標金鑰`branch-key-id`相關聯的 的欄位名稱。`keyFieldName` 可以是任何字串，但對於資料庫中的所有其他欄位必須是唯一的。當您將新記錄寫入資料庫時，識別用於為該記錄產生任何信標的`branch-key-id`信標金鑰的 會存放在此欄位中。您必須在信標查詢中包含此欄位，並識別重新計算信標所需的適當信標金鑰資料。如需詳細資訊，請參閱[查詢多租戶資料庫中的信標](searchable-encryption-multitenant.md#query-multitenant-beacons)。
+ **cacheTTL**

  本機信標快取內信標金鑰資料項目在過期前可以使用的秒數。該值必須大於零。當快取限制 TTL 過期時，會從本機快取移出項目。
+ **（選用） 快取**

  如果您想要自訂快取類型或可在本機快取中存放的分支金鑰材料項目數量，請在初始化 keyring 時指定快取類型和項目容量。

  階層式 keyring 支援下列快取類型：預設、MultiThreaded、StormTracking和共用。如需示範如何定義每個快取類型的詳細資訊和範例，請參閱 [選擇快取](#hierarchical-keyring-caches)。

  如果您未指定快取，階層式 keyring 會自動使用預設快取類型，並將進入容量設定為 1000。
下列範例會使用分支金鑰 ID 供應商建立階層 keyring，快取限制 TLL 為 600 秒，而進入容量為 1000。  

```
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder()
        .keyStore(branchKeyStoreName)
        .branchKeyIdSupplier(branchKeyIdSupplier)
        .ttlSeconds(600)
        .cache(CacheType.builder() //OPTIONAL
                .Default(DefaultCache.builder()
                        .entryCapacity(1000)
                        .build())
                .build());
final IKeyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
```

```
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var keyringInput = new CreateAwsKmsHierarchicalKeyringInput
{
   KeyStore = keystore,
   BranchKeyIdSupplier = branchKeyIdSupplier,
   TtlSeconds = 600, 
   Cache = new CacheType
   {
        Default = new DefaultCache { EntryCapacity = 1000 }
   }
};
var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
```

```
let provider_config = MaterialProvidersConfig::builder().build()?;
    let mat_prov = client::Client::from_conf(provider_config)?;
    let kms_keyring = mat_prov
        .create_aws_kms_hierarchical_keyring()
        .branch_key_id(branch_key_id)
        .key_store(key_store)
        .ttl_seconds(600)
        .send()
        .await?;
```

# AWS KMS ECDH keyring
<a name="use-kms-ecdh-keyring"></a>


****  

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

**重要**  
 AWS KMS ECDH keyring 僅適用於 1.5.0 版或更新版本的物料提供者程式庫。

 AWS KMS ECDH keyring 使用非對稱金鑰協議[AWS KMS keys](https://docs.aws.amazon.com/kms/latest/developerguide/key-types.html)，在兩方之間衍生共用對稱包裝金鑰。首先， keyring 使用橢圓曲線 Diffie-Hellman (ECDH) 金鑰協議演算法，從寄件者的 KMS 金鑰對和收件人的公有金鑰中的私有金鑰衍生共用秘密。然後， keyring 會使用共用秘密來衍生保護資料加密金鑰的共用包裝金鑰。 AWS 資料庫加密 SDK 用來衍生共用包裝金鑰的金鑰衍生函數 (`KDF_CTR_HMAC_SHA384`) 符合[金鑰衍生的 NIST 建議](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-108r1-upd1.pdf)。

金鑰衍生函數會傳回 64 個位元組的金鑰材料。為了確保雙方都使用正確的金鑰材料， AWS 資料庫加密 SDK 會使用前 32 個位元組做為承諾金鑰，最後 32 個位元組做為共用包裝金鑰。在解密時，如果 keyring 無法重現存放在加密記錄的材料描述欄位中的相同承諾金鑰和共用包裝金鑰，則操作會失敗。例如，如果您使用以 **Alice** 私有金鑰和 **Bob** 公有金鑰設定的 keyring 加密記錄，則以 **Bob **私有金鑰和 **Alice 公**有金鑰設定的 keyring 將重現相同的承諾金鑰和共用包裝金鑰，並能夠解密記錄。如果 Bob 的公有金鑰不是來自 KMS 金鑰對，則 Bob 可以建立[原始 ECDH keyring](use-raw-ecdh-keyring.md) 來解密記錄。

 AWS KMS ECDH keyring 使用 AES-GCM 使用對稱金鑰加密記錄。然後，資料金鑰會使用 AES-GCM 使用衍生的共用包裝金鑰進行信封加密。每個 AWS KMS ECDH keyring 只能有一個共用包裝金鑰，但您可以在多 keyring 中單獨包含多個 AWS KMS ECDH keyring 或與其他 [keyring ](use-multi-keyring.md)一起包含。

**Topics**
+ [AWS KMS ECDH keyring 的必要許可](#kms-ecdh-permissions)
+ [建立 AWS KMS ECDH keyring](#kms-ecdh-create)
+ [建立 AWS KMS ECDH 探索 keyring](#kms-ecdh-discovery)

## AWS KMS ECDH keyring 的必要許可
<a name="kms-ecdh-permissions"></a>

 AWS Database Encryption SDK 不需要 AWS 帳戶，也不依賴任何 AWS 服務。不過，若要使用 AWS KMS ECDH keyring，您需要 AWS 帳戶以及 keyring AWS KMS keys 中 的下列最低許可。許可會根據您使用的金鑰協議結構描述而有所不同。
+ 若要使用`KmsPrivateKeyToStaticPublicKey`金鑰協議結構描述加密和解密記錄，您需要*寄件者*非對稱 KMS 金鑰對上的 [kms:GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) 和 [kms:DeriveSharedSecret](https://docs.aws.amazon.com/kms/latest/APIReference/API_DeriveSharedSecret.html)。如果您在執行個體化 keyring 時直接提供寄件者的 DER 編碼公有金鑰，則只需要寄件者的非對稱 KMS 金鑰對上的 [kms:DeriveSharedSecret](https://docs.aws.amazon.com/kms/latest/APIReference/API_DeriveSharedSecret.html) 許可。
+ 若要使用`KmsPublicKeyDiscovery`金鑰協議結構描述解密記錄，您需要指定非對稱 KMS 金鑰對上的 [kms:DeriveSharedSecret](https://docs.aws.amazon.com/kms/latest/APIReference/API_DeriveSharedSecret.html) 和 [kms:GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) 許可。

## 建立 AWS KMS ECDH keyring
<a name="kms-ecdh-create"></a>

若要建立加密和解密資料的 AWS KMS ECDH keyring，您必須使用`KmsPrivateKeyToStaticPublicKey`金鑰協議結構描述。若要使用`KmsPrivateKeyToStaticPublicKey`金鑰協議結構描述初始化 AWS KMS ECDH keyring，請提供下列值：
+ **寄件者的 AWS KMS key ID**

  必須識別`KeyUsage`值為 的非對稱 NIST 建議的橢圓曲線 (ECC)KMS 金鑰對`KEY_AGREEMENT`。寄件者的私有金鑰用於衍生共用秘密。
+ **（選用） 寄件者的公有金鑰**

  必須是 DER 編碼的 X.509 公有金鑰，也稱為 `SubjectPublicKeyInfo`(SPKI)，如 [RFC 5280 ](https://tools.ietf.org/html/rfc5280)所定義。

   AWS KMS [GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) 操作會以所需的 DER 編碼格式傳回非對稱 KMS 金鑰對的公有金鑰。

  若要減少 keyring 進行的 AWS KMS 呼叫數量，您可以直接提供寄件者的公有金鑰。如果未為寄件者的公有金鑰提供值， keyring 會呼叫 AWS KMS 來擷取寄件者的公有金鑰。
+ **收件人的公有金鑰**

  您必須提供收件人的 DER 編碼 X.509 公有金鑰，也稱為 `SubjectPublicKeyInfo`(SPKI)，如 [RFC 5280 ](https://tools.ietf.org/html/rfc5280)所定義。

   AWS KMS [GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) 操作會以所需的 DER 編碼格式傳回非對稱 KMS 金鑰對的公有金鑰。
+ **曲線規格**

  識別指定金鑰對中的橢圓曲線規格。寄件者和收件人的金鑰對必須具有相同的曲線規格。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`
+ **（選用） 授予權杖的清單**

  如果您使用[授權](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)控制對 AWS KMS ECDH keyring 中 KMS 金鑰的存取，您必須在初始化 keyring 時提供所有必要的授予字符。

------
#### [ C\$1 / .NET ]

下列範例會使用寄件者的 KMS 金鑰、寄件者的公有金鑰和收件人的公有金鑰，使用 建立 AWS KMS ECDH keyring。此範例使用選用`senderPublicKey`參數來提供寄件者的公有金鑰。如果您未提供寄件者的公有金鑰， keyring 會呼叫 AWS KMS 來擷取寄件者的公有金鑰。寄件者和收件人的金鑰對都在`ECC_NIST_P256`曲線上。

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());

// Must be DER-encoded X.509 public keys
var BobPublicKey = new MemoryStream(new byte[] { });
var AlicePublicKey = new MemoryStream(new byte[] { });

// Create the AWS KMS ECDH static keyring
var staticConfiguration = new KmsEcdhStaticConfigurations
{
    KmsPrivateKeyToStaticPublicKey = new KmsPrivateKeyToStaticPublicKeyInput
    {
        SenderKmsIdentifier = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab",
        SenderPublicKey = BobPublicKey,
        RecipientPublicKey = AlicePublicKey
    }
};
	    
var createKeyringInput = new CreateAwsKmsEcdhKeyringInput
{
    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
    KmsClient = new AmazonKeyManagementServiceClient(),
    KeyAgreementScheme = staticConfiguration
};

var keyring = materialProviders.CreateAwsKmsEcdhKeyring(createKeyringInput);
```

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

下列範例會使用寄件者的 KMS 金鑰、寄件者的公有金鑰和收件人的公有金鑰，使用 建立 AWS KMS ECDH keyring。此範例使用選用`senderPublicKey`參數來提供寄件者的公有金鑰。如果您未提供寄件者的公有金鑰， keyring 會呼叫 AWS KMS 來擷取寄件者的公有金鑰。寄件者和收件人的金鑰對都在`ECC_NIST_P256`曲線上。

```
// Retrieve public keys
// Must be DER-encoded X.509 public keys                                
ByteBuffer BobPublicKey = getPublicKeyBytes("arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab");
        ByteBuffer AlicePublicKey = getPublicKeyBytes("arn:aws:kms:us-west-2:111122223333:key/0987dcba-09fe-87dc-65ba-ab0987654321"); 

// Create the AWS KMS ECDH static keyring
        final CreateAwsKmsEcdhKeyringInput senderKeyringInput =
          CreateAwsKmsEcdhKeyringInput.builder()
            .kmsClient(KmsClient.create())
            .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
            .KeyAgreementScheme(
              KmsEcdhStaticConfigurations.builder()
                .KmsPrivateKeyToStaticPublicKey(
                  KmsPrivateKeyToStaticPublicKeyInput.builder()
                    .senderKmsIdentifier("arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab")
                    .senderPublicKey(BobPublicKey)
                    .recipientPublicKey(AlicePublicKey)
                    .build()).build()).build();
```

------
#### [ Rust ]

下列範例會使用寄件者的 KMS 金鑰、寄件者的公有金鑰和收件人的公有金鑰，使用 建立 AWS KMS ECDH keyring。此範例使用選用`sender_public_key`參數來提供寄件者的公有金鑰。如果您未提供寄件者的公有金鑰， keyring 會呼叫 AWS KMS 來擷取寄件者的公有金鑰。

```
// Retrieve public keys
// Must be DER-encoded X.509 keys
let public_key_file_content_sender = std::fs::read_to_string(Path::new(EXAMPLE_KMS_ECC_PUBLIC_KEY_FILENAME_SENDER))?;
let parsed_public_key_file_content_sender = parse(public_key_file_content_sender)?;
let public_key_sender_utf8_bytes = parsed_public_key_file_content_sender.contents();

let public_key_file_content_recipient = std::fs::read_to_string(Path::new(EXAMPLE_KMS_ECC_PUBLIC_KEY_FILENAME_RECIPIENT))?;
let parsed_public_key_file_content_recipient = parse(public_key_file_content_recipient)?;
let public_key_recipient_utf8_bytes = parsed_public_key_file_content_recipient.contents();

// Create KmsPrivateKeyToStaticPublicKeyInput
let kms_ecdh_static_configuration_input =
    KmsPrivateKeyToStaticPublicKeyInput::builder()
        .sender_kms_identifier(arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab)
        // Must be a UTF8 DER-encoded X.509 public key
        .sender_public_key(public_key_sender_utf8_bytes)
        // Must be a UTF8 DER-encoded X.509 public key
        .recipient_public_key(public_key_recipient_utf8_bytes)
        .build()?;

let kms_ecdh_static_configuration = KmsEcdhStaticConfigurations::KmsPrivateKeyToStaticPublicKey(kms_ecdh_static_configuration_input);

// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create AWS KMS ECDH keyring
let kms_ecdh_keyring = mpl
    .create_aws_kms_ecdh_keyring()
    .kms_client(kms_client)
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(kms_ecdh_static_configuration)
    .send()
    .await?;
```

------

## 建立 AWS KMS ECDH 探索 keyring
<a name="kms-ecdh-discovery"></a>

解密時，最佳實務是指定 AWS 資料庫加密 SDK 可以使用的金鑰。若要遵循此最佳實務，請使用具有`KmsPrivateKeyToStaticPublicKey`金鑰協議結構描述的 AWS KMS ECDH keyring。不過，您也可以建立 AWS KMS ECDH 探索 keyring，也就是可解密指定 KMS 金鑰對之公有金鑰符合加密記錄之材料描述欄位中存放*之收件人*公有金鑰的任何記錄的 AWS KMS ECDH keyring。

**重要**  
當您使用`KmsPublicKeyDiscovery`金鑰協議結構描述解密記錄時，您接受所有公有金鑰，無論誰擁有它。

若要使用`KmsPublicKeyDiscovery`金鑰協議結構描述初始化 AWS KMS ECDH keyring，請提供下列值：
+ **收件人的 AWS KMS key ID**

  必須識別`KeyUsage`值為 的非對稱 NIST 建議的橢圓曲線 (ECC)KMS 金鑰對`KEY_AGREEMENT`。
+ **曲線規格**

  識別收件人 KMS 金鑰對中的橢圓曲線規格。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`
+ **（選用） 授予權杖的清單**

  如果您使用[授權](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)控制對 AWS KMS ECDH keyring 中 KMS 金鑰的存取，您必須在初始化 keyring 時提供所有必要的授予字符。

------
#### [ C\$1 / .NET ]

下列範例會在`ECC_NIST_P256`曲線上建立具有 KMS 金鑰對的 AWS KMS ECDH 探索 keyring。您必須擁有指定 KMS 金鑰對的 [kms:GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) 和 [kms:DeriveSharedSecret](https://docs.aws.amazon.com/kms/latest/APIReference/API_DeriveSharedSecret.html) 許可。此 keyring 可以解密指定 KMS 金鑰對的公有金鑰符合存放在加密記錄之資料描述欄位中的收件人公有金鑰的任何記錄。

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());

// Create the AWS KMS ECDH discovery keyring
var discoveryConfiguration = new KmsEcdhStaticConfigurations
{
    KmsPublicKeyDiscovery = new KmsPublicKeyDiscoveryInput
    {
        RecipientKmsIdentifier = "arn:aws:kms:us-west-2:111122223333:key/0987dcba-09fe-87dc-65ba-ab0987654321"
    }
		    
};
var createKeyringInput = new CreateAwsKmsEcdhKeyringInput
{
    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
    KmsClient = new AmazonKeyManagementServiceClient(),
    KeyAgreementScheme = discoveryConfiguration
};
var keyring = materialProviders.CreateAwsKmsEcdhKeyring(createKeyringInput);
```

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

下列範例會在`ECC_NIST_P256`曲線上建立具有 KMS 金鑰對的 AWS KMS ECDH 探索 keyring。您必須擁有指定 KMS 金鑰對的 [kms:GetPublicKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html) 和 [kms:DeriveSharedSecret](https://docs.aws.amazon.com/kms/latest/APIReference/API_DeriveSharedSecret.html) 許可。此 keyring 可以解密指定 KMS 金鑰對的公有金鑰符合存放在加密記錄之資料描述欄位中的收件人公有金鑰的任何記錄。

```
// Create the AWS KMS ECDH discovery keyring
final CreateAwsKmsEcdhKeyringInput recipientKeyringInput =
  CreateAwsKmsEcdhKeyringInput.builder()
    .kmsClient(KmsClient.create())
    .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
    .KeyAgreementScheme(
      KmsEcdhStaticConfigurations.builder()
        .KmsPublicKeyDiscovery(
          KmsPublicKeyDiscoveryInput.builder()
            .recipientKmsIdentifier("arn:aws:kms:us-west-2:111122223333:key/0987dcba-09fe-87dc-65ba-ab0987654321").build()
        ).build())
    .build();
```

------
#### [ Rust ]

```
// Create KmsPublicKeyDiscoveryInput
let kms_ecdh_discovery_static_configuration_input =
    KmsPublicKeyDiscoveryInput::builder()
        .recipient_kms_identifier(ecc_recipient_key_arn)
        .build()?;

let kms_ecdh_discovery_static_configuration = KmsEcdhStaticConfigurations::KmsPublicKeyDiscovery(kms_ecdh_discovery_static_configuration_input);

// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create AWS KMS ECDH discovery keyring
let kms_ecdh_discovery_keyring = mpl
    .create_aws_kms_ecdh_keyring()
    .kms_client(kms_client.clone())
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(kms_ecdh_discovery_static_configuration)
    .send()
    .await?;
```

------

# 原始 AES keyring
<a name="use-raw-aes-keyring"></a>


****  

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

 AWS Database Encryption SDK 可讓您使用您提供的 AES 對稱金鑰，做為保護資料金鑰的包裝金鑰。您需要產生、存放和保護金鑰材料，最好是在硬體安全模組 (HSM) 或金鑰管理系統中。當您需要提供包裝金鑰並在本機或離線加密資料金鑰時，請使用原始 AES keyring。

原始 AES keyring 會使用 AES-GCM 演算法和您指定為位元組陣列的包裝金鑰來加密資料。每個原始 AES keyring 中只能指定一個包裝金鑰，但您可以在多重 keyring 中單獨包含多個原始 AES keyring 或與其他 [keyring ](use-multi-keyring.md)一起包含。

**金鑰命名空間和名稱**

若要識別 keyring 中的 AES 金鑰，原始 AES keyring 會使用您提供的*金鑰命名空間*和*金鑰名稱*。這些值並非機密。它們會以純文字顯示在 AWS Database Encryption SDK 新增至記錄[的資料描述](concepts.md#material-description)中。我們建議您使用 HSM 或金鑰管理系統的金鑰命名空間，以及識別該系統中 AES 金鑰的金鑰名稱。

**注意**  
金鑰命名空間和金鑰名稱等同於 中的*提供者 ID* （或*提供者*) 和*金鑰 ID* 欄位`JceMasterKey`。

如果您建構不同的 keyring 來加密和解密指定欄位，命名空間和名稱值至關重要。如果解密 keyring 中的金鑰命名空間和金鑰名稱不是加密 keyring 中金鑰命名空間和金鑰名稱的完全區分大小寫相符項目，即使金鑰材料位元組相同，也不會使用解密 keyring。

例如，您可以定義金鑰命名空間`HSM_01`和金鑰名稱 的原始 AES keyring`AES_256_012`。然後，您可以使用 keyring 來加密一些資料。若要解密該資料，請使用相同的金鑰命名空間、金鑰名稱和金鑰材料來建構原始 AES keyring。

下列範例示範如何建立原始 AES keyring。`AESWrappingKey` 變數代表您提供的金鑰材料。

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

```
final CreateRawAesKeyringInput keyringInput = CreateRawAesKeyringInput.builder()
        .keyName("AES_256_012")
        .keyNamespace("HSM_01")
        .wrappingKey(AESWrappingKey)
        .wrappingAlg(AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16)
        .build();
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
IKeyring rawAesKeyring = matProv.CreateRawAesKeyring(keyringInput);
```

------
#### [ C\$1 / .NET ]

```
var keyNamespace = "HSM_01";
var keyName = "AES_256_012";

// This example uses the key generator in Bouncy Castle to generate the key material.
// In production, use key material from a secure source.
var aesWrappingKey = new MemoryStream(GeneratorUtilities.GetKeyGenerator("AES256").GenerateKey());

// Create the keyring
var keyringInput = new CreateRawAesKeyringInput
{
    KeyNamespace = keyNamespace,
    KeyName = keyName,
    WrappingKey = AESWrappingKey,
    WrappingAlg = AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16
};

var matProv = new MaterialProviders(new MaterialProvidersConfig());
IKeyring rawAesKeyring = matProv.CreateRawAesKeyring(keyringInput);
```

------
#### [ Rust ]

```
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;
let raw_aes_keyring = mpl
    .create_raw_aes_keyring()
    .key_name("AES_256_012")
    .key_namespace("HSM_01")
    .wrapping_key(aes_key_bytes)
    .wrapping_alg(AesWrappingAlg::AlgAes256GcmIv12Tag16)
    .send()
    .await?;
```

------

# 原始 RSA keyring
<a name="use-raw-rsa-keyring"></a>


****  

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

原始 RSA keyring 會使用您提供的 RSA 公有和私有金鑰，對本機記憶體中的資料金鑰執行非對稱加密和解密。您需要產生、存放和保護私有金鑰，最好是在硬體安全模組 (HSM) 或金鑰管理系統中。加密函數會根據 RSA 公開金鑰加密資料金鑰。解密函數會使用私有金鑰解密資料金鑰。您可以從數個 RSA 填補模式中選擇。

加密和解密的原始 RSA keyring，必須包含非對稱公開金鑰和私有金鑰對。不過，您可以使用只有公有金鑰的原始 RSA keyring 來加密資料，也可以使用只有私有金鑰的原始 RSA keyring 來解密資料。您可以在[多 keyring 中包含任何原始 RSA keyring](use-multi-keyring.md)。如果您使用公有和私有金鑰設定原始 RSA keyring，請確定它們是相同金鑰對的一部分。

 當原始 RSA keyring 與 RSA 非對稱加密金鑰搭配使用 適用於 JAVA 的 AWS Encryption SDK 時，其相當於 ，並與 中的 [JceMasterKey](https://aws.github.io/aws-encryption-sdk-java/com/amazonaws/encryptionsdk/jce/JceMasterKey.html) 互通。

**注意**  
原始 RSA keyring 不支援非對稱 KMS 金鑰。若要使用非對稱 RSA KMS 金鑰，請建構 [AWS KMS keyring](use-kms-keyring.md)。

**命名空間和名稱**

為了識別 keyring 中的 RSA 金鑰材料，原始 RSA keyring 會使用您提供的*金鑰命名空間*和*金鑰名稱*。這些值並非機密。它們會以純文字顯示在 AWS Database Encryption SDK 新增至記錄[的資料描述](concepts.md#material-description)中。我們建議您使用金鑰命名空間和金鑰名稱，以識別 HSM 或金鑰管理系統中的 RSA 金鑰對 （或其私有金鑰）。

**注意**  
金鑰命名空間和金鑰名稱等同於 中的*提供者 ID* （或*提供者*) 和*金鑰 ID* 欄位`JceMasterKey`。

如果您建構不同的 keyring 來加密和解密指定的記錄，命名空間和名稱值至關重要。如果解密 keyring 中的金鑰命名空間和金鑰名稱與加密 keyring 中的金鑰命名空間和金鑰名稱不完全、區分大小寫相符，即使金鑰來自相同的金鑰對，也不會使用解密 keyring。

無論 keyring 包含 RSA 公有金鑰、RSA 私有金鑰或金鑰對中的兩個金鑰，加密和解密 keyring 中金鑰材料的金鑰命名空間和金鑰名稱都必須相同。例如，假設您使用金鑰命名空間和金鑰`HSM_01`名稱 的 RSA 公有金鑰的原始 RSA keyring 來加密資料`RSA_2048_06`。若要解密該資料，請使用私有金鑰 （或金鑰對） 和相同的金鑰命名空間和名稱來建構原始 RSA keyring。

**填補模式**

您必須為用於加密和解密的原始 RSA keyring 指定填補模式，或使用您語言實作的功能來為您指定。

 AWS Encryption SDK 支援下列填補模式，受限於每種語言的限制。我們建議使用 [OAEP](https://tools.ietf.org/html/rfc8017#section-7.1) 填補模式，特別是使用 SHA-256 的 OAEP 和使用 SHA-256 填補的 MGF1。[PKCS1](https://tools.ietf.org/html/rfc8017#section-7.2) 填補模式僅支援回溯相容性。
+ 使用 SHA-1 的 OAEP 和使用 SHA-1 填補的 MGF1 SHA-1 
+ OAEP 搭配 SHA-256 和 MGF1 搭配 SHA-256 填補
+ OAEP 搭配 SHA-384 和 MGF1 搭配 SHA-384 填補
+ OAEP 搭配 SHA-512 和 MGF1 搭配 SHA-512 填補
+ PKCS1 v1.5 填補 

下列 Java 範例示範如何使用 RSA 金鑰對的公有和私有金鑰建立原始 RSA keyring，以及使用 SHA-256 建立 OAEP，並使用 SHA-256 填補模式建立 MGF1。`RSAPublicKey` 和 `RSAPrivateKey`變數代表您提供的金鑰材料。

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

```
final CreateRawRsaKeyringInput keyringInput = CreateRawRsaKeyringInput.builder()
        .keyName("RSA_2048_06")
        .keyNamespace("HSM_01")
        .paddingScheme(PaddingScheme.OAEP_SHA256_MGF1)
        .publicKey(RSAPublicKey)
        .privateKey(RSAPrivateKey)
        .build();
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
IKeyring rawRsaKeyring = matProv.CreateRawRsaKeyring(keyringInput);
```

------
#### [ C\$1 / .NET ]

```
var keyNamespace = "HSM_01";
var keyName = "RSA_2048_06";

// Get public and private keys from PEM files
var publicKey = new MemoryStream(System.IO.File.ReadAllBytes("RSAKeyringExamplePublicKey.pem"));
var privateKey = new MemoryStream(System.IO.File.ReadAllBytes("RSAKeyringExamplePrivateKey.pem"));

// Create the keyring input
var keyringInput = new CreateRawRsaKeyringInput
{
    KeyNamespace = keyNamespace,
    KeyName = keyName,
    PaddingScheme = PaddingScheme.OAEP_SHA512_MGF1,
    PublicKey = publicKey,
    PrivateKey = privateKey
};

// Create the keyring
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var rawRsaKeyring = matProv.CreateRawRsaKeyring(keyringInput);
```

------
#### [ Rust ]

```
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;
let raw_rsa_keyring = mpl
    .create_raw_rsa_keyring()
    .key_name("RSA_2048_06")
    .key_namespace("HSM_01")
    .padding_scheme(PaddingScheme::OaepSha256Mgf1)
    .public_key(RSA_public_key)
    .private_key(RSA_private_key)
    .send()
    .await?;
```

------

# 原始 ECDH keyring
<a name="use-raw-ecdh-keyring"></a>


****  

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

**重要**  
原始 ECDH keyring 僅適用於材質提供者程式庫的 1.5.0 版。

原始 ECDH keyring 會使用您提供的橢圓曲線公有/私有金鑰對，在兩方之間衍生共用包裝金鑰。首先， keyring 會使用寄件者的私有金鑰、收件人的公有金鑰和橢圓曲線 Diffie-Hellman (ECDH) 金鑰協議演算法衍生共用秘密。然後， keyring 會使用共用秘密來衍生保護資料加密金鑰的共用包裝金鑰。 AWS Database Encryption SDK 用來衍生共用包裝金鑰的金鑰衍生函數 (`KDF_CTR_HMAC_SHA384`) 符合[金鑰衍生的 NIST 建議](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-108r1-upd1.pdf)。

金鑰衍生函數會傳回 64 個位元組的金鑰材料。為了確保雙方都使用正確的金鑰材料， AWS 資料庫加密 SDK 會使用前 32 個位元組做為承諾金鑰，最後 32 個位元組做為共用包裝金鑰。在解密時，如果 keyring 無法重現存放在加密記錄的材料描述欄位中的相同承諾金鑰和共用包裝金鑰，則操作會失敗。例如，如果您使用使用 **Alice** 私有金鑰和 **Bob** 公有金鑰設定的 keyring 加密記錄，則使用 **Bob **私有金鑰和 **Alice 公**有金鑰設定的 keyring 將重現相同的承諾金鑰和共用包裝金鑰，並能夠解密記錄。如果 Bob 的公有 AWS KMS key 金鑰來自 對，則 Bob 可以建立 [AWS KMS ECDH keyring](use-kms-ecdh-keyring.md) 來解密記錄。

原始 ECDH keyring 使用 AES-GCM 使用對稱金鑰加密記錄。然後，資料金鑰會使用 AES-GCM 使用衍生的共用包裝金鑰進行信封加密。每個原始 ECDH keyring 只能有一個共用包裝金鑰，但您可以在多 keyring 中單獨包含多個原始 ECDH keyring 或與其他 [keyring ](use-multi-keyring.md)一起包含。

您負責產生、儲存和保護您的私有金鑰，最好是在硬體安全模組 (HSM) 或金鑰管理系統中。寄件者和收件人的金鑰對大多位於相同的橢圓曲線上。 AWS Database Encryption SDK 支援下列橢圓立方體規格：
+ `ECC_NIST_P256`
+ `ECC_NIST_P384`
+ `ECC_NIST_P512`

## 建立原始 ECDH keyring
<a name="raw-ecdh-create"></a>

原始 ECDH keyring 支援三個金鑰協議結構描述：`RawPrivateKeyToStaticPublicKey`、 `EphemeralPrivateKeyToStaticPublicKey`和 `PublicKeyDiscovery`。您選取的金鑰協議結構描述會決定您可以執行哪些密碼編譯操作，以及如何組合金鑰材料。

**Topics**
+ [RawPrivateKeyToStaticPublicKey](#raw-ecdh-RawPrivateKeyToStaticPublicKey)
+ [EphemeralPrivateKeyToStaticPublicKey](#raw-ecdh-EphemeralPrivateKeyToStaticPublicKey)
+ [PublicKeyDiscovery](#raw-ecdh-PublicKeyDiscovery)

### RawPrivateKeyToStaticPublicKey
<a name="raw-ecdh-RawPrivateKeyToStaticPublicKey"></a>

使用`RawPrivateKeyToStaticPublicKey`金鑰協議結構描述，在 keyring 中靜態設定寄件者的私有金鑰和收件人的公有金鑰。此金鑰協議結構描述可以加密和解密記錄。

若要使用`RawPrivateKeyToStaticPublicKey`金鑰協議結構描述初始化原始 ECDH keyring，請提供下列值：
+ **寄件者的私有金鑰**

  您必須提供寄件者的 PEM 編碼私有金鑰 (PKCS \$18 PrivateKeyInfo 結構），如 [RFC 5958 ](https://tools.ietf.org/html/rfc5958#section-2)所定義。
+ **收件人的公有金鑰**

  您必須提供收件人的 DER 編碼 X.509 公有金鑰，也稱為 `SubjectPublicKeyInfo`(SPKI)，如 [RFC 5280 ](https://tools.ietf.org/html/rfc5280)所定義。

  您可以指定非對稱金鑰協議 KMS 金鑰對的公有金鑰，或從外部產生的金鑰對的公有金鑰 AWS。
+ **曲線規格**

  識別指定金鑰對中的橢圓曲線規格。寄件者和收件人的金鑰對必須具有相同的曲線規格。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`

------
#### [ C\$1 / .NET ]

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());
	    var BobPrivateKey = new MemoryStream(new byte[] { });
	    var AlicePublicKey = new MemoryStream(new byte[] { });

	    // Create the Raw ECDH static keyring
	    var staticConfiguration = new RawEcdhStaticConfigurations()
	    {
		    RawPrivateKeyToStaticPublicKey = new RawPrivateKeyToStaticPublicKeyInput
		    {
			    SenderStaticPrivateKey = BobPrivateKey,
			    RecipientPublicKey = AlicePublicKey
		    }
	    };
	    
	    var createKeyringInput = new CreateRawEcdhKeyringInput() 
	    {
		    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
		    KeyAgreementScheme = staticConfiguration 
	    };

	    var keyring = materialProviders.CreateRawEcdhKeyring(createKeyringInput);
```

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

下列 Java 範例使用`RawPrivateKeyToStaticPublicKey`金鑰協議結構描述來靜態設定寄件者的私有金鑰和收件人的公有金鑰。兩個金鑰對都在`ECC_NIST_P256`曲線上。

```
private static void StaticRawKeyring() {
    // Instantiate material providers
    final MaterialProviders materialProviders =
      MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();

    KeyPair senderKeys = GetRawEccKey();
    KeyPair recipient = GetRawEccKey();

    // Create the Raw ECDH static keyring
    final CreateRawEcdhKeyringInput rawKeyringInput =
      CreateRawEcdhKeyringInput.builder()
        .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
        .KeyAgreementScheme(
          RawEcdhStaticConfigurations.builder()
            .RawPrivateKeyToStaticPublicKey(
                RawPrivateKeyToStaticPublicKeyInput.builder()
                  // Must be a PEM-encoded private key
                  .senderStaticPrivateKey(ByteBuffer.wrap(senderKeys.getPrivate().getEncoded()))
                  // Must be a DER-encoded X.509 public key
                  .recipientPublicKey(ByteBuffer.wrap(recipient.getPublic().getEncoded()))
                  .build()
            )
            .build()
        ).build();

    final IKeyring staticKeyring = materialProviders.CreateRawEcdhKeyring(rawKeyringInput);
}
```

------
#### [ Rust ]

下列 Python 範例使用`raw_ecdh_static_configuration`金鑰協議結構描述來靜態設定寄件者的私有金鑰和收件人的公有金鑰。兩個金鑰對必須位於相同的曲線上。

```
// Create keyring input
let raw_ecdh_static_configuration_input =
    RawPrivateKeyToStaticPublicKeyInput::builder()
        // Must be a UTF8 PEM-encoded private key
        .sender_static_private_key(private_key_sender_utf8_bytes)
        // Must be a UTF8 DER-encoded X.509 public key
        .recipient_public_key(public_key_recipient_utf8_bytes)
        .build()?;

let raw_ecdh_static_configuration = RawEcdhStaticConfigurations::RawPrivateKeyToStaticPublicKey(raw_ecdh_static_configuration_input);

// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create raw ECDH static keyring
let raw_ecdh_keyring = mpl
    .create_raw_ecdh_keyring()
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(raw_ecdh_static_configuration)
    .send()
    .await?;
```

------

### EphemeralPrivateKeyToStaticPublicKey
<a name="raw-ecdh-EphemeralPrivateKeyToStaticPublicKey"></a>

使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述設定的 keyring 會在本機建立新的金鑰對，並針對每個加密呼叫衍生唯一的共用包裝金鑰。

此金鑰協議結構描述只能加密記錄。若要解密使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述加密的記錄，您必須使用以相同收件人的公有金鑰設定的探索金鑰協議結構描述。若要解密，您可以使用原始 ECDH keyring 搭配[`PublicKeyDiscovery`](#raw-ecdh-PublicKeyDiscovery)金鑰協議演算法，或者，如果收件人的公有金鑰來自非對稱金鑰協議 KMS 金鑰對，您可以使用 AWS KMS ECDH keyring 搭配 [KmsPublicKeyDiscovery](use-kms-ecdh-keyring.md#kms-ecdh-discovery) 金鑰協議結構描述。

若要使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述初始化原始 ECDH keyring，請提供下列值：
+ **收件人的公有金鑰**

  您必須提供收件人的 DER 編碼 X.509 公有金鑰，也稱為 `SubjectPublicKeyInfo`(SPKI)，如 [RFC 5280 ](https://tools.ietf.org/html/rfc5280)所定義。

  您可以指定非對稱金鑰協議 KMS 金鑰對的公有金鑰，或從外部產生的金鑰對的公有金鑰 AWS。
+ **曲線規格**

  識別指定公有金鑰中的橢圓曲線規格。

  加密時， keyring 會在指定的曲線上建立新的金鑰對，並使用新的私有金鑰和指定的公有金鑰來衍生共用包裝金鑰。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`

------
#### [ C\$1 / .NET ]

下列範例會使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述建立原始 ECDH keyring。加密時， keyring 將在指定的`ECC_NIST_P256`曲線上於本機建立新的金鑰對。

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());
	    var AlicePublicKey = new MemoryStream(new byte[] { });

	    // Create the Raw ECDH ephemeral keyring
	    var ephemeralConfiguration = new RawEcdhStaticConfigurations()
	    {
		    EphemeralPrivateKeyToStaticPublicKey = new EphemeralPrivateKeyToStaticPublicKeyInput
		    {
			    RecipientPublicKey = AlicePublicKey
		    }
	    };
	    
	    var createKeyringInput = new CreateRawEcdhKeyringInput() 
	    {
		    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
		    KeyAgreementScheme = ephemeralConfiguration
	    };

	    var keyring = materialProviders.CreateRawEcdhKeyring(createKeyringInput);
```

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

下列範例會使用`EphemeralPrivateKeyToStaticPublicKey`金鑰協議結構描述建立原始 ECDH keyring。加密時， keyring 將在指定的`ECC_NIST_P256`曲線上於本機建立新的金鑰對。

```
private static void EphemeralRawEcdhKeyring() {
    // Instantiate material providers
    final MaterialProviders materialProviders =
      MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();

    ByteBuffer recipientPublicKey = getPublicKeyBytes();

    // Create the Raw ECDH ephemeral keyring
    final CreateRawEcdhKeyringInput ephemeralInput =
      CreateRawEcdhKeyringInput.builder()
        .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
        .KeyAgreementScheme(
          RawEcdhStaticConfigurations.builder()
            .EphemeralPrivateKeyToStaticPublicKey(
              EphemeralPrivateKeyToStaticPublicKeyInput.builder()
                .recipientPublicKey(recipientPublicKey)
                .build()
            )
            .build()
        ).build();

    final IKeyring ephemeralKeyring = materialProviders.CreateRawEcdhKeyring(ephemeralInput);
}
```

------
#### [ Rust ]

下列範例會使用`ephemeral_raw_ecdh_static_configuration`金鑰協議結構描述建立原始 ECDH keyring。加密時， keyring 會在指定的曲線上於本機建立新的金鑰對。

```
// Create EphemeralPrivateKeyToStaticPublicKeyInput
let ephemeral_raw_ecdh_static_configuration_input =
    EphemeralPrivateKeyToStaticPublicKeyInput::builder()
        // Must be a UTF8 DER-encoded X.509 public key
        .recipient_public_key(public_key_recipient_utf8_bytes)
        .build()?;

let ephemeral_raw_ecdh_static_configuration =
    RawEcdhStaticConfigurations::EphemeralPrivateKeyToStaticPublicKey(ephemeral_raw_ecdh_static_configuration_input);

// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create raw ECDH ephemeral private key keyring
let ephemeral_raw_ecdh_keyring = mpl
    .create_raw_ecdh_keyring()
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(ephemeral_raw_ecdh_static_configuration)
    .send()
    .await?;
```

------

### PublicKeyDiscovery
<a name="raw-ecdh-PublicKeyDiscovery"></a>

解密時，最佳實務是指定 AWS 資料庫加密 SDK 可以使用的包裝金鑰。若要遵循此最佳實務，請使用指定寄件者私有金鑰和收件人公有金鑰的 ECDH keyring。不過，您也可以建立原始 ECDH 探索 keyring，也就是原始 ECDH keyring，該 keyring 可以解密指定金鑰的公有金鑰與儲存在加密記錄的資料描述欄位中的收件人公有金鑰的任何記錄。此金鑰協議結構描述只能解密記錄。

**重要**  
當您使用`PublicKeyDiscovery`金鑰協議結構描述解密記錄時，您接受所有公有金鑰，無論誰擁有它。

若要使用`PublicKeyDiscovery`金鑰協議結構描述初始化原始 ECDH keyring，請提供下列值：
+ **收件人的靜態私有金鑰**

  您必須提供收件人的 PEM 編碼私有金鑰 (PKCS \$18 PrivateKeyInfo 結構），如 [RFC 5958 ](https://tools.ietf.org/html/rfc5958#section-2)所定義。
+ **曲線規格**

  識別指定私有金鑰中的橢圓曲線規格。寄件者和收件人的金鑰對必須具有相同的曲線規格。

  有效值：`ECC_NIST_P256`、`ECC_NIS_P384`、`ECC_NIST_P512`

------
#### [ C\$1 / .NET ]

下列範例會使用`PublicKeyDiscovery`金鑰協議結構描述建立原始 ECDH keyring。此 keyring 可以解密任何記錄，其中指定的私有金鑰的公有金鑰符合存放在加密記錄的材料描述欄位中的收件人公有金鑰。

```
// Instantiate material providers
var materialProviders = new MaterialProviders(new MaterialProvidersConfig());
	    var AlicePrivateKey = new MemoryStream(new byte[] { });

	    // Create the Raw ECDH discovery keyring
	    var discoveryConfiguration = new RawEcdhStaticConfigurations()
	    {
		    PublicKeyDiscovery = new PublicKeyDiscoveryInput
		    {
			    RecipientStaticPrivateKey = AlicePrivateKey
		    }
	    };
	    
	    var createKeyringInput = new CreateRawEcdhKeyringInput() 
	    {
		    CurveSpec = ECDHCurveSpec.ECC_NIST_P256,
		    KeyAgreementScheme = discoveryConfiguration 
	    };

	    var keyring = materialProviders.CreateRawEcdhKeyring(createKeyringInput);
```

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

下列範例會使用`PublicKeyDiscovery`金鑰協議結構描述建立原始 ECDH keyring。此 keyring 可以解密任何記錄，其中指定的私有金鑰的公有金鑰符合存放在加密記錄的材料描述欄位中的收件人公有金鑰。

```
private static void RawEcdhDiscovery() {
    // Instantiate material providers
    final MaterialProviders materialProviders =
      MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();

    KeyPair recipient = GetRawEccKey();

    // Create the Raw ECDH discovery keyring
    final CreateRawEcdhKeyringInput rawKeyringInput =
      CreateRawEcdhKeyringInput.builder()
        .curveSpec(ECDHCurveSpec.ECC_NIST_P256)
        .KeyAgreementScheme(
          RawEcdhStaticConfigurations.builder()
            .PublicKeyDiscovery(
              PublicKeyDiscoveryInput.builder()
                // Must be a PEM-encoded private key
                .recipientStaticPrivateKey(ByteBuffer.wrap(sender.getPrivate().getEncoded()))
                .build()
            )
            .build()
        ).build();

    final IKeyring publicKeyDiscovery  = materialProviders.CreateRawEcdhKeyring(rawKeyringInput);
}
```

------
#### [ Rust ]

下列範例會使用`discovery_raw_ecdh_static_configuration`金鑰協議結構描述建立原始 ECDH keyring。此 keyring 可以解密任何訊息，其中指定的私有金鑰的公有金鑰符合存放在訊息加密文字上的收件人公有金鑰。

```
// Create PublicKeyDiscoveryInput
let discovery_raw_ecdh_static_configuration_input =
    PublicKeyDiscoveryInput::builder()
        // Must be a UTF8 PEM-encoded private key
        .recipient_static_private_key(private_key_recipient_utf8_bytes)
        .build()?;

let discovery_raw_ecdh_static_configuration =
    RawEcdhStaticConfigurations::PublicKeyDiscovery(discovery_raw_ecdh_static_configuration_input);

// Create raw ECDH discovery private key keyring
let discovery_raw_ecdh_keyring = mpl
    .create_raw_ecdh_keyring()
    .curve_spec(ecdh_curve_spec)
    .key_agreement_scheme(discovery_raw_ecdh_static_configuration)
    .send()
    .await?;
```

------

# 多重 keyring
<a name="use-multi-keyring"></a>


****  

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

您可以結合 keyring 成為多重 keyring。*多重 keyring* 是一種 keyring，其中包含相同或不同類型的一或多個個別 keyring。效果就像是使用系列中的數個 keyring。使用多重 keyring 來加密資料時，其任何 keyring 中的任何包裝金鑰均可以解密該資料。

建立多重 keyring 來加密資料時，您會指定其中一個 keyring 做為*產生器 keyring*。所有其他 keyring 稱為*子 keyring*。產生器 keyring 會產生並加密純文字資料金鑰。然後，所有子 keyring 中的所有包裝金鑰會加密相同的純文字資料金鑰。該多重 keyring 會為多重 keyring 中的每個包裝金鑰傳回純文字金鑰和一個加密的資料金鑰。如果產生器 keyring 是 [KMS keyring](use-kms-keyring.md)， AWS KMS 則 keyring 中的產生器金鑰會產生並加密純文字金鑰。然後， AWS KMS keyring AWS KMS keys 中的所有其他項目，以及 multi-keyring 中所有子 keyring 中的所有包裝金鑰，請加密相同的純文字金鑰。

解密時， AWS 資料庫加密 SDK 會使用 keyring 來嘗試解密其中一個加密的資料金鑰。按照在多重 keyring 中指定的順序呼叫 keyring。只要任何 keyring 中的任何金鑰可以解密已加密的資料金鑰，處理就會停止。

若要建立多重 keyring，請先將子 keyring 執行個體化。在此範例中，我們使用 AWS KMS keyring 和原始 AES keyring，但您可以在多 keyring 中結合任何支援的 keyring。

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

```
// 1. Create the raw AES keyring.
final MaterialProviders matProv = MaterialProviders.builder()
        .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
        .build();
final CreateRawAesKeyringInput createRawAesKeyringInput = CreateRawAesKeyringInput.builder()
        .keyName("AES_256_012")
        .keyNamespace("HSM_01")
        .wrappingKey(AESWrappingKey)
        .wrappingAlg(AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16)
        .build();
IKeyring rawAesKeyring = matProv.CreateRawAesKeyring(createRawAesKeyringInput);

// 2. Create the AWS KMS keyring.
final CreateAwsKmsMrkMultiKeyringInput createAwsKmsMrkMultiKeyringInput = CreateAwsKmsMrkMultiKeyringInput.builder()
        .generator(kmsKeyArn)
        .build();
IKeyring awsKmsMrkMultiKeyring = matProv.CreateAwsKmsMrkMultiKeyring(createAwsKmsMrkMultiKeyringInput);
```

------
#### [ C\$1 / .NET ]

```
// 1. Create the raw AES keyring.
var keyNamespace = "HSM_01";
var keyName = "AES_256_012";
                    
var matProv = new MaterialProviders(new MaterialProvidersConfig());
var createRawAesKeyringInput = new CreateRawAesKeyringInput
{
    KeyName = "keyName",
    KeyNamespace = "myNamespaces",
    WrappingKey = AESWrappingKey,
    WrappingAlg = AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16
};
var rawAesKeyring = matProv.CreateRawAesKeyring(createRawAesKeyringInput);
                
// 2. Create the AWS KMS keyring.
//    We create a MRK multi keyring, as this interface also supports
//    single-region KMS keys,
//    and creates the KMS client for us automatically.
var createAwsKmsMrkMultiKeyringInput = new CreateAwsKmsMrkMultiKeyringInput
{
    Generator = keyArn
};
var awsKmsMrkMultiKeyring = matProv.CreateAwsKmsMrkMultiKeyring(createAwsKmsMrkMultiKeyringInput);
```

------
#### [ Rust ]

```
// 1. Create the raw AES keyring
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

let raw_aes_keyring = mpl
    .create_raw_aes_keyring()
    .key_name("AES_256_012")
    .key_namespace("HSM_01")
    .wrapping_key(aes_key_bytes)
    .wrapping_alg(AesWrappingAlg::AlgAes256GcmIv12Tag16)
    .send()
    .await?;                
                
// 2. Create the AWS KMS keyring
let aws_kms_mrk_multi_keyring = mpl
    .create_aws_kms_mrk_multi_keyring()
    .generator(key_arn)
    .send()
    .await?;
```

------

接著，建立多重 keyring，並指定其產生器 keyring (如果有)。在此範例中，我們會建立多 keyring，其中 AWS KMS keyring 是產生器 keyring，而 AES keyring 是子 keyring。

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

Java `CreateMultiKeyringInput`建構函數可讓您定義產生器 keyring 和子 keyring。產生的`createMultiKeyringInput`物件是不可變的。

```
final CreateMultiKeyringInput createMultiKeyringInput = CreateMultiKeyringInput.builder()
        .generator(awsKmsMrkMultiKeyring)
        .childKeyrings(Collections.singletonList(rawAesKeyring))
        .build();
IKeyring multiKeyring = matProv.CreateMultiKeyring(createMultiKeyringInput);
```

------
#### [ C\$1 / .NET ]

 .NET `CreateMultiKeyringInput` 建構函數可讓您定義產生器 keyring 和子 keyring。產生的`CreateMultiKeyringInput`物件是不可變的。

```
var createMultiKeyringInput = new CreateMultiKeyringInput
{
    Generator = awsKmsMrkMultiKeyring,
    ChildKeyrings = new List<IKeyring> { rawAesKeyring }
};
var multiKeyring = matProv.CreateMultiKeyring(createMultiKeyringInput);
```

------
#### [ Rust ]

```
let multi_keyring = mpl
    .create_multi_keyring()
    .generator(aws_kms_mrk_multi_keyring)
    .child_keyrings(vec![raw_aes_keyring.clone()])
    .send()
    .await?;
```

------

現在，您可以使用多重 keyring 來加密和解密資料。