配置 AWS Encryption SDK - AWS Encryption SDK

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

配置 AWS Encryption SDK

AWS Encryption SDK 的设计易于使用。尽管 AWS Encryption SDK 有多个配置选项,但默认值均经过精心选择,以便既实用又安全地用于大多数应用程序。但是,您可能需要调整配置以提高性能或在设计中加入自定义功能。

配置实现时,请查看 AWS Encryption SDK 最佳实践并尽量实现。

选择编程语言

AWS Encryption SDK 有多种编程语言。语言实现旨在实现完全互操作并提供相同的功能,尽管这些功能可能以不同的方式实现。通常,您使用与您的应用程序兼容的库。但是,您可以为特定的实现选择一种编程语言。例如,如果您更喜欢使用密钥环,则可以选择 AWS Encryption SDK for C 或 AWS Encryption SDK for JavaScript。

选择包装密钥

AWS Encryption SDK 生成唯一的对称数据密钥以加密每条消息。除非使用数据密钥缓存,否则无需配置、管理或使用数据密钥。AWS Encryption SDK 会为您执行这些操作。

但是,必须选择一个或多个包装密钥来加密每个数据密钥。AWS Encryption SDK 支持不同大小的 AES 对称密钥和 RSA 非对称密钥。还支持 AWS Key Management Service(AWS KMS)对称加密 AWS KMS keys。您应对包装密钥的安全性和持久性负责,因此我们建议您在硬件安全模块或密钥基础设施服务(例如 AWS KMS)中使用加密密钥。

要指定用于加密和解密的包装密钥,您可以使用密钥环(C 和 JavaScript)或主密钥提供程序(Java、Python、AWS Encryption CLI)。您可以指定一个包装密钥或多个相同或不同类型的包装密钥。如果您使用多个包装密钥来包装一个数据密钥,则每个包装密钥将加密同一数据密钥的副本。加密的数据密钥(每个包装密钥一个)与加密的数据一起存储在 AWS Encryption SDK 返回的加密消息中。要解密数据,AWS Encryption SDK 必须首先使用您的一个包装密钥来解密已加密的数据密钥。

要指定密钥环或主密钥提供程序中的 AWS KMS key,请使用支持的 AWS KMS 密钥标识符。有关 AWS KMS 密钥的密钥标识符的详细信息,请参阅《AWS Key Management Service 开发人员指南》中的密钥标识符

  • 使用 AWS Encryption SDK for Java、AWS Encryption SDK for JavaScript、AWS Encryption SDK for Python 或 AWS Encryption CLI 进行加密时,您可以使用任何有效的密钥标识符(密钥 ID、密钥 ARN、别名名称或别名 ARN)作为 KMS 密钥。在通过 AWS Encryption SDK for C 加密时,您只能使用密钥 ID 或密钥 ARN。

    如果您在加密时为 KMS 密钥指定别名名称或别名 ARN,则 AWS Encryption SDK 会保存当前与该别名关联的密钥 ARN;但不会保存别名。对别名的更改不会影响用于解密数据密钥的 KMS 密钥。

  • 在严格模式(指定特定的包装密钥)下解密时,必须使用密钥 ARN 来识别 AWS KMS keys。该要求适用于 AWS Encryption SDK的所有语言实施。

    使用 AWS KMS 密钥环加密时,AWS Encryption SDK 会将 AWS KMS key 的密钥 ARN 存储在加密数据密钥的元数据中。在严格模式下解密时,在尝试使用包装密钥解密加密的数据密钥之前,AWS Encryption SDK 会验证密钥环(或主密钥提供程序)中是否出现相同的密钥 ARN。如果您使用不同的密钥标识符,则即使标识符引用相同的密钥,AWS Encryption SDK 也不会识别或使用 AWS KMS key。

要将原始 AES 密钥原始 RSA 密钥对指定为密钥环中的包装密钥,必须指定命名空间和名称。在主密钥提供程序中,Provider ID 等同于命名空间,Key ID 等同于名称。解密时,必须为每个原始包装密钥使用与加密时完全相同的命名空间和名称。如果您使用不同的命名空间或名称,即使密钥材料相同,AWS Encryption SDK 也不会识别或使用包装密钥。

使用多区域 AWS KMS keys

您可以在 AWS Encryption SDK 中使用 AWS Key Management Service(AWS KMS)多区域密钥作为包装密钥。如果您在一个 AWS 区域 中使用多区域密钥进行加密,则可以使用其他 AWS 区域 中的相关多区域密钥进行解密。AWS Encryption SDK 版本 2.3.x 和 AWS Encryption CLI 版本 3.0.x 中引入了对多区域密钥的支持。

AWS KMS 多区域密钥是不同 AWS 区域 中的一组 AWS KMS keys,具有相同的密钥材料和密钥 ID。您可以像在不同区域使用相同的密钥一样使用这些相关密钥。多区域密钥支持常见的灾难恢复和备份场景,这些场景要求在一个区域进行加密,并在另一个区域进行解密,而无需跨区域调用 AWS KMS。有关多区域密钥的更多信息,请参阅《AWS Key Management Service 开发人员指南》中的使用多区域密钥

为了支持多区域密钥,AWS Encryption SDK 包括 AWS KMS 支持多区域的密钥环和主密钥提供程序。每种编程语言中新的支持多区域的符号同时支持单区域密钥和多区域密钥。

  • 对于单区域密钥,支持多区域的符号的行为就像单区域 AWS KMS 密钥环和主密钥提供程序一样。该密钥尝试仅使用加密数据的单区域密钥来解密加密文字。

  • 对于多区域密钥,支持多区域的符号会尝试使用加密数据的相同多区域密钥或您指定的区域中的相关多区域密钥来解密加密文字。

在使用多个 KMS 密钥的支持多区域的密钥环和主密钥提供程序中,您可以指定多个单区域和多区域密钥。但是,您只能在每组相关的多区域密钥中指定一个密钥。如果您使用相同的密钥 ID 指定多个密钥标识符,则构造函数调用将失败。

您还可以将多区域密钥与标准、单区域 AWS KMS 密钥环和主密钥提供程序一起使用。但是,您必须在同一区域使用相同的多区域密钥进行加密和解密。单区域密钥环和主密钥提供程序尝试仅使用加密数据的密钥来解密加密文字。

以下示例说明如何使用多区域密钥以及新的支持多区域的密钥环和主密钥提供程序来加密和解密数据。这些示例使用每个区域中的相关多区域密钥对 us-east-1 区域中的数据进行加密,并对 us-west-2 区域中的数据进行解密。在运行这些示例之前,请将示例多区域密钥 ARN 替换为您的 AWS 账户 中的有效值。

C

要使用多区域密钥进行加密,请使用 Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() 方法实例化密钥环。指定多区域密钥。

这个简单的示例不包括加密上下文。有关在 C 语言中使用加密上下文的示例,请参阅 加密和解密字符串

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for C 存储库中的 kms_multi_region_keys.cpp

/* Encrypt with a multi-Region KMS key in us-east-1 */ /* Load error strings for debugging */ aws_cryptosdk_load_error_strings(); /* Initialize a multi-Region keyring */ const char *mrk_us_east_1 = "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; struct aws_cryptosdk_keyring *mrk_keyring = Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder().Build(mrk_us_east_1); /* Create a session; release the keyring */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(aws_default_allocator(), AWS_CRYPTOSDK_ENCRYPT, mrk_keyring); aws_cryptosdk_keyring_release(mrk_keyring); /* Encrypt the data * aws_cryptosdk_session_process_full is designed for non-streaming data */ aws_cryptosdk_session_process_full( session, ciphertext, ciphertext_buf_sz, &ciphertext_len, plaintext, plaintext_len)); /* Clean up the session */ aws_cryptosdk_session_destroy(session);
C# / .NET

要在美国东部(弗吉尼亚州北部)(us-east-1)区域中使用多区域密钥加密,请实例化一个 CreateAwsKmsMrkKeyringInput 对象,其中包含多区域密钥的密钥标识符和指定区域的 AWS KMS 客户端。然后使用 CreateAwsKmsMrkKeyring() 方法创建密钥环。

CreateAwsKmsMrkKeyring() 方法创建的密钥环只包含一个多区域密钥。要使用多个包装密钥(包括多区域密钥)进行加密,请使用 CreateAwsKmsMrkMultiKeyring() 方法。

有关完整的示例,请参阅 GitHub 上适用于 .NET 的 AWS Encryption SDK 存储库中的 AwsKmsMrkKeyringExample.cs

//Encrypt with a multi-Region KMS key in us-east-1 Region // Instantiate the AWS Encryption SDK and material providers var encryptionSdk = AwsEncryptionSdkFactory.CreateDefaultAwsEncryptionSdk(); var materialProviders = AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders(); // Multi-Region keys have a distinctive key ID that begins with 'mrk' // Specify a multi-Region key in us-east-1 string mrkUSEast1 = "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; // Create the keyring // You can specify the Region or get the Region from the key ARN var createMrkEncryptKeyringInput = new CreateAwsKmsMrkKeyringInput { KmsClient = new AmazonKeyManagementServiceClient(RegionEndpoint.USEast1), KmsKeyId = mrkUSEast1 }; var mrkEncryptKeyring = materialProviders.CreateAwsKmsMrkKeyring(createMrkEncryptKeyringInput); // Define the encryption context var encryptionContext = new Dictionary<string, string>() { {"purpose", "test"} }; // Encrypt your plaintext data. var encryptInput = new EncryptInput { Plaintext = plaintext, Keyring = mrkEncryptKeyring, EncryptionContext = encryptionContext }; var encryptOutput = encryptionSdk.Encrypt(encryptInput);
AWS Encryption CLI

此示例对 us-east-1 区域中的多区域密钥下的 hello.txt 文件进行加密。由于此示例指定了带有区域元素的密钥 ARN,所以其中不使用 --wrapping-keys 参数的 region 属性。

当包装密钥的密钥 ID 未指定区域时,您可以使用 --wrapping-keysregion 属性来指定区域,例如 --wrapping-keys key=$keyID region=us-east-1

# Encrypt with a multi-Region KMS key in us-east-1 Region # To run this example, replace the fictitious key ARN with a valid value. $ mrkUSEast1=arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab $ aws-encryption-cli --encrypt \ --input hello.txt \ --wrapping-keys key=$mrkUSEast1 \ --metadata-output ~/metadata \ --encryption-context purpose=test \ --output .
Java

要使用多区域密钥加密,请实例化 AwsKmsMrkAwareMasterKeyProvider 并指定多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for Java 存储库中的 BasicMultiRegionKeyEncryptionExample.java

//Encrypt with a multi-Region KMS key in us-east-1 Region // Instantiate the client final AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build(); // Multi-Region keys have a distinctive key ID that begins with 'mrk' // Specify a multi-Region key in us-east-1 final String mrkUSEast1 = "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; // Instantiate an AWS KMS master key provider in strict mode for multi-Region keys // Configure it to encrypt with the multi-Region key in us-east-1 final AwsKmsMrkAwareMasterKeyProvider kmsMrkProvider = AwsKmsMrkAwareMasterKeyProvider .builder() .buildStrict(mrkUSEast1); // Create an encryption context final Map<String, String> encryptionContext = Collections.singletonMap("Purpose", "Test"); // Encrypt your plaintext data final CryptoResult<byte[], AwsKmsMrkAwareMasterKey> encryptResult = crypto.encryptData( kmsMrkProvider, encryptionContext, sourcePlaintext); byte[] ciphertext = encryptResult.getResult();
JavaScript Browser

要使用多区域密钥进行加密,请使用 buildAwsKmsMrkAwareStrictMultiKeyringBrowser() 方法创建密钥环并指定多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for JavaScript 存储库中的 kms_multi_region_simple.ts

/* Encrypt with a multi-Region KMS key in us-east-1 Region */ import { buildAwsKmsMrkAwareStrictMultiKeyringBrowser, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-browser' /* Instantiate an AWS Encryption SDK client */ const { encrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } /* Instantiate an AWS KMS client * The AWS Encryption SDK for JavaScript gets the Region from the key ARN */ const clientProvider = (region: string) => new KMS({ region, credentials }) /* Specify a multi-Region key in us-east-1 */ const multiRegionUsEastKey = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Instantiate the keyring */ const encryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringBrowser({ generatorKeyId: multiRegionUsEastKey, clientProvider, }) /* Set the encryption context */ const context = { purpose: 'test', } /* Test data to encrypt */ const cleartext = new Uint8Array([1, 2, 3, 4, 5]) /* Encrypt the data */ const { result } = await encrypt(encryptKeyring, cleartext, { encryptionContext: context, })
JavaScript Node.js

要使用多区域密钥进行加密,请使用 buildAwsKmsMrkAwareStrictMultiKeyringNode() 方法创建密钥环并指定多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for JavaScript 存储库中的 kms_multi_region_simple.ts

//Encrypt with a multi-Region KMS key in us-east-1 Region import { buildClient } from '@aws-crypto/client-node' /* Instantiate the AWS Encryption SDK client const { encrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) /* Test string to encrypt */ const cleartext = 'asdf' /* Multi-Region keys have a distinctive key ID that begins with 'mrk' * Specify a multi-Region key in us-east-1 */ const multiRegionUsEastKey = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Create an AWS KMS keyring */ const mrkEncryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringNode({ generatorKeyId: multiRegionUsEastKey, }) /* Specify an encryption context */ const context = { purpose: 'test', } /* Create an encryption keyring */ const { result } = await encrypt(mrkEncryptKeyring, cleartext, { encryptionContext: context, })
Python

要使用 AWS KMS 多区域密钥进行加密,请使用 MRKAwareStrictAwsKmsMasterKeyProvider() 方法并指定多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for Python 存储库中的 mrk_aware_kms_provider.py

* Encrypt with a multi-Region KMS key in us-east-1 Region # Instantiate the client client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Specify a multi-Region key in us-east-1 mrk_us_east_1 = "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab" # Use the multi-Region method to create the master key provider # in strict mode strict_mrk_key_provider = MRKAwareStrictAwsKmsMasterKeyProvider( key_ids=[mrk_us_east_1] ) # Set the encryption context encryption_context = { "purpose": "test" } # Encrypt your plaintext data ciphertext, encrypt_header = client.encrypt( source=source_plaintext, encryption_context=encryption_context, key_provider=strict_mrk_key_provider )

接下来,将您的加密文字移至 us-west-2 区域。您无需重新加密加密文字。

要在严格模式下解密 us-west-2 区域中的加密文字,请使用 us-west-2 区域中相关多区域密钥的密钥 ARN 来实例化支持多区域的符号。如果您在其他区域(包括加密该密钥的 us-east-1)中指定相关多区域密钥的密钥 ARN,则支持多区域的符号将为该 AWS KMS key 发出跨区域调用。

在严格模式下解密时,支持多区域的符号需要密钥 ARN。仅接受每组相关的多区域密钥中的一个密钥 ARN。

在运行这些示例之前,请将示例多区域密钥 ARN 替换为您的 AWS 账户 中的有效值。

C

要在严格模式下使用多区域密钥进行解密,请使用 Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() 方法实例化密钥环。在本地(us-west-2)区域中指定相关的多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for C 存储库中的 kms_multi_region_keys.cpp

/* Decrypt with a related multi-Region KMS key in us-west-2 Region */ /* Load error strings for debugging */ aws_cryptosdk_load_error_strings(); /* Initialize a multi-Region keyring */ const char *mrk_us_west_2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; struct aws_cryptosdk_keyring *mrk_keyring = Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder().Build(mrk_us_west_2); /* Create a session; release the keyring */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(aws_default_allocator(), AWS_CRYPTOSDK_ENCRYPT, mrk_keyring); aws_cryptosdk_session_set_commitment_policy(session, COMMITMENT_POLICY_REQUIRE_ENCRYPT_REQUIRE_DECRYPT); aws_cryptosdk_keyring_release(mrk_keyring); /* Decrypt the ciphertext * aws_cryptosdk_session_process_full is designed for non-streaming data */ aws_cryptosdk_session_process_full( session, plaintext, plaintext_buf_sz, &plaintext_len, ciphertext, ciphertext_len)); /* Clean up the session */ aws_cryptosdk_session_destroy(session);
C# / .NET

要在严格模式下使用单个多区域密钥进行解密,请使用与组装输入和创建用于加密的密钥环相同的构造函数和方法。使用相关多区域密钥的密钥 ARN 和美国西部(俄勒冈州)(us-west-2)区域的 AWS KMS 客户端实例化 CreateAwsKmsMrkKeyringInput 对象。然后使用 CreateAwsKmsMrkKeyring() 方法通过一个多区域 KMS 密钥创建多区域密钥环。

有关完整的示例,请参阅 GitHub 上适用于 .NET 的 AWS Encryption SDK 存储库中的 AwsKmsMrkKeyringExample.cs

// Decrypt with a related multi-Region KMS key in us-west-2 Region // Instantiate the AWS Encryption SDK and material providers var encryptionSdk = AwsEncryptionSdkFactory.CreateDefaultAwsEncryptionSdk(); var materialProviders = AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders(); // Specify the key ARN of the multi-Region key in us-west-2 string mrkUSWest2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; // Instantiate the keyring input // You can specify the Region or get the Region from the key ARN var createMrkDecryptKeyringInput = new CreateAwsKmsMrkKeyringInput { KmsClient = new AmazonKeyManagementServiceClient(RegionEndpoint.USWest2), KmsKeyId = mrkUSWest2 }; // Create the multi-Region keyring var mrkDecryptKeyring = materialProviders.CreateAwsKmsMrkKeyring(createMrkDecryptKeyringInput); // Decrypt the ciphertext var decryptInput = new DecryptInput { Ciphertext = ciphertext, Keyring = mrkDecryptKeyring }; var decryptOutput = encryptionSdk.Decrypt(decryptInput);
AWS Encryption CLI

要使用 us-west-2 区域中的相关多区域密钥进行解密,请使用 --wrapping-keys 参数的 key 属性来指定其密钥 ARN。

# Decrypt with a related multi-Region KMS key in us-west-2 Region # To run this example, replace the fictitious key ARN with a valid value. $ mrkUSWest2=arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab $ aws-encryption-cli --decrypt \ --input hello.txt.encrypted \ --wrapping-keys key=$mrkUSWest2 \ --commitment-policy require-encrypt-require-decrypt \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --max-encrypted-data-keys 1 \ --buffer \ --output .
Java

要在严格模式下解密,请实例化 AwsKmsMrkAwareMasterKeyProvider 并在本地(us-west-2)区域中指定相关的多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for Java 存储库中的 BasicMultiRegionKeyEncryptionExample.java

// Decrypt with a related multi-Region KMS key in us-west-2 Region // Instantiate the client final AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build(); // Related multi-Region keys have the same key ID. Their key ARNs differs only in the Region field. String mrkUSWest2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; // Use the multi-Region method to create the master key provider // in strict mode AwsKmsMrkAwareMasterKeyProvider kmsMrkProvider = AwsKmsMrkAwareMasterKeyProvider.builder() .buildStrict(mrkUSWest2); // Decrypt your ciphertext CryptoResult<byte[], AwsKmsMrkAwareMasterKey> decryptResult = crypto.decryptData( kmsMrkProvider, ciphertext); byte[] decrypted = decryptResult.getResult();
JavaScript Browser

要在严格模式下解密,请使用 buildAwsKmsMrkAwareStrictMultiKeyringBrowser() 方法创建密钥环并在本地(us-west-2)区域中指定相关的多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for JavaScript 存储库中的 kms_multi_region_simple.ts

/* Decrypt with a related multi-Region KMS key in us-west-2 Region */ import { buildAwsKmsMrkAwareStrictMultiKeyringBrowser, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-browser' /* Instantiate an AWS Encryption SDK client */ const { decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } /* Instantiate an AWS KMS client * The AWS Encryption SDK for JavaScript gets the Region from the key ARN */ const clientProvider = (region: string) => new KMS({ region, credentials }) /* Specify a multi-Region key in us-west-2 */ const multiRegionUsWestKey = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Instantiate the keyring */ const mrkDecryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringBrowser({ generatorKeyId: multiRegionUsWestKey, clientProvider, }) /* Decrypt the data */ const { plaintext, messageHeader } = await decrypt(mrkDecryptKeyring, result)
JavaScript Node.js

要在严格模式下解密,请使用 buildAwsKmsMrkAwareStrictMultiKeyringNode() 方法创建密钥环并在本地(us-west-2)区域中指定相关的多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for JavaScript 存储库中的 kms_multi_region_simple.ts

/* Decrypt with a related multi-Region KMS key in us-west-2 Region */ import { buildClient } from '@aws-crypto/client-node' /* Instantiate the client const { decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) /* Multi-Region keys have a distinctive key ID that begins with 'mrk' * Specify a multi-Region key in us-east-1 */ const multiRegionUsWestKey = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Create an AWS KMS keyring */ const mrkDecryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringNode({ generatorKeyId: multiRegionUsWestKey, }) /* Decrypt your ciphertext */ const { plaintext, messageHeader } = await decrypt(decryptKeyring, result)
Python

要在严格模式下解密,请使用 MRKAwareStrictAwsKmsMasterKeyProvider() 方法创建主密钥提供程序。在本地(us-west-2)区域中指定相关的多区域密钥。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for Python 存储库中的 mrk_aware_kms_provider.py

# Decrypt with a related multi-Region KMS key in us-west-2 Region # Instantiate the client client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Related multi-Region keys have the same key ID. Their key ARNs differs only in the Region field mrk_us_west_2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab" # Use the multi-Region method to create the master key provider # in strict mode strict_mrk_key_provider = MRKAwareStrictAwsKmsMasterKeyProvider( key_ids=[mrk_us_west_2] ) # Decrypt your ciphertext plaintext, _ = client.decrypt( source=ciphertext, key_provider=strict_mrk_key_provider )

您还可以在发现模式下使用 AWS KMS 多区域密钥进行解密。在发现模式下解密时,不需指定任何 AWS KMS keys。(有关单区域 AWS KMS Discovery 密钥环的信息,请参阅 使用 AWS KMS Discovery 密钥环。)

如果您使用多区域密钥加密,则发现模式下支持多区域的符号将尝试使用本地区域中的相关多区域密钥进行解密。如果不存在,则调用失败。在发现模式下,AWS Encryption SDK 不会尝试跨区域调用用于加密的多区域密钥。

注意

如果您在发现模式下使用支持多区域的符号来加密数据,则加密操作将失败。

以下示例说明如何在发现模式下使用支持多区域的符号进行解密。由于您未指定 AWS KMS key,因此 AWS Encryption SDK 必须从其他来源获取区域。如果可能,请明确指定本地区域。否则,AWS Encryption SDK 将从 AWS SDK 中为您的编程语言配置的区域获取本地区域。

在运行这些示例之前,请将示例账户 ID 和多区域密钥 ARN 替换为您的 AWS 账户 中的有效值。

C

要使用多区域密钥在发现模式下解密,请使用 Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() 方法构建密钥环,使用 Aws::Cryptosdk::KmsKeyring::DiscoveryFilter::Builder() 方法构建发现筛选条件。要指定本地区域,请定义 ClientConfiguration 并在 AWS KMS 客户端中指定。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for C 存储库中的 kms_multi_region_keys.cpp

/* Decrypt in discovery mode with a multi-Region KMS key */ /* Load error strings for debugging */ aws_cryptosdk_load_error_strings(); /* Construct a discovery filter for the account and partition. The * filter is optional, but it's a best practice that we recommend. */ const char *account_id = "111122223333"; const char *partition = "aws"; const std::shared_ptr<Aws::Cryptosdk::KmsKeyring::DiscoveryFilter> discovery_filter = Aws::Cryptosdk::KmsKeyring::DiscoveryFilter::Builder(partition).AddAccount(account_id).Build(); /* Create an AWS KMS client in the desired region. */ const char *region = "us-west-2"; Aws::Client::ClientConfiguration client_config; client_config.region = region; const std::shared_ptr<Aws::KMS::KMSClient> kms_client = Aws::MakeShared<Aws::KMS::KMSClient>("AWS_SAMPLE_CODE", client_config); struct aws_cryptosdk_keyring *mrk_keyring = Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() .WithKmsClient(kms_client) .BuildDiscovery(region, discovery_filter); /* Create a session; release the keyring */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(aws_default_allocator(), AWS_CRYPTOSDK_DECRYPT, mrk_keyring); aws_cryptosdk_keyring_release(mrk_keyring); commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT /* Decrypt the ciphertext * aws_cryptosdk_session_process_full is designed for non-streaming data */ aws_cryptosdk_session_process_full( session, plaintext, plaintext_buf_sz, &plaintext_len, ciphertext, ciphertext_len)); /* Clean up the session */ aws_cryptosdk_session_destroy(session);
C# / .NET

要在适用于 .NET 的 AWS Encryption SDK 中创建支持多区域的 Discovery 密钥环,请实例化 CreateAwsKmsMrkDiscoveryKeyringInput 对象,该对象使用特定 AWS 区域 的 AWS KMS 客户端,以及一个可选的发现筛选条件,将 KMS 密钥限制在特定的 AWS 分区和账户内。然后通过输入对象调用 CreateAwsKmsMrkDiscoveryKeyring() 方法。有关完整的示例,请参阅 GitHub 上适用于 .NET 的 AWS Encryption SDK 存储库中的 AwsKmsMrkDiscoveryKeyringExample.cs

要为多个 AWS 区域 创建支持多区域的 Discovery 密钥环,请使用 CreateAwsKmsMrkDiscoveryMultiKeyring() 方法创建多密钥环,或者使用 CreateAwsKmsMrkDiscoveryKeyring() 创建多个支持多区域的 Discovery 密钥环,然后使用 CreateMultiKeyring() 方法将其组合成一个多密钥环。

有关示例,请参阅 AwsKmsMrkDiscoveryMultiKeyringExample.cs

// Decrypt in discovery mode with a multi-Region KMS key // Instantiate the AWS Encryption SDK and material providers var encryptionSdk = AwsEncryptionSdkFactory.CreateDefaultAwsEncryptionSdk(); var materialProviders = AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders(); List<string> account = new List<string> { "111122223333" }; // Instantiate the discovery filter DiscoveryFilter mrkDiscoveryFilter = new DiscoveryFilter() { AccountIds = account, Partition = "aws" } // Create the keyring var createMrkDiscoveryKeyringInput = new CreateAwsKmsMrkDiscoveryKeyringInput { KmsClient = new AmazonKeyManagementServiceClient(RegionEndpoint.USWest2), DiscoveryFilter = mrkDiscoveryFilter }; var mrkDiscoveryKeyring = materialProviders.CreateAwsKmsMrkDiscoveryKeyring(createMrkDiscoveryKeyringInput); // Decrypt the ciphertext var decryptInput = new DecryptInput { Ciphertext = ciphertext, Keyring = mrkDiscoveryKeyring }; var decryptOutput = encryptionSdk.Decrypt(decryptInput);
AWS Encryption CLI

要在发现模式下解密,请使用 --wrapping-keys 参数的 discovery 属性。discovery-accountdiscovery-partition 属性创建了一个发现筛选条件,该筛选条件是可选的,但建议使用。

要指定区域,此命令包括 --wrapping-keys 参数的 region 属性。

# Decrypt in discovery mode with a multi-Region KMS key $ aws-encryption-cli --decrypt \ --input hello.txt.encrypted \ --wrapping-keys discovery=true \ discovery-account=111122223333 \ discovery-partition=aws \ region=us-west-2 \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --max-encrypted-data-keys 1 \ --buffer \ --output .
Java

要指定本地区域,请使用 builder().withDiscoveryMrkRegion 参数。否则,AWS Encryption SDK 将从 AWS SDK for Java 中配置的区域获取本地区域。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for Java 存储库中的 DiscoveryMultiRegionDecryptionExample.java

// Decrypt in discovery mode with a multi-Region KMS key // Instantiate the client final AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build(); DiscoveryFilter discoveryFilter = new DiscoveryFilter("aws", 111122223333); AwsKmsMrkAwareMasterKeyProvider mrkDiscoveryProvider = AwsKmsMrkAwareMasterKeyProvider .builder() .withDiscoveryMrkRegion(Region.US_WEST_2) .buildDiscovery(discoveryFilter); // Decrypt your ciphertext final CryptoResult<byte[], AwsKmsMrkAwareMasterKey> decryptResult = crypto .decryptData(mrkDiscoveryProvider, ciphertext);
JavaScript Browser

要使用对称多区域密钥在发现模式下解密,请使用 AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser() 方法。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for JavaScript 存储库中的 kms_multi_region_discovery.ts

/* Decrypt in discovery mode with a multi-Region KMS key */ import { AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-browser' /* Instantiate an AWS Encryption SDK client */ const { decrypt } = buildClient() declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } /* Instantiate the KMS client with an explicit Region */ const client = new KMS({ region: 'us-west-2', credentials }) /* Create a discovery filter */ const discoveryFilter = { partition: 'aws', accountIDs: ['111122223333'] } /* Create an AWS KMS discovery keyring */ const mrkDiscoveryKeyring = new AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser({ client, discoveryFilter, }) /* Decrypt the data */ const { plaintext, messageHeader } = await decrypt(mrkDiscoveryKeyring, ciphertext)
JavaScript Node.js

要使用对称多区域密钥在发现模式下解密,请使用 AwsKmsMrkAwareSymmetricDiscoveryKeyringNode() 方法。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for JavaScript 存储库中的 kms_multi_region_discovery.ts

/* Decrypt in discovery mode with a multi-Region KMS key */ import { AwsKmsMrkAwareSymmetricDiscoveryKeyringNode, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-node' /* Instantiate the Encryption SDK client const { decrypt } = buildClient() /* Instantiate the KMS client with an explicit Region */ const client = new KMS({ region: 'us-west-2' }) /* Create a discovery filter */ const discoveryFilter = { partition: 'aws', accountIDs: ['111122223333'] } /* Create an AWS KMS discovery keyring */ const mrkDiscoveryKeyring = new AwsKmsMrkAwareSymmetricDiscoveryKeyringNode({ client, discoveryFilter, }) /* Decrypt your ciphertext */ const { plaintext, messageHeader } = await decrypt(mrkDiscoveryKeyring, result)
Python

要使用多区域密钥在发现模式下解密,请使用 MRKAwareDiscoveryAwsKmsMasterKeyProvider() 方法。

有关完整的示例,请参阅 GitHub 上 AWS Encryption SDK for Python 存储库中的 mrk_aware_kms_provider.py

# Decrypt in discovery mode with a multi-Region KMS key # Instantiate the client client = aws_encryption_sdk.EncryptionSDKClient() # Create the discovery filter and specify the region decrypt_kwargs = dict( discovery_filter=DiscoveryFilter(account_ids="111122223333", partition="aws"), discovery_region="us-west-2", ) # Use the multi-Region method to create the master key provider # in discovery mode mrk_discovery_key_provider = MRKAwareDiscoveryAwsKmsMasterKeyProvider(**decrypt_kwargs) # Decrypt your ciphertext plaintext, _ = client.decrypt( source=ciphertext, key_provider=mrk_discovery_key_provider )

选择算法套件

AWS Encryption SDK 支持多种对称加密和非对称加密算法,用于在您指定的包装密钥下对数据密钥进行加密。但是,当使用这些数据密钥来加密您的数据时,AWS Encryption SDK 默认使用推荐的算法套件,该套件使用带有密钥派生数字签名密钥承诺的 AES-GCM 算法。尽管默认算法套件可能适用于大多数应用程序,但您可以选择备用算法套件。例如,没有数字签名的算法套件可以满足某些信任模型的需求。有关 AWS Encryption SDK 支持的算法套件的信息,请参阅 AWS Encryption SDK中支持的算法套件

以下示例向您显示在加密时如何选择备用算法套件。这些示例选择了推荐的 AES-GCM 算法套件,该套件具有密钥派生和密钥承诺,但没有数字签名。使用不包含数字签名的算法套件进行加密时,请在解密时使用仅限未签名的解密模式。这种模式在流式传输解密时最有用,如果遇到签名的加密文字,则会失败。

C

要在 AWS Encryption SDK for C 中指定备用算法套件,必须明确创建 CMM。然后将 aws_cryptosdk_default_cmm_set_alg_id 与 CMM 和选定的算法套件一起使用。

/* Specify an algorithm suite without signing */ /* Load error strings for debugging */ aws_cryptosdk_load_error_strings(); /* Construct an AWS KMS keyring */ struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(key_arn); /* To set an alternate algorithm suite, create an cryptographic materials manager (CMM) explicitly */ struct aws_cryptosdk_cmm *cmm = aws_cryptosdk_default_cmm_new(aws_default_allocator(), kms_keyring); aws_cryptosdk_keyring_release(kms_keyring); /* Specify the algorithm suite for the CMM */ aws_cryptosdk_default_cmm_set_alg_id(cmm, ALG_AES256_GCM_HKDF_SHA512_COMMIT_KEY); /* Construct the session with the CMM, then release the CMM reference */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_cmm_2(alloc, AWS_CRYPTOSDK_ENCRYPT, cmm); aws_cryptosdk_cmm_release(cmm); /* Encrypt the data Use aws_cryptosdk_session_process_full with non-streaming data */ if (AWS_OP_SUCCESS != aws_cryptosdk_session_process_full( session, ciphertext, ciphertext_buf_sz, &ciphertext_len, plaintext, plaintext_len)) { aws_cryptosdk_session_destroy(session); return AWS_OP_ERR; }

解密未经数字签名加密的数据时,请使用 AWS_CRYPTOSDK_DECRYPT_UNSIGNED。如果遇到签名的加密文字,这会导致解密失败。

/* Decrypt unsigned streaming data */ /* Load error strings for debugging */ aws_cryptosdk_load_error_strings(); /* Construct an AWS KMS keyring */ struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(key_arn); /* Create a session for decrypting with the AWS KMS keyring Then release the keyring reference */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(alloc, AWS_CRYPTOSDK_DECRYPT_UNSIGNED, kms_keyring); aws_cryptosdk_keyring_release(kms_keyring); if (!session) { return AWS_OP_ERR; } /* Limit encrypted data keys */ aws_cryptosdk_session_set_max_encrypted_data_keys(session, 1); /* Decrypt Use aws_cryptosdk_session_process_full with non-streaming data */ if (AWS_OP_SUCCESS != aws_cryptosdk_session_process_full( session, plaintext, plaintext_buf_sz, &plaintext_len, ciphertext, ciphertext_len)) { aws_cryptosdk_session_destroy(session); return AWS_OP_ERR; }
C# / .NET

要在适用于 .NET 的 AWS Encryption SDK 中指定备用算法套件,请指定 EncryptInput 对象的 AlgorithmSuiteId 属性。适用于 .NET 的 AWS Encryption SDK 包含可用于标识首选算法套件的常量

适用于 .NET 的 AWS Encryption SDK 没有在流式传输解密时检测签名加密文字的方法,因为此库不支持流式传输数据。

// Specify an algorithm suite without signing // Instantiate the AWS Encryption SDK and material providers var encryptionSdk = AwsEncryptionSdkFactory.CreateDefaultAwsEncryptionSdk(); var materialProviders = AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders(); // Create the keyring var keyringInput = new CreateAwsKmsKeyringInput { KmsClient = new AmazonKeyManagementServiceClient(), KmsKeyId = keyArn }; var keyring = materialProviders.CreateAwsKmsKeyring(keyringInput); // Encrypt your plaintext data var encryptInput = new EncryptInput { Plaintext = plaintext, Keyring = keyring, AlgorithmSuiteId = AlgorithmSuiteId.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY }; var encryptOutput = encryptionSdk.Encrypt(encryptInput);
AWS Encryption CLI

加密 hello.txt 文件时,此示例使用 --algorithm 参数来指定不带数字签名的算法套件。

# Specify an algorithm suite without signing # To run this example, replace the fictitious key ARN with a valid value. $ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab $ aws-encryption-cli --encrypt \ --input hello.txt \ --wrapping-keys key=$keyArn \ --algorithm AES_256_GCM_HKDF_SHA512_COMMIT_KEY \ --metadata-output ~/metadata \ --encryption-context purpose=test \ --commitment-policy require-encrypt-require-decrypt \ --output hello.txt.encrypted \ --decode

解密时,此示例使用 --decrypt-unsigned 参数。建议使用此参数来确保您正在解密未签名的加密文字,尤其是使用 CLI,该工具始终流式传输输入和输出。

# Decrypt unsigned streaming data # To run this example, replace the fictitious key ARN with a valid value. $ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab $ aws-encryption-cli --decrypt-unsigned \ --input hello.txt.encrypted \ --wrapping-keys key=$keyArn \ --max-encrypted-data-keys 1 \ --commitment-policy require-encrypt-require-decrypt \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --output .
Java

要指定备用算法套件,请使用 AwsCrypto.builder().withEncryptionAlgorithm() 方法。此示例指定了不带数字签名的备用算法套件。

// Specify an algorithm suite without signing // Instantiate the client AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .withEncryptionAlgorithm(CryptoAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY) .build(); String awsKmsKey = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; // Create a master key provider in strict mode KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder() .buildStrict(awsKmsKey); // Create an encryption context to identify this ciphertext Map<String, String> encryptionContext = Collections.singletonMap("Example", "FileStreaming"); // Encrypt your plaintext data CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData( masterKeyProvider, sourcePlaintext, encryptionContext); byte[] ciphertext = encryptResult.getResult();

在流式传输数据进行解密时,请使用 createUnsignedMessageDecryptingStream() 方法确保您正在解密的所有加密文字均未签名。

// Decrypt unsigned streaming data // Instantiate the client AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .withMaxEncryptedDataKeys(1) .build(); // Create a master key provider in strict mode String awsKmsKey = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder() .buildStrict(awsKmsKey); // Decrypt the encrypted message FileInputStream in = new FileInputStream(srcFile + ".encrypted"); CryptoInputStream<KmsMasterKey> decryptingStream = crypto.createUnsignedMessageDecryptingStream(masterKeyProvider, in); // Return the plaintext data // Write the plaintext data to disk FileOutputStream out = new FileOutputStream(srcFile + ".decrypted"); IOUtils.copy(decryptingStream, out); decryptingStream.close();
JavaScript Browser

要指定备用算法套件,请使用带有 AlgorithmSuiteIdentifier 枚举值的 suiteId 参数。

// Specify an algorithm suite without signing // Instantiate the client const { encrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) // Specify a KMS key const generatorKeyId = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; // Create a keyring with the KMS key const keyring = new KmsKeyringBrowser({ generatorKeyId }) // Encrypt your plaintext data const { result } = await encrypt(keyring, cleartext, { suiteId: AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA512_COMMIT_KEY, encryptionContext: context, })

解密时,请使用标准 decrypt 方法。AWS Encryption SDK for JavaScript 在浏览器中没有 decrypt-unsigned 模式,因为浏览器不支持串流。

// Decrypt unsigned streaming data // Instantiate the client const { decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) // Create a keyring with the same KMS key used to encrypt const generatorKeyId = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; const keyring = new KmsKeyringBrowser({ generatorKeyId }) // Decrypt the encrypted message const { plaintext, messageHeader } = await decrypt(keyring, ciphertextMessage)
JavaScript Node.js

要指定备用算法套件,请使用带有 AlgorithmSuiteIdentifier 枚举值的 suiteId 参数。

// Specify an algorithm suite without signing // Instantiate the client const { encrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) // Specify a KMS key const generatorKeyId = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; // Create a keyring with the KMS key const keyring = new KmsKeyringNode({ generatorKeyId }) // Encrypt your plaintext data const { result } = await encrypt(keyring, cleartext, { suiteId: AlgorithmSuiteIdentifier.ALG_AES256_GCM_IV12_TAG16_HKDF_SHA512_COMMIT_KEY, encryptionContext: context, })

解密未经数字签名加密的数据时,请使用 decryptUnsignedMessageStream。如果遇到签名的加密文字,此方法会失败。

// Decrypt unsigned streaming data // Instantiate the client const { decryptUnsignedMessageStream } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) // Create a keyring with the same KMS key used to encrypt const generatorKeyId = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; const keyring = new KmsKeyringNode({ generatorKeyId }) // Decrypt the encrypted message const outputStream = createReadStream(filename) .pipe(decryptUnsignedMessageStream(keyring))
Python

要指定备用加密算法,请使用带有 Algorithm 枚举值的 algorithm 参数。

# Specify an algorithm suite without signing # Instantiate a client client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT, max_encrypted_data_keys=1) # Create a master key provider in strict mode aws_kms_key = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab" aws_kms_strict_master_key_provider = StrictAwsKmsMasterKeyProvider( key_ids=[aws_kms_key] ) # Encrypt the plaintext using an alternate algorithm suite ciphertext, encrypted_message_header = client.encrypt( algorithm=Algorithm.AES_256_GCM_HKDF_SHA512_COMMIT_KEY, source=source_plaintext, key_provider=kms_key_provider )

解密未经数字签名加密的消息时,请使用 decrypt-unsigned 串流模式,尤其是在流式传输的同时解密时。

# Decrypt unsigned streaming data # Instantiate the client client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT, max_encrypted_data_keys=1) # Create a master key provider in strict mode aws_kms_key = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab" aws_kms_strict_master_key_provider = StrictAwsKmsMasterKeyProvider( key_ids=[aws_kms_key] ) # Decrypt with decrypt-unsigned with open(ciphertext_filename, "rb") as ciphertext, open(cycled_plaintext_filename, "wb") as plaintext: with client.stream(mode="decrypt-unsigned", source=ciphertext, key_provider=master_key_provider) as decryptor: for chunk in decryptor: plaintext.write(chunk) # Verify that the encryption context assert all( pair in decryptor.header.encryption_context.items() for pair in encryptor.header.encryption_context.items() ) return ciphertext_filename, cycled_plaintext_filename

限制加密数据密钥

您可以在加密消息中限制加密数据密钥的数量。此最佳实践功能可以帮助您在加密时检测配置错误的密钥环,或者在解密时检测恶意加密文字。这样还可以防止对您的关键基础设施进行不必要、昂贵、可能详尽的调用。当您解密来自不可信来源的消息时,限制加密数据密钥最有用。

尽管大多数加密消息在加密中使用的每个包装密钥都有一个加密数据密钥,但加密的消息最多可以包含 65535 个加密数据密钥。恶意攻击者可能会使用成千上万个加密数据密钥构造加密消息,但这些密钥都无法解密。因此,AWS Encryption SDK 会尝试解密每个加密数据密钥,直到用尽消息中的加密数据密钥。

要限制加密数据密钥,请使用 MaxEncryptedDataKeys 参数。从 AWS Encryption SDK 版本 1.9.x 和 2.2.x 开始,此参数可用于所有支持的编程语言。这是可选的,并且在加密和解密时有效。以下示例对使用三个不同的包装密钥加密的数据进行解密。将 MaxEncryptedDataKeys 值设置为 3。

C
/* Load error strings for debugging */ aws_cryptosdk_load_error_strings(); /* Construct an AWS KMS keyring */ struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(key_arn1, { key_arn2, key_arn3 }); /* Create a session */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(alloc, AWS_CRYPTOSDK_DECRYPT, kms_keyring); aws_cryptosdk_keyring_release(kms_keyring); /* Limit encrypted data keys */ aws_cryptosdk_session_set_max_encrypted_data_keys(session, 3); /* Decrypt */ size_t ciphertext_consumed_output; aws_cryptosdk_session_process(session, plaintext_output, plaintext_buf_sz_output, &plaintext_len_output, ciphertext_input, ciphertext_len_input, &ciphertext_consumed_output); assert(aws_cryptosdk_session_is_done(session)); assert(ciphertext_consumed == ciphertext_len);
C# / .NET

要限制适用于 .NET 的 AWS Encryption SDK 中的加密数据密钥,请为适用于 .NET 的 AWS Encryption SDK 实例化客户端,并将其可选 MaxEncryptedDataKeys 参数设置为所需的值。然后,在配置的 AWS Encryption SDK 实例上调用 Decrypt() 方法。

// Decrypt with limited data keys // Instantiate the material providers var materialProviders = AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders(); // Configure the commitment policy on the AWS Encryption SDK instance var config = new AwsEncryptionSdkConfig { MaxEncryptedDataKeys = 3 }; var encryptionSdk = AwsEncryptionSdkFactory.CreateAwsEncryptionSdk(config); // Create the keyring string keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; var createKeyringInput = new CreateAwsKmsKeyringInput { KmsClient = new AmazonKeyManagementServiceClient(), KmsKeyId = keyArn }; var decryptKeyring = materialProviders.CreateAwsKmsKeyring(createKeyringInput); // Decrypt the ciphertext var decryptInput = new DecryptInput { Ciphertext = ciphertext, Keyring = decryptKeyring }; var decryptOutput = encryptionSdk.Decrypt(decryptInput);
AWS Encryption CLI
# Decrypt with limited encrypted data keys $ aws-encryption-cli --decrypt \ --input hello.txt.encrypted \ --wrapping-keys key=$key_arn1 key=$key_arn2 key=$key_arn3 \ --buffer \ --max-encrypted-data-keys 3 \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --output .
Java
// Construct a client with limited encrypted data keys final AwsCrypto crypto = AwsCrypto.builder() .withMaxEncryptedDataKeys(3) .build(); // Create an AWS KMS master key provider final KmsMasterKeyProvider keyProvider = KmsMasterKeyProvider.builder() .buildStrict(keyArn1, keyArn2, keyArn3); // Decrypt final CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(keyProvider, ciphertext)
JavaScript Browser
// Construct a client with limited encrypted data keys const { encrypt, decrypt } = buildClient({ maxEncryptedDataKeys: 3 }) declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } const clientProvider = getClient(KMS, { credentials: { accessKeyId, secretAccessKey, sessionToken } }) // Create an AWS KMS keyring const keyring = new KmsKeyringBrowser({ clientProvider, keyIds: [keyArn1, keyArn2, keyArn3], }) // Decrypt const { plaintext, messageHeader } = await decrypt(keyring, ciphertext)
JavaScript Node.js
// Construct a client with limited encrypted data keys const { encrypt, decrypt } = buildClient({ maxEncryptedDataKeys: 3 }) // Create an AWS KMS keyring const keyring = new KmsKeyringBrowser({ keyIds: [keyArn1, keyArn2, keyArn3], }) // Decrypt const { plaintext, messageHeader } = await decrypt(keyring, ciphertext)
Python
# Instantiate a client with limited encrypted data keys client = aws_encryption_sdk.EncryptionSDKClient(max_encrypted_data_keys=3) # Create an AWS KMS master key provider master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider( key_ids=[key_arn1, key_arn2, key_arn3]) # Decrypt plaintext, header = client.decrypt(source=ciphertext, key_provider=master_key_provider)

创建发现筛选条件

解密使用 KMS 密钥加密的数据时,最佳实践是在严格模式下解密,也就是说,将包装密钥仅限于您指定的密钥。但是,如有必要,您也可以在发现模式下解密,在这种模式下,您无需指定任何包装密钥。在此模式下,无论谁拥有或有权访问加密数据密钥的 KMS 密钥,AWS KMS 都可以使用该 KMS 密钥对其进行解密。

如果您必须在发现模式下解密,我们建议您始终使用发现筛选条件,该筛选条件将可用的 KMS 密钥限制为指定 AWS 账户 和分区中的密钥。发现筛选条件是可选的,但这是最佳实践。

使用下表确定发现筛选条件的分区值。

区域 分区
AWS 区域 aws
中国区域 aws-cn
AWS GovCloud (US) Regions aws-us-gov

本节中的示例向您显示如何创建发现筛选条件。在使用代码之前,请将示例值替换为 AWS 账户 和分区的有效值。

C

有关完整的示例,请参阅 AWS Encryption SDK for C 中的 kms_discovery.cpp

/* Create a discovery filter for an AWS account and partition */ const char *account_id = "111122223333"; const char *partition = "aws"; const std::shared_ptr<Aws::Cryptosdk::KmsKeyring::DiscoveryFilter> discovery_filter = Aws::Cryptosdk::KmsKeyring::DiscoveryFilter::Builder(partition).AddAccount(account_id).Build();
C# / .NET

有关完整的示例,请参阅适用于 .NET 的 AWS Encryption SDK 中的 DiscoveryFilterExample.cs

// Create a discovery filter for an AWS account and partition List<string> account = new List<string> { "111122223333" }; DiscoveryFilter exampleDiscoveryFilter = new DiscoveryFilter() { AccountIds = account, Partition = "aws" }
AWS Encryption CLI
# Decrypt in discovery mode with a discovery filter $ aws-encryption-cli --decrypt \ --input hello.txt.encrypted \ --wrapping-keys discovery=true \ discovery-account=111122223333 \ discovery-partition=aws \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --max-encrypted-data-keys 1 \ --buffer \ --output .
Java

有关完整的示例,请参阅 AWS Encryption SDK for Java 中的 DiscoveryDecryptionExample.java

// Create a discovery filter for an AWS account and partition DiscoveryFilter discoveryFilter = new DiscoveryFilter("aws", 111122223333);
JavaScript (Node and Browser)

有关完整的示例,请参阅 AWS Encryption SDK for JavaScript 中的 kms_filtered_discovery.ts(Node.js)和 kms_multi_region_discovery.ts(浏览器)。

/* Create a discovery filter for an AWS account and partition */ const discoveryFilter = { accountIDs: ['111122223333'], partition: 'aws', }
Python

有关完整的示例,请参阅 AWS Encryption SDK for Python 中的 discovery_kms_provider.py

# Create the discovery filter and specify the region decrypt_kwargs = dict( discovery_filter=DiscoveryFilter(account_ids="111122223333", partition="aws"), discovery_region="us-west-2", )

设置承诺策略

承诺策略是一种配置设置,用于确定您的应用程序是否使用密钥承诺进行加密和解密。使用密钥承诺进行加密和解密是 AWS Encryption SDK 最佳实践

设置和调整承诺策略是从 AWS Encryption SDK 版本 1.7.x 及更早版本迁移到版本 2.0.x 及更高版本的关键步骤。迁移主题中详细解释了这一进展。

AWS Encryption SDK 最新版本(从版本 2.0.x 开始)中的默认承诺策略值 RequireEncryptRequireDecrypt 非常适合大多数情况。但是,如果您需要解密未经密钥承诺而加密的加密文字,则可能需要将承诺策略更改为 RequireEncryptAllowDecrypt。有关如何使用每种编程语言设置承诺策略的示例,请参阅 设置您的承诺策略

使用串流数据

在流式传输数据进行解密时,请注意,在完整性检查完成后、在验证数字签名之前,AWS Encryption SDK 返回的是解密后的明文。为确保在签名通过验证之前不返回或使用明文,我们建议您缓冲流式传输的明文,直到整个解密过程完成。

只有当您流式传输加密文字进行解密时,并且只有当您使用包含数字签名的算法套件(例如默认算法套件)时,才会出现这个问题。

为了简化缓冲,某些 AWS Encryption SDK 语言实现(例如 Node.js 中的 AWS Encryption SDK for JavaScript)在解密方法中包含缓冲功能。始终流式传输输入和输出的 AWS Encryption CLI 在版本 1.9.x 和 2.2.x 中引入了 --buffer 参数。在其他语言实现中,您可以使用现有的缓冲功能。(适用于 .NET 的 AWS Encryption SDK 不支持串流。)

如果您使用的是没有数字签名的算法套件,请务必在每种语言实现中使用 decrypt-unsigned 功能。此功能可以解密加密文字,但如果遇到签名的加密文字,则会失败。有关详细信息,请参阅 选择算法套件

缓存数据密钥

通常,不鼓励重复使用数据密钥,但 AWS Encryption SDK 提供了数据密钥缓存选项,可限制对数据密钥的重复使用。数据密钥缓存可以提高某些应用程序的性能并减少对密钥基础设施的调用。在生产环境中使用数据密钥缓存之前,请调整安全阈值并进行测试,以确保重复使用数据密钥的好处大于缺点。