

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

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

您可以結合 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 中的所有包裝金鑰，會加密相同的純文字金鑰。

如果您建立沒有產生器 keyring 的多 keyring，則可以單獨使用它來解密資料，但不能加密。或者，若要在加密操作中使用沒有產生器 keyring 的多 keyring，您可以將它指定為另一個 multi-keyring 中的子 keyring。沒有產生器 keyring 的多 keyring 無法指定為另一個 multi-keyring 中的產生器 keyring。

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

從 [1.7.*x* 版](about-versions.md#version-1.7)開始，當加密的資料金鑰是在 AWS Key Management Service (AWS KMS) keyring （或主金鑰提供者） 下加密時， AWS Encryption SDK 一律會將 的金鑰 ARN 傳遞 AWS KMS key 至 AWS KMS [Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 操作的 `KeyId` 參數。這是 AWS KMS 最佳實務，可確保您使用您想要使用的包裝金鑰來解密加密的資料金鑰。

若要查看多重 keyring 的工作範例，請參閱：
+ C：[multi\$1keyring.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/multi_keyring.cpp)[]()
+ C\$1 / .NET：[MultiKeyringExample.cs](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/Examples/Keyring/MultiKeyringExample.cs)
+ JavaScript Node.js：[multi\$1keyring.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-node/src/multi_keyring.ts)
+ JavaScript 瀏覽器：[multi\$1keyring.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-browser/src/multi_keyring.ts)
+ Java：[MultiKeyringExample.java](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/keyrings/MultiKeyringExample.java)
+ Python：[multi\$1keyring\$1example.py](https://github.com/aws/aws-encryption-sdk-python/tree/master/examples/src/multi_keyring_example.py)

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

------
#### [ C ]

```
/* Define an AWS KMS keyring. For details, see [string.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/string.cpp) */
struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(example_key);

// Define a Raw AES keyring. For details, see [raw\$1aes\$1keyring.c](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/raw_aes_keyring.c) */
struct aws_cryptosdk_keyring *aes_keyring = aws_cryptosdk_raw_aes_keyring_new(
        alloc, wrapping_key_namespace, wrapping_key_name, wrapping_key, AWS_CRYPTOSDK_AES256);
```

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

```
// Define an AWS KMS keyring. For details, see [AwsKmsKeyringExample.cs](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/Examples/Keyring/AwsKmsKeyringExample.cs).
var kmsKeyring = materialProviders.CreateAwsKmsKeyring(createKmsKeyringInput);

// Define a Raw AES keyring. For details, see [RawAESKeyringExample.cs](https://github.com/aws/aws-encryption-sdk/tree/mainline/AwsEncryptionSDK/runtimes/net/Examples/Keyring/RawAESKeyringExample.cs).
var aesKeyring = materialProviders.CreateRawAesKeyring(createAesKeyringInput);
```

------
#### [ JavaScript Browser ]

下列範例使用 `buildClient`函數來指定[預設承諾政策](migrate-commitment-policy.md) `REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。您也可以使用 `buildClient`來限制加密訊息中的加密資料金鑰數量。如需詳細資訊，請參閱[限制加密的資料金鑰](configure.md#config-limit-keys)。

```
import {
  KmsKeyringBrowser,
  KMS,
  getClient,
  RawAesKeyringWebCrypto,
  RawAesWrappingSuiteIdentifier,
  MultiKeyringWebCrypto,
  buildClient,
  CommitmentPolicy,
  synchronousRandomValues,
} from '@aws-crypto/client-browser'

const { encrypt, decrypt } = buildClient(
  CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)

const clientProvider = getClient(KMS, { credentials })

// Define an AWS KMS keyring. For details, see [kms\$1simple.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-browser/src/kms_simple.ts). 
const kmsKeyring = new KmsKeyringBrowser({ generatorKeyId: exampleKey })

// Define a Raw AES keyring. For details, see [aes\$1simple.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-browser/src/aes_simple.ts).
const aesKeyring = new RawAesKeyringWebCrypto({ keyName, keyNamespace, wrappingSuite, masterKey })
```

------
#### [ JavaScript Node.js ]

下列範例使用 `buildClient`函數來指定[預設承諾政策](migrate-commitment-policy.md) `REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。您也可以使用 `buildClient`來限制加密訊息中的加密資料金鑰數量。如需詳細資訊，請參閱[限制加密的資料金鑰](configure.md#config-limit-keys)。

```
import {
  MultiKeyringNode,
  KmsKeyringNode,
  RawAesKeyringNode,
  RawAesWrappingSuiteIdentifier,
  buildClient,
  CommitmentPolicy,
} from '@aws-crypto/client-node'

const { encrypt, decrypt } = buildClient(
  CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
)

// Define an AWS KMS keyring. For details, see [kms\$1simple.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-node/src/kms_simple.ts). 
const kmsKeyring = new KmsKeyringNode({ generatorKeyId: exampleKey })

// Define a Raw AES keyring. For details, see [raw\$1aes\$1keyring\$1node.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/raw-aes-keyring-node/src/raw_aes_keyring_node.ts).
const aesKeyring = new RawAesKeyringNode({ keyName, keyNamespace, wrappingSuite, unencryptedMasterKey })
```

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

```
// Define 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);

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

------
#### [ Python ]

下列範例會使用[預設承諾政策](migrate-commitment-policy.md) 來執行個體化 AWS Encryption SDK 用戶端`REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。

```
# Create the AWS KMS keyring
kms_client = boto3.client('kms', region_name="us-west-2")
        
mat_prov: AwsCryptographicMaterialProviders = AwsCryptographicMaterialProviders(
    config=MaterialProvidersConfig()
)

kms_keyring_input: CreateAwsKmsKeyringInput = CreateAwsKmsKeyringInput(
    generator=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab,
    kms_client=kms_client
)

kms_keyring: IKeyring = mat_prov.create_aws_kms_keyring(
    input=kms_keyring_input
)
                        
# Create Raw AES keyring
key_name_space = "HSM_01"
key_name = "AES_256_012"
                            
raw_aes_keyring_input: CreateRawAesKeyringInput = CreateRawAesKeyringInput(
    key_namespace=key_name_space,
    key_name=key_name,
    wrapping_key=AESWrappingKey,
    wrapping_alg=AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16
)

raw_aes_keyring: IKeyring = mat_prov.create_raw_aes_keyring(
    input=raw_aes_keyring_input
)
```

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

```
// Instantiate the AWS Encryption SDK client
let esdk_config = AwsEncryptionSdkConfig::builder().build()?;
let esdk_client = esdk_client::Client::from_conf(esdk_config)?;

// Create the AWS KMS client
let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
let kms_client = aws_sdk_kms::Client::new(&sdk_config);

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

// Create an AWS KMS keyring
let kms_keyring = mpl
    .create_aws_kms_keyring()
    .kms_key_id(kms_key_id)
    .kms_client(kms_client)
    .send()
    .await?;
    
// Create a Raw AES keyring
let key_namespace: &str = "my-key-namespace";
let key_name: &str = "my-aes-key-name";

let raw_aes_keyring = mpl
    .create_raw_aes_keyring()
    .key_name(key_name)
    .key_namespace(key_namespace)
    .wrapping_key(aws_smithy_types::Blob::new(AESWrappingKey))
    .wrapping_alg(AesWrappingAlg::AlgAes256GcmIv12Tag16)
    .send()
    .await?;
```

------
#### [ Go ]

```
import (
    "context"
    
	mpl "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygenerated"
	mpltypes "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygeneratedtypes"
	client "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygenerated"
	esdktypes "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygeneratedtypes"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/kms"
)

// Instantiate the AWS Encryption SDK client
encryptionClient, err := client.NewClient(esdktypes.AwsEncryptionSdkConfig{})
if err != nil {
    panic(err)
}

// Create an AWS KMS client
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
    panic(err)
}
kmsClient := kms.NewFromConfig(cfg, func(o *kms.Options) {
    o.Region = KmsKeyRegion
})

// Instantiate the material providers library
matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{})
if err != nil {
    panic(err)
}

// Create an AWS KMS keyring
awsKmsKeyringInput := mpltypes.CreateAwsKmsKeyringInput{
    KmsClient: kmsClient,
    KmsKeyId:  kmsKeyId,
}
awsKmsKeyring, err := matProv.CreateAwsKmsKeyring(context.Background(), awsKmsKeyringInput)
if err != nil {
    panic(err)
}

// Create a Raw AES keyring
var keyNamespace = "my-key-namespace"
var keyName = "my-aes-key-name"

aesKeyRingInput := mpltypes.CreateRawAesKeyringInput{
    KeyName:      keyName,
    KeyNamespace: keyNamespace,
    WrappingKey:  AESWrappingKey,
    WrappingAlg:  mpltypes.AesWrappingAlgAlgAes256GcmIv12Tag16,
}
aesKeyring, err := matProv.CreateRawAesKeyring(context.Background(), aesKeyRingInput)
```

------

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

------
#### [ C ]

在 C 中的多重 keyring 建構函數中，您只會指定其產生器 keyring。

```
struct aws_cryptosdk_keyring *multi_keyring = aws_cryptosdk_multi_keyring_new(alloc, kms_keyring);
```

若要將子 keyring 新增至您的多重 keyring，請使用 `aws_cryptosdk_multi_keyring_add_child` 方法。您需要為您新增的每個子 keyring 呼叫該方法一次。

```
// Add the Raw AES keyring (C only)
aws_cryptosdk_multi_keyring_add_child(multi_keyring, aes_keyring);
```

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

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

```
var createMultiKeyringInput = new CreateMultiKeyringInput
{
    Generator = kmsKeyring,
    ChildKeyrings = new List<IKeyring>() {aesKeyring}
};

var multiKeyring = materialProviders.CreateMultiKeyring(createMultiKeyringInput);
```

------
#### [ JavaScript Browser ]

JavaScript 多重 keyring 是不可變的。JavaScript 多 keyring 建構函數可讓您指定產生器 keyring 和多個子 keyring。

```
const clientProvider = getClient(KMS, { credentials })

const multiKeyring = new MultiKeyringWebCrypto(generator: kmsKeyring, children: [aesKeyring]);
```

------
#### [ JavaScript Node.js ]

JavaScript 多重 keyring 是不可變的。JavaScript 多 keyring 建構函數可讓您指定產生器 keyring 和多個子 keyring。

```
const multiKeyring = new MultiKeyringNode(generator: kmsKeyring, children: [aesKeyring]);
```

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

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

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

------
#### [ Python ]

```
multi_keyring_input: CreateMultiKeyringInput = CreateMultiKeyringInput(
    generator=kms_keyring,
    child_keyrings=[raw_aes_keyring]
)

multi_keyring: IKeyring = mat_prov.create_multi_keyring(
    input=multi_keyring_input
)
```

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

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

------
#### [ Go ]

```
createMultiKeyringInput := mpltypes.CreateMultiKeyringInput{
		Generator:     awsKmsKeyring,
		ChildKeyrings: []mpltypes.IKeyring{rawAESKeyring},
	}
	multiKeyring, err := matProv.CreateMultiKeyring(context.Background(), createMultiKeyringInput)
	if err != nil {
		panic(err)
	}
```

------

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