12
12
import com .amazonaws .encryptionsdk .kms .AwsKmsCmkId ;
13
13
import com .amazonaws .encryptionsdk .kms .KmsMasterKeyProvider ;
14
14
15
+ import java .util .ArrayList ;
15
16
import java .util .Arrays ;
16
17
import java .util .HashMap ;
18
+ import java .util .List ;
17
19
import java .util .Map ;
18
20
21
+ import static java .util .stream .Collectors .toList ;
22
+
19
23
/**
20
- * In earlier versions of the AWS Encryption SDK, you used master key providers to determine how your data keys are protected.
24
+ * You might have used master key providers to protect your data keys
25
+ * in an earlier version of the AWS Encryption SDK.
26
+ * This example shows how to configure a keyring that behaves like an AWS KMS master key provider.
21
27
* <p>
22
- * The AWS Encryption SDK provided an AWS KMS master key provider for interacting with AWS Key Management Service (AWS KMS).
23
- * Like the AWS KMS keyring,
24
- * the AWS KMS master key provider encrypts with all CMKs that you identify,
25
- * but unlike the AWS KMS keyring,
26
- * the AWS KMS master key provider always attempts to decrypt
27
- * *any* data keys that were encrypted under an AWS KMS CMK.
28
+ * The AWS Encryption SDK provided an AWS KMS master key provider for
29
+ * interacting with AWS Key Management Service (AWS KMS).
30
+ * On encrypt, the AWS KMS master key provider behaves like the AWS KMS keyring
31
+ * and encrypts with all CMKs that you identify.
32
+ * However, on decrypt,
33
+ * the AWS KMS master key provider reviews each encrypted data key (EDK).
34
+ * If the EDK was encrypted under an AWS KMS CMK,
35
+ * the AWS KMS master key provider attempts to decrypt it.
36
+ * Whether decryption succeeds depends on permissions on the CMK.
37
+ * This continues until the AWS KMS master key provider either runs out of EDKs
38
+ * or succeeds in decrypting an EDK.
28
39
* We have found that separating these two behaviors
29
40
* makes the expected behavior clearer,
30
41
* so that is what we did with the AWS KMS keyring and the AWS KMS discovery keyring.
31
42
* However, as you migrate from master key providers to keyrings,
32
43
* you might want a keyring that behaves like the AWS KMS master key provider.
33
44
* <p>
34
- * This example shows how to configure a keyring that behaves like an AWS KMS master key provider.
35
- * <p>
36
45
* For more examples of how to use the AWS KMS keyring,
37
46
* see the 'keyring/awskms' directory.
38
47
*/
@@ -41,10 +50,11 @@ public class ActLikeAwsKmsMasterKeyProvider {
41
50
/**
42
51
* Demonstrate how to create a keyring that behaves like an AWS KMS master key provider.
43
52
*
44
- * @param awsKmsCmk The ARN of an AWS KMS CMK that protects data keys
45
- * @param sourcePlaintext Plaintext to encrypt
53
+ * @param awsKmsCmk The ARN of an AWS KMS CMK that protects data keys
54
+ * @param awsKmsAdditionalCmks Additional ARNs of secondary AWS KMS CMKs
55
+ * @param sourcePlaintext Plaintext to encrypt
46
56
*/
47
- public static void run (final AwsKmsCmkId awsKmsCmk , final byte [] sourcePlaintext ) {
57
+ public static void run (final AwsKmsCmkId awsKmsCmk , final List < AwsKmsCmkId > awsKmsAdditionalCmks , byte [] sourcePlaintext ) {
48
58
// Instantiate the AWS Encryption SDK.
49
59
final AwsCrypto awsEncryptionSdk = new AwsCrypto ();
50
60
@@ -59,22 +69,42 @@ public static void run(final AwsKmsCmkId awsKmsCmk, final byte[] sourcePlaintext
59
69
60
70
// This is the master key provider whose behavior we want to reproduce.
61
71
//
62
- // When encrypting, this master key provider uses only the specified `aws_kms_cmk`.
72
+ // When encrypting, this master key provider generates the data key using the first CMK in the list
73
+ // and encrypts the data key using all specified CMKs.
63
74
// However, when decrypting, this master key provider attempts to decrypt
64
75
// any data keys that were encrypted under an AWS KMS CMK.
76
+ final List <String > masterKeyProviderCmks = new ArrayList <>();
77
+ masterKeyProviderCmks .add (awsKmsCmk .toString ());
78
+ masterKeyProviderCmks .addAll (awsKmsAdditionalCmks .stream ().map (AwsKmsCmkId ::toString ).collect (toList ()));
65
79
final KmsMasterKeyProvider masterKeyProviderToReplicate = KmsMasterKeyProvider .builder ()
66
- .withKeysForEncryption (awsKmsCmk . toString () ).build ();
80
+ .withKeysForEncryption (masterKeyProviderCmks ).build ();
67
81
68
- // Create a single-CMK keyring that encrypts and decrypts using a single AWS KMS CMK.
69
- final Keyring singleCmkKeyring = StandardKeyrings .awsKms (awsKmsCmk );
82
+ // Create a CMK keyring that encrypts and decrypts using the specified AWS KMS CMKs.
83
+ //
84
+ // This keyring reproduces the encryption behavior of the AWS KMS master key provider.
85
+ //
86
+ // The AWS KMS keyring requires that you explicitly identify the CMK
87
+ // that you want the keyring to use to generate the data key.
88
+ final Keyring cmkKeyring = StandardKeyrings .awsKmsBuilder ()
89
+ .generatorKeyId (awsKmsCmk )
90
+ .keyIds (awsKmsAdditionalCmks )
91
+ .build ();
70
92
71
93
// Create an AWS KMS discovery keyring that will attempt to decrypt
72
94
// any data keys that were encrypted under an AWS KMS CMK.
73
95
final Keyring discoveryKeyring = StandardKeyrings .awsKmsDiscoveryBuilder ().build ();
74
96
75
97
// Combine the single-CMK and discovery keyrings
76
98
// to create a keyring that behaves like an AWS KMS master key provider.
77
- final Keyring keyring = StandardKeyrings .multi (singleCmkKeyring , discoveryKeyring );
99
+ //
100
+ // The CMK keyring reproduces the encryption behavior
101
+ // and the discovery keyring reproduces the decryption behavior.
102
+ // This also means that it does not matter if the CMK keyring fails on decrypt,
103
+ // for example if you configured it with aliases which would work on encrypt
104
+ // but fail to match any encrypted data keys on decrypt,
105
+ // because the discovery keyring attempts to decrypt any AWS KMS-encrypted
106
+ // data keys that it finds.
107
+ final Keyring keyring = StandardKeyrings .multi (cmkKeyring , discoveryKeyring );
78
108
79
109
// Encrypt your plaintext data.
80
110
final AwsCryptoResult <byte []> encryptResult = awsEncryptionSdk .encrypt (
0 commit comments